@masterteam/components 0.0.80 → 0.0.82

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,13 @@
1
1
  import * as i0 from '@angular/core';
2
- import { input, output, signal, computed, effect, forwardRef, Component } from '@angular/core';
2
+ import { input, output, signal, computed, effect, forwardRef, Component, contentChild, TemplateRef } from '@angular/core';
3
+ import * as i1$2 from '@angular/common';
3
4
  import { CommonModule } from '@angular/common';
4
- import * as i1$1 from '@angular/forms';
5
+ import * as i2 from '@angular/forms';
5
6
  import { FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
6
7
  import * as i1 from '@angular/cdk/drag-drop';
7
8
  import { moveItemInArray, DragDropModule } from '@angular/cdk/drag-drop';
9
+ import * as i1$1 from 'primeng/tooltip';
10
+ import { TooltipModule } from 'primeng/tooltip';
8
11
 
9
12
  /**
10
13
  * Flat Formula Token Model
@@ -106,7 +109,8 @@ function createFunctionTokens(signature, depth = 0) {
106
109
  /**
107
110
  * Create a property token
108
111
  */
109
- function createPropertyToken(propertyKey, propertyType = 'current', depth = 0, functionId, argIndex) {
112
+ function createPropertyToken(propertyKey, propertyType = 'current', depth = 0, functionId, argIndex, display) {
113
+ const usesFullPath = propertyKey.startsWith('@');
110
114
  const prefix = propertyType === 'current'
111
115
  ? '@'
112
116
  : propertyType === 'children'
@@ -115,7 +119,8 @@ function createPropertyToken(propertyKey, propertyType = 'current', depth = 0, f
115
119
  return {
116
120
  id: generateTokenId(),
117
121
  type: 'property',
118
- value: `${prefix}${propertyKey}`,
122
+ value: usesFullPath ? propertyKey : `${prefix}${propertyKey}`,
123
+ display,
119
124
  propertyType,
120
125
  depth,
121
126
  functionId,
@@ -333,7 +338,8 @@ function createFunctionBlock(signature, name) {
333
338
  };
334
339
  }
335
340
  /** Create a property block */
336
- function createPropertyBlock(propertyKey, propertyType = 'current') {
341
+ function createPropertyBlock(propertyKey, propertyType = 'current', display) {
342
+ const usesFullPath = propertyKey.startsWith('@');
337
343
  const prefix = propertyType === 'current'
338
344
  ? '@'
339
345
  : propertyType === 'children'
@@ -342,7 +348,8 @@ function createPropertyBlock(propertyKey, propertyType = 'current') {
342
348
  return {
343
349
  id: generateSmartBlockId(),
344
350
  type: 'property',
345
- value: `${prefix}${propertyKey}`,
351
+ value: usesFullPath ? propertyKey : `${prefix}${propertyKey}`,
352
+ display,
346
353
  propertyType,
347
354
  propertyKey,
348
355
  };
@@ -680,7 +687,7 @@ class FormulaEditor {
680
687
  return createFunctionTokens(block.signature || `${block.functionName}()`, 0);
681
688
  case 'property':
682
689
  return [
683
- createPropertyToken(block.propertyKey || block.value, block.propertyType),
690
+ createPropertyToken(block.propertyKey || block.value, block.propertyType, 0, undefined, undefined, block.display),
684
691
  ];
685
692
  case 'operator':
686
693
  return [createOperatorToken(block.operatorSymbol || block.value)];
@@ -712,7 +719,7 @@ class FormulaEditor {
712
719
  useExisting: forwardRef(() => FormulaEditor),
713
720
  multi: true,
714
721
  },
715
- ], 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 }] });
722
+ ], 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.display ?? 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 }] });
716
723
  }
717
724
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: FormulaEditor, decorators: [{
718
725
  type: Component,
@@ -722,7 +729,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
722
729
  useExisting: forwardRef(() => FormulaEditor),
723
730
  multi: true,
724
731
  },
725
- ], 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"] }]
732
+ ], 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.display ?? 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"] }]
726
733
  }], 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"] }] } });
727
734
 
728
735
  /**
@@ -743,19 +750,23 @@ class FormulaToolbarItem {
743
750
  description = input('', ...(ngDevMode ? [{ debugName: "description" }] : []));
744
751
  /** Function signature (for functions only, e.g., "SUM(values)") */
745
752
  signature = input(...(ngDevMode ? [undefined, { debugName: "signature" }] : []));
753
+ /** Function examples (for functions only) */
754
+ examples = input([], ...(ngDevMode ? [{ debugName: "examples" }] : []));
746
755
  /** Property type for properties */
747
756
  propertyType = input('current', ...(ngDevMode ? [{ debugName: "propertyType" }] : []));
748
757
  /** Insert event - emits SmartBlock */
749
758
  onInsert = output();
750
759
  /** Computed display value */
751
760
  displayValue = computed(() => this.display() ?? this.value(), ...(ngDevMode ? [{ debugName: "displayValue" }] : []));
761
+ /** Check if has rich tooltip content (signature or examples) */
762
+ hasRichTooltip = computed(() => this.type() === 'function' && (this.signature() || this.examples().length > 0), ...(ngDevMode ? [{ debugName: "hasRichTooltip" }] : []));
752
763
  /** Build SmartBlock from item data */
753
764
  smartBlock = computed(() => {
754
765
  switch (this.type()) {
755
766
  case 'function':
756
767
  return createFunctionBlock(this.signature() || `${this.value()}()`, this.value());
757
768
  case 'property':
758
- return createPropertyBlock(this.value(), this.propertyType());
769
+ return createPropertyBlock(this.value(), this.propertyType(), this.display());
759
770
  case 'operator':
760
771
  return createOperatorBlock(this.value());
761
772
  default:
@@ -780,14 +791,118 @@ class FormulaToolbarItem {
780
791
  this.onInsert.emit(this.smartBlock());
781
792
  }
782
793
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: FormulaToolbarItem, deps: [], target: i0.ɵɵFactoryTarget.Component });
783
- 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 }] });
794
+ 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 }, examples: { classPropertyName: "examples", publicName: "examples", 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 [pTooltip]=\"hasRichTooltip() ? richTooltip : description()\"\r\n [tooltipPosition]=\"'bottom'\"\r\n [showDelay]=\"300\"\r\n [hideDelay]=\"100\"\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\r\n<!-- Rich tooltip template for functions -->\r\n<ng-template #richTooltip>\r\n <div class=\"max-w-xs space-y-2.5 p-1\">\r\n <!-- Signature (first) -->\r\n @if (signature()) {\r\n <div class=\"rounded bg-slate-700 px-2.5 py-1.5\">\r\n <code class=\"font-mono text-sm text-emerald-400\">{{ signature() }}</code>\r\n </div>\r\n }\r\n\r\n <!-- Description -->\r\n @if (description()) {\r\n <p class=\"text-sm leading-relaxed text-slate-200\">{{ description() }}</p>\r\n }\r\n\r\n <!-- Examples -->\r\n @if (examples().length > 0) {\r\n <div class=\"space-y-1.5 border-t border-slate-600 pt-2\">\r\n <span class=\"text-xs font-semibold uppercase tracking-wider text-slate-400\">Examples</span>\r\n <div class=\"space-y-1.5\">\r\n @for (example of examples(); track $index) {\r\n <div class=\"rounded bg-slate-800 px-2.5 py-1.5\">\r\n <code class=\"font-mono text-xs text-amber-300\">{{ example }}</code>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n</ng-template>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i1$1.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }] });
784
795
  }
785
796
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: FormulaToolbarItem, decorators: [{
786
797
  type: Component,
787
- args: [{ selector: 'mt-formula-toolbar-item', standalone: true, imports: [CommonModule], host: {
798
+ args: [{ selector: 'mt-formula-toolbar-item', standalone: true, imports: [CommonModule, TooltipModule], host: {
788
799
  class: 'inline-block',
789
- }, 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" }]
790
- }], 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"] }] } });
800
+ }, 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 [pTooltip]=\"hasRichTooltip() ? richTooltip : description()\"\r\n [tooltipPosition]=\"'bottom'\"\r\n [showDelay]=\"300\"\r\n [hideDelay]=\"100\"\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\r\n<!-- Rich tooltip template for functions -->\r\n<ng-template #richTooltip>\r\n <div class=\"max-w-xs space-y-2.5 p-1\">\r\n <!-- Signature (first) -->\r\n @if (signature()) {\r\n <div class=\"rounded bg-slate-700 px-2.5 py-1.5\">\r\n <code class=\"font-mono text-sm text-emerald-400\">{{ signature() }}</code>\r\n </div>\r\n }\r\n\r\n <!-- Description -->\r\n @if (description()) {\r\n <p class=\"text-sm leading-relaxed text-slate-200\">{{ description() }}</p>\r\n }\r\n\r\n <!-- Examples -->\r\n @if (examples().length > 0) {\r\n <div class=\"space-y-1.5 border-t border-slate-600 pt-2\">\r\n <span class=\"text-xs font-semibold uppercase tracking-wider text-slate-400\">Examples</span>\r\n <div class=\"space-y-1.5\">\r\n @for (example of examples(); track $index) {\r\n <div class=\"rounded bg-slate-800 px-2.5 py-1.5\">\r\n <code class=\"font-mono text-xs text-amber-300\">{{ example }}</code>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n</ng-template>\r\n" }]
801
+ }], 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 }] }], examples: [{ type: i0.Input, args: [{ isSignal: true, alias: "examples", required: false }] }], propertyType: [{ type: i0.Input, args: [{ isSignal: true, alias: "propertyType", required: false }] }], onInsert: [{ type: i0.Output, args: ["onInsert"] }] } });
802
+
803
+ const DEFAULT_OPERATORS = [
804
+ // Arithmetic
805
+ {
806
+ symbol: '+',
807
+ name: 'Add',
808
+ type: 'arithmetic',
809
+ description: 'Addition',
810
+ precedence: 4,
811
+ },
812
+ {
813
+ symbol: '-',
814
+ name: 'Subtract',
815
+ type: 'arithmetic',
816
+ description: 'Subtraction',
817
+ precedence: 4,
818
+ },
819
+ {
820
+ symbol: '*',
821
+ name: 'Multiply',
822
+ type: 'arithmetic',
823
+ description: 'Multiplication',
824
+ precedence: 5,
825
+ },
826
+ {
827
+ symbol: '/',
828
+ name: 'Divide',
829
+ type: 'arithmetic',
830
+ description: 'Division',
831
+ precedence: 5,
832
+ },
833
+ {
834
+ symbol: '%',
835
+ name: 'Modulo',
836
+ type: 'arithmetic',
837
+ description: 'Modulo',
838
+ precedence: 5,
839
+ },
840
+ // Comparison
841
+ {
842
+ symbol: '==',
843
+ name: 'Equal',
844
+ type: 'comparison',
845
+ description: 'Equal to',
846
+ precedence: 3,
847
+ },
848
+ {
849
+ symbol: '!=',
850
+ name: 'Not Equal',
851
+ type: 'comparison',
852
+ description: 'Not equal to',
853
+ precedence: 3,
854
+ },
855
+ {
856
+ symbol: '>',
857
+ name: 'Greater',
858
+ type: 'comparison',
859
+ description: 'Greater than',
860
+ precedence: 3,
861
+ },
862
+ {
863
+ symbol: '<',
864
+ name: 'Less',
865
+ type: 'comparison',
866
+ description: 'Less than',
867
+ precedence: 3,
868
+ },
869
+ {
870
+ symbol: '>=',
871
+ name: 'Greater or Equal',
872
+ type: 'comparison',
873
+ description: 'Greater than or equal',
874
+ precedence: 3,
875
+ },
876
+ {
877
+ symbol: '<=',
878
+ name: 'Less or Equal',
879
+ type: 'comparison',
880
+ description: 'Less than or equal',
881
+ precedence: 3,
882
+ },
883
+ // Logical
884
+ {
885
+ symbol: '&&',
886
+ name: 'And',
887
+ type: 'logical',
888
+ description: 'Logical AND',
889
+ precedence: 2,
890
+ },
891
+ {
892
+ symbol: '||',
893
+ name: 'Or',
894
+ type: 'logical',
895
+ description: 'Logical OR',
896
+ precedence: 1,
897
+ },
898
+ {
899
+ symbol: '!',
900
+ name: 'Not',
901
+ type: 'logical',
902
+ description: 'Logical NOT',
903
+ precedence: 6,
904
+ },
905
+ ];
791
906
 
792
907
  /**
793
908
  * Formula Toolbar Component
@@ -800,10 +915,14 @@ class FormulaToolbar {
800
915
  // ============ INPUTS ============
801
916
  /** Known properties to show in properties tab */
802
917
  knownProperties = input([], ...(ngDevMode ? [{ debugName: "knownProperties" }] : []));
918
+ /** Custom properties template */
919
+ propertiesTemplate = input(null, ...(ngDevMode ? [{ debugName: "propertiesTemplate" }] : []));
920
+ /** Projected properties template */
921
+ projectedPropertiesTemplate = contentChild('properties', { ...(ngDevMode ? { debugName: "projectedPropertiesTemplate" } : {}), read: TemplateRef });
803
922
  /** Function categories (from API or static data) */
804
923
  functionCategories = input([], ...(ngDevMode ? [{ debugName: "functionCategories" }] : []));
805
- /** Operators list */
806
- operators = input([], ...(ngDevMode ? [{ debugName: "operators" }] : []));
924
+ /** Operators list (overridable) */
925
+ operators = input(DEFAULT_OPERATORS, ...(ngDevMode ? [{ debugName: "operators" }] : []));
807
926
  /** Initial active tab */
808
927
  initialTab = input('functions', ...(ngDevMode ? [{ debugName: "initialTab" }] : []));
809
928
  /** Placeholder for search input */
@@ -824,6 +943,12 @@ class FormulaToolbar {
824
943
  { label: 'Properties', value: 'properties' },
825
944
  { label: 'Operators', value: 'operators' },
826
945
  ];
946
+ /** Context for custom properties template */
947
+ propertiesTemplateContext = {
948
+ insertBlock: (block) => this.insertBlock(block),
949
+ };
950
+ /** Resolve properties template (projected first, input fallback) */
951
+ resolvedPropertiesTemplate = computed(() => this.projectedPropertiesTemplate() ?? this.propertiesTemplate(), ...(ngDevMode ? [{ debugName: "resolvedPropertiesTemplate" }] : []));
827
952
  /** Search query */
828
953
  searchQuery = signal('', ...(ngDevMode ? [{ debugName: "searchQuery" }] : []));
829
954
  /** Custom value input */
@@ -1058,12 +1183,14 @@ class FormulaToolbar {
1058
1183
  this.customValue.set('');
1059
1184
  }
1060
1185
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: FormulaToolbar, deps: [], target: i0.ɵɵFactoryTarget.Component });
1061
- 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"] }] });
1186
+ 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 }, propertiesTemplate: { classPropertyName: "propertiesTemplate", publicName: "propertiesTemplate", 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" }, queries: [{ propertyName: "projectedPropertiesTemplate", first: true, predicate: ["properties"], descendants: true, read: TemplateRef, isSignal: true }], ngImport: i0, template: "<div\r\n class=\"flex flex-col border-b border-slate-200 dark:border-slate-700\"\r\n [class.h-52]=\"activeTab() !== 'properties' || !resolvedPropertiesTemplate()\"\r\n>\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 @if (tab.value !== \"properties\" || !resolvedPropertiesTemplate()) {\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 }\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\r\n class=\"flex-1 p-2.5\"\r\n [class.overflow-y-auto]=\"\r\n activeTab() !== 'properties' || !resolvedPropertiesTemplate()\r\n \"\r\n >\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 [examples]=\"fn.examples ?? []\"\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 (resolvedPropertiesTemplate(); as template) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"template\"\r\n [ngTemplateOutletContext]=\"propertiesTemplateContext\"\r\n />\r\n } @else {\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 }\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: "directive", type: i1$2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.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: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.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", "examples", "propertyType"], outputs: ["onInsert"] }] });
1062
1187
  }
1063
1188
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: FormulaToolbar, decorators: [{
1064
1189
  type: Component,
1065
- 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" }]
1066
- }], 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"] }] } });
1190
+ args: [{ selector: 'mt-formula-toolbar', standalone: true, imports: [CommonModule, FormsModule, FormulaToolbarItem], template: "<div\r\n class=\"flex flex-col border-b border-slate-200 dark:border-slate-700\"\r\n [class.h-52]=\"activeTab() !== 'properties' || !resolvedPropertiesTemplate()\"\r\n>\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 @if (tab.value !== \"properties\" || !resolvedPropertiesTemplate()) {\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 }\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\r\n class=\"flex-1 p-2.5\"\r\n [class.overflow-y-auto]=\"\r\n activeTab() !== 'properties' || !resolvedPropertiesTemplate()\r\n \"\r\n >\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 [examples]=\"fn.examples ?? []\"\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 (resolvedPropertiesTemplate(); as template) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"template\"\r\n [ngTemplateOutletContext]=\"propertiesTemplateContext\"\r\n />\r\n } @else {\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 }\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" }]
1191
+ }], ctorParameters: () => [], propDecorators: { knownProperties: [{ type: i0.Input, args: [{ isSignal: true, alias: "knownProperties", required: false }] }], propertiesTemplate: [{ type: i0.Input, args: [{ isSignal: true, alias: "propertiesTemplate", required: false }] }], projectedPropertiesTemplate: [{ type: i0.ContentChild, args: ['properties', { ...{
1192
+ read: TemplateRef,
1193
+ }, isSignal: true }] }], 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"] }] } });
1067
1194
 
1068
1195
  /**
1069
1196
  * Formula Status Bar Component
@@ -1122,5 +1249,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
1122
1249
  * Generated bundle index. Do not edit.
1123
1250
  */
1124
1251
 
1125
- 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 };
1252
+ export { DEFAULT_OPERATORS, 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 };
1126
1253
  //# sourceMappingURL=masterteam-components-formula.mjs.map