@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.
- package/assets/common.css +1 -1
- package/fesm2022/masterteam-components-formula.mjs +147 -20
- package/fesm2022/masterteam-components-formula.mjs.map +1 -1
- package/fesm2022/masterteam-components-multi-select-field.mjs +6 -3
- package/fesm2022/masterteam-components-multi-select-field.mjs.map +1 -1
- package/fesm2022/masterteam-components-radio-cards-field.mjs +1 -1
- package/fesm2022/masterteam-components-radio-cards-field.mjs.map +1 -1
- package/fesm2022/masterteam-components-radio-cards.mjs +13 -4
- package/fesm2022/masterteam-components-radio-cards.mjs.map +1 -1
- package/fesm2022/masterteam-components-select-field.mjs +2 -2
- package/fesm2022/masterteam-components-select-field.mjs.map +1 -1
- package/fesm2022/masterteam-components-tree.mjs +69 -39
- package/fesm2022/masterteam-components-tree.mjs.map +1 -1
- package/fesm2022/masterteam-components.mjs +35 -2
- package/fesm2022/masterteam-components.mjs.map +1 -1
- package/package.json +1 -1
- package/types/masterteam-components-formula.d.ts +28 -8
- package/types/masterteam-components-multi-select-field.d.ts +4 -1
- package/types/masterteam-components-radio-cards.d.ts +5 -2
- package/types/masterteam-components-tree.d.ts +8 -5
- package/types/masterteam-components.d.ts +34 -3
|
@@ -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
|
|
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 [
|
|
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 [
|
|
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(
|
|
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 }] }],
|
|
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
|