import * as i0 from '@angular/core';
import { input, output, signal, computed, effect, forwardRef, Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import * as i1$1 from '@angular/forms';
import { FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
import * as i1 from '@angular/cdk/drag-drop';
import { moveItemInArray, DragDropModule } from '@angular/cdk/drag-drop';

/**
 * Flat Formula Token Model
 *
 * The formula is represented as a FLAT array of tokens.
 * This approach provides:
 * - Better performance (no deep component nesting)
 * - Solid drag-drop behavior (functions move as complete units)
 * - Simple serialization (just join token values)
 *
 * STRUCTURE RULES:
 * - fn-open: "IF(" - function name + opening paren as ONE token
 * - fn-close: ")" - closing paren, belongs to a function
 * - fn-separator: "," - argument separator, belongs to a function
 * - Dragging any structural token moves the ENTIRE function
 * - Content tokens (property, operator, literal) can move individually
 */
// ============ UTILITY FUNCTIONS ============
/** Generate unique token ID */
function generateTokenId() {
    return `tok_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`;
}
/** Generate unique function ID */
function generateFunctionId() {
    return `fn_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`;
}
/** Parse function signature like "SUM(values)" or "IF(cond, a, b)" */
function parseSignature(signature) {
    const match = signature.match(/^(\w+)\((.*)\)$/);
    if (!match)
        return { name: signature, args: [] };
    const name = match[1];
    const argsStr = match[2].trim();
    if (!argsStr)
        return { name, args: [] };
    const args = [];
    let current = '';
    let depth = 0;
    for (const char of argsStr) {
        if (char === '(')
            depth++;
        else if (char === ')')
            depth--;
        else if (char === ',' && depth === 0) {
            args.push(current.trim());
            current = '';
            continue;
        }
        current += char;
    }
    if (current.trim())
        args.push(current.trim());
    return { name, args };
}
/**
 * Create a function's tokens from signature
 * e.g., "IF(condition, trueVal, falseVal)" creates:
 * - fn-open: "IF("
 * - fn-separator: "," (x2)
 * - fn-close: ")"
 */
function createFunctionTokens(signature, depth = 0) {
    const parsed = parseSignature(signature);
    const functionId = generateFunctionId();
    const tokens = [];
    // Opening token: "NAME("
    tokens.push({
        id: generateTokenId(),
        type: 'fn-open',
        value: `${parsed.name}(`,
        functionId,
        functionName: parsed.name,
        depth,
        dragBehavior: 'function',
    });
    // Separators for arguments (one less than arg count)
    for (let i = 0; i < parsed.args.length - 1; i++) {
        tokens.push({
            id: generateTokenId(),
            type: 'fn-separator',
            value: ',',
            functionId,
            depth,
            argIndex: i, // Separator AFTER this argument
            dragBehavior: 'function',
        });
    }
    // Closing token: ")"
    tokens.push({
        id: generateTokenId(),
        type: 'fn-close',
        value: ')',
        functionId,
        depth,
        dragBehavior: 'function',
    });
    return tokens;
}
/**
 * Create a property token
 */
function createPropertyToken(propertyKey, propertyType = 'current', depth = 0, functionId, argIndex) {
    const prefix = propertyType === 'current'
        ? '@'
        : propertyType === 'children'
            ? '*.'
            : '$.';
    return {
        id: generateTokenId(),
        type: 'property',
        value: `${prefix}${propertyKey}`,
        propertyType,
        depth,
        functionId,
        argIndex,
        dragBehavior: 'single',
    };
}
/**
 * Create an operator token
 */
function createOperatorToken(symbol, depth = 0, functionId, argIndex) {
    return {
        id: generateTokenId(),
        type: 'operator',
        value: symbol,
        depth,
        functionId,
        argIndex,
        dragBehavior: 'single',
    };
}
/**
 * Create a literal token
 */
function createLiteralToken(value, depth = 0, functionId, argIndex) {
    let displayValue = String(value);
    let literalType = 'string';
    if (typeof value === 'number') {
        literalType = 'number';
    }
    else if (typeof value === 'boolean') {
        literalType = 'boolean';
    }
    else if (typeof value === 'string' && !value.startsWith('"')) {
        displayValue = `"${value}"`;
    }
    return {
        id: generateTokenId(),
        type: 'literal',
        value: displayValue,
        literalType,
        depth,
        functionId,
        argIndex,
        dragBehavior: 'single',
    };
}
// ============ TOKEN ARRAY OPERATIONS ============
/**
 * Find the complete range of a function in the token array
 * This includes ALL tokens between fn-open and fn-close (including nested content)
 * Returns [startIndex, endIndex] inclusive
 */
function findFunctionRange(tokens, functionId) {
    // Find the fn-open token with this functionId
    const openIndex = tokens.findIndex((t) => t.functionId === functionId && t.type === 'fn-open');
    if (openIndex === -1)
        return null;
    // Now find the matching fn-close by counting depth
    // Start from fn-open and find matching close paren
    let depth = 1;
    for (let i = openIndex + 1; i < tokens.length; i++) {
        const token = tokens[i];
        if (token.type === 'fn-open') {
            depth++;
        }
        else if (token.type === 'fn-close') {
            depth--;
            if (depth === 0) {
                // Found the matching close
                return [openIndex, i];
            }
        }
    }
    // Fallback: find fn-close with same functionId
    const closeIndex = tokens.findIndex((t) => t.functionId === functionId && t.type === 'fn-close');
    if (closeIndex === -1)
        return null;
    return [openIndex, closeIndex];
}
/**
 * Get all tokens belonging to a function (including nested content)
 */
function getFunctionTokens(tokens, functionId) {
    const range = findFunctionRange(tokens, functionId);
    if (!range)
        return [];
    return tokens.slice(range[0], range[1] + 1);
}
/**
 * Validate if a drop position is allowed
 */
function isValidDropPosition(tokens, dropIndex, draggedTokens) {
    // Can always drop at start or end
    if (dropIndex === 0 || dropIndex === tokens.length)
        return true;
    const _prevToken = tokens[dropIndex - 1];
    const _nextToken = tokens[dropIndex];
    // If dragging a function, check if it would create invalid nesting
    const isDraggingFunction = draggedTokens.some((t) => t.type === 'fn-open' || t.type === 'fn-close');
    if (isDraggingFunction) {
        // Don't allow dropping a function that would break structure
        // For now, allow all - we can refine later
    }
    return true;
}
/**
 * Serialize tokens to formula string
 */
function serializeTokens(tokens) {
    const parts = [];
    let lastType = null;
    for (const token of tokens) {
        // Add space between tokens (except after fn-open, before fn-close, after separator)
        if (lastType &&
            lastType !== 'fn-open' &&
            token.type !== 'fn-close' &&
            token.type !== 'fn-separator' &&
            lastType !== 'fn-separator') {
            parts.push(' ');
        }
        parts.push(token.value);
        lastType = token.type;
    }
    return parts.join('');
}
/**
 * Clone a token with new ID
 */
function cloneToken(token) {
    return {
        ...token,
        id: generateTokenId(),
    };
}
/**
 * Clone multiple tokens with new IDs and new function IDs
 */
function cloneTokens(tokens) {
    // Map old function IDs to new ones
    const functionIdMap = new Map();
    return tokens.map((token) => {
        const newToken = cloneToken(token);
        // Remap function IDs
        if (token.functionId) {
            if (!functionIdMap.has(token.functionId)) {
                functionIdMap.set(token.functionId, generateFunctionId());
            }
            newToken.functionId = functionIdMap.get(token.functionId);
        }
        return newToken;
    });
}
/**
 * Update depth for all tokens (after move)
 */
function recalculateDepths(tokens) {
    let currentDepth = 0;
    const result = [];
    for (const token of tokens) {
        if (token.type === 'fn-open') {
            result.push({ ...token, depth: currentDepth });
            currentDepth++;
        }
        else if (token.type === 'fn-close') {
            currentDepth--;
            result.push({ ...token, depth: currentDepth });
        }
        else {
            result.push({ ...token, depth: currentDepth });
        }
    }
    return result;
}
/**
 * Find which argument index a position belongs to within a function
 */
function getArgumentIndexAtPosition(tokens, functionId, position) {
    const range = findFunctionRange(tokens, functionId);
    if (!range)
        return 0;
    let argIndex = 0;
    for (let i = range[0] + 1; i < position && i <= range[1]; i++) {
        if (tokens[i].type === 'fn-separator' &&
            tokens[i].functionId === functionId) {
            argIndex++;
        }
    }
    return argIndex;
}

/**
 * Smart Formula Block - Types and Factory Functions
 * Defines the block structure and creation helpers
 */
/** Generate unique block ID */
function generateSmartBlockId() {
    return `sb_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
}
/** Create a function block from signature */
function createFunctionBlock(signature, name) {
    const parsed = parseSignature(signature);
    return {
        id: generateSmartBlockId(),
        type: 'function',
        value: parsed.name,
        functionName: name || parsed.name,
        signature,
        arguments: parsed.args.map((arg) => ({
            id: generateSmartBlockId(),
            name: arg,
            blocks: [],
            placeholder: arg,
        })),
    };
}
/** Create a property block */
function createPropertyBlock(propertyKey, propertyType = 'current') {
    const prefix = propertyType === 'current'
        ? '@'
        : propertyType === 'children'
            ? '*.'
            : '$.';
    return {
        id: generateSmartBlockId(),
        type: 'property',
        value: `${prefix}${propertyKey}`,
        propertyType,
        propertyKey,
    };
}
/** Create an operator block */
function createOperatorBlock(symbol) {
    return {
        id: generateSmartBlockId(),
        type: 'operator',
        value: symbol,
        operatorSymbol: symbol,
    };
}
/** Create a literal block */
function createLiteralBlock(value) {
    return {
        id: generateSmartBlockId(),
        type: 'literal',
        value: String(value),
        literalValue: value,
    };
}
/** Deep clone a block with new IDs */
function cloneBlock(block) {
    const newBlock = { ...block, id: generateSmartBlockId() };
    if (block.arguments) {
        newBlock.arguments = block.arguments.map((arg) => ({
            ...arg,
            id: generateSmartBlockId(),
            blocks: arg.blocks.map((b) => cloneBlock(b)),
        }));
    }
    return newBlock;
}

/**
 * Validation Result Models
 * API response types for formula validation
 */

/**
 * Formula Block Model - Types for formula functions and operators
 */

// Models index

class FormulaEditor {
    // ============ INPUTS ============
    placeholder = input('Click toolbar items to build formula...', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
    initialTokens = input([], ...(ngDevMode ? [{ debugName: "initialTokens" }] : []));
    disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
    // ============ OUTPUTS ============
    formulaChange = output();
    tokensChange = output();
    onBlur = output();
    onFocus = output();
    // ============ STATE ============
    tokens = signal([], ...(ngDevMode ? [{ debugName: "tokens" }] : []));
    /** Index range being dragged [start, end] inclusive */
    draggedRange = null;
    /** Is currently dragging */
    isDragging = signal(false, ...(ngDevMode ? [{ debugName: "isDragging" }] : []));
    /** Hovered function ID for highlighting */
    hoveredFunctionId = signal(null, ...(ngDevMode ? [{ debugName: "hoveredFunctionId" }] : []));
    /** Is focused */
    isFocused = signal(false, ...(ngDevMode ? [{ debugName: "isFocused" }] : []));
    // ============ CVA ============
    onChange = () => { };
    onTouched = () => { };
    // ============ COMPUTED ============
    /** Line numbers based on token count */
    lines = computed(() => {
        const count = Math.max(1, Math.ceil(this.tokens().length / 8));
        return Array(count).fill(0);
    }, ...(ngDevMode ? [{ debugName: "lines" }] : []));
    /** Serialized formula string */
    formulaString = computed(() => serializeTokens(this.tokens()), ...(ngDevMode ? [{ debugName: "formulaString" }] : []));
    constructor() {
        // Initialize from input
        effect(() => {
            const initial = this.initialTokens();
            if (initial.length > 0) {
                this.tokens.set(initial);
            }
        });
    }
    // ============ CONTROL VALUE ACCESSOR ============
    writeValue(value) {
        if (value === null || value === undefined) {
            this.tokens.set([]);
            return;
        }
        // Value should be tokens array
        if (Array.isArray(value)) {
            this.tokens.set(value);
        }
    }
    registerOnChange(fn) {
        this.onChange = fn;
    }
    registerOnTouched(fn) {
        this.onTouched = fn;
    }
    // ============ PUBLIC API ============
    /**
     * Add a block from toolbar (converts SmartBlock to tokens)
     */
    addBlock(block) {
        if (this.disabled())
            return;
        const newTokens = this.smartBlockToTokens(block);
        this.tokens.update((tokens) => [...tokens, ...cloneTokens(newTokens)]);
        this.emit();
    }
    /**
     * Add tokens directly
     */
    addTokens(newTokens) {
        if (this.disabled())
            return;
        this.tokens.update((tokens) => [...tokens, ...cloneTokens(newTokens)]);
        this.emit();
    }
    /**
     * Clear all tokens
     */
    clear() {
        if (this.disabled())
            return;
        this.tokens.set([]);
        this.emit();
    }
    /**
     * Get current formula string
     */
    serialize() {
        return this.formulaString();
    }
    /**
     * Get current tokens
     */
    getTokens() {
        return this.tokens();
    }
    // ============ FOCUS HANDLERS ============
    handleFocus() {
        this.isFocused.set(true);
        this.onFocus.emit();
    }
    handleBlur() {
        this.isFocused.set(false);
        this.onTouched();
        this.onBlur.emit();
    }
    // ============ DRAG HANDLERS ============
    /**
     * Handle drag start - determine what tokens to drag
     */
    onDragStart(event, token, index) {
        if (this.disabled())
            return;
        this.isDragging.set(true);
        if (token.dragBehavior === 'function' && token.functionId) {
            // Drag entire function (all tokens from fn-open to fn-close)
            const range = findFunctionRange(this.tokens(), token.functionId);
            if (range) {
                this.draggedRange = range;
            }
            else {
                // Fallback to single token if range not found
                this.draggedRange = [index, index];
            }
        }
        else {
            // Drag single token
            this.draggedRange = [index, index];
        }
    }
    /**
     * Handle drop - reorder tokens in the formula
     */
    onDrop(event) {
        if (this.disabled())
            return;
        this.isDragging.set(false);
        const { previousIndex, currentIndex } = event;
        // No movement
        if (previousIndex === currentIndex) {
            this.resetDragState();
            return;
        }
        // No drag data (shouldn't happen but be safe)
        if (!this.draggedRange) {
            this.resetDragState();
            return;
        }
        const [start, end] = this.draggedRange;
        const count = end - start + 1;
        const isSingleToken = start === end;
        // Block dropping inside own range (only for multi-token drag)
        if (!isSingleToken && currentIndex > start && currentIndex <= end) {
            this.resetDragState();
            return;
        }
        const tokens = [...this.tokens()];
        if (isSingleToken) {
            // Simple single-token move using CDK utility
            moveItemInArray(tokens, previousIndex, currentIndex);
        }
        else {
            // Multi-token move (function with all content)
            // 1. Extract the tokens we're moving
            const moving = tokens.splice(start, count);
            // 2. Calculate insert position
            let insertAt;
            if (currentIndex <= start) {
                // Moving left/backward - insert at drop position
                insertAt = currentIndex;
            }
            else {
                // Moving right/forward
                // After removal, adjust for removed count and insert AFTER drop target
                insertAt = currentIndex - count + 1;
            }
            // 3. Clamp and insert
            insertAt = Math.max(0, Math.min(insertAt, tokens.length));
            tokens.splice(insertAt, 0, ...moving);
        }
        // Update state with recalculated depths
        this.tokens.set(recalculateDepths(tokens));
        this.resetDragState();
        this.emit();
    }
    /**
     * Reset drag state
     */
    resetDragState() {
        this.draggedRange = null;
    }
    /**
     * Handle drag end
     * NOTE: CDK fires cdkDragEnded BEFORE cdkDropListDropped
     * So we don't reset draggedRange here - onDrop handles it
     */
    onDragEnd() {
        this.isDragging.set(false);
    }
    // ============ DELETE ============
    /**
     * Remove a token or function
     */
    removeToken(token, index) {
        if (this.disabled())
            return;
        if (token.dragBehavior === 'function' && token.functionId) {
            // Remove entire function
            const range = findFunctionRange(this.tokens(), token.functionId);
            if (range) {
                this.tokens.update((tokens) => {
                    const newTokens = [...tokens];
                    newTokens.splice(range[0], range[1] - range[0] + 1);
                    return recalculateDepths(newTokens);
                });
            }
        }
        else {
            // Remove single token
            this.tokens.update((tokens) => tokens.filter((_, i) => i !== index));
        }
        this.emit();
    }
    // ============ HOVER EFFECTS ============
    onTokenHover(token) {
        if (token.functionId && token.dragBehavior === 'function') {
            this.hoveredFunctionId.set(token.functionId);
        }
    }
    onTokenLeave() {
        this.hoveredFunctionId.set(null);
    }
    /**
     * Check if token should be highlighted
     * Only structural tokens (fn-open, fn-close, fn-separator) get highlighted
     * Content tokens (property, operator, literal) inside function are NOT highlighted
     */
    isHighlighted(token) {
        const hoveredId = this.hoveredFunctionId();
        if (!hoveredId)
            return false;
        // Only highlight structural tokens of the function, not content inside
        const isStructural = token.type === 'fn-open' ||
            token.type === 'fn-close' ||
            token.type === 'fn-separator';
        return isStructural && token.functionId === hoveredId;
    }
    // ============ STYLING ============
    /** Base token classes */
    baseTokenClasses = 'inline-flex items-center px-2 py-1 rounded text-sm font-medium cursor-grab select-none whitespace-nowrap active:cursor-grabbing';
    /**
     * Get Tailwind classes for a token
     */
    getTokenClasses(token) {
        const base = this.baseTokenClasses;
        // Type-based styling using Tailwind
        switch (token.type) {
            case 'fn-open':
                // Function opening: "IF(" - rounded left only
                return `${base} bg-slate-200 dark:bg-slate-700 text-slate-700 dark:text-slate-300 font-semibold hover:bg-slate-300 dark:hover:bg-slate-600 rounded-r-none pr-0.5`;
            case 'fn-close':
                // Function closing: ")" - rounded right only
                return `${base} bg-slate-200 dark:bg-slate-700 text-slate-700 dark:text-slate-300 font-semibold hover:bg-slate-300 dark:hover:bg-slate-600 rounded-l-none pl-0.5`;
            case 'fn-separator':
                // Function separator: ","
                return `${base} bg-slate-200 dark:bg-slate-700 text-slate-700 dark:text-slate-300 font-semibold hover:bg-slate-300 dark:hover:bg-slate-600 rounded-sm px-1`;
            case 'property':
                // Property tokens - amber colors
                return `${base} bg-amber-100 dark:bg-amber-900/30 text-amber-700 dark:text-amber-300 font-semibold hover:bg-amber-200 dark:hover:bg-amber-900/50`;
            case 'operator':
                // Operator tokens - sky colors
                return `${base} bg-sky-100 dark:bg-sky-900/30 text-sky-700 dark:text-sky-300 font-bold hover:bg-sky-200 dark:hover:bg-sky-900/50 px-2`;
            case 'literal':
                // Literal tokens - emerald colors
                return `${base} bg-emerald-100 dark:bg-emerald-900/30 text-emerald-700 dark:text-emerald-300 hover:bg-emerald-200 dark:hover:bg-emerald-900/50`;
            default:
                return base;
        }
    }
    // ============ CONVERSION ============
    /**
     * Convert SmartBlock to FormulaTokens
     */
    smartBlockToTokens(block) {
        switch (block.type) {
            case 'function':
                return createFunctionTokens(block.signature || `${block.functionName}()`, 0);
            case 'property':
                return [
                    createPropertyToken(block.propertyKey || block.value, block.propertyType),
                ];
            case 'operator':
                return [createOperatorToken(block.operatorSymbol || block.value)];
            case 'literal':
                return [createLiteralToken(block.literalValue ?? block.value)];
            default:
                return [createLiteralToken(block.value)];
        }
    }
    // ============ EMIT ============
    emit() {
        const formula = this.formulaString();
        const tokens = this.tokens();
        this.tokensChange.emit(tokens);
        this.formulaChange.emit(formula);
        this.onChange(tokens);
    }
    // ============ CDK HELPERS ============
    /**
     * Track function for ngFor
     */
    trackByToken(_index, token) {
        return token.id;
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: FormulaEditor, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: FormulaEditor, isStandalone: true, selector: "mt-formula-editor", inputs: { placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, initialTokens: { classPropertyName: "initialTokens", publicName: "initialTokens", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { formulaChange: "formulaChange", tokensChange: "tokensChange", onBlur: "onBlur", onFocus: "onFocus" }, providers: [
            {
                provide: NG_VALUE_ACCESSOR,
                useExisting: forwardRef(() => FormulaEditor),
                multi: true,
            },
        ], ngImport: i0, template: "<div\r\n  class=\"flex border border-surface-200 dark:border-surface-700 rounded-md bg-white dark:bg-surface-800 min-h-20 font-mono text-sm focus-within:border-primary focus-within:ring-2 focus-within:ring-primary/10\"\r\n  [class.opacity-60]=\"disabled()\"\r\n  [class.pointer-events-none]=\"disabled()\"\r\n  (focus)=\"handleFocus()\"\r\n  (blur)=\"handleBlur()\"\r\n  tabindex=\"0\"\r\n>\r\n  <!-- Line Numbers -->\r\n  <div\r\n    class=\"flex flex-col px-1.5 py-2 bg-surface-50 dark:bg-surface-900 border-r border-surface-200 dark:border-surface-700 rounded-l-md select-none min-w-6 text-right\"\r\n  >\r\n    @for (line of lines(); track $index) {\r\n      <div class=\"text-surface-400 dark:text-surface-500 text-sm leading-6\">\r\n        {{ $index + 1 }}\r\n      </div>\r\n    }\r\n  </div>\r\n\r\n  <!-- Editor Content - Single Drop Zone -->\r\n  <div\r\n    class=\"flex-1 p-2 flex flex-wrap gap-0.5 items-start content-start min-h-14 cursor-text\"\r\n    cdkDropList\r\n    cdkDropListOrientation=\"mixed\"\r\n    [cdkDropListData]=\"tokens()\"\r\n    [cdkDropListDisabled]=\"disabled()\"\r\n    (cdkDropListDropped)=\"onDrop($event)\"\r\n  >\r\n    @if (tokens().length === 0) {\r\n      <div class=\"text-surface-400 dark:text-surface-500 text-sm italic\">\r\n        {{ placeholder() }}\r\n      </div>\r\n    } @else {\r\n      @for (token of tokens(); track token.id; let i = $index) {\r\n        <div\r\n          class=\"relative inline-flex items-center group\"\r\n          cdkDrag\r\n          [cdkDragData]=\"token\"\r\n          [cdkDragDisabled]=\"disabled()\"\r\n          (cdkDragStarted)=\"onDragStart($event, token, i)\"\r\n          (cdkDragEnded)=\"onDragEnd()\"\r\n        >\r\n          <!-- Drag Placeholder (thin cursor line) -->\r\n          <div\r\n            *cdkDragPlaceholder\r\n            class=\"w-2 min-w-2 h-5 bg-primary rounded-sm opacity-80\"\r\n          ></div>\r\n\r\n          <!-- Token -->\r\n          <span\r\n            [class]=\"getTokenClasses(token)\"\r\n            [class.border-b-2]=\"!isDragging() && isHighlighted(token)\"\r\n            [class.border-primary]=\"!isDragging() && isHighlighted(token)\"\r\n            (mouseenter)=\"onTokenHover(token)\"\r\n            (mouseleave)=\"onTokenLeave()\"\r\n          >\r\n            {{ token.value }}\r\n          </span>\r\n\r\n          <!-- Delete Button (shows on hover, hidden during drag) -->\r\n          @if (!isDragging() && !disabled()) {\r\n            <button\r\n              type=\"button\"\r\n              class=\"absolute -top-1.5 -right-1.5 w-3.5 h-3.5 flex items-center justify-center bg-red-500 hover:bg-red-600 text-white rounded-full cursor-pointer scale-75 hover:scale-100 opacity-0 group-hover:opacity-100 pointer-events-none group-hover:pointer-events-auto z-10\"\r\n              (click)=\"removeToken(token, i); $event.stopPropagation()\"\r\n              [title]=\"\r\n                token.dragBehavior === 'function' ? 'Remove function' : 'Remove'\r\n              \"\r\n            >\r\n              <svg\r\n                class=\"h-2.5 w-2.5\"\r\n                fill=\"none\"\r\n                viewBox=\"0 0 24 24\"\r\n                stroke=\"currentColor\"\r\n                stroke-width=\"3\"\r\n              >\r\n                <path\r\n                  stroke-linecap=\"round\"\r\n                  stroke-linejoin=\"round\"\r\n                  d=\"M6 18L18 6M6 6l12 12\"\r\n                />\r\n              </svg>\r\n            </button>\r\n          }\r\n        </div>\r\n      }\r\n    }\r\n  </div>\r\n</div>\r\n", styles: [".cdk-drag-preview{width:20px!important;height:20px!important;min-width:20px!important;min-height:20px!important;max-width:20px!important;max-height:20px!important;border-radius:4px;opacity:.9;overflow:hidden!important;cursor:grabbing}.cdk-drag-animating{transition:none!important}.cdk-drag-dragging{opacity:1}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i1.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i1.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i1.CdkDragPlaceholder, selector: "ng-template[cdkDragPlaceholder]", inputs: ["data"] }, { kind: "ngmodule", type: FormsModule }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: FormulaEditor, decorators: [{
            type: Component,
            args: [{ selector: 'mt-formula-editor', standalone: true, imports: [CommonModule, DragDropModule, FormsModule], providers: [
                        {
                            provide: NG_VALUE_ACCESSOR,
                            useExisting: forwardRef(() => FormulaEditor),
                            multi: true,
                        },
                    ], template: "<div\r\n  class=\"flex border border-surface-200 dark:border-surface-700 rounded-md bg-white dark:bg-surface-800 min-h-20 font-mono text-sm focus-within:border-primary focus-within:ring-2 focus-within:ring-primary/10\"\r\n  [class.opacity-60]=\"disabled()\"\r\n  [class.pointer-events-none]=\"disabled()\"\r\n  (focus)=\"handleFocus()\"\r\n  (blur)=\"handleBlur()\"\r\n  tabindex=\"0\"\r\n>\r\n  <!-- Line Numbers -->\r\n  <div\r\n    class=\"flex flex-col px-1.5 py-2 bg-surface-50 dark:bg-surface-900 border-r border-surface-200 dark:border-surface-700 rounded-l-md select-none min-w-6 text-right\"\r\n  >\r\n    @for (line of lines(); track $index) {\r\n      <div class=\"text-surface-400 dark:text-surface-500 text-sm leading-6\">\r\n        {{ $index + 1 }}\r\n      </div>\r\n    }\r\n  </div>\r\n\r\n  <!-- Editor Content - Single Drop Zone -->\r\n  <div\r\n    class=\"flex-1 p-2 flex flex-wrap gap-0.5 items-start content-start min-h-14 cursor-text\"\r\n    cdkDropList\r\n    cdkDropListOrientation=\"mixed\"\r\n    [cdkDropListData]=\"tokens()\"\r\n    [cdkDropListDisabled]=\"disabled()\"\r\n    (cdkDropListDropped)=\"onDrop($event)\"\r\n  >\r\n    @if (tokens().length === 0) {\r\n      <div class=\"text-surface-400 dark:text-surface-500 text-sm italic\">\r\n        {{ placeholder() }}\r\n      </div>\r\n    } @else {\r\n      @for (token of tokens(); track token.id; let i = $index) {\r\n        <div\r\n          class=\"relative inline-flex items-center group\"\r\n          cdkDrag\r\n          [cdkDragData]=\"token\"\r\n          [cdkDragDisabled]=\"disabled()\"\r\n          (cdkDragStarted)=\"onDragStart($event, token, i)\"\r\n          (cdkDragEnded)=\"onDragEnd()\"\r\n        >\r\n          <!-- Drag Placeholder (thin cursor line) -->\r\n          <div\r\n            *cdkDragPlaceholder\r\n            class=\"w-2 min-w-2 h-5 bg-primary rounded-sm opacity-80\"\r\n          ></div>\r\n\r\n          <!-- Token -->\r\n          <span\r\n            [class]=\"getTokenClasses(token)\"\r\n            [class.border-b-2]=\"!isDragging() && isHighlighted(token)\"\r\n            [class.border-primary]=\"!isDragging() && isHighlighted(token)\"\r\n            (mouseenter)=\"onTokenHover(token)\"\r\n            (mouseleave)=\"onTokenLeave()\"\r\n          >\r\n            {{ token.value }}\r\n          </span>\r\n\r\n          <!-- Delete Button (shows on hover, hidden during drag) -->\r\n          @if (!isDragging() && !disabled()) {\r\n            <button\r\n              type=\"button\"\r\n              class=\"absolute -top-1.5 -right-1.5 w-3.5 h-3.5 flex items-center justify-center bg-red-500 hover:bg-red-600 text-white rounded-full cursor-pointer scale-75 hover:scale-100 opacity-0 group-hover:opacity-100 pointer-events-none group-hover:pointer-events-auto z-10\"\r\n              (click)=\"removeToken(token, i); $event.stopPropagation()\"\r\n              [title]=\"\r\n                token.dragBehavior === 'function' ? 'Remove function' : 'Remove'\r\n              \"\r\n            >\r\n              <svg\r\n                class=\"h-2.5 w-2.5\"\r\n                fill=\"none\"\r\n                viewBox=\"0 0 24 24\"\r\n                stroke=\"currentColor\"\r\n                stroke-width=\"3\"\r\n              >\r\n                <path\r\n                  stroke-linecap=\"round\"\r\n                  stroke-linejoin=\"round\"\r\n                  d=\"M6 18L18 6M6 6l12 12\"\r\n                />\r\n              </svg>\r\n            </button>\r\n          }\r\n        </div>\r\n      }\r\n    }\r\n  </div>\r\n</div>\r\n", styles: [".cdk-drag-preview{width:20px!important;height:20px!important;min-width:20px!important;min-height:20px!important;max-width:20px!important;max-height:20px!important;border-radius:4px;opacity:.9;overflow:hidden!important;cursor:grabbing}.cdk-drag-animating{transition:none!important}.cdk-drag-dragging{opacity:1}\n"] }]
        }], ctorParameters: () => [], propDecorators: { placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], initialTokens: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialTokens", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], formulaChange: [{ type: i0.Output, args: ["formulaChange"] }], tokensChange: [{ type: i0.Output, args: ["tokensChange"] }], onBlur: [{ type: i0.Output, args: ["onBlur"] }], onFocus: [{ type: i0.Output, args: ["onFocus"] }] } });

/**
 * Toolbar Item Component
 * Clickable item in the toolbar (function, property, operator)
 * Items are clicked to insert - no drag from toolbar
 *
 * This is a pure input/output component with no service dependencies.
 */
class FormulaToolbarItem {
    /** Item type */
    type = input.required(...(ngDevMode ? [{ debugName: "type" }] : []));
    /** Item value (function name, property key, operator symbol) */
    value = input.required(...(ngDevMode ? [{ debugName: "value" }] : []));
    /** Display value (optional, defaults to value) */
    display = input(...(ngDevMode ? [undefined, { debugName: "display" }] : []));
    /** Description for tooltip */
    description = input('', ...(ngDevMode ? [{ debugName: "description" }] : []));
    /** Function signature (for functions only, e.g., "SUM(values)") */
    signature = input(...(ngDevMode ? [undefined, { debugName: "signature" }] : []));
    /** Property type for properties */
    propertyType = input('current', ...(ngDevMode ? [{ debugName: "propertyType" }] : []));
    /** Insert event - emits SmartBlock */
    onInsert = output();
    /** Computed display value */
    displayValue = computed(() => this.display() ?? this.value(), ...(ngDevMode ? [{ debugName: "displayValue" }] : []));
    /** Build SmartBlock from item data */
    smartBlock = computed(() => {
        switch (this.type()) {
            case 'function':
                return createFunctionBlock(this.signature() || `${this.value()}()`, this.value());
            case 'property':
                return createPropertyBlock(this.value(), this.propertyType());
            case 'operator':
                return createOperatorBlock(this.value());
            default:
                return createOperatorBlock(this.value());
        }
    }, ...(ngDevMode ? [{ debugName: "smartBlock" }] : []));
    /** Item CSS class based on type */
    itemClass = computed(() => {
        switch (this.type()) {
            case 'function':
                return 'bg-slate-200 text-slate-700 hover:bg-slate-300 dark:bg-slate-700 dark:text-slate-300 dark:hover:bg-slate-600';
            case 'property':
                return 'bg-amber-100 text-amber-700 hover:bg-amber-200 dark:bg-amber-900/30 dark:text-amber-300 dark:hover:bg-amber-900/50';
            case 'operator':
                return 'bg-sky-100 text-sky-700 hover:bg-sky-200 dark:bg-sky-900/30 dark:text-sky-300 dark:hover:bg-sky-900/50';
            default:
                return 'bg-slate-100 text-slate-700 dark:bg-slate-800 dark:text-slate-300';
        }
    }, ...(ngDevMode ? [{ debugName: "itemClass" }] : []));
    /** Handle click - emit the SmartBlock */
    handleClick() {
        this.onInsert.emit(this.smartBlock());
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: FormulaToolbarItem, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: FormulaToolbarItem, isStandalone: true, selector: "mt-formula-toolbar-item", inputs: { type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: true, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: true, transformFunction: null }, display: { classPropertyName: "display", publicName: "display", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, signature: { classPropertyName: "signature", publicName: "signature", isSignal: true, isRequired: false, transformFunction: null }, propertyType: { classPropertyName: "propertyType", publicName: "propertyType", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onInsert: "onInsert" }, host: { classAttribute: "inline-block" }, ngImport: i0, template: "<button\r\n  type=\"button\"\r\n  class=\"inline-flex cursor-pointer items-center gap-1 rounded px-2 py-1 text-sm font-medium transition-colors hover:shadow-sm active:scale-95\"\r\n  [class]=\"itemClass()\"\r\n  [title]=\"description()\"\r\n  (click)=\"handleClick()\"\r\n>\r\n  @if (type() === \"function\") {\r\n    <span class=\"text-sm opacity-60\">\u0192</span>\r\n  }\r\n  {{ displayValue() }}\r\n</button>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: FormulaToolbarItem, decorators: [{
            type: Component,
            args: [{ selector: 'mt-formula-toolbar-item', standalone: true, imports: [CommonModule], host: {
                        class: 'inline-block',
                    }, template: "<button\r\n  type=\"button\"\r\n  class=\"inline-flex cursor-pointer items-center gap-1 rounded px-2 py-1 text-sm font-medium transition-colors hover:shadow-sm active:scale-95\"\r\n  [class]=\"itemClass()\"\r\n  [title]=\"description()\"\r\n  (click)=\"handleClick()\"\r\n>\r\n  @if (type() === \"function\") {\r\n    <span class=\"text-sm opacity-60\">\u0192</span>\r\n  }\r\n  {{ displayValue() }}\r\n</button>\r\n" }]
        }], propDecorators: { type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: true }] }], display: [{ type: i0.Input, args: [{ isSignal: true, alias: "display", required: false }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }], signature: [{ type: i0.Input, args: [{ isSignal: true, alias: "signature", required: false }] }], propertyType: [{ type: i0.Input, args: [{ isSignal: true, alias: "propertyType", required: false }] }], onInsert: [{ type: i0.Output, args: ["onInsert"] }] } });

/**
 * Formula Toolbar Component
 * Vertical tabs toolbar with functions, properties, and operators
 *
 * This is a PURE input/output component with NO service dependencies.
 * All data (functions, operators, properties) must be passed via inputs.
 */
class FormulaToolbar {
    // ============ INPUTS ============
    /** Known properties to show in properties tab */
    knownProperties = input([], ...(ngDevMode ? [{ debugName: "knownProperties" }] : []));
    /** Function categories (from API or static data) */
    functionCategories = input([], ...(ngDevMode ? [{ debugName: "functionCategories" }] : []));
    /** Operators list */
    operators = input([], ...(ngDevMode ? [{ debugName: "operators" }] : []));
    /** Initial active tab */
    initialTab = input('functions', ...(ngDevMode ? [{ debugName: "initialTab" }] : []));
    /** Placeholder for search input */
    searchPlaceholder = input('Search...', ...(ngDevMode ? [{ debugName: "searchPlaceholder" }] : []));
    /** Labels */
    labels = input({}, ...(ngDevMode ? [{ debugName: "labels" }] : []));
    // ============ OUTPUTS ============
    /** Insert event - emits SmartBlock for the editor */
    onBlockInsert = output();
    /** Tab change event */
    onTabChange = output();
    // ============ STATE ============
    /** Active tab */
    activeTab = signal('functions', ...(ngDevMode ? [{ debugName: "activeTab" }] : []));
    /** Tab options */
    tabOptions = [
        { label: 'Functions', value: 'functions' },
        { label: 'Properties', value: 'properties' },
        { label: 'Operators', value: 'operators' },
    ];
    /** Search query */
    searchQuery = signal('', ...(ngDevMode ? [{ debugName: "searchQuery" }] : []));
    /** Custom value input */
    customValue = signal('', ...(ngDevMode ? [{ debugName: "customValue" }] : []));
    /** Detected type of custom value */
    customValueType = computed(() => {
        const val = this.customValue().trim();
        if (!val)
            return 'text';
        // Check if it's a number
        if (/^-?\d+(\.\d+)?$/.test(val)) {
            return 'number';
        }
        // Check if it's a quoted string
        if ((val.startsWith('"') && val.endsWith('"')) ||
            (val.startsWith("'") && val.endsWith("'"))) {
            return 'string';
        }
        return 'text';
    }, ...(ngDevMode ? [{ debugName: "customValueType" }] : []));
    /** Preview of custom value */
    customValuePreview = computed(() => {
        const val = this.customValue().trim();
        if (!val)
            return '';
        const type = this.customValueType();
        if (type === 'string') {
            // Show the quoted string as-is
            return val;
        }
        if (type === 'number') {
            return val;
        }
        // For unquoted text, show as string preview
        return `"${val}"`;
    }, ...(ngDevMode ? [{ debugName: "customValuePreview" }] : []));
    /** CSS class for custom value type */
    customValueTypeClass = computed(() => {
        switch (this.customValueType()) {
            case 'number':
                return 'bg-rose-100 text-rose-700 hover:bg-rose-200 dark:bg-rose-900/30 dark:text-rose-300 dark:hover:bg-rose-900/50';
            case 'string':
                return 'bg-emerald-100 text-emerald-700 hover:bg-emerald-200 dark:bg-emerald-900/30 dark:text-emerald-300 dark:hover:bg-emerald-900/50';
            default:
                return 'bg-slate-100 text-slate-700 hover:bg-slate-200 dark:bg-slate-700 dark:text-slate-300 dark:hover:bg-slate-600';
        }
    }, ...(ngDevMode ? [{ debugName: "customValueTypeClass" }] : []));
    constructor() {
        // Initialize active tab from input
        effect(() => {
            const initial = this.initialTab();
            if (initial) {
                this.activeTab.set(initial);
            }
        });
    }
    // ============ COMPUTED ============
    /** Filtered categories based on search */
    filteredCategories = computed(() => {
        const query = this.searchQuery().toLowerCase();
        const categories = this.functionCategories();
        if (!query)
            return categories;
        return categories
            .map((cat) => ({
            ...cat,
            functions: cat.functions.filter((fn) => fn.name.toLowerCase().includes(query) ||
                fn.description.toLowerCase().includes(query)),
        }))
            .filter((cat) => cat.functions.length > 0);
    }, ...(ngDevMode ? [{ debugName: "filteredCategories" }] : []));
    /** Filtered properties based on search */
    filteredProperties = computed(() => {
        const query = this.searchQuery().toLowerCase();
        const props = this.knownProperties();
        if (!query)
            return props;
        return props.filter((p) => p.toLowerCase().includes(query));
    }, ...(ngDevMode ? [{ debugName: "filteredProperties" }] : []));
    /** Filtered operators based on search */
    filteredOperators = computed(() => {
        const query = this.searchQuery().toLowerCase();
        const ops = this.operators();
        if (!query)
            return ops;
        return ops.filter((op) => op.symbol.toLowerCase().includes(query) ||
            op.name.toLowerCase().includes(query) ||
            op.description.toLowerCase().includes(query));
    }, ...(ngDevMode ? [{ debugName: "filteredOperators" }] : []));
    /** Count of filtered items per tab */
    filteredFunctionsCount = computed(() => this.filteredCategories().reduce((sum, cat) => sum + cat.functions.length, 0), ...(ngDevMode ? [{ debugName: "filteredFunctionsCount" }] : []));
    filteredPropertiesCount = computed(() => this.filteredProperties().length, ...(ngDevMode ? [{ debugName: "filteredPropertiesCount" }] : []));
    filteredOperatorsCount = computed(() => this.filteredOperators().length, ...(ngDevMode ? [{ debugName: "filteredOperatorsCount" }] : []));
    /** Smart search effect - switches to tab with results */
    smartSearchEffect = effect(() => {
        const query = this.searchQuery();
        if (!query || query.length < 2)
            return;
        const currentTab = this.activeTab();
        const functionsCount = this.filteredFunctionsCount();
        const propertiesCount = this.filteredPropertiesCount();
        const operatorsCount = this.filteredOperatorsCount();
        // Check if current tab has results
        const currentHasResults = (currentTab === 'functions' && functionsCount > 0) ||
            (currentTab === 'properties' && propertiesCount > 0) ||
            (currentTab === 'operators' && operatorsCount > 0);
        // If current tab has no results, switch to first tab with results
        if (!currentHasResults) {
            if (functionsCount > 0) {
                this.activeTab.set('functions');
            }
            else if (propertiesCount > 0) {
                this.activeTab.set('properties');
            }
            else if (operatorsCount > 0) {
                this.activeTab.set('operators');
            }
        }
    }, ...(ngDevMode ? [{ debugName: "smartSearchEffect" }] : []));
    /** Group operators by type */
    operatorGroups = computed(() => {
        const ops = this.filteredOperators();
        const groups = new Map();
        ops.forEach((op) => {
            const type = op.type || 'other';
            if (!groups.has(type)) {
                groups.set(type, []);
            }
            groups.get(type).push(op);
        });
        return Array.from(groups.entries()).map(([type, operators]) => ({
            type: type.charAt(0).toUpperCase() + type.slice(1),
            operators,
        }));
    }, ...(ngDevMode ? [{ debugName: "operatorGroups" }] : []));
    /** Total item count for current tab */
    itemCount = computed(() => {
        switch (this.activeTab()) {
            case 'functions':
                return this.filteredCategories().reduce((sum, cat) => sum + cat.functions.length, 0);
            case 'properties':
                return this.filteredProperties().length;
            case 'operators':
                return this.filteredOperators().length;
            default:
                return 0;
        }
    }, ...(ngDevMode ? [{ debugName: "itemCount" }] : []));
    // ============ COMPUTED LABELS ============
    labelFunctions = computed(() => this.labels()?.functions ?? 'Functions', ...(ngDevMode ? [{ debugName: "labelFunctions" }] : []));
    labelProperties = computed(() => this.labels()?.properties ?? 'Properties', ...(ngDevMode ? [{ debugName: "labelProperties" }] : []));
    labelOperators = computed(() => this.labels()?.operators ?? 'Operators', ...(ngDevMode ? [{ debugName: "labelOperators" }] : []));
    labelNoFunctions = computed(() => this.labels()?.noFunctionsFound ?? 'No functions found', ...(ngDevMode ? [{ debugName: "labelNoFunctions" }] : []));
    labelNoProperties = computed(() => this.labels()?.noPropertiesAvailable ?? 'No properties available', ...(ngDevMode ? [{ debugName: "labelNoProperties" }] : []));
    labelNoOperators = computed(() => this.labels()?.noOperatorsFound ?? 'No operators found', ...(ngDevMode ? [{ debugName: "labelNoOperators" }] : []));
    // ============ METHODS ============
    /** Get count for a specific tab (filtered when searching) */
    getTabCount(tab) {
        const query = this.searchQuery();
        if (query) {
            // When searching, show filtered count
            switch (tab) {
                case 'functions':
                    return this.filteredFunctionsCount();
                case 'properties':
                    return this.filteredPropertiesCount();
                case 'operators':
                    return this.filteredOperatorsCount();
                default:
                    return 0;
            }
        }
        else {
            // When not searching, show total count
            switch (tab) {
                case 'functions':
                    return this.functionCategories().reduce((sum, cat) => sum + cat.functions.length, 0);
                case 'properties':
                    return this.knownProperties().length;
                case 'operators':
                    return this.operators().length;
                default:
                    return 0;
            }
        }
    }
    /** Check if a tab has results when searching */
    tabHasResults(tab) {
        return this.getTabCount(tab) > 0;
    }
    /** Set active tab */
    setActiveTab(tab) {
        this.activeTab.set(tab);
        this.onTabChange.emit(tab);
    }
    /** Emit block insert event */
    insertBlock(block) {
        this.onBlockInsert.emit(block);
    }
    /** Clear search */
    clearSearch() {
        this.searchQuery.set('');
    }
    /** Insert custom value */
    insertCustomValue() {
        const val = this.customValue().trim();
        if (!val)
            return;
        const type = this.customValueType();
        let literalValue;
        if (type === 'number') {
            literalValue = parseFloat(val);
        }
        else if (type === 'string') {
            // Remove quotes for storage, keep the content
            literalValue = val.slice(1, -1);
        }
        else {
            // Treat as string, add quotes
            literalValue = val;
        }
        const block = createLiteralBlock(literalValue);
        // For strings, ensure the value includes quotes for display
        if (type === 'string' || type === 'text') {
            block.value = type === 'string' ? val : `"${val}"`;
        }
        this.onBlockInsert.emit(block);
        this.clearCustomValue();
    }
    /** Clear custom value input */
    clearCustomValue() {
        this.customValue.set('');
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: FormulaToolbar, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: FormulaToolbar, isStandalone: true, selector: "mt-formula-toolbar", inputs: { knownProperties: { classPropertyName: "knownProperties", publicName: "knownProperties", isSignal: true, isRequired: false, transformFunction: null }, functionCategories: { classPropertyName: "functionCategories", publicName: "functionCategories", isSignal: true, isRequired: false, transformFunction: null }, operators: { classPropertyName: "operators", publicName: "operators", isSignal: true, isRequired: false, transformFunction: null }, initialTab: { classPropertyName: "initialTab", publicName: "initialTab", isSignal: true, isRequired: false, transformFunction: null }, searchPlaceholder: { classPropertyName: "searchPlaceholder", publicName: "searchPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onBlockInsert: "onBlockInsert", onTabChange: "onTabChange" }, ngImport: i0, template: "<div class=\"flex h-52 flex-col border-b border-slate-200 dark:border-slate-700\">\r\n  <!-- Top Bar: Search + Quick Insert -->\r\n  <div\r\n    class=\"flex items-center gap-2 border-b border-slate-200 px-3 py-2 dark:border-slate-700\"\r\n  >\r\n    <!-- Search Field -->\r\n    <div class=\"relative flex-1\">\r\n      <svg\r\n        class=\"absolute start-3 top-1/2 h-4 w-4 -translate-y-1/2 text-slate-400\"\r\n        fill=\"none\"\r\n        viewBox=\"0 0 24 24\"\r\n        stroke=\"currentColor\"\r\n        stroke-width=\"2\"\r\n      >\r\n        <path\r\n          stroke-linecap=\"round\"\r\n          stroke-linejoin=\"round\"\r\n          d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\"\r\n        />\r\n      </svg>\r\n      <input\r\n        type=\"text\"\r\n        class=\"w-full rounded-lg border border-slate-300 bg-white py-1.5 ps-9 pe-8 text-sm text-slate-700 placeholder:text-slate-400 focus:border-primary focus:outline-none focus:ring-2 focus:ring-primary/20 transition-all duration-200 dark:border-slate-600 dark:bg-slate-900 dark:text-slate-200 dark:placeholder:text-slate-500\"\r\n        [placeholder]=\"searchPlaceholder()\"\r\n        [(ngModel)]=\"searchQuery\"\r\n      />\r\n      @if (searchQuery()) {\r\n        <button\r\n          type=\"button\"\r\n          class=\"absolute end-2 top-1/2 -translate-y-1/2 rounded p-0.5 text-slate-400 hover:bg-slate-200 hover:text-slate-600 transition-all duration-200 dark:hover:bg-slate-700\"\r\n          (click)=\"clearSearch()\"\r\n        >\r\n          <svg\r\n            class=\"h-4 w-4\"\r\n            fill=\"none\"\r\n            viewBox=\"0 0 24 24\"\r\n            stroke=\"currentColor\"\r\n            stroke-width=\"2\"\r\n          >\r\n            <path\r\n              stroke-linecap=\"round\"\r\n              stroke-linejoin=\"round\"\r\n              d=\"M6 18L18 6M6 6l12 12\"\r\n            />\r\n          </svg>\r\n        </button>\r\n      }\r\n    </div>\r\n\r\n    <!-- Separator -->\r\n    <div class=\"h-6 w-px bg-slate-200 dark:bg-slate-600\"></div>\r\n\r\n    <!-- Quick Insert Input -->\r\n    <div class=\"relative flex items-center gap-2\">\r\n      <span\r\n        class=\"text-sm font-medium text-slate-500 dark:text-slate-400 uppercase tracking-wide\"\r\n        >Insert:</span\r\n      >\r\n      <div class=\"relative\">\r\n        <input\r\n          #customValueInput\r\n          type=\"text\"\r\n          class=\"w-32 rounded-md border border-dashed border-slate-300 bg-slate-50 px-3 py-1.5 text-sm font-mono text-slate-700 placeholder:text-slate-400 focus:border-primary focus:bg-white focus:outline-none focus:ring-2 focus:ring-primary/20 transition-all duration-200 dark:border-slate-600 dark:bg-slate-800 dark:text-slate-200 dark:placeholder:text-slate-500 dark:focus:bg-slate-900\"\r\n          placeholder='123 or \"text\"'\r\n          [(ngModel)]=\"customValue\"\r\n          (keydown.enter)=\"insertCustomValue()\"\r\n          (keydown.escape)=\"clearCustomValue()\"\r\n        />\r\n      </div>\r\n\r\n      <!-- Insert Button with Type Preview -->\r\n      @if (customValue()) {\r\n        <button\r\n          type=\"button\"\r\n          class=\"inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-sm font-medium transition-all duration-200 hover:shadow-sm active:scale-95\"\r\n          [class]=\"customValueTypeClass()\"\r\n          (click)=\"insertCustomValue()\"\r\n          [title]=\"'Insert ' + customValueType() + ' (Enter)'\"\r\n        >\r\n          @switch (customValueType()) {\r\n            @case (\"number\") {\r\n              <svg\r\n                class=\"h-3 w-3\"\r\n                fill=\"none\"\r\n                viewBox=\"0 0 24 24\"\r\n                stroke=\"currentColor\"\r\n                stroke-width=\"2\"\r\n              >\r\n                <path\r\n                  stroke-linecap=\"round\"\r\n                  stroke-linejoin=\"round\"\r\n                  d=\"M7 20l4-16m2 16l4-16M6 9h14M4 15h14\"\r\n                />\r\n              </svg>\r\n            }\r\n            @case (\"string\") {\r\n              <svg\r\n                class=\"h-3 w-3\"\r\n                fill=\"none\"\r\n                viewBox=\"0 0 24 24\"\r\n                stroke=\"currentColor\"\r\n                stroke-width=\"2\"\r\n              >\r\n                <path\r\n                  stroke-linecap=\"round\"\r\n                  stroke-linejoin=\"round\"\r\n                  d=\"M7.5 8.25h9m-9 3H12m-9.75 1.51c0 1.6 1.123 2.994 2.707 3.227 1.129.166 2.27.293 3.423.379.35.026.67.21.865.501L12 21l2.755-4.133a1.14 1.14 0 01.865-.501 48.172 48.172 0 003.423-.379c1.584-.233 2.707-1.626 2.707-3.228V6.741c0-1.602-1.123-2.995-2.707-3.228A48.394 48.394 0 0012 3c-2.392 0-4.744.175-7.043.513C3.373 3.746 2.25 5.14 2.25 6.741v6.018z\"\r\n                />\r\n              </svg>\r\n            }\r\n            @default {\r\n              <svg\r\n                class=\"h-3 w-3\"\r\n                fill=\"none\"\r\n                viewBox=\"0 0 24 24\"\r\n                stroke=\"currentColor\"\r\n                stroke-width=\"2\"\r\n              >\r\n                <path\r\n                  stroke-linecap=\"round\"\r\n                  stroke-linejoin=\"round\"\r\n                  d=\"M12 4.5v15m7.5-7.5h-15\"\r\n                />\r\n              </svg>\r\n            }\r\n          }\r\n          <span class=\"max-w-16 truncate\">{{ customValuePreview() }}</span>\r\n        </button>\r\n      }\r\n    </div>\r\n  </div>\r\n\r\n  <!-- Main Content Row -->\r\n  <div class=\"flex flex-1 overflow-hidden\">\r\n    <!-- Vertical Tabs -->\r\n    <div\r\n      class=\"flex w-44 flex-col border-e border-slate-200 dark:border-slate-700\"\r\n    >\r\n      @for (tab of tabOptions; track tab.value) {\r\n        <button\r\n          type=\"button\"\r\n          class=\"flex cursor-pointer items-center gap-2 px-3 py-2.5 text-start text-sm font-medium transition-all duration-200\"\r\n          [class]=\"\r\n            activeTab() === tab.value\r\n              ? 'bg-white border-e-2 border-primary text-primary dark:bg-slate-900'\r\n              : searchQuery() && !tabHasResults(tab.value)\r\n                ? 'text-slate-300 dark:text-slate-600'\r\n                : 'text-slate-600 hover:bg-slate-100 hover:text-slate-800 dark:text-slate-300 dark:hover:bg-slate-700'\r\n          \"\r\n          (click)=\"setActiveTab(tab.value)\"\r\n        >\r\n          <!-- Tab Icons -->\r\n          @switch (tab.value) {\r\n            @case (\"functions\") {\r\n              <svg\r\n                class=\"h-5 w-5 shrink-0\"\r\n                fill=\"none\"\r\n                viewBox=\"0 0 24 24\"\r\n                stroke=\"currentColor\"\r\n                stroke-width=\"2\"\r\n              >\r\n                <path\r\n                  stroke-linecap=\"round\"\r\n                  stroke-linejoin=\"round\"\r\n                  d=\"M17.25 6.75L22.5 12l-5.25 5.25m-10.5 0L1.5 12l5.25-5.25m7.5-3l-4.5 16.5\"\r\n                />\r\n              </svg>\r\n            }\r\n            @case (\"properties\") {\r\n              <svg\r\n                class=\"h-5 w-5 shrink-0\"\r\n                fill=\"none\"\r\n                viewBox=\"0 0 24 24\"\r\n                stroke=\"currentColor\"\r\n                stroke-width=\"2\"\r\n              >\r\n                <path\r\n                  stroke-linecap=\"round\"\r\n                  stroke-linejoin=\"round\"\r\n                  d=\"M9.568 3H5.25A2.25 2.25 0 003 5.25v4.318c0 .597.237 1.17.659 1.591l9.581 9.581c.699.699 1.78.872 2.607.33a18.095 18.095 0 005.223-5.223c.542-.827.369-1.908-.33-2.607L11.16 3.66A2.25 2.25 0 009.568 3z\"\r\n                />\r\n                <path\r\n                  stroke-linecap=\"round\"\r\n                  stroke-linejoin=\"round\"\r\n                  d=\"M6 6h.008v.008H6V6z\"\r\n                />\r\n              </svg>\r\n            }\r\n            @case (\"operators\") {\r\n              <svg\r\n                class=\"h-5 w-5 shrink-0\"\r\n                fill=\"none\"\r\n                viewBox=\"0 0 24 24\"\r\n                stroke=\"currentColor\"\r\n                stroke-width=\"2\"\r\n              >\r\n                <path\r\n                  stroke-linecap=\"round\"\r\n                  stroke-linejoin=\"round\"\r\n                  d=\"M15.75 15.75V18m-7.5-6.75h.008v.008H8.25v-.008zm0 2.25h.008v.008H8.25V13.5zm0 2.25h.008v.008H8.25v-.008zm0 2.25h.008v.008H8.25V18zm2.498-6.75h.007v.008h-.007v-.008zm0 2.25h.007v.008h-.007V13.5zm0 2.25h.007v.008h-.007v-.008zm0 2.25h.007v.008h-.007V18zm2.504-6.75h.008v.008h-.008v-.008zm0 2.25h.008v.008h-.008V13.5zm0 2.25h.008v.008h-.008v-.008zm0 2.25h.008v.008h-.008V18zm2.498-6.75h.008v.008h-.008v-.008zm0 2.25h.008v.008h-.008V13.5zM8.25 6h7.5v2.25h-7.5V6zM12 2.25c-1.892 0-3.758.11-5.593.322C5.307 2.7 4.5 3.65 4.5 4.757V19.5a2.25 2.25 0 002.25 2.25h10.5a2.25 2.25 0 002.25-2.25V4.757c0-1.108-.806-2.057-1.907-2.185A48.507 48.507 0 0012 2.25z\"\r\n                />\r\n              </svg>\r\n            }\r\n          }\r\n          <!-- Label (always visible) -->\r\n          <span class=\"truncate whitespace-nowrap text-sm\">{{\r\n            tab.label\r\n          }}</span>\r\n          <!-- Count Badge -->\r\n          <span\r\n            class=\"ms-auto rounded-full px-1.5 py-0.5 text-xs font-semibold\"\r\n            [class]=\"\r\n              activeTab() === tab.value\r\n                ? 'bg-primary/10 text-primary'\r\n                : 'bg-slate-200 text-slate-600 dark:bg-slate-600 dark:text-slate-300'\r\n            \"\r\n          >\r\n            {{ getTabCount(tab.value) }}\r\n          </span>\r\n        </button>\r\n      }\r\n    </div>\r\n\r\n    <!-- Content Area -->\r\n    <div class=\"flex flex-1 flex-col overflow-hidden\">\r\n      <!-- Items Grid -->\r\n      <div class=\"flex-1 overflow-y-auto p-2.5\">\r\n        @switch (activeTab()) {\r\n          @case (\"functions\") {\r\n            @if (filteredCategories().length === 0) {\r\n              <div\r\n                class=\"flex h-full items-center justify-center text-sm text-slate-400 dark:text-slate-500\"\r\n              >\r\n                {{ labelNoFunctions() }}\r\n              </div>\r\n            } @else {\r\n              <div class=\"space-y-3\">\r\n                @for (category of filteredCategories(); track category.name) {\r\n                  <div>\r\n                    <div class=\"mb-2 flex items-center gap-2\">\r\n                      <span\r\n                        class=\"text-sm font-semibold uppercase tracking-wider text-slate-500 dark:text-slate-400\"\r\n                      >\r\n                        {{ category.name }}\r\n                      </span>\r\n                      <span\r\n                        class=\"h-px flex-1 bg-slate-200/60 dark:bg-slate-700/60\"\r\n                      ></span>\r\n                      <span\r\n                        class=\"text-sm text-slate-400 dark:text-slate-500\"\r\n                        >{{ category.functions.length }}</span\r\n                      >\r\n                    </div>\r\n                    <div class=\"flex flex-wrap gap-1.5\">\r\n                      @for (fn of category.functions; track fn.name) {\r\n                        <mt-formula-toolbar-item\r\n                          type=\"function\"\r\n                          [value]=\"fn.name\"\r\n                          [description]=\"fn.description\"\r\n                          [signature]=\"fn.signature\"\r\n                          (onInsert)=\"insertBlock($event)\"\r\n                        />\r\n                      }\r\n                    </div>\r\n                  </div>\r\n                }\r\n              </div>\r\n            }\r\n          }\r\n          @case (\"properties\") {\r\n            @if (filteredProperties().length === 0) {\r\n              <div\r\n                class=\"flex h-full items-center justify-center text-sm text-slate-400 dark:text-slate-500\"\r\n              >\r\n                {{ labelNoProperties() }}\r\n              </div>\r\n            } @else {\r\n              <div class=\"flex flex-wrap gap-1.5\">\r\n                @for (prop of filteredProperties(); track prop) {\r\n                  <mt-formula-toolbar-item\r\n                    type=\"property\"\r\n                    [value]=\"prop\"\r\n                    [description]=\"'Property: ' + prop\"\r\n                    propertyType=\"current\"\r\n                    (onInsert)=\"insertBlock($event)\"\r\n                  />\r\n                }\r\n              </div>\r\n            }\r\n          }\r\n          @case (\"operators\") {\r\n            @if (filteredOperators().length === 0) {\r\n              <div\r\n                class=\"flex h-full items-center justify-center text-sm text-slate-400 dark:text-slate-500\"\r\n              >\r\n                {{ labelNoOperators() }}\r\n              </div>\r\n            } @else {\r\n              <div class=\"space-y-3\">\r\n                @for (group of operatorGroups(); track group.type) {\r\n                  <div>\r\n                    <div class=\"mb-2 flex items-center gap-2\">\r\n                      <span\r\n                        class=\"text-sm font-semibold uppercase tracking-wider text-slate-500 dark:text-slate-400\"\r\n                      >\r\n                        {{ group.type }}\r\n                      </span>\r\n                      <span\r\n                        class=\"h-px flex-1 bg-slate-200/60 dark:bg-slate-700/60\"\r\n                      ></span>\r\n                    </div>\r\n                    <div class=\"flex flex-wrap gap-1.5\">\r\n                      @for (op of group.operators; track op.symbol) {\r\n                        <mt-formula-toolbar-item\r\n                          type=\"operator\"\r\n                          [value]=\"op.symbol\"\r\n                          [description]=\"op.description\"\r\n                          (onInsert)=\"insertBlock($event)\"\r\n                        />\r\n                      }\r\n                    </div>\r\n                  </div>\r\n                }\r\n              </div>\r\n            }\r\n          }\r\n        }\r\n      </div>\r\n    </div>\r\n  </div>\r\n</div>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: FormulaToolbarItem, selector: "mt-formula-toolbar-item", inputs: ["type", "value", "display", "description", "signature", "propertyType"], outputs: ["onInsert"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: FormulaToolbar, decorators: [{
            type: Component,
            args: [{ selector: 'mt-formula-toolbar', standalone: true, imports: [CommonModule, FormsModule, FormulaToolbarItem], template: "<div class=\"flex h-52 flex-col border-b border-slate-200 dark:border-slate-700\">\r\n  <!-- Top Bar: Search + Quick Insert -->\r\n  <div\r\n    class=\"flex items-center gap-2 border-b border-slate-200 px-3 py-2 dark:border-slate-700\"\r\n  >\r\n    <!-- Search Field -->\r\n    <div class=\"relative flex-1\">\r\n      <svg\r\n        class=\"absolute start-3 top-1/2 h-4 w-4 -translate-y-1/2 text-slate-400\"\r\n        fill=\"none\"\r\n        viewBox=\"0 0 24 24\"\r\n        stroke=\"currentColor\"\r\n        stroke-width=\"2\"\r\n      >\r\n        <path\r\n          stroke-linecap=\"round\"\r\n          stroke-linejoin=\"round\"\r\n          d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\"\r\n        />\r\n      </svg>\r\n      <input\r\n        type=\"text\"\r\n        class=\"w-full rounded-lg border border-slate-300 bg-white py-1.5 ps-9 pe-8 text-sm text-slate-700 placeholder:text-slate-400 focus:border-primary focus:outline-none focus:ring-2 focus:ring-primary/20 transition-all duration-200 dark:border-slate-600 dark:bg-slate-900 dark:text-slate-200 dark:placeholder:text-slate-500\"\r\n        [placeholder]=\"searchPlaceholder()\"\r\n        [(ngModel)]=\"searchQuery\"\r\n      />\r\n      @if (searchQuery()) {\r\n        <button\r\n          type=\"button\"\r\n          class=\"absolute end-2 top-1/2 -translate-y-1/2 rounded p-0.5 text-slate-400 hover:bg-slate-200 hover:text-slate-600 transition-all duration-200 dark:hover:bg-slate-700\"\r\n          (click)=\"clearSearch()\"\r\n        >\r\n          <svg\r\n            class=\"h-4 w-4\"\r\n            fill=\"none\"\r\n            viewBox=\"0 0 24 24\"\r\n            stroke=\"currentColor\"\r\n            stroke-width=\"2\"\r\n          >\r\n            <path\r\n              stroke-linecap=\"round\"\r\n              stroke-linejoin=\"round\"\r\n              d=\"M6 18L18 6M6 6l12 12\"\r\n            />\r\n          </svg>\r\n        </button>\r\n      }\r\n    </div>\r\n\r\n    <!-- Separator -->\r\n    <div class=\"h-6 w-px bg-slate-200 dark:bg-slate-600\"></div>\r\n\r\n    <!-- Quick Insert Input -->\r\n    <div class=\"relative flex items-center gap-2\">\r\n      <span\r\n        class=\"text-sm font-medium text-slate-500 dark:text-slate-400 uppercase tracking-wide\"\r\n        >Insert:</span\r\n      >\r\n      <div class=\"relative\">\r\n        <input\r\n          #customValueInput\r\n          type=\"text\"\r\n          class=\"w-32 rounded-md border border-dashed border-slate-300 bg-slate-50 px-3 py-1.5 text-sm font-mono text-slate-700 placeholder:text-slate-400 focus:border-primary focus:bg-white focus:outline-none focus:ring-2 focus:ring-primary/20 transition-all duration-200 dark:border-slate-600 dark:bg-slate-800 dark:text-slate-200 dark:placeholder:text-slate-500 dark:focus:bg-slate-900\"\r\n          placeholder='123 or \"text\"'\r\n          [(ngModel)]=\"customValue\"\r\n          (keydown.enter)=\"insertCustomValue()\"\r\n          (keydown.escape)=\"clearCustomValue()\"\r\n        />\r\n      </div>\r\n\r\n      <!-- Insert Button with Type Preview -->\r\n      @if (customValue()) {\r\n        <button\r\n          type=\"button\"\r\n          class=\"inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-sm font-medium transition-all duration-200 hover:shadow-sm active:scale-95\"\r\n          [class]=\"customValueTypeClass()\"\r\n          (click)=\"insertCustomValue()\"\r\n          [title]=\"'Insert ' + customValueType() + ' (Enter)'\"\r\n        >\r\n          @switch (customValueType()) {\r\n            @case (\"number\") {\r\n              <svg\r\n                class=\"h-3 w-3\"\r\n                fill=\"none\"\r\n                viewBox=\"0 0 24 24\"\r\n                stroke=\"currentColor\"\r\n                stroke-width=\"2\"\r\n              >\r\n                <path\r\n                  stroke-linecap=\"round\"\r\n                  stroke-linejoin=\"round\"\r\n                  d=\"M7 20l4-16m2 16l4-16M6 9h14M4 15h14\"\r\n                />\r\n              </svg>\r\n            }\r\n            @case (\"string\") {\r\n              <svg\r\n                class=\"h-3 w-3\"\r\n                fill=\"none\"\r\n                viewBox=\"0 0 24 24\"\r\n                stroke=\"currentColor\"\r\n                stroke-width=\"2\"\r\n              >\r\n                <path\r\n                  stroke-linecap=\"round\"\r\n                  stroke-linejoin=\"round\"\r\n                  d=\"M7.5 8.25h9m-9 3H12m-9.75 1.51c0 1.6 1.123 2.994 2.707 3.227 1.129.166 2.27.293 3.423.379.35.026.67.21.865.501L12 21l2.755-4.133a1.14 1.14 0 01.865-.501 48.172 48.172 0 003.423-.379c1.584-.233 2.707-1.626 2.707-3.228V6.741c0-1.602-1.123-2.995-2.707-3.228A48.394 48.394 0 0012 3c-2.392 0-4.744.175-7.043.513C3.373 3.746 2.25 5.14 2.25 6.741v6.018z\"\r\n                />\r\n              </svg>\r\n            }\r\n            @default {\r\n              <svg\r\n                class=\"h-3 w-3\"\r\n                fill=\"none\"\r\n                viewBox=\"0 0 24 24\"\r\n                stroke=\"currentColor\"\r\n                stroke-width=\"2\"\r\n              >\r\n                <path\r\n                  stroke-linecap=\"round\"\r\n                  stroke-linejoin=\"round\"\r\n                  d=\"M12 4.5v15m7.5-7.5h-15\"\r\n                />\r\n              </svg>\r\n            }\r\n          }\r\n          <span class=\"max-w-16 truncate\">{{ customValuePreview() }}</span>\r\n        </button>\r\n      }\r\n    </div>\r\n  </div>\r\n\r\n  <!-- Main Content Row -->\r\n  <div class=\"flex flex-1 overflow-hidden\">\r\n    <!-- Vertical Tabs -->\r\n    <div\r\n      class=\"flex w-44 flex-col border-e border-slate-200 dark:border-slate-700\"\r\n    >\r\n      @for (tab of tabOptions; track tab.value) {\r\n        <button\r\n          type=\"button\"\r\n          class=\"flex cursor-pointer items-center gap-2 px-3 py-2.5 text-start text-sm font-medium transition-all duration-200\"\r\n          [class]=\"\r\n            activeTab() === tab.value\r\n              ? 'bg-white border-e-2 border-primary text-primary dark:bg-slate-900'\r\n              : searchQuery() && !tabHasResults(tab.value)\r\n                ? 'text-slate-300 dark:text-slate-600'\r\n                : 'text-slate-600 hover:bg-slate-100 hover:text-slate-800 dark:text-slate-300 dark:hover:bg-slate-700'\r\n          \"\r\n          (click)=\"setActiveTab(tab.value)\"\r\n        >\r\n          <!-- Tab Icons -->\r\n          @switch (tab.value) {\r\n            @case (\"functions\") {\r\n              <svg\r\n                class=\"h-5 w-5 shrink-0\"\r\n                fill=\"none\"\r\n                viewBox=\"0 0 24 24\"\r\n                stroke=\"currentColor\"\r\n                stroke-width=\"2\"\r\n              >\r\n                <path\r\n                  stroke-linecap=\"round\"\r\n                  stroke-linejoin=\"round\"\r\n                  d=\"M17.25 6.75L22.5 12l-5.25 5.25m-10.5 0L1.5 12l5.25-5.25m7.5-3l-4.5 16.5\"\r\n                />\r\n              </svg>\r\n            }\r\n            @case (\"properties\") {\r\n              <svg\r\n                class=\"h-5 w-5 shrink-0\"\r\n                fill=\"none\"\r\n                viewBox=\"0 0 24 24\"\r\n                stroke=\"currentColor\"\r\n                stroke-width=\"2\"\r\n              >\r\n                <path\r\n                  stroke-linecap=\"round\"\r\n                  stroke-linejoin=\"round\"\r\n                  d=\"M9.568 3H5.25A2.25 2.25 0 003 5.25v4.318c0 .597.237 1.17.659 1.591l9.581 9.581c.699.699 1.78.872 2.607.33a18.095 18.095 0 005.223-5.223c.542-.827.369-1.908-.33-2.607L11.16 3.66A2.25 2.25 0 009.568 3z\"\r\n                />\r\n                <path\r\n                  stroke-linecap=\"round\"\r\n                  stroke-linejoin=\"round\"\r\n                  d=\"M6 6h.008v.008H6V6z\"\r\n                />\r\n              </svg>\r\n            }\r\n            @case (\"operators\") {\r\n              <svg\r\n                class=\"h-5 w-5 shrink-0\"\r\n                fill=\"none\"\r\n                viewBox=\"0 0 24 24\"\r\n                stroke=\"currentColor\"\r\n                stroke-width=\"2\"\r\n              >\r\n                <path\r\n                  stroke-linecap=\"round\"\r\n                  stroke-linejoin=\"round\"\r\n                  d=\"M15.75 15.75V18m-7.5-6.75h.008v.008H8.25v-.008zm0 2.25h.008v.008H8.25V13.5zm0 2.25h.008v.008H8.25v-.008zm0 2.25h.008v.008H8.25V18zm2.498-6.75h.007v.008h-.007v-.008zm0 2.25h.007v.008h-.007V13.5zm0 2.25h.007v.008h-.007v-.008zm0 2.25h.007v.008h-.007V18zm2.504-6.75h.008v.008h-.008v-.008zm0 2.25h.008v.008h-.008V13.5zm0 2.25h.008v.008h-.008v-.008zm0 2.25h.008v.008h-.008V18zm2.498-6.75h.008v.008h-.008v-.008zm0 2.25h.008v.008h-.008V13.5zM8.25 6h7.5v2.25h-7.5V6zM12 2.25c-1.892 0-3.758.11-5.593.322C5.307 2.7 4.5 3.65 4.5 4.757V19.5a2.25 2.25 0 002.25 2.25h10.5a2.25 2.25 0 002.25-2.25V4.757c0-1.108-.806-2.057-1.907-2.185A48.507 48.507 0 0012 2.25z\"\r\n                />\r\n              </svg>\r\n            }\r\n          }\r\n          <!-- Label (always visible) -->\r\n          <span class=\"truncate whitespace-nowrap text-sm\">{{\r\n            tab.label\r\n          }}</span>\r\n          <!-- Count Badge -->\r\n          <span\r\n            class=\"ms-auto rounded-full px-1.5 py-0.5 text-xs font-semibold\"\r\n            [class]=\"\r\n              activeTab() === tab.value\r\n                ? 'bg-primary/10 text-primary'\r\n                : 'bg-slate-200 text-slate-600 dark:bg-slate-600 dark:text-slate-300'\r\n            \"\r\n          >\r\n            {{ getTabCount(tab.value) }}\r\n          </span>\r\n        </button>\r\n      }\r\n    </div>\r\n\r\n    <!-- Content Area -->\r\n    <div class=\"flex flex-1 flex-col overflow-hidden\">\r\n      <!-- Items Grid -->\r\n      <div class=\"flex-1 overflow-y-auto p-2.5\">\r\n        @switch (activeTab()) {\r\n          @case (\"functions\") {\r\n            @if (filteredCategories().length === 0) {\r\n              <div\r\n                class=\"flex h-full items-center justify-center text-sm text-slate-400 dark:text-slate-500\"\r\n              >\r\n                {{ labelNoFunctions() }}\r\n              </div>\r\n            } @else {\r\n              <div class=\"space-y-3\">\r\n                @for (category of filteredCategories(); track category.name) {\r\n                  <div>\r\n                    <div class=\"mb-2 flex items-center gap-2\">\r\n                      <span\r\n                        class=\"text-sm font-semibold uppercase tracking-wider text-slate-500 dark:text-slate-400\"\r\n                      >\r\n                        {{ category.name }}\r\n                      </span>\r\n                      <span\r\n                        class=\"h-px flex-1 bg-slate-200/60 dark:bg-slate-700/60\"\r\n                      ></span>\r\n                      <span\r\n                        class=\"text-sm text-slate-400 dark:text-slate-500\"\r\n                        >{{ category.functions.length }}</span\r\n                      >\r\n                    </div>\r\n                    <div class=\"flex flex-wrap gap-1.5\">\r\n                      @for (fn of category.functions; track fn.name) {\r\n                        <mt-formula-toolbar-item\r\n                          type=\"function\"\r\n                          [value]=\"fn.name\"\r\n                          [description]=\"fn.description\"\r\n                          [signature]=\"fn.signature\"\r\n                          (onInsert)=\"insertBlock($event)\"\r\n                        />\r\n                      }\r\n                    </div>\r\n                  </div>\r\n                }\r\n              </div>\r\n            }\r\n          }\r\n          @case (\"properties\") {\r\n            @if (filteredProperties().length === 0) {\r\n              <div\r\n                class=\"flex h-full items-center justify-center text-sm text-slate-400 dark:text-slate-500\"\r\n              >\r\n                {{ labelNoProperties() }}\r\n              </div>\r\n            } @else {\r\n              <div class=\"flex flex-wrap gap-1.5\">\r\n                @for (prop of filteredProperties(); track prop) {\r\n                  <mt-formula-toolbar-item\r\n                    type=\"property\"\r\n                    [value]=\"prop\"\r\n                    [description]=\"'Property: ' + prop\"\r\n                    propertyType=\"current\"\r\n                    (onInsert)=\"insertBlock($event)\"\r\n                  />\r\n                }\r\n              </div>\r\n            }\r\n          }\r\n          @case (\"operators\") {\r\n            @if (filteredOperators().length === 0) {\r\n              <div\r\n                class=\"flex h-full items-center justify-center text-sm text-slate-400 dark:text-slate-500\"\r\n              >\r\n                {{ labelNoOperators() }}\r\n              </div>\r\n            } @else {\r\n              <div class=\"space-y-3\">\r\n                @for (group of operatorGroups(); track group.type) {\r\n                  <div>\r\n                    <div class=\"mb-2 flex items-center gap-2\">\r\n                      <span\r\n                        class=\"text-sm font-semibold uppercase tracking-wider text-slate-500 dark:text-slate-400\"\r\n                      >\r\n                        {{ group.type }}\r\n                      </span>\r\n                      <span\r\n                        class=\"h-px flex-1 bg-slate-200/60 dark:bg-slate-700/60\"\r\n                      ></span>\r\n                    </div>\r\n                    <div class=\"flex flex-wrap gap-1.5\">\r\n                      @for (op of group.operators; track op.symbol) {\r\n                        <mt-formula-toolbar-item\r\n                          type=\"operator\"\r\n                          [value]=\"op.symbol\"\r\n                          [description]=\"op.description\"\r\n                          (onInsert)=\"insertBlock($event)\"\r\n                        />\r\n                      }\r\n                    </div>\r\n                  </div>\r\n                }\r\n              </div>\r\n            }\r\n          }\r\n        }\r\n      </div>\r\n    </div>\r\n  </div>\r\n</div>\r\n" }]
        }], ctorParameters: () => [], propDecorators: { knownProperties: [{ type: i0.Input, args: [{ isSignal: true, alias: "knownProperties", required: false }] }], functionCategories: [{ type: i0.Input, args: [{ isSignal: true, alias: "functionCategories", required: false }] }], operators: [{ type: i0.Input, args: [{ isSignal: true, alias: "operators", required: false }] }], initialTab: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialTab", required: false }] }], searchPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPlaceholder", required: false }] }], labels: [{ type: i0.Input, args: [{ isSignal: true, alias: "labels", required: false }] }], onBlockInsert: [{ type: i0.Output, args: ["onBlockInsert"] }], onTabChange: [{ type: i0.Output, args: ["onTabChange"] }] } });

/**
 * Formula Status Bar Component
 * Displays validation status, complexity, and dependencies
 *
 * This is a PURE input/output component with NO service dependencies.
 */
class FormulaStatusBar {
    // ============ INPUTS ============
    /** Validation result */
    validation = input(null, ...(ngDevMode ? [{ debugName: "validation" }] : []));
    /** Labels for i18n support */
    labels = input({}, ...(ngDevMode ? [{ debugName: "labels" }] : []));
    // ============ COMPUTED ============
    /** Is formula valid */
    isValid = computed(() => this.validation()?.isValid ?? true, ...(ngDevMode ? [{ debugName: "isValid" }] : []));
    /** Complexity score */
    complexity = computed(() => this.validation()?.complexity ?? 0, ...(ngDevMode ? [{ debugName: "complexity" }] : []));
    /** Dependencies list */
    dependencies = computed(() => this.validation()?.dependencies ?? [], ...(ngDevMode ? [{ debugName: "dependencies" }] : []));
    /** Dependencies as text */
    dependenciesText = computed(() => {
        const deps = this.dependencies();
        if (deps.length <= 3) {
            return deps.join(', ');
        }
        return `${deps.slice(0, 3).join(', ')} +${deps.length - 3}`;
    }, ...(ngDevMode ? [{ debugName: "dependenciesText" }] : []));
    /** First error */
    firstError = computed(() => this.validation()?.errors[0] ?? null, ...(ngDevMode ? [{ debugName: "firstError" }] : []));
    /** Complexity CSS class */
    complexityClass = computed(() => {
        const c = this.complexity();
        if (c <= 10)
            return 'text-emerald-600 dark:text-emerald-400';
        if (c <= 25)
            return 'text-amber-600 dark:text-amber-400';
        return 'text-rose-600 dark:text-rose-400';
    }, ...(ngDevMode ? [{ debugName: "complexityClass" }] : []));
    // ============ COMPUTED LABELS ============
    labelValid = computed(() => this.labels()?.valid ?? 'Valid', ...(ngDevMode ? [{ debugName: "labelValid" }] : []));
    labelInvalid = computed(() => this.labels()?.invalid ?? 'Invalid', ...(ngDevMode ? [{ debugName: "labelInvalid" }] : []));
    labelComplexity = computed(() => this.labels()?.complexity ?? 'Complexity', ...(ngDevMode ? [{ debugName: "labelComplexity" }] : []));
    labelDependencies = computed(() => this.labels()?.dependencies ?? 'Dependencies', ...(ngDevMode ? [{ debugName: "labelDependencies" }] : []));
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: FormulaStatusBar, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: FormulaStatusBar, isStandalone: true, selector: "mt-formula-status-bar", inputs: { validation: { classPropertyName: "validation", publicName: "validation", isSignal: true, isRequired: false, transformFunction: null }, labels: { classPropertyName: "labels", publicName: "labels", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div\r\n  class=\"flex items-center gap-4 border-t border-slate-200 px-4 py-2 text-sm dark:border-slate-700\"\r\n>\r\n  <!-- Validation Status -->\r\n  <div class=\"flex items-center gap-1.5\">\r\n    @if (isValid()) {\r\n      <span\r\n        class=\"flex h-5 w-5 items-center justify-center rounded-full bg-emerald-100 text-emerald-600 dark:bg-emerald-900 dark:text-emerald-400\"\r\n      >\r\n        <svg\r\n          class=\"h-3.5 w-3.5\"\r\n          fill=\"none\"\r\n          viewBox=\"0 0 24 24\"\r\n          stroke=\"currentColor\"\r\n          stroke-width=\"2.5\"\r\n        >\r\n          <path\r\n            stroke-linecap=\"round\"\r\n            stroke-linejoin=\"round\"\r\n            d=\"M5 13l4 4L19 7\"\r\n          />\r\n        </svg>\r\n      </span>\r\n      <span class=\"font-medium text-emerald-600 dark:text-emerald-400\">\r\n        {{ labelValid() }}\r\n      </span>\r\n    } @else {\r\n      <span\r\n        class=\"flex h-5 w-5 items-center justify-center rounded-full bg-rose-100 text-rose-600 dark:bg-rose-900 dark:text-rose-400\"\r\n      >\r\n        <svg\r\n          class=\"h-3.5 w-3.5\"\r\n          fill=\"none\"\r\n          viewBox=\"0 0 24 24\"\r\n          stroke=\"currentColor\"\r\n          stroke-width=\"2.5\"\r\n        >\r\n          <path\r\n            stroke-linecap=\"round\"\r\n            stroke-linejoin=\"round\"\r\n            d=\"M6 18L18 6M6 6l12 12\"\r\n          />\r\n        </svg>\r\n      </span>\r\n      <span class=\"font-medium text-rose-600 dark:text-rose-400\">\r\n        {{ labelInvalid() }}\r\n      </span>\r\n    }\r\n  </div>\r\n\r\n  <!-- Separator -->\r\n  <div class=\"h-4 w-px bg-slate-300 dark:bg-slate-600\"></div>\r\n\r\n  <!-- Complexity -->\r\n  <div class=\"flex items-center gap-1.5 text-slate-500 dark:text-slate-400\">\r\n    <svg class=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\r\n      <path\r\n        stroke-linecap=\"round\"\r\n        stroke-linejoin=\"round\"\r\n        stroke-width=\"2\"\r\n        d=\"M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z\"\r\n      />\r\n    </svg>\r\n    <span>{{ labelComplexity() }}:</span>\r\n    <span class=\"font-medium\" [class]=\"complexityClass()\">\r\n      {{ complexity() }}\r\n    </span>\r\n  </div>\r\n\r\n  <!-- Dependencies -->\r\n  @if (dependencies().length > 0) {\r\n    <div class=\"h-4 w-px bg-slate-300 dark:bg-slate-600\"></div>\r\n    <div class=\"flex items-center gap-1.5 text-slate-500 dark:text-slate-400\">\r\n      <svg\r\n        class=\"h-4 w-4\"\r\n        fill=\"none\"\r\n        viewBox=\"0 0 24 24\"\r\n        stroke=\"currentColor\"\r\n      >\r\n        <path\r\n          stroke-linecap=\"round\"\r\n          stroke-linejoin=\"round\"\r\n          stroke-width=\"2\"\r\n          d=\"M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1\"\r\n        />\r\n      </svg>\r\n      <span>{{ labelDependencies() }}:</span>\r\n      <span class=\"font-medium text-slate-700 dark:text-slate-300\">\r\n        {{ dependenciesText() }}\r\n      </span>\r\n    </div>\r\n  }\r\n\r\n  <!-- Error message (if any) -->\r\n  @if (firstError(); as error) {\r\n    <div\r\n      class=\"ms-auto flex items-center gap-1.5 text-rose-600 dark:text-rose-400\"\r\n    >\r\n      <svg\r\n        class=\"h-4 w-4\"\r\n        fill=\"none\"\r\n        viewBox=\"0 0 24 24\"\r\n        stroke=\"currentColor\"\r\n      >\r\n        <path\r\n          stroke-linecap=\"round\"\r\n          stroke-linejoin=\"round\"\r\n          stroke-width=\"2\"\r\n          d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\"\r\n        />\r\n      </svg>\r\n      <span class=\"text-xs\">{{ error.message }}</span>\r\n      <span class=\"text-xs opacity-60\"\r\n        >({{ error.line }}:{{ error.column }})</span\r\n      >\r\n    </div>\r\n  }\r\n</div>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: FormulaStatusBar, decorators: [{
            type: Component,
            args: [{ selector: 'mt-formula-status-bar', standalone: true, imports: [CommonModule], template: "<div\r\n  class=\"flex items-center gap-4 border-t border-slate-200 px-4 py-2 text-sm dark:border-slate-700\"\r\n>\r\n  <!-- Validation Status -->\r\n  <div class=\"flex items-center gap-1.5\">\r\n    @if (isValid()) {\r\n      <span\r\n        class=\"flex h-5 w-5 items-center justify-center rounded-full bg-emerald-100 text-emerald-600 dark:bg-emerald-900 dark:text-emerald-400\"\r\n      >\r\n        <svg\r\n          class=\"h-3.5 w-3.5\"\r\n          fill=\"none\"\r\n          viewBox=\"0 0 24 24\"\r\n          stroke=\"currentColor\"\r\n          stroke-width=\"2.5\"\r\n        >\r\n          <path\r\n            stroke-linecap=\"round\"\r\n            stroke-linejoin=\"round\"\r\n            d=\"M5 13l4 4L19 7\"\r\n          />\r\n        </svg>\r\n      </span>\r\n      <span class=\"font-medium text-emerald-600 dark:text-emerald-400\">\r\n        {{ labelValid() }}\r\n      </span>\r\n    } @else {\r\n      <span\r\n        class=\"flex h-5 w-5 items-center justify-center rounded-full bg-rose-100 text-rose-600 dark:bg-rose-900 dark:text-rose-400\"\r\n      >\r\n        <svg\r\n          class=\"h-3.5 w-3.5\"\r\n          fill=\"none\"\r\n          viewBox=\"0 0 24 24\"\r\n          stroke=\"currentColor\"\r\n          stroke-width=\"2.5\"\r\n        >\r\n          <path\r\n            stroke-linecap=\"round\"\r\n            stroke-linejoin=\"round\"\r\n            d=\"M6 18L18 6M6 6l12 12\"\r\n          />\r\n        </svg>\r\n      </span>\r\n      <span class=\"font-medium text-rose-600 dark:text-rose-400\">\r\n        {{ labelInvalid() }}\r\n      </span>\r\n    }\r\n  </div>\r\n\r\n  <!-- Separator -->\r\n  <div class=\"h-4 w-px bg-slate-300 dark:bg-slate-600\"></div>\r\n\r\n  <!-- Complexity -->\r\n  <div class=\"flex items-center gap-1.5 text-slate-500 dark:text-slate-400\">\r\n    <svg class=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\">\r\n      <path\r\n        stroke-linecap=\"round\"\r\n        stroke-linejoin=\"round\"\r\n        stroke-width=\"2\"\r\n        d=\"M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z\"\r\n      />\r\n    </svg>\r\n    <span>{{ labelComplexity() }}:</span>\r\n    <span class=\"font-medium\" [class]=\"complexityClass()\">\r\n      {{ complexity() }}\r\n    </span>\r\n  </div>\r\n\r\n  <!-- Dependencies -->\r\n  @if (dependencies().length > 0) {\r\n    <div class=\"h-4 w-px bg-slate-300 dark:bg-slate-600\"></div>\r\n    <div class=\"flex items-center gap-1.5 text-slate-500 dark:text-slate-400\">\r\n      <svg\r\n        class=\"h-4 w-4\"\r\n        fill=\"none\"\r\n        viewBox=\"0 0 24 24\"\r\n        stroke=\"currentColor\"\r\n      >\r\n        <path\r\n          stroke-linecap=\"round\"\r\n          stroke-linejoin=\"round\"\r\n          stroke-width=\"2\"\r\n          d=\"M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1\"\r\n        />\r\n      </svg>\r\n      <span>{{ labelDependencies() }}:</span>\r\n      <span class=\"font-medium text-slate-700 dark:text-slate-300\">\r\n        {{ dependenciesText() }}\r\n      </span>\r\n    </div>\r\n  }\r\n\r\n  <!-- Error message (if any) -->\r\n  @if (firstError(); as error) {\r\n    <div\r\n      class=\"ms-auto flex items-center gap-1.5 text-rose-600 dark:text-rose-400\"\r\n    >\r\n      <svg\r\n        class=\"h-4 w-4\"\r\n        fill=\"none\"\r\n        viewBox=\"0 0 24 24\"\r\n        stroke=\"currentColor\"\r\n      >\r\n        <path\r\n          stroke-linecap=\"round\"\r\n          stroke-linejoin=\"round\"\r\n          stroke-width=\"2\"\r\n          d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\"\r\n        />\r\n      </svg>\r\n      <span class=\"text-xs\">{{ error.message }}</span>\r\n      <span class=\"text-xs opacity-60\"\r\n        >({{ error.line }}:{{ error.column }})</span\r\n      >\r\n    </div>\r\n  }\r\n</div>\r\n" }]
        }], propDecorators: { validation: [{ type: i0.Input, args: [{ isSignal: true, alias: "validation", required: false }] }], labels: [{ type: i0.Input, args: [{ isSignal: true, alias: "labels", required: false }] }] } });

// Formula components public API

/**
 * Generated bundle index. Do not edit.
 */

export { FormulaEditor, FormulaStatusBar, FormulaToolbar, FormulaToolbarItem, cloneBlock, cloneToken, cloneTokens, createFunctionBlock, createFunctionTokens, createLiteralBlock, createLiteralToken, createOperatorBlock, createOperatorToken, createPropertyBlock, createPropertyToken, findFunctionRange, generateFunctionId, generateSmartBlockId, generateTokenId, getArgumentIndexAtPosition, getFunctionTokens, isValidDropPosition, parseSignature, recalculateDepths, serializeTokens };
//# sourceMappingURL=masterteam-components-formula.mjs.map
