@masterteam/formula-builder 0.0.9 → 0.0.11
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.
|
@@ -51,9 +51,9 @@ class FormulaValidatorService {
|
|
|
51
51
|
/** Debounce time in ms */
|
|
52
52
|
DEBOUNCE_MS = 300;
|
|
53
53
|
/** Current validation result */
|
|
54
|
-
_validation = signal(EMPTY_VALIDATION, ...(ngDevMode ? [{ debugName: "_validation" }] : []));
|
|
54
|
+
_validation = signal(EMPTY_VALIDATION, ...(ngDevMode ? [{ debugName: "_validation" }] : /* istanbul ignore next */ []));
|
|
55
55
|
/** Loading state */
|
|
56
|
-
_isValidating = signal(false, ...(ngDevMode ? [{ debugName: "_isValidating" }] : []));
|
|
56
|
+
_isValidating = signal(false, ...(ngDevMode ? [{ debugName: "_isValidating" }] : /* istanbul ignore next */ []));
|
|
57
57
|
/** Validation subject for debouncing */
|
|
58
58
|
validateSubject = new Subject();
|
|
59
59
|
unwrapResponse(response) {
|
|
@@ -169,10 +169,10 @@ class FormulaValidatorService {
|
|
|
169
169
|
getComplexity() {
|
|
170
170
|
return this._validation().complexity;
|
|
171
171
|
}
|
|
172
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
173
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.
|
|
172
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: FormulaValidatorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
173
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: FormulaValidatorService, providedIn: 'root' });
|
|
174
174
|
}
|
|
175
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
175
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: FormulaValidatorService, decorators: [{
|
|
176
176
|
type: Injectable,
|
|
177
177
|
args: [{ providedIn: 'root' }]
|
|
178
178
|
}], ctorParameters: () => [] });
|
|
@@ -280,10 +280,10 @@ class FormulaContextService {
|
|
|
280
280
|
return of(null);
|
|
281
281
|
}));
|
|
282
282
|
}
|
|
283
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
284
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.
|
|
283
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: FormulaContextService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
284
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: FormulaContextService, providedIn: 'root' });
|
|
285
285
|
}
|
|
286
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
286
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: FormulaContextService, decorators: [{
|
|
287
287
|
type: Injectable,
|
|
288
288
|
args: [{ providedIn: 'root' }]
|
|
289
289
|
}] });
|
|
@@ -321,10 +321,10 @@ class FormulaAutocompleteService {
|
|
|
321
321
|
return of(null);
|
|
322
322
|
}));
|
|
323
323
|
}
|
|
324
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
325
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.
|
|
324
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: FormulaAutocompleteService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
325
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: FormulaAutocompleteService, providedIn: 'root' });
|
|
326
326
|
}
|
|
327
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
327
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: FormulaAutocompleteService, decorators: [{
|
|
328
328
|
type: Injectable,
|
|
329
329
|
args: [{ providedIn: 'root' }]
|
|
330
330
|
}] });
|
|
@@ -447,31 +447,31 @@ class FormulaBuilder {
|
|
|
447
447
|
contextService = inject(FormulaContextService);
|
|
448
448
|
autocompleteService = inject(FormulaAutocompleteService);
|
|
449
449
|
/** Reference to the formula editor */
|
|
450
|
-
editor = viewChild('formulaEditor', ...(ngDevMode ? [{ debugName: "editor" }] : []));
|
|
451
|
-
codeEditor = viewChild('formulaEditorCode', ...(ngDevMode ? [{ debugName: "codeEditor" }] : []));
|
|
450
|
+
editor = viewChild('formulaEditor', ...(ngDevMode ? [{ debugName: "editor" }] : /* istanbul ignore next */ []));
|
|
451
|
+
codeEditor = viewChild('formulaEditorCode', ...(ngDevMode ? [{ debugName: "codeEditor" }] : /* istanbul ignore next */ []));
|
|
452
452
|
// ===== INPUTS =====
|
|
453
453
|
/** Properties per table path (e.g., "Current", "Children.Project") */
|
|
454
|
-
propertiesByPath = input({}, ...(ngDevMode ? [{ debugName: "propertiesByPath" }] : []));
|
|
454
|
+
propertiesByPath = input({}, ...(ngDevMode ? [{ debugName: "propertiesByPath" }] : /* istanbul ignore next */ []));
|
|
455
455
|
/** Level schema ID for validation context */
|
|
456
|
-
levelSchemaId = input(...(ngDevMode ? [undefined, { debugName: "levelSchemaId" }] : []));
|
|
456
|
+
levelSchemaId = input(...(ngDevMode ? [undefined, { debugName: "levelSchemaId" }] : /* istanbul ignore next */ []));
|
|
457
457
|
/** Optional module ID when the formula is scoped inside a level-linked module */
|
|
458
|
-
moduleId = input(...(ngDevMode ? [undefined, { debugName: "moduleId" }] : []));
|
|
458
|
+
moduleId = input(...(ngDevMode ? [undefined, { debugName: "moduleId" }] : /* istanbul ignore next */ []));
|
|
459
459
|
/** Optional current context entity key, e.g. LevelData or Risk */
|
|
460
|
-
contextEntityTypeKey = input(...(ngDevMode ? [undefined, { debugName: "contextEntityTypeKey" }] : []));
|
|
460
|
+
contextEntityTypeKey = input(...(ngDevMode ? [undefined, { debugName: "contextEntityTypeKey" }] : /* istanbul ignore next */ []));
|
|
461
461
|
/** Template ID for validation context */
|
|
462
|
-
templateId = input(...(ngDevMode ? [undefined, { debugName: "templateId" }] : []));
|
|
462
|
+
templateId = input(...(ngDevMode ? [undefined, { debugName: "templateId" }] : /* istanbul ignore next */ []));
|
|
463
463
|
/** Placeholder text */
|
|
464
|
-
placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
|
|
464
|
+
placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
|
|
465
465
|
/** Hide the top toolbar */
|
|
466
|
-
hideToolbar = input(false, ...(ngDevMode ? [{ debugName: "hideToolbar" }] : []));
|
|
466
|
+
hideToolbar = input(false, ...(ngDevMode ? [{ debugName: "hideToolbar" }] : /* istanbul ignore next */ []));
|
|
467
467
|
/** Hide the status bar */
|
|
468
|
-
hideStatusBar = input(false, ...(ngDevMode ? [{ debugName: "hideStatusBar" }] : []));
|
|
468
|
+
hideStatusBar = input(false, ...(ngDevMode ? [{ debugName: "hideStatusBar" }] : /* istanbul ignore next */ []));
|
|
469
469
|
/** Visible toolbar tabs */
|
|
470
|
-
toolbarTabs = input(DEFAULT_TOOLBAR_TABS, ...(ngDevMode ? [{ debugName: "toolbarTabs" }] : []));
|
|
470
|
+
toolbarTabs = input(DEFAULT_TOOLBAR_TABS, ...(ngDevMode ? [{ debugName: "toolbarTabs" }] : /* istanbul ignore next */ []));
|
|
471
471
|
/** Force code editor mode and hide the mode toggle */
|
|
472
|
-
codeOnly = input(false, ...(ngDevMode ? [{ debugName: "codeOnly" }] : []));
|
|
472
|
+
codeOnly = input(false, ...(ngDevMode ? [{ debugName: "codeOnly" }] : /* istanbul ignore next */ []));
|
|
473
473
|
/** Use Process Builder current-only Formula Engine endpoints */
|
|
474
|
-
isProcessBuilder = input(false, ...(ngDevMode ? [{ debugName: "isProcessBuilder" }] : []));
|
|
474
|
+
isProcessBuilder = input(false, ...(ngDevMode ? [{ debugName: "isProcessBuilder" }] : /* istanbul ignore next */ []));
|
|
475
475
|
// ===== OUTPUTS =====
|
|
476
476
|
/** Emits validation result on change */
|
|
477
477
|
validationChange = output();
|
|
@@ -479,13 +479,13 @@ class FormulaBuilder {
|
|
|
479
479
|
tokensChange = output();
|
|
480
480
|
// ===== STATE =====
|
|
481
481
|
/** Editor focus state */
|
|
482
|
-
hasFocus = signal(false, ...(ngDevMode ? [{ debugName: "hasFocus" }] : []));
|
|
482
|
+
hasFocus = signal(false, ...(ngDevMode ? [{ debugName: "hasFocus" }] : /* istanbul ignore next */ []));
|
|
483
483
|
/** Form control value */
|
|
484
|
-
expressionValue = signal('', ...(ngDevMode ? [{ debugName: "expressionValue" }] : []));
|
|
485
|
-
builderValue = signal([], ...(ngDevMode ? [{ debugName: "builderValue" }] : []));
|
|
484
|
+
expressionValue = signal('', ...(ngDevMode ? [{ debugName: "expressionValue" }] : /* istanbul ignore next */ []));
|
|
485
|
+
builderValue = signal([], ...(ngDevMode ? [{ debugName: "builderValue" }] : /* istanbul ignore next */ []));
|
|
486
486
|
/** Tokens for the editor */
|
|
487
|
-
tokens = signal([], ...(ngDevMode ? [{ debugName: "tokens" }] : []));
|
|
488
|
-
expression = computed(() => this.expressionValue(), ...(ngDevMode ? [{ debugName: "expression" }] : []));
|
|
487
|
+
tokens = signal([], ...(ngDevMode ? [{ debugName: "tokens" }] : /* istanbul ignore next */ []));
|
|
488
|
+
expression = computed(() => this.expressionValue(), ...(ngDevMode ? [{ debugName: "expression" }] : /* istanbul ignore next */ []));
|
|
489
489
|
resolvedContextEntityTypeKey = computed(() => {
|
|
490
490
|
const value = this.contextEntityTypeKey();
|
|
491
491
|
if (typeof value !== 'string') {
|
|
@@ -493,7 +493,7 @@ class FormulaBuilder {
|
|
|
493
493
|
}
|
|
494
494
|
const normalized = value.trim();
|
|
495
495
|
return normalized.length > 0 ? normalized : undefined;
|
|
496
|
-
}, ...(ngDevMode ? [{ debugName: "resolvedContextEntityTypeKey" }] : []));
|
|
496
|
+
}, ...(ngDevMode ? [{ debugName: "resolvedContextEntityTypeKey" }] : /* istanbul ignore next */ []));
|
|
497
497
|
isModuleContext = computed(() => {
|
|
498
498
|
const contextType = this.resolvedContextEntityTypeKey() ??
|
|
499
499
|
this.builderContext()?.contextEntityTypeKey;
|
|
@@ -502,7 +502,7 @@ class FormulaBuilder {
|
|
|
502
502
|
}
|
|
503
503
|
const normalized = contextType.trim().toLowerCase();
|
|
504
504
|
return normalized.length > 0 && normalized !== 'leveldata';
|
|
505
|
-
}, ...(ngDevMode ? [{ debugName: "isModuleContext" }] : []));
|
|
505
|
+
}, ...(ngDevMode ? [{ debugName: "isModuleContext" }] : /* istanbul ignore next */ []));
|
|
506
506
|
autocompleteProvider = (request) => {
|
|
507
507
|
return this.autocompleteService.getSuggestions({
|
|
508
508
|
...request,
|
|
@@ -515,37 +515,37 @@ class FormulaBuilder {
|
|
|
515
515
|
/** Track last synced builder JSON to avoid loops */
|
|
516
516
|
lastBuilderJson = '';
|
|
517
517
|
/** Editor mode */
|
|
518
|
-
editorMode = signal('builder', ...(ngDevMode ? [{ debugName: "editorMode" }] : []));
|
|
519
|
-
isCodeMode = computed(() => this.editorMode() === 'code', ...(ngDevMode ? [{ debugName: "isCodeMode" }] : []));
|
|
520
|
-
isCodeModeLocked = signal(false, ...(ngDevMode ? [{ debugName: "isCodeModeLocked" }] : []));
|
|
521
|
-
showModeToggle = computed(() => !this.codeOnly(), ...(ngDevMode ? [{ debugName: "showModeToggle" }] : []));
|
|
522
|
-
formulaApiMode = computed(() => this.isProcessBuilder() ? 'current-only' : 'default', ...(ngDevMode ? [{ debugName: "formulaApiMode" }] : []));
|
|
518
|
+
editorMode = signal('builder', ...(ngDevMode ? [{ debugName: "editorMode" }] : /* istanbul ignore next */ []));
|
|
519
|
+
isCodeMode = computed(() => this.editorMode() === 'code', ...(ngDevMode ? [{ debugName: "isCodeMode" }] : /* istanbul ignore next */ []));
|
|
520
|
+
isCodeModeLocked = signal(false, ...(ngDevMode ? [{ debugName: "isCodeModeLocked" }] : /* istanbul ignore next */ []));
|
|
521
|
+
showModeToggle = computed(() => !this.codeOnly(), ...(ngDevMode ? [{ debugName: "showModeToggle" }] : /* istanbul ignore next */ []));
|
|
522
|
+
formulaApiMode = computed(() => this.isProcessBuilder() ? 'current-only' : 'default', ...(ngDevMode ? [{ debugName: "formulaApiMode" }] : /* istanbul ignore next */ []));
|
|
523
523
|
resolvedToolbarTabs = computed(() => {
|
|
524
524
|
const tabs = this.toolbarTabs();
|
|
525
525
|
return tabs.length > 0 ? tabs : DEFAULT_TOOLBAR_TABS;
|
|
526
|
-
}, ...(ngDevMode ? [{ debugName: "resolvedToolbarTabs" }] : []));
|
|
526
|
+
}, ...(ngDevMode ? [{ debugName: "resolvedToolbarTabs" }] : /* istanbul ignore next */ []));
|
|
527
527
|
codeModeSnapshotTokens = [];
|
|
528
528
|
codeModeSnapshotExpression = '';
|
|
529
529
|
/** ControlValueAccessor callbacks */
|
|
530
530
|
onChange = () => { };
|
|
531
531
|
onTouched = () => { };
|
|
532
532
|
/** Disabled state */
|
|
533
|
-
isDisabled = signal(false, ...(ngDevMode ? [{ debugName: "isDisabled" }] : []));
|
|
533
|
+
isDisabled = signal(false, ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
|
|
534
534
|
/** Validation result from service */
|
|
535
535
|
validation = this.validatorService.validation;
|
|
536
536
|
/** Is validation in progress */
|
|
537
537
|
isValidating = this.validatorService.isValidating;
|
|
538
538
|
/** Builder context from API */
|
|
539
|
-
builderContext = signal(null, ...(ngDevMode ? [{ debugName: "builderContext" }] : []));
|
|
539
|
+
builderContext = signal(null, ...(ngDevMode ? [{ debugName: "builderContext" }] : /* istanbul ignore next */ []));
|
|
540
540
|
/** Function categories from context */
|
|
541
|
-
functionCategories = computed(() => this.builderContext()?.functions?.categories ?? [], ...(ngDevMode ? [{ debugName: "functionCategories" }] : []));
|
|
541
|
+
functionCategories = computed(() => this.builderContext()?.functions?.categories ?? [], ...(ngDevMode ? [{ debugName: "functionCategories" }] : /* istanbul ignore next */ []));
|
|
542
542
|
/** Is builder context loading */
|
|
543
|
-
isContextLoading = signal(false, ...(ngDevMode ? [{ debugName: "isContextLoading" }] : []));
|
|
543
|
+
isContextLoading = signal(false, ...(ngDevMode ? [{ debugName: "isContextLoading" }] : /* istanbul ignore next */ []));
|
|
544
544
|
contextRequestId = 0;
|
|
545
545
|
/** Properties loaded from API */
|
|
546
|
-
propertiesByPathApi = signal({}, ...(ngDevMode ? [{ debugName: "propertiesByPathApi" }] : []));
|
|
546
|
+
propertiesByPathApi = signal({}, ...(ngDevMode ? [{ debugName: "propertiesByPathApi" }] : /* istanbul ignore next */ []));
|
|
547
547
|
/** Current property list loading path */
|
|
548
|
-
propertyLoadingPath = signal(null, ...(ngDevMode ? [{ debugName: "propertyLoadingPath" }] : []));
|
|
548
|
+
propertyLoadingPath = signal(null, ...(ngDevMode ? [{ debugName: "propertyLoadingPath" }] : /* istanbul ignore next */ []));
|
|
549
549
|
constructor() {
|
|
550
550
|
// Validate when formula changes
|
|
551
551
|
effect(() => {
|
|
@@ -911,24 +911,32 @@ class FormulaBuilder {
|
|
|
911
911
|
this.codeModeSnapshotExpression = '';
|
|
912
912
|
}
|
|
913
913
|
// ===== PROPERTY COMPOSER =====
|
|
914
|
-
propertyScope = signal('', ...(ngDevMode ? [{ debugName: "propertyScope" }] : []));
|
|
915
|
-
propertyPathSegments = signal([], ...(ngDevMode ? [{ debugName: "propertyPathSegments" }] : []));
|
|
916
|
-
propertyFieldKey = signal('', ...(ngDevMode ? [{ debugName: "propertyFieldKey" }] : []));
|
|
917
|
-
nextTokenRulesByPath = signal({}, ...(ngDevMode ? [{ debugName: "nextTokenRulesByPath" }] : []));
|
|
914
|
+
propertyScope = signal('', ...(ngDevMode ? [{ debugName: "propertyScope" }] : /* istanbul ignore next */ []));
|
|
915
|
+
propertyPathSegments = signal([], ...(ngDevMode ? [{ debugName: "propertyPathSegments" }] : /* istanbul ignore next */ []));
|
|
916
|
+
propertyFieldKey = signal('', ...(ngDevMode ? [{ debugName: "propertyFieldKey" }] : /* istanbul ignore next */ []));
|
|
917
|
+
nextTokenRulesByPath = signal({}, ...(ngDevMode ? [{ debugName: "nextTokenRulesByPath" }] : /* istanbul ignore next */ []));
|
|
918
918
|
contextOperators = computed(() => {
|
|
919
919
|
return this.builderContext()?.schemaDescriptor?.operators ?? [];
|
|
920
|
-
}, ...(ngDevMode ? [{ debugName: "contextOperators" }] : []));
|
|
921
|
-
baseOperator = computed(() => this.contextOperators().find((op) => op.token === this.propertyScope()), ...(ngDevMode ? [{ debugName: "baseOperator" }] : []));
|
|
920
|
+
}, ...(ngDevMode ? [{ debugName: "contextOperators" }] : /* istanbul ignore next */ []));
|
|
921
|
+
baseOperator = computed(() => this.contextOperators().find((op) => op.token === this.propertyScope()), ...(ngDevMode ? [{ debugName: "baseOperator" }] : /* istanbul ignore next */ []));
|
|
922
922
|
baseRule = computed(() => {
|
|
923
923
|
const scope = this.propertyScope();
|
|
924
924
|
return this.builderContext()?.schemaDescriptor?.nextTokenRules?.[scope];
|
|
925
|
-
}, ...(ngDevMode ? [{ debugName: "baseRule" }] : []));
|
|
925
|
+
}, ...(ngDevMode ? [{ debugName: "baseRule" }] : /* istanbul ignore next */ []));
|
|
926
926
|
availableScopes = computed(() => {
|
|
927
927
|
const operators = this.contextOperators();
|
|
928
928
|
if (operators.length === 0)
|
|
929
929
|
return [];
|
|
930
|
+
const baseRules = this.builderContext()?.schemaDescriptor?.nextTokenRules ?? {};
|
|
930
931
|
const priority = new Map(PROPERTY_SCOPE_PRIORITY.map((token, index) => [token, index]));
|
|
931
|
-
|
|
932
|
+
const scopedOperators = operators.filter((operator) => operator.token.trim().length > 0);
|
|
933
|
+
return [...scopedOperators]
|
|
934
|
+
.filter((operator) => {
|
|
935
|
+
const parameterKind = baseRules[operator.token]?.parameterKind ?? operator.parameterKind;
|
|
936
|
+
const requiresParameter = operator.requiresParameter ?? Boolean(parameterKind);
|
|
937
|
+
return ((!parameterKind && !requiresParameter) ||
|
|
938
|
+
getAllowedValues(baseRules[operator.token]).length > 0);
|
|
939
|
+
})
|
|
932
940
|
.sort((a, b) => {
|
|
933
941
|
const aPriority = priority.get(a.token) ?? Number.MAX_SAFE_INTEGER;
|
|
934
942
|
const bPriority = priority.get(b.token) ?? Number.MAX_SAFE_INTEGER;
|
|
@@ -943,13 +951,13 @@ class FormulaBuilder {
|
|
|
943
951
|
requiresParam: operator.requiresParameter ?? false,
|
|
944
952
|
optional: !operator.requiresParameter,
|
|
945
953
|
}));
|
|
946
|
-
}, ...(ngDevMode ? [{ debugName: "availableScopes" }] : []));
|
|
954
|
+
}, ...(ngDevMode ? [{ debugName: "availableScopes" }] : /* istanbul ignore next */ []));
|
|
947
955
|
/** Radio card options for scope selection */
|
|
948
956
|
scopeOptions = computed(() => this.availableScopes().map((scope) => ({
|
|
949
957
|
id: scope.key,
|
|
950
958
|
name: this.getOperatorDisplayName(scope.key),
|
|
951
959
|
icon: SCOPE_ICON_MAP[scope.key] ?? DEFAULT_SCOPE_ICON,
|
|
952
|
-
})), ...(ngDevMode ? [{ debugName: "scopeOptions" }] : []));
|
|
960
|
+
})), ...(ngDevMode ? [{ debugName: "scopeOptions" }] : /* istanbul ignore next */ []));
|
|
953
961
|
/** Handle scope selection from radio cards */
|
|
954
962
|
onScopeChange(item) {
|
|
955
963
|
this.setPropertyScope(String(item.id));
|
|
@@ -963,20 +971,20 @@ class FormulaBuilder {
|
|
|
963
971
|
baseRule: this.baseRule(),
|
|
964
972
|
rulesByPath: this.nextTokenRulesByPath(),
|
|
965
973
|
});
|
|
966
|
-
}, ...(ngDevMode ? [{ debugName: "pathSegments" }] : []));
|
|
974
|
+
}, ...(ngDevMode ? [{ debugName: "pathSegments" }] : /* istanbul ignore next */ []));
|
|
967
975
|
isDirectAccess = computed(() => {
|
|
968
976
|
const operator = this.baseOperator();
|
|
969
977
|
const needsParameter = Boolean(operator?.parameterKind) || Boolean(operator?.requiresParameter);
|
|
970
978
|
return !needsParameter && this.pathSegments().length === 0;
|
|
971
|
-
}, ...(ngDevMode ? [{ debugName: "isDirectAccess" }] : []));
|
|
972
|
-
propertyTablePath = computed(() => buildTablePath(this.propertyScope(), this.pathSegments(), this.baseOperator(), false), ...(ngDevMode ? [{ debugName: "propertyTablePath" }] : []));
|
|
973
|
-
resolvedTablePath = computed(() => buildTablePath(this.propertyScope(), this.pathSegments(), this.baseOperator(), true), ...(ngDevMode ? [{ debugName: "resolvedTablePath" }] : []));
|
|
979
|
+
}, ...(ngDevMode ? [{ debugName: "isDirectAccess" }] : /* istanbul ignore next */ []));
|
|
980
|
+
propertyTablePath = computed(() => buildTablePath(this.propertyScope(), this.pathSegments(), this.baseOperator(), false), ...(ngDevMode ? [{ debugName: "propertyTablePath" }] : /* istanbul ignore next */ []));
|
|
981
|
+
resolvedTablePath = computed(() => buildTablePath(this.propertyScope(), this.pathSegments(), this.baseOperator(), true), ...(ngDevMode ? [{ debugName: "resolvedTablePath" }] : /* istanbul ignore next */ []));
|
|
974
982
|
currentNextTokenRules = computed(() => {
|
|
975
983
|
const path = this.resolvedTablePath();
|
|
976
984
|
if (!path)
|
|
977
985
|
return {};
|
|
978
986
|
return this.nextTokenRulesByPath()[path] ?? {};
|
|
979
|
-
}, ...(ngDevMode ? [{ debugName: "currentNextTokenRules" }] : []));
|
|
987
|
+
}, ...(ngDevMode ? [{ debugName: "currentNextTokenRules" }] : /* istanbul ignore next */ []));
|
|
980
988
|
nextOperatorOptions = computed(() => {
|
|
981
989
|
const rules = this.currentNextTokenRules();
|
|
982
990
|
const operators = this.contextOperators();
|
|
@@ -995,7 +1003,7 @@ class FormulaBuilder {
|
|
|
995
1003
|
};
|
|
996
1004
|
})
|
|
997
1005
|
.filter((option) => option.allowedValues.length > 0 || !option.requiresParameter);
|
|
998
|
-
}, ...(ngDevMode ? [{ debugName: "nextOperatorOptions" }] : []));
|
|
1006
|
+
}, ...(ngDevMode ? [{ debugName: "nextOperatorOptions" }] : /* istanbul ignore next */ []));
|
|
999
1007
|
canAddNextSegment = computed(() => {
|
|
1000
1008
|
if (this.nextOperatorOptions().length === 0)
|
|
1001
1009
|
return false;
|
|
@@ -1004,10 +1012,10 @@ class FormulaBuilder {
|
|
|
1004
1012
|
return false;
|
|
1005
1013
|
}
|
|
1006
1014
|
return segments.every((segment) => !segment.requiresParameter || Boolean(segment.value));
|
|
1007
|
-
}, ...(ngDevMode ? [{ debugName: "canAddNextSegment" }] : []));
|
|
1015
|
+
}, ...(ngDevMode ? [{ debugName: "canAddNextSegment" }] : /* istanbul ignore next */ []));
|
|
1008
1016
|
propertiesComponent = computed(() => {
|
|
1009
1017
|
return this.builderContext()?.contextEntityTypeKey;
|
|
1010
|
-
}, ...(ngDevMode ? [{ debugName: "propertiesComponent" }] : []));
|
|
1018
|
+
}, ...(ngDevMode ? [{ debugName: "propertiesComponent" }] : /* istanbul ignore next */ []));
|
|
1011
1019
|
mergedPropertiesByPath = computed(() => {
|
|
1012
1020
|
const merged = {
|
|
1013
1021
|
...this.propertiesByPath(),
|
|
@@ -1019,11 +1027,11 @@ class FormulaBuilder {
|
|
|
1019
1027
|
}
|
|
1020
1028
|
});
|
|
1021
1029
|
return merged;
|
|
1022
|
-
}, ...(ngDevMode ? [{ debugName: "mergedPropertiesByPath" }] : []));
|
|
1030
|
+
}, ...(ngDevMode ? [{ debugName: "mergedPropertiesByPath" }] : /* istanbul ignore next */ []));
|
|
1023
1031
|
isPropertyLoading = computed(() => {
|
|
1024
1032
|
const path = this.resolvedTablePath();
|
|
1025
1033
|
return Boolean(path) && this.propertyLoadingPath() === path;
|
|
1026
|
-
}, ...(ngDevMode ? [{ debugName: "isPropertyLoading" }] : []));
|
|
1034
|
+
}, ...(ngDevMode ? [{ debugName: "isPropertyLoading" }] : /* istanbul ignore next */ []));
|
|
1027
1035
|
propertyOptions = computed(() => {
|
|
1028
1036
|
const path = this.resolvedTablePath();
|
|
1029
1037
|
if (!path)
|
|
@@ -1034,16 +1042,16 @@ class FormulaBuilder {
|
|
|
1034
1042
|
key: prop.key,
|
|
1035
1043
|
name: prop.name ?? prop.key,
|
|
1036
1044
|
}));
|
|
1037
|
-
}, ...(ngDevMode ? [{ debugName: "propertyOptions" }] : []));
|
|
1045
|
+
}, ...(ngDevMode ? [{ debugName: "propertyOptions" }] : /* istanbul ignore next */ []));
|
|
1038
1046
|
selectedProperty = computed(() => {
|
|
1039
1047
|
const key = this.propertyFieldKey();
|
|
1040
1048
|
return this.propertyOptions().find((prop) => prop.key === key) ?? null;
|
|
1041
|
-
}, ...(ngDevMode ? [{ debugName: "selectedProperty" }] : []));
|
|
1049
|
+
}, ...(ngDevMode ? [{ debugName: "selectedProperty" }] : /* istanbul ignore next */ []));
|
|
1042
1050
|
canInsertProperty = computed(() => {
|
|
1043
1051
|
if (!this.selectedProperty())
|
|
1044
1052
|
return false;
|
|
1045
1053
|
return Boolean(this.resolvedTablePath());
|
|
1046
|
-
}, ...(ngDevMode ? [{ debugName: "canInsertProperty" }] : []));
|
|
1054
|
+
}, ...(ngDevMode ? [{ debugName: "canInsertProperty" }] : /* istanbul ignore next */ []));
|
|
1047
1055
|
setPropertyScope(scope) {
|
|
1048
1056
|
if (this.propertyScope() === scope) {
|
|
1049
1057
|
return;
|
|
@@ -1103,16 +1111,16 @@ class FormulaBuilder {
|
|
|
1103
1111
|
}
|
|
1104
1112
|
return token;
|
|
1105
1113
|
}
|
|
1106
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
1107
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.
|
|
1114
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: FormulaBuilder, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1115
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: FormulaBuilder, isStandalone: true, selector: "mt-formula-builder", inputs: { propertiesByPath: { classPropertyName: "propertiesByPath", publicName: "propertiesByPath", isSignal: true, isRequired: false, transformFunction: null }, levelSchemaId: { classPropertyName: "levelSchemaId", publicName: "levelSchemaId", isSignal: true, isRequired: false, transformFunction: null }, moduleId: { classPropertyName: "moduleId", publicName: "moduleId", isSignal: true, isRequired: false, transformFunction: null }, contextEntityTypeKey: { classPropertyName: "contextEntityTypeKey", publicName: "contextEntityTypeKey", isSignal: true, isRequired: false, transformFunction: null }, templateId: { classPropertyName: "templateId", publicName: "templateId", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, hideToolbar: { classPropertyName: "hideToolbar", publicName: "hideToolbar", isSignal: true, isRequired: false, transformFunction: null }, hideStatusBar: { classPropertyName: "hideStatusBar", publicName: "hideStatusBar", isSignal: true, isRequired: false, transformFunction: null }, toolbarTabs: { classPropertyName: "toolbarTabs", publicName: "toolbarTabs", isSignal: true, isRequired: false, transformFunction: null }, codeOnly: { classPropertyName: "codeOnly", publicName: "codeOnly", isSignal: true, isRequired: false, transformFunction: null }, isProcessBuilder: { classPropertyName: "isProcessBuilder", publicName: "isProcessBuilder", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { validationChange: "validationChange", tokensChange: "tokensChange" }, host: { classAttribute: "block" }, providers: [
|
|
1108
1116
|
{
|
|
1109
1117
|
provide: NG_VALUE_ACCESSOR,
|
|
1110
1118
|
useExisting: forwardRef(() => FormulaBuilder),
|
|
1111
1119
|
multi: true,
|
|
1112
1120
|
},
|
|
1113
|
-
], viewQueries: [{ propertyName: "editor", first: true, predicate: ["formulaEditor"], descendants: true, isSignal: true }, { propertyName: "codeEditor", first: true, predicate: ["formulaEditorCode"], descendants: true, isSignal: true }], ngImport: i0, template: "<mt-card\r\n headless\r\n [class.ring-2]=\"hasFocus()\"\r\n [class.ring-primary]=\"hasFocus()\"\r\n [paddingless]=\"true\"\r\n>\r\n <div\r\n *transloco=\"let t; prefix: 'formulaBuilder'\"\r\n class=\"flex flex-col overflow-hidden\"\r\n >\r\n <!-- Toolbar - Pass data via inputs (pure component) -->\r\n @if (!hideToolbar()) {\r\n <mt-formula-toolbar\r\n [functionCategories]=\"functionCategories()\"\r\n [visibleTabs]=\"resolvedToolbarTabs()\"\r\n (onBlockInsert)=\"onBlockInsert($event)\"\r\n >\r\n <ng-template #properties let-insertBlock=\"insertBlock\">\r\n @if (isContextLoading()) {\r\n <div class=\"flex flex-col gap-4 p-4\">\r\n <div class=\"flex items-center justify-between gap-4\">\r\n <p-skeleton\r\n width=\"18rem\"\r\n height=\"2.5rem\"\r\n styleClass=\"rounded-md\"\r\n />\r\n <p-skeleton\r\n width=\"7rem\"\r\n height=\"2.5rem\"\r\n styleClass=\"rounded-md\"\r\n />\r\n </div>\r\n <div class=\"flex items-center gap-4\">\r\n <div\r\n class=\"flex min-h-11 min-w-0 flex-1 flex-col gap-2 rounded-lg bg-slate-50 px-3 py-2 dark:bg-slate-800/50\"\r\n >\r\n <div class=\"flex items-center gap-2\">\r\n <p-skeleton\r\n width=\"3rem\"\r\n height=\"1rem\"\r\n styleClass=\"rounded-md\"\r\n />\r\n <div\r\n class=\"h-4 w-px shrink-0 bg-slate-200 dark:bg-slate-700\"\r\n ></div>\r\n <p-skeleton\r\n class=\"flex-1\"\r\n height=\"2rem\"\r\n styleClass=\"rounded-md\"\r\n />\r\n </div>\r\n <div\r\n class=\"flex items-center gap-2 border-t border-slate-200 pt-2 dark:border-slate-700\"\r\n >\r\n <p-skeleton\r\n width=\"3rem\"\r\n height=\"1rem\"\r\n styleClass=\"rounded-md\"\r\n />\r\n <div\r\n class=\"h-4 w-px shrink-0 bg-slate-200 dark:bg-slate-700\"\r\n ></div>\r\n <p-skeleton\r\n class=\"flex-1\"\r\n height=\"2.5rem\"\r\n styleClass=\"rounded-md\"\r\n />\r\n </div>\r\n <p-skeleton height=\"2rem\" styleClass=\"rounded-md\" />\r\n </div>\r\n </div>\r\n </div>\r\n } @else {\r\n <div class=\"flex flex-col gap-4 p-4\">\r\n <!-- Scope Selection - Full width, centered -->\r\n <div class=\"flex items-center justify-between gap-4\">\r\n <mt-radio-cards\r\n [options]=\"scopeOptions()\"\r\n [activeId]=\"propertyScope()\"\r\n (selectionChange)=\"onScopeChange($event)\"\r\n size=\"small\"\r\n />\r\n </div>\r\n\r\n <!-- Path + Field + Preview Row -->\r\n <div class=\"flex items-center gap-4\">\r\n <!-- Path Container - Flexible -->\r\n <div\r\n class=\"flex min-h-11 min-w-0 flex-1 flex-col gap-2 rounded-lg bg-slate-50 px-3 py-2 dark:bg-slate-800/50\"\r\n >\r\n <div class=\"flex items-center gap-2\">\r\n <span\r\n class=\"shrink-0 text-xs font-semibold uppercase tracking-wider text-slate-400\"\r\n >{{ t(\"properties.path\") }}</span\r\n >\r\n <div\r\n class=\"h-4 w-px shrink-0 bg-slate-200 dark:bg-slate-700\"\r\n ></div>\r\n <div class=\"flex min-w-0 flex-1 items-center gap-2\">\r\n @if (isDirectAccess()) {\r\n <span\r\n class=\"rounded-md bg-emerald-100 px-2.5 py-1 text-xs font-medium text-emerald-600 dark:bg-emerald-900/30 dark:text-emerald-400\"\r\n >\r\n \u2713 {{ t(\"properties.direct-access\") }}\r\n </span>\r\n } @else if (pathSegments().length === 0) {\r\n <span class=\"text-xs italic text-slate-400\">{{\r\n t(\"properties.no-path-configured\")\r\n }}</span>\r\n } @else {\r\n <div\r\n class=\"flex min-w-0 flex-1 items-center gap-1.5 overflow-x-auto\"\r\n >\r\n @for (\r\n segment of pathSegments();\r\n track $index;\r\n let segmentIndex = $index\r\n ) {\r\n @if (segmentIndex > 0) {\r\n <span\r\n class=\"shrink-0 text-slate-300 dark:text-slate-600\"\r\n >\u203A</span\r\n >\r\n }\r\n <mt-button\r\n type=\"button\"\r\n [label]=\"\r\n segment.value ||\r\n t('properties.select') +\r\n ' ' +\r\n getOperatorDisplayName(segment.operatorToken)\r\n \"\r\n icon=\"arrow.chevron-down\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n [severity]=\"\r\n segment.value ? 'primary' : 'secondary'\r\n \"\r\n [iconPos]=\"'end'\"\r\n (onClick)=\"pathPopover.toggle($event)\"\r\n ></mt-button>\r\n\r\n <p-popover\r\n #pathPopover\r\n [style]=\"{ width: 'max-content' }\"\r\n appendTo=\"body\"\r\n >\r\n <div class=\"p-2\">\r\n <div\r\n class=\"mb-2 text-xs font-semibold uppercase text-slate-400\"\r\n >\r\n {{ t(\"properties.select\") }}\r\n {{\r\n getOperatorDisplayName(\r\n segment.operatorToken\r\n )\r\n }}\r\n </div>\r\n <div class=\"flex flex-col gap-1\">\r\n @for (\r\n option of segmentOptions(segmentIndex);\r\n track option.key\r\n ) {\r\n <mt-button\r\n type=\"button\"\r\n [label]=\"option.name\"\r\n [icon]=\"\r\n segment.value === option.key\r\n ? 'general.check'\r\n : 'general.minus'\r\n \"\r\n [iconPos]=\"'end'\"\r\n size=\"small\"\r\n severity=\"secondary\"\r\n [styleClass]=\"\r\n 'w-full justify-start rounded-md px-2.5 py-1.5 text-left text-xs font-medium transition-colors ' +\r\n (segment.value === option.key\r\n ? 'bg-primary text-white'\r\n : 'text-slate-600 hover:bg-slate-100 dark:text-slate-300 dark:hover:bg-slate-700')\r\n \"\r\n (onClick)=\"\r\n setPathSegmentValue(\r\n segmentIndex,\r\n option.key\r\n );\r\n pathPopover.hide()\r\n \"\r\n ></mt-button>\r\n }\r\n </div>\r\n @if (segment.optional) {\r\n <mt-button\r\n type=\"button\"\r\n [label]=\"t('actions.clear')\"\r\n [outlined]=\"true\"\r\n icon=\"general.x-close\"\r\n [iconPos]=\"'end'\"\r\n size=\"small\"\r\n severity=\"danger\"\r\n styleClass=\"mt-2 w-full rounded-md border border-slate-200 py-1 text-xs text-slate-400 hover:bg-slate-50 dark:border-slate-700\"\r\n (onClick)=\"\r\n setPathSegmentValue(segmentIndex, null);\r\n pathPopover.hide()\r\n \"\r\n ></mt-button>\r\n }\r\n </div>\r\n </p-popover>\r\n\r\n @if (\r\n segment.canRemove &&\r\n segmentIndex === pathSegments().length - 1\r\n ) {\r\n <mt-button\r\n type=\"button\"\r\n icon=\"general.x-close\"\r\n size=\"small\"\r\n severity=\"danger\"\r\n styleClass=\"flex size-5 shrink-0 items-center justify-center rounded-full bg-red-500 text-white hover:bg-red-600\"\r\n (onClick)=\"removePathSegment(segmentIndex)\"\r\n ></mt-button>\r\n }\r\n }\r\n <mt-button\r\n type=\"button\"\r\n icon=\"general.plus\"\r\n size=\"small\"\r\n severity=\"primary\"\r\n [disabled]=\"!canAddNextSegment()\"\r\n [class.hidden]=\"!canAddNextSegment()\"\r\n styleClass=\"flex size-6 shrink-0 items-center justify-center rounded-md bg-primary text-xs font-bold text-white hover:opacity-90 disabled:opacity-50\"\r\n (onClick)=\"nextOperatorPopover.toggle($event)\"\r\n ></mt-button>\r\n </div>\r\n }\r\n <p-popover\r\n #nextOperatorPopover\r\n [style]=\"{ width: 'max-content' }\"\r\n appendTo=\"body\"\r\n >\r\n <div class=\"p-2\">\r\n <div\r\n class=\"mb-2 text-xs font-semibold uppercase text-slate-400\"\r\n >\r\n {{ t(\"properties.add-segment\") }}\r\n </div>\r\n <div class=\"flex flex-col gap-1\">\r\n @for (\r\n option of nextOperatorOptions();\r\n track option.token\r\n ) {\r\n <mt-button\r\n type=\"button\"\r\n [label]=\"getOperatorDisplayName(option.token)\"\r\n icon=\"general.plus\"\r\n [iconPos]=\"'end'\"\r\n size=\"small\"\r\n severity=\"secondary\"\r\n styleClass=\"w-full justify-start rounded-md px-2.5 py-1.5 text-left text-xs font-medium transition-colors text-slate-600 hover:bg-slate-100 dark:text-slate-300 dark:hover:bg-slate-700\"\r\n (onClick)=\"\r\n onAddSegmentSelection(\r\n option.token,\r\n nextOperatorPopover\r\n )\r\n \"\r\n ></mt-button>\r\n }\r\n </div>\r\n </div>\r\n </p-popover>\r\n </div>\r\n </div>\r\n\r\n <!-- Field Selection - Under Path -->\r\n <div\r\n class=\"flex items-center gap-2 border-t border-slate-200 pt-2 dark:border-slate-700\"\r\n >\r\n <span\r\n class=\"shrink-0 text-xs font-semibold uppercase tracking-wider text-slate-400\"\r\n >{{ t(\"properties.field\") }}</span\r\n >\r\n <div\r\n class=\"h-4 w-px shrink-0 bg-slate-200 dark:bg-slate-700\"\r\n ></div>\r\n @if (isPropertyLoading()) {\r\n <p-skeleton\r\n class=\"flex-1\"\r\n height=\"2.5rem\"\r\n styleClass=\"rounded-md\"\r\n />\r\n } @else {\r\n <mt-select-field\r\n class=\"flex-1\"\r\n [label]=\"''\"\r\n [filter]=\"true\"\r\n [hasPlaceholderPrefix]=\"false\"\r\n [placeholder]=\"t('properties.select')\"\r\n [(ngModel)]=\"propertyFieldKey\"\r\n [options]=\"propertyOptions()\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n [size]=\"'small'\"\r\n />\r\n }\r\n </div>\r\n <div\r\n class=\"w-full truncate rounded-lg bg-amber-100 px-3 py-2 text-sm font-semibold text-amber-700 shadow-sm hover:bg-amber-200 dark:bg-amber-900/30 dark:text-amber-300 dark:hover:bg-amber-900/50\"\r\n [mtTooltip]=\"\r\n '@' +\r\n propertyTablePath() +\r\n '::' +\r\n (selectedProperty()?.key ?? '...')\r\n \"\r\n tooltipPosition=\"top\"\r\n >\r\n @{{ propertyTablePath() }}::{{\r\n selectedProperty()?.key ?? \"...\"\r\n }}\r\n </div>\r\n <div class=\"flex justify-end\">\r\n <mt-button\r\n type=\"button\"\r\n [label]=\"t('actions.insert')\"\r\n icon=\"general.plus\"\r\n severity=\"primary\"\r\n [disabled]=\"!canInsertProperty()\"\r\n (onClick)=\"insertSelectedProperty(insertBlock)\"\r\n ></mt-button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </ng-template>\r\n </mt-formula-toolbar>\r\n }\r\n\r\n <!-- Editor Area -->\r\n <div class=\"p-3\">\r\n <div\r\n class=\"overflow-hidden rounded-lg border border-surface-200 bg-white dark:border-surface-700 dark:bg-surface-800\"\r\n >\r\n @if (showModeToggle()) {\r\n <div\r\n class=\"flex items-center justify-end border-b border-surface-200 px-3 py-2 dark:border-surface-700\"\r\n >\r\n <mt-toggle-field\r\n [label]=\"t('codeMode')\"\r\n labelPosition=\"end\"\r\n size=\"small\"\r\n [ngModel]=\"isCodeMode()\"\r\n [readonly]=\"isCodeModeLocked()\"\r\n [pInputs]=\"{ disabled: isCodeModeLocked() }\"\r\n (ngModelChange)=\"onModeToggle($event)\"\r\n />\r\n </div>\r\n }\r\n <div class=\"p-0\">\r\n @if (isCodeMode()) {\r\n <mt-formula-editor-code\r\n #formulaEditorCode\r\n [placeholder]=\"placeholder() || t('placeholder')\"\r\n [initialFormula]=\"expression()\"\r\n [borderless]=\"true\"\r\n [autocompleteProvider]=\"autocompleteProvider\"\r\n (formulaChange)=\"onCodeFormulaChange($event)\"\r\n (onFocus)=\"onEditorFocus()\"\r\n (onBlur)=\"onEditorBlur()\"\r\n />\r\n } @else {\r\n <mt-formula-editor\r\n #formulaEditor\r\n [placeholder]=\"placeholder() || t('placeholder')\"\r\n [initialTokens]=\"tokens()\"\r\n [borderless]=\"true\"\r\n (formulaChange)=\"onFormulaChange($event)\"\r\n (tokensChange)=\"onTokensChange($event)\"\r\n (onFocus)=\"onEditorFocus()\"\r\n (onBlur)=\"onEditorBlur()\"\r\n />\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Status Bar - Pass data via inputs (pure component) -->\r\n @if (!hideStatusBar()) {\r\n <mt-formula-status-bar [validation]=\"validation()\" />\r\n }\r\n </div>\r\n</mt-card>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: SelectField, selector: "mt-select-field", inputs: ["field", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], outputs: ["onChange"] }, { kind: "directive", type: Tooltip, selector: "[mtTooltip]" }, { kind: "component", type: RadioCards, selector: "mt-radio-cards", inputs: ["circle", "color", "size", "columns", "options", "activeId", "itemTemplate"], outputs: ["optionsChange", "activeIdChange", "selectionChange"] }, { kind: "component", type: ToggleField, selector: "mt-toggle-field", inputs: ["label", "inputId", "labelPosition", "placeholder", "readonly", "pInputs", "required", "toggleShape", "size", "icon", "descriptionCard"], outputs: ["onChange"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "component", type: i2.Popover, selector: "p-popover", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions", "motionOptions"], outputs: ["onShow", "onHide"] }, { kind: "component", type: Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "component", type: FormulaToolbar, selector: "mt-formula-toolbar", inputs: ["knownProperties", "propertiesTemplate", "functionCategories", "operators", "initialTab", "visibleTabs", "searchPlaceholder", "labels"], outputs: ["onBlockInsert", "onTabChange"] }, { kind: "component", type: FormulaStatusBar, selector: "mt-formula-status-bar", inputs: ["validation", "labels"] }, { kind: "component", type: FormulaEditor, selector: "mt-formula-editor", inputs: ["placeholder", "initialTokens", "disabled", "borderless"], outputs: ["formulaChange", "tokensChange", "onBlur", "onFocus"] }, { kind: "component", type: FormulaEditorCode, selector: "mt-formula-editor-code", inputs: ["placeholder", "initialFormula", "disabled", "language", "theme", "borderless", "autocompleteProvider", "autocompleteDebounceMs"], outputs: ["formulaChange", "onBlur", "onFocus"] }] });
|
|
1121
|
+
], viewQueries: [{ propertyName: "editor", first: true, predicate: ["formulaEditor"], descendants: true, isSignal: true }, { propertyName: "codeEditor", first: true, predicate: ["formulaEditorCode"], descendants: true, isSignal: true }], ngImport: i0, template: "<mt-card\r\n headless\r\n [class.ring-2]=\"hasFocus()\"\r\n [class.ring-primary]=\"hasFocus()\"\r\n [paddingless]=\"true\"\r\n>\r\n <div\r\n *transloco=\"let t; prefix: 'formulaBuilder'\"\r\n class=\"flex flex-col overflow-hidden\"\r\n >\r\n <!-- Toolbar - Pass data via inputs (pure component) -->\r\n @if (!hideToolbar()) {\r\n <mt-formula-toolbar\r\n [functionCategories]=\"functionCategories()\"\r\n [visibleTabs]=\"resolvedToolbarTabs()\"\r\n (onBlockInsert)=\"onBlockInsert($event)\"\r\n >\r\n <ng-template #properties let-insertBlock=\"insertBlock\">\r\n @if (isContextLoading()) {\r\n <div class=\"flex flex-col gap-4 p-4\">\r\n <div class=\"flex items-center justify-between gap-4\">\r\n <p-skeleton\r\n width=\"18rem\"\r\n height=\"2.5rem\"\r\n styleClass=\"rounded-md\"\r\n />\r\n <p-skeleton\r\n width=\"7rem\"\r\n height=\"2.5rem\"\r\n styleClass=\"rounded-md\"\r\n />\r\n </div>\r\n <div class=\"flex items-center gap-4\">\r\n <div\r\n class=\"flex min-h-11 min-w-0 flex-1 flex-col gap-2 rounded-lg bg-slate-50 px-3 py-2 dark:bg-slate-800/50\"\r\n >\r\n <div class=\"flex items-center gap-2\">\r\n <p-skeleton\r\n width=\"3rem\"\r\n height=\"1rem\"\r\n styleClass=\"rounded-md\"\r\n />\r\n <div\r\n class=\"h-4 w-px shrink-0 bg-slate-200 dark:bg-slate-700\"\r\n ></div>\r\n <p-skeleton\r\n class=\"flex-1\"\r\n height=\"2rem\"\r\n styleClass=\"rounded-md\"\r\n />\r\n </div>\r\n <div\r\n class=\"flex items-center gap-2 border-t border-slate-200 pt-2 dark:border-slate-700\"\r\n >\r\n <p-skeleton\r\n width=\"3rem\"\r\n height=\"1rem\"\r\n styleClass=\"rounded-md\"\r\n />\r\n <div\r\n class=\"h-4 w-px shrink-0 bg-slate-200 dark:bg-slate-700\"\r\n ></div>\r\n <p-skeleton\r\n class=\"flex-1\"\r\n height=\"2.5rem\"\r\n styleClass=\"rounded-md\"\r\n />\r\n </div>\r\n <p-skeleton height=\"2rem\" styleClass=\"rounded-md\" />\r\n </div>\r\n </div>\r\n </div>\r\n } @else {\r\n <div class=\"flex flex-col gap-4 p-4\">\r\n <!-- Scope Selection - Full width, centered -->\r\n <div class=\"flex items-center justify-between gap-4\">\r\n <mt-radio-cards\r\n [options]=\"scopeOptions()\"\r\n [activeId]=\"propertyScope()\"\r\n (selectionChange)=\"onScopeChange($event)\"\r\n size=\"small\"\r\n />\r\n </div>\r\n\r\n <!-- Path + Field + Preview Row -->\r\n <div class=\"flex items-center gap-4\">\r\n <!-- Path Container - Flexible -->\r\n <div\r\n class=\"flex min-h-11 min-w-0 flex-1 flex-col gap-2 rounded-lg bg-slate-50 px-3 py-2 dark:bg-slate-800/50\"\r\n >\r\n <div class=\"flex items-center gap-2\">\r\n <span\r\n class=\"shrink-0 text-xs font-semibold uppercase tracking-wider text-slate-400\"\r\n >{{ t(\"properties.path\") }}</span\r\n >\r\n <div\r\n class=\"h-4 w-px shrink-0 bg-slate-200 dark:bg-slate-700\"\r\n ></div>\r\n <div class=\"flex min-w-0 flex-1 items-center gap-2\">\r\n @if (isDirectAccess()) {\r\n <span\r\n class=\"rounded-md bg-emerald-100 px-2.5 py-1 text-xs font-medium text-emerald-600 dark:bg-emerald-900/30 dark:text-emerald-400\"\r\n >\r\n \u2713 {{ t(\"properties.direct-access\") }}\r\n </span>\r\n } @else if (pathSegments().length === 0) {\r\n <span class=\"text-xs italic text-slate-400\">{{\r\n t(\"properties.no-path-configured\")\r\n }}</span>\r\n } @else {\r\n <div\r\n class=\"flex min-w-0 flex-1 items-center gap-1.5 overflow-x-auto\"\r\n >\r\n @for (\r\n segment of pathSegments();\r\n track $index;\r\n let segmentIndex = $index\r\n ) {\r\n @if (segmentIndex > 0) {\r\n <span\r\n class=\"shrink-0 text-slate-300 dark:text-slate-600\"\r\n >\u203A</span\r\n >\r\n }\r\n <mt-button\r\n type=\"button\"\r\n [label]=\"\r\n segment.value ||\r\n t('properties.select') +\r\n ' ' +\r\n getOperatorDisplayName(segment.operatorToken)\r\n \"\r\n icon=\"arrow.chevron-down\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n [severity]=\"\r\n segment.value ? 'primary' : 'secondary'\r\n \"\r\n [iconPos]=\"'end'\"\r\n (onClick)=\"pathPopover.toggle($event)\"\r\n ></mt-button>\r\n\r\n <p-popover\r\n #pathPopover\r\n [style]=\"{ width: 'max-content' }\"\r\n appendTo=\"body\"\r\n >\r\n <div class=\"p-2\">\r\n <div\r\n class=\"mb-2 text-xs font-semibold uppercase text-slate-400\"\r\n >\r\n {{ t(\"properties.select\") }}\r\n {{\r\n getOperatorDisplayName(\r\n segment.operatorToken\r\n )\r\n }}\r\n </div>\r\n <div\r\n class=\"flex max-h-[min(24rem,calc(100vh-10rem))] flex-col gap-1 overflow-y-auto pr-1\"\r\n >\r\n @for (\r\n option of segmentOptions(segmentIndex);\r\n track option.key\r\n ) {\r\n <mt-button\r\n type=\"button\"\r\n [label]=\"option.name\"\r\n [icon]=\"\r\n segment.value === option.key\r\n ? 'general.check'\r\n : 'general.minus'\r\n \"\r\n [iconPos]=\"'end'\"\r\n size=\"small\"\r\n severity=\"secondary\"\r\n [styleClass]=\"\r\n 'w-full justify-start rounded-md px-2.5 py-1.5 text-left text-xs font-medium transition-colors ' +\r\n (segment.value === option.key\r\n ? 'bg-primary text-white'\r\n : 'text-slate-600 hover:bg-slate-100 dark:text-slate-300 dark:hover:bg-slate-700')\r\n \"\r\n (onClick)=\"\r\n setPathSegmentValue(\r\n segmentIndex,\r\n option.key\r\n );\r\n pathPopover.hide()\r\n \"\r\n ></mt-button>\r\n }\r\n </div>\r\n @if (segment.optional) {\r\n <mt-button\r\n type=\"button\"\r\n [label]=\"t('actions.clear')\"\r\n [outlined]=\"true\"\r\n icon=\"general.x-close\"\r\n [iconPos]=\"'end'\"\r\n size=\"small\"\r\n severity=\"danger\"\r\n styleClass=\"mt-2 w-full rounded-md border border-slate-200 py-1 text-xs text-slate-400 hover:bg-slate-50 dark:border-slate-700\"\r\n (onClick)=\"\r\n setPathSegmentValue(segmentIndex, null);\r\n pathPopover.hide()\r\n \"\r\n ></mt-button>\r\n }\r\n </div>\r\n </p-popover>\r\n\r\n @if (\r\n segment.canRemove &&\r\n segmentIndex === pathSegments().length - 1\r\n ) {\r\n <mt-button\r\n type=\"button\"\r\n icon=\"general.x-close\"\r\n size=\"small\"\r\n severity=\"danger\"\r\n styleClass=\"flex size-5 shrink-0 items-center justify-center rounded-full bg-red-500 text-white hover:bg-red-600\"\r\n (onClick)=\"removePathSegment(segmentIndex)\"\r\n ></mt-button>\r\n }\r\n }\r\n <mt-button\r\n type=\"button\"\r\n icon=\"general.plus\"\r\n size=\"small\"\r\n severity=\"primary\"\r\n [disabled]=\"!canAddNextSegment()\"\r\n [class.hidden]=\"!canAddNextSegment()\"\r\n styleClass=\"flex size-6 shrink-0 items-center justify-center rounded-md bg-primary text-xs font-bold text-white hover:opacity-90 disabled:opacity-50\"\r\n (onClick)=\"nextOperatorPopover.toggle($event)\"\r\n ></mt-button>\r\n </div>\r\n }\r\n <p-popover\r\n #nextOperatorPopover\r\n [style]=\"{ width: 'max-content' }\"\r\n appendTo=\"body\"\r\n >\r\n <div class=\"p-2\">\r\n <div\r\n class=\"mb-2 text-xs font-semibold uppercase text-slate-400\"\r\n >\r\n {{ t(\"properties.add-segment\") }}\r\n </div>\r\n <div\r\n class=\"flex max-h-[min(24rem,calc(100vh-10rem))] flex-col gap-1 overflow-y-auto pr-1\"\r\n >\r\n @for (\r\n option of nextOperatorOptions();\r\n track option.token\r\n ) {\r\n <mt-button\r\n type=\"button\"\r\n [label]=\"getOperatorDisplayName(option.token)\"\r\n icon=\"general.plus\"\r\n [iconPos]=\"'end'\"\r\n size=\"small\"\r\n severity=\"secondary\"\r\n styleClass=\"w-full justify-start rounded-md px-2.5 py-1.5 text-left text-xs font-medium transition-colors text-slate-600 hover:bg-slate-100 dark:text-slate-300 dark:hover:bg-slate-700\"\r\n (onClick)=\"\r\n onAddSegmentSelection(\r\n option.token,\r\n nextOperatorPopover\r\n )\r\n \"\r\n ></mt-button>\r\n }\r\n </div>\r\n </div>\r\n </p-popover>\r\n </div>\r\n </div>\r\n\r\n <!-- Field Selection - Under Path -->\r\n <div\r\n class=\"flex items-center gap-2 border-t border-slate-200 pt-2 dark:border-slate-700\"\r\n >\r\n <span\r\n class=\"shrink-0 text-xs font-semibold uppercase tracking-wider text-slate-400\"\r\n >{{ t(\"properties.field\") }}</span\r\n >\r\n <div\r\n class=\"h-4 w-px shrink-0 bg-slate-200 dark:bg-slate-700\"\r\n ></div>\r\n @if (isPropertyLoading()) {\r\n <p-skeleton\r\n class=\"flex-1\"\r\n height=\"2.5rem\"\r\n styleClass=\"rounded-md\"\r\n />\r\n } @else {\r\n <mt-select-field\r\n class=\"flex-1\"\r\n [label]=\"''\"\r\n [filter]=\"true\"\r\n [hasPlaceholderPrefix]=\"false\"\r\n [placeholder]=\"t('properties.select')\"\r\n [(ngModel)]=\"propertyFieldKey\"\r\n [options]=\"propertyOptions()\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n [size]=\"'small'\"\r\n />\r\n }\r\n </div>\r\n <div\r\n class=\"w-full truncate rounded-lg bg-amber-100 px-3 py-2 text-sm font-semibold text-amber-700 shadow-sm hover:bg-amber-200 dark:bg-amber-900/30 dark:text-amber-300 dark:hover:bg-amber-900/50\"\r\n [mtTooltip]=\"\r\n '@' +\r\n propertyTablePath() +\r\n '::' +\r\n (selectedProperty()?.key ?? '...')\r\n \"\r\n tooltipPosition=\"top\"\r\n >\r\n @{{ propertyTablePath() }}::{{\r\n selectedProperty()?.key ?? \"...\"\r\n }}\r\n </div>\r\n <div class=\"flex justify-end\">\r\n <mt-button\r\n type=\"button\"\r\n [label]=\"t('actions.insert')\"\r\n icon=\"general.plus\"\r\n severity=\"primary\"\r\n [disabled]=\"!canInsertProperty()\"\r\n (onClick)=\"insertSelectedProperty(insertBlock)\"\r\n ></mt-button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </ng-template>\r\n </mt-formula-toolbar>\r\n }\r\n\r\n <!-- Editor Area -->\r\n <div class=\"p-3\">\r\n <div\r\n class=\"overflow-hidden rounded-lg border border-surface-200 bg-white dark:border-surface-700 dark:bg-surface-800\"\r\n >\r\n @if (showModeToggle()) {\r\n <div\r\n class=\"flex items-center justify-end border-b border-surface-200 px-3 py-2 dark:border-surface-700\"\r\n >\r\n <mt-toggle-field\r\n [label]=\"t('codeMode')\"\r\n labelPosition=\"end\"\r\n size=\"small\"\r\n [ngModel]=\"isCodeMode()\"\r\n [readonly]=\"isCodeModeLocked()\"\r\n [pInputs]=\"{ disabled: isCodeModeLocked() }\"\r\n (ngModelChange)=\"onModeToggle($event)\"\r\n />\r\n </div>\r\n }\r\n <div class=\"p-0\">\r\n @if (isCodeMode()) {\r\n <mt-formula-editor-code\r\n #formulaEditorCode\r\n [placeholder]=\"placeholder() || t('placeholder')\"\r\n [initialFormula]=\"expression()\"\r\n [borderless]=\"true\"\r\n [autocompleteProvider]=\"autocompleteProvider\"\r\n (formulaChange)=\"onCodeFormulaChange($event)\"\r\n (onFocus)=\"onEditorFocus()\"\r\n (onBlur)=\"onEditorBlur()\"\r\n />\r\n } @else {\r\n <mt-formula-editor\r\n #formulaEditor\r\n [placeholder]=\"placeholder() || t('placeholder')\"\r\n [initialTokens]=\"tokens()\"\r\n [borderless]=\"true\"\r\n (formulaChange)=\"onFormulaChange($event)\"\r\n (tokensChange)=\"onTokensChange($event)\"\r\n (onFocus)=\"onEditorFocus()\"\r\n (onBlur)=\"onEditorBlur()\"\r\n />\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Status Bar - Pass data via inputs (pure component) -->\r\n @if (!hideStatusBar()) {\r\n <mt-formula-status-bar [validation]=\"validation()\" />\r\n }\r\n </div>\r\n</mt-card>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: Card, selector: "mt-card", inputs: ["class", "title", "paddingless"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: SelectField, selector: "mt-select-field", inputs: ["field", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape"], outputs: ["onChange"] }, { kind: "directive", type: Tooltip, selector: "[mtTooltip]" }, { kind: "component", type: RadioCards, selector: "mt-radio-cards", inputs: ["circle", "color", "size", "columns", "options", "activeId", "itemTemplate"], outputs: ["optionsChange", "activeIdChange", "selectionChange"] }, { kind: "component", type: ToggleField, selector: "mt-toggle-field", inputs: ["label", "inputId", "labelPosition", "placeholder", "readonly", "pInputs", "required", "toggleShape", "size", "icon", "descriptionCard"], outputs: ["onChange"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "component", type: i2.Popover, selector: "p-popover", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions", "motionOptions"], outputs: ["onShow", "onHide"] }, { kind: "component", type: Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "component", type: FormulaToolbar, selector: "mt-formula-toolbar", inputs: ["knownProperties", "propertiesTemplate", "functionCategories", "operators", "initialTab", "visibleTabs", "searchPlaceholder", "labels"], outputs: ["onBlockInsert", "onTabChange"] }, { kind: "component", type: FormulaStatusBar, selector: "mt-formula-status-bar", inputs: ["validation", "labels"] }, { kind: "component", type: FormulaEditor, selector: "mt-formula-editor", inputs: ["placeholder", "initialTokens", "disabled", "borderless"], outputs: ["formulaChange", "tokensChange", "onBlur", "onFocus"] }, { kind: "component", type: FormulaEditorCode, selector: "mt-formula-editor-code", inputs: ["placeholder", "initialFormula", "disabled", "language", "theme", "borderless", "autocompleteProvider", "autocompleteDebounceMs"], outputs: ["formulaChange", "onBlur", "onFocus"] }] });
|
|
1114
1122
|
}
|
|
1115
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
1123
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: FormulaBuilder, decorators: [{
|
|
1116
1124
|
type: Component,
|
|
1117
1125
|
args: [{ selector: 'mt-formula-builder', standalone: true, imports: [
|
|
1118
1126
|
CommonModule,
|
|
@@ -1138,7 +1146,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
|
|
|
1138
1146
|
useExisting: forwardRef(() => FormulaBuilder),
|
|
1139
1147
|
multi: true,
|
|
1140
1148
|
},
|
|
1141
|
-
], template: "<mt-card\r\n headless\r\n [class.ring-2]=\"hasFocus()\"\r\n [class.ring-primary]=\"hasFocus()\"\r\n [paddingless]=\"true\"\r\n>\r\n <div\r\n *transloco=\"let t; prefix: 'formulaBuilder'\"\r\n class=\"flex flex-col overflow-hidden\"\r\n >\r\n <!-- Toolbar - Pass data via inputs (pure component) -->\r\n @if (!hideToolbar()) {\r\n <mt-formula-toolbar\r\n [functionCategories]=\"functionCategories()\"\r\n [visibleTabs]=\"resolvedToolbarTabs()\"\r\n (onBlockInsert)=\"onBlockInsert($event)\"\r\n >\r\n <ng-template #properties let-insertBlock=\"insertBlock\">\r\n @if (isContextLoading()) {\r\n <div class=\"flex flex-col gap-4 p-4\">\r\n <div class=\"flex items-center justify-between gap-4\">\r\n <p-skeleton\r\n width=\"18rem\"\r\n height=\"2.5rem\"\r\n styleClass=\"rounded-md\"\r\n />\r\n <p-skeleton\r\n width=\"7rem\"\r\n height=\"2.5rem\"\r\n styleClass=\"rounded-md\"\r\n />\r\n </div>\r\n <div class=\"flex items-center gap-4\">\r\n <div\r\n class=\"flex min-h-11 min-w-0 flex-1 flex-col gap-2 rounded-lg bg-slate-50 px-3 py-2 dark:bg-slate-800/50\"\r\n >\r\n <div class=\"flex items-center gap-2\">\r\n <p-skeleton\r\n width=\"3rem\"\r\n height=\"1rem\"\r\n styleClass=\"rounded-md\"\r\n />\r\n <div\r\n class=\"h-4 w-px shrink-0 bg-slate-200 dark:bg-slate-700\"\r\n ></div>\r\n <p-skeleton\r\n class=\"flex-1\"\r\n height=\"2rem\"\r\n styleClass=\"rounded-md\"\r\n />\r\n </div>\r\n <div\r\n class=\"flex items-center gap-2 border-t border-slate-200 pt-2 dark:border-slate-700\"\r\n >\r\n <p-skeleton\r\n width=\"3rem\"\r\n height=\"1rem\"\r\n styleClass=\"rounded-md\"\r\n />\r\n <div\r\n class=\"h-4 w-px shrink-0 bg-slate-200 dark:bg-slate-700\"\r\n ></div>\r\n <p-skeleton\r\n class=\"flex-1\"\r\n height=\"2.5rem\"\r\n styleClass=\"rounded-md\"\r\n />\r\n </div>\r\n <p-skeleton height=\"2rem\" styleClass=\"rounded-md\" />\r\n </div>\r\n </div>\r\n </div>\r\n } @else {\r\n <div class=\"flex flex-col gap-4 p-4\">\r\n <!-- Scope Selection - Full width, centered -->\r\n <div class=\"flex items-center justify-between gap-4\">\r\n <mt-radio-cards\r\n [options]=\"scopeOptions()\"\r\n [activeId]=\"propertyScope()\"\r\n (selectionChange)=\"onScopeChange($event)\"\r\n size=\"small\"\r\n />\r\n </div>\r\n\r\n <!-- Path + Field + Preview Row -->\r\n <div class=\"flex items-center gap-4\">\r\n <!-- Path Container - Flexible -->\r\n <div\r\n class=\"flex min-h-11 min-w-0 flex-1 flex-col gap-2 rounded-lg bg-slate-50 px-3 py-2 dark:bg-slate-800/50\"\r\n >\r\n <div class=\"flex items-center gap-2\">\r\n <span\r\n class=\"shrink-0 text-xs font-semibold uppercase tracking-wider text-slate-400\"\r\n >{{ t(\"properties.path\") }}</span\r\n >\r\n <div\r\n class=\"h-4 w-px shrink-0 bg-slate-200 dark:bg-slate-700\"\r\n ></div>\r\n <div class=\"flex min-w-0 flex-1 items-center gap-2\">\r\n @if (isDirectAccess()) {\r\n <span\r\n class=\"rounded-md bg-emerald-100 px-2.5 py-1 text-xs font-medium text-emerald-600 dark:bg-emerald-900/30 dark:text-emerald-400\"\r\n >\r\n \u2713 {{ t(\"properties.direct-access\") }}\r\n </span>\r\n } @else if (pathSegments().length === 0) {\r\n <span class=\"text-xs italic text-slate-400\">{{\r\n t(\"properties.no-path-configured\")\r\n }}</span>\r\n } @else {\r\n <div\r\n class=\"flex min-w-0 flex-1 items-center gap-1.5 overflow-x-auto\"\r\n >\r\n @for (\r\n segment of pathSegments();\r\n track $index;\r\n let segmentIndex = $index\r\n ) {\r\n @if (segmentIndex > 0) {\r\n <span\r\n class=\"shrink-0 text-slate-300 dark:text-slate-600\"\r\n >\u203A</span\r\n >\r\n }\r\n <mt-button\r\n type=\"button\"\r\n [label]=\"\r\n segment.value ||\r\n t('properties.select') +\r\n ' ' +\r\n getOperatorDisplayName(segment.operatorToken)\r\n \"\r\n icon=\"arrow.chevron-down\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n [severity]=\"\r\n segment.value ? 'primary' : 'secondary'\r\n \"\r\n [iconPos]=\"'end'\"\r\n (onClick)=\"pathPopover.toggle($event)\"\r\n ></mt-button>\r\n\r\n <p-popover\r\n #pathPopover\r\n [style]=\"{ width: 'max-content' }\"\r\n appendTo=\"body\"\r\n >\r\n <div class=\"p-2\">\r\n <div\r\n class=\"mb-2 text-xs font-semibold uppercase text-slate-400\"\r\n >\r\n {{ t(\"properties.select\") }}\r\n {{\r\n getOperatorDisplayName(\r\n segment.operatorToken\r\n )\r\n }}\r\n </div>\r\n <div class=\"flex flex-col gap-1\">\r\n @for (\r\n option of segmentOptions(segmentIndex);\r\n track option.key\r\n ) {\r\n <mt-button\r\n type=\"button\"\r\n [label]=\"option.name\"\r\n [icon]=\"\r\n segment.value === option.key\r\n ? 'general.check'\r\n : 'general.minus'\r\n \"\r\n [iconPos]=\"'end'\"\r\n size=\"small\"\r\n severity=\"secondary\"\r\n [styleClass]=\"\r\n 'w-full justify-start rounded-md px-2.5 py-1.5 text-left text-xs font-medium transition-colors ' +\r\n (segment.value === option.key\r\n ? 'bg-primary text-white'\r\n : 'text-slate-600 hover:bg-slate-100 dark:text-slate-300 dark:hover:bg-slate-700')\r\n \"\r\n (onClick)=\"\r\n setPathSegmentValue(\r\n segmentIndex,\r\n option.key\r\n );\r\n pathPopover.hide()\r\n \"\r\n ></mt-button>\r\n }\r\n </div>\r\n @if (segment.optional) {\r\n <mt-button\r\n type=\"button\"\r\n [label]=\"t('actions.clear')\"\r\n [outlined]=\"true\"\r\n icon=\"general.x-close\"\r\n [iconPos]=\"'end'\"\r\n size=\"small\"\r\n severity=\"danger\"\r\n styleClass=\"mt-2 w-full rounded-md border border-slate-200 py-1 text-xs text-slate-400 hover:bg-slate-50 dark:border-slate-700\"\r\n (onClick)=\"\r\n setPathSegmentValue(segmentIndex, null);\r\n pathPopover.hide()\r\n \"\r\n ></mt-button>\r\n }\r\n </div>\r\n </p-popover>\r\n\r\n @if (\r\n segment.canRemove &&\r\n segmentIndex === pathSegments().length - 1\r\n ) {\r\n <mt-button\r\n type=\"button\"\r\n icon=\"general.x-close\"\r\n size=\"small\"\r\n severity=\"danger\"\r\n styleClass=\"flex size-5 shrink-0 items-center justify-center rounded-full bg-red-500 text-white hover:bg-red-600\"\r\n (onClick)=\"removePathSegment(segmentIndex)\"\r\n ></mt-button>\r\n }\r\n }\r\n <mt-button\r\n type=\"button\"\r\n icon=\"general.plus\"\r\n size=\"small\"\r\n severity=\"primary\"\r\n [disabled]=\"!canAddNextSegment()\"\r\n [class.hidden]=\"!canAddNextSegment()\"\r\n styleClass=\"flex size-6 shrink-0 items-center justify-center rounded-md bg-primary text-xs font-bold text-white hover:opacity-90 disabled:opacity-50\"\r\n (onClick)=\"nextOperatorPopover.toggle($event)\"\r\n ></mt-button>\r\n </div>\r\n }\r\n <p-popover\r\n #nextOperatorPopover\r\n [style]=\"{ width: 'max-content' }\"\r\n appendTo=\"body\"\r\n >\r\n <div class=\"p-2\">\r\n <div\r\n class=\"mb-2 text-xs font-semibold uppercase text-slate-400\"\r\n >\r\n {{ t(\"properties.add-segment\") }}\r\n </div>\r\n <div class=\"flex flex-col gap-1\">\r\n @for (\r\n option of nextOperatorOptions();\r\n track option.token\r\n ) {\r\n <mt-button\r\n type=\"button\"\r\n [label]=\"getOperatorDisplayName(option.token)\"\r\n icon=\"general.plus\"\r\n [iconPos]=\"'end'\"\r\n size=\"small\"\r\n severity=\"secondary\"\r\n styleClass=\"w-full justify-start rounded-md px-2.5 py-1.5 text-left text-xs font-medium transition-colors text-slate-600 hover:bg-slate-100 dark:text-slate-300 dark:hover:bg-slate-700\"\r\n (onClick)=\"\r\n onAddSegmentSelection(\r\n option.token,\r\n nextOperatorPopover\r\n )\r\n \"\r\n ></mt-button>\r\n }\r\n </div>\r\n </div>\r\n </p-popover>\r\n </div>\r\n </div>\r\n\r\n <!-- Field Selection - Under Path -->\r\n <div\r\n class=\"flex items-center gap-2 border-t border-slate-200 pt-2 dark:border-slate-700\"\r\n >\r\n <span\r\n class=\"shrink-0 text-xs font-semibold uppercase tracking-wider text-slate-400\"\r\n >{{ t(\"properties.field\") }}</span\r\n >\r\n <div\r\n class=\"h-4 w-px shrink-0 bg-slate-200 dark:bg-slate-700\"\r\n ></div>\r\n @if (isPropertyLoading()) {\r\n <p-skeleton\r\n class=\"flex-1\"\r\n height=\"2.5rem\"\r\n styleClass=\"rounded-md\"\r\n />\r\n } @else {\r\n <mt-select-field\r\n class=\"flex-1\"\r\n [label]=\"''\"\r\n [filter]=\"true\"\r\n [hasPlaceholderPrefix]=\"false\"\r\n [placeholder]=\"t('properties.select')\"\r\n [(ngModel)]=\"propertyFieldKey\"\r\n [options]=\"propertyOptions()\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n [size]=\"'small'\"\r\n />\r\n }\r\n </div>\r\n <div\r\n class=\"w-full truncate rounded-lg bg-amber-100 px-3 py-2 text-sm font-semibold text-amber-700 shadow-sm hover:bg-amber-200 dark:bg-amber-900/30 dark:text-amber-300 dark:hover:bg-amber-900/50\"\r\n [mtTooltip]=\"\r\n '@' +\r\n propertyTablePath() +\r\n '::' +\r\n (selectedProperty()?.key ?? '...')\r\n \"\r\n tooltipPosition=\"top\"\r\n >\r\n @{{ propertyTablePath() }}::{{\r\n selectedProperty()?.key ?? \"...\"\r\n }}\r\n </div>\r\n <div class=\"flex justify-end\">\r\n <mt-button\r\n type=\"button\"\r\n [label]=\"t('actions.insert')\"\r\n icon=\"general.plus\"\r\n severity=\"primary\"\r\n [disabled]=\"!canInsertProperty()\"\r\n (onClick)=\"insertSelectedProperty(insertBlock)\"\r\n ></mt-button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </ng-template>\r\n </mt-formula-toolbar>\r\n }\r\n\r\n <!-- Editor Area -->\r\n <div class=\"p-3\">\r\n <div\r\n class=\"overflow-hidden rounded-lg border border-surface-200 bg-white dark:border-surface-700 dark:bg-surface-800\"\r\n >\r\n @if (showModeToggle()) {\r\n <div\r\n class=\"flex items-center justify-end border-b border-surface-200 px-3 py-2 dark:border-surface-700\"\r\n >\r\n <mt-toggle-field\r\n [label]=\"t('codeMode')\"\r\n labelPosition=\"end\"\r\n size=\"small\"\r\n [ngModel]=\"isCodeMode()\"\r\n [readonly]=\"isCodeModeLocked()\"\r\n [pInputs]=\"{ disabled: isCodeModeLocked() }\"\r\n (ngModelChange)=\"onModeToggle($event)\"\r\n />\r\n </div>\r\n }\r\n <div class=\"p-0\">\r\n @if (isCodeMode()) {\r\n <mt-formula-editor-code\r\n #formulaEditorCode\r\n [placeholder]=\"placeholder() || t('placeholder')\"\r\n [initialFormula]=\"expression()\"\r\n [borderless]=\"true\"\r\n [autocompleteProvider]=\"autocompleteProvider\"\r\n (formulaChange)=\"onCodeFormulaChange($event)\"\r\n (onFocus)=\"onEditorFocus()\"\r\n (onBlur)=\"onEditorBlur()\"\r\n />\r\n } @else {\r\n <mt-formula-editor\r\n #formulaEditor\r\n [placeholder]=\"placeholder() || t('placeholder')\"\r\n [initialTokens]=\"tokens()\"\r\n [borderless]=\"true\"\r\n (formulaChange)=\"onFormulaChange($event)\"\r\n (tokensChange)=\"onTokensChange($event)\"\r\n (onFocus)=\"onEditorFocus()\"\r\n (onBlur)=\"onEditorBlur()\"\r\n />\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Status Bar - Pass data via inputs (pure component) -->\r\n @if (!hideStatusBar()) {\r\n <mt-formula-status-bar [validation]=\"validation()\" />\r\n }\r\n </div>\r\n</mt-card>\r\n" }]
|
|
1149
|
+
], template: "<mt-card\r\n headless\r\n [class.ring-2]=\"hasFocus()\"\r\n [class.ring-primary]=\"hasFocus()\"\r\n [paddingless]=\"true\"\r\n>\r\n <div\r\n *transloco=\"let t; prefix: 'formulaBuilder'\"\r\n class=\"flex flex-col overflow-hidden\"\r\n >\r\n <!-- Toolbar - Pass data via inputs (pure component) -->\r\n @if (!hideToolbar()) {\r\n <mt-formula-toolbar\r\n [functionCategories]=\"functionCategories()\"\r\n [visibleTabs]=\"resolvedToolbarTabs()\"\r\n (onBlockInsert)=\"onBlockInsert($event)\"\r\n >\r\n <ng-template #properties let-insertBlock=\"insertBlock\">\r\n @if (isContextLoading()) {\r\n <div class=\"flex flex-col gap-4 p-4\">\r\n <div class=\"flex items-center justify-between gap-4\">\r\n <p-skeleton\r\n width=\"18rem\"\r\n height=\"2.5rem\"\r\n styleClass=\"rounded-md\"\r\n />\r\n <p-skeleton\r\n width=\"7rem\"\r\n height=\"2.5rem\"\r\n styleClass=\"rounded-md\"\r\n />\r\n </div>\r\n <div class=\"flex items-center gap-4\">\r\n <div\r\n class=\"flex min-h-11 min-w-0 flex-1 flex-col gap-2 rounded-lg bg-slate-50 px-3 py-2 dark:bg-slate-800/50\"\r\n >\r\n <div class=\"flex items-center gap-2\">\r\n <p-skeleton\r\n width=\"3rem\"\r\n height=\"1rem\"\r\n styleClass=\"rounded-md\"\r\n />\r\n <div\r\n class=\"h-4 w-px shrink-0 bg-slate-200 dark:bg-slate-700\"\r\n ></div>\r\n <p-skeleton\r\n class=\"flex-1\"\r\n height=\"2rem\"\r\n styleClass=\"rounded-md\"\r\n />\r\n </div>\r\n <div\r\n class=\"flex items-center gap-2 border-t border-slate-200 pt-2 dark:border-slate-700\"\r\n >\r\n <p-skeleton\r\n width=\"3rem\"\r\n height=\"1rem\"\r\n styleClass=\"rounded-md\"\r\n />\r\n <div\r\n class=\"h-4 w-px shrink-0 bg-slate-200 dark:bg-slate-700\"\r\n ></div>\r\n <p-skeleton\r\n class=\"flex-1\"\r\n height=\"2.5rem\"\r\n styleClass=\"rounded-md\"\r\n />\r\n </div>\r\n <p-skeleton height=\"2rem\" styleClass=\"rounded-md\" />\r\n </div>\r\n </div>\r\n </div>\r\n } @else {\r\n <div class=\"flex flex-col gap-4 p-4\">\r\n <!-- Scope Selection - Full width, centered -->\r\n <div class=\"flex items-center justify-between gap-4\">\r\n <mt-radio-cards\r\n [options]=\"scopeOptions()\"\r\n [activeId]=\"propertyScope()\"\r\n (selectionChange)=\"onScopeChange($event)\"\r\n size=\"small\"\r\n />\r\n </div>\r\n\r\n <!-- Path + Field + Preview Row -->\r\n <div class=\"flex items-center gap-4\">\r\n <!-- Path Container - Flexible -->\r\n <div\r\n class=\"flex min-h-11 min-w-0 flex-1 flex-col gap-2 rounded-lg bg-slate-50 px-3 py-2 dark:bg-slate-800/50\"\r\n >\r\n <div class=\"flex items-center gap-2\">\r\n <span\r\n class=\"shrink-0 text-xs font-semibold uppercase tracking-wider text-slate-400\"\r\n >{{ t(\"properties.path\") }}</span\r\n >\r\n <div\r\n class=\"h-4 w-px shrink-0 bg-slate-200 dark:bg-slate-700\"\r\n ></div>\r\n <div class=\"flex min-w-0 flex-1 items-center gap-2\">\r\n @if (isDirectAccess()) {\r\n <span\r\n class=\"rounded-md bg-emerald-100 px-2.5 py-1 text-xs font-medium text-emerald-600 dark:bg-emerald-900/30 dark:text-emerald-400\"\r\n >\r\n \u2713 {{ t(\"properties.direct-access\") }}\r\n </span>\r\n } @else if (pathSegments().length === 0) {\r\n <span class=\"text-xs italic text-slate-400\">{{\r\n t(\"properties.no-path-configured\")\r\n }}</span>\r\n } @else {\r\n <div\r\n class=\"flex min-w-0 flex-1 items-center gap-1.5 overflow-x-auto\"\r\n >\r\n @for (\r\n segment of pathSegments();\r\n track $index;\r\n let segmentIndex = $index\r\n ) {\r\n @if (segmentIndex > 0) {\r\n <span\r\n class=\"shrink-0 text-slate-300 dark:text-slate-600\"\r\n >\u203A</span\r\n >\r\n }\r\n <mt-button\r\n type=\"button\"\r\n [label]=\"\r\n segment.value ||\r\n t('properties.select') +\r\n ' ' +\r\n getOperatorDisplayName(segment.operatorToken)\r\n \"\r\n icon=\"arrow.chevron-down\"\r\n [outlined]=\"true\"\r\n size=\"small\"\r\n [severity]=\"\r\n segment.value ? 'primary' : 'secondary'\r\n \"\r\n [iconPos]=\"'end'\"\r\n (onClick)=\"pathPopover.toggle($event)\"\r\n ></mt-button>\r\n\r\n <p-popover\r\n #pathPopover\r\n [style]=\"{ width: 'max-content' }\"\r\n appendTo=\"body\"\r\n >\r\n <div class=\"p-2\">\r\n <div\r\n class=\"mb-2 text-xs font-semibold uppercase text-slate-400\"\r\n >\r\n {{ t(\"properties.select\") }}\r\n {{\r\n getOperatorDisplayName(\r\n segment.operatorToken\r\n )\r\n }}\r\n </div>\r\n <div\r\n class=\"flex max-h-[min(24rem,calc(100vh-10rem))] flex-col gap-1 overflow-y-auto pr-1\"\r\n >\r\n @for (\r\n option of segmentOptions(segmentIndex);\r\n track option.key\r\n ) {\r\n <mt-button\r\n type=\"button\"\r\n [label]=\"option.name\"\r\n [icon]=\"\r\n segment.value === option.key\r\n ? 'general.check'\r\n : 'general.minus'\r\n \"\r\n [iconPos]=\"'end'\"\r\n size=\"small\"\r\n severity=\"secondary\"\r\n [styleClass]=\"\r\n 'w-full justify-start rounded-md px-2.5 py-1.5 text-left text-xs font-medium transition-colors ' +\r\n (segment.value === option.key\r\n ? 'bg-primary text-white'\r\n : 'text-slate-600 hover:bg-slate-100 dark:text-slate-300 dark:hover:bg-slate-700')\r\n \"\r\n (onClick)=\"\r\n setPathSegmentValue(\r\n segmentIndex,\r\n option.key\r\n );\r\n pathPopover.hide()\r\n \"\r\n ></mt-button>\r\n }\r\n </div>\r\n @if (segment.optional) {\r\n <mt-button\r\n type=\"button\"\r\n [label]=\"t('actions.clear')\"\r\n [outlined]=\"true\"\r\n icon=\"general.x-close\"\r\n [iconPos]=\"'end'\"\r\n size=\"small\"\r\n severity=\"danger\"\r\n styleClass=\"mt-2 w-full rounded-md border border-slate-200 py-1 text-xs text-slate-400 hover:bg-slate-50 dark:border-slate-700\"\r\n (onClick)=\"\r\n setPathSegmentValue(segmentIndex, null);\r\n pathPopover.hide()\r\n \"\r\n ></mt-button>\r\n }\r\n </div>\r\n </p-popover>\r\n\r\n @if (\r\n segment.canRemove &&\r\n segmentIndex === pathSegments().length - 1\r\n ) {\r\n <mt-button\r\n type=\"button\"\r\n icon=\"general.x-close\"\r\n size=\"small\"\r\n severity=\"danger\"\r\n styleClass=\"flex size-5 shrink-0 items-center justify-center rounded-full bg-red-500 text-white hover:bg-red-600\"\r\n (onClick)=\"removePathSegment(segmentIndex)\"\r\n ></mt-button>\r\n }\r\n }\r\n <mt-button\r\n type=\"button\"\r\n icon=\"general.plus\"\r\n size=\"small\"\r\n severity=\"primary\"\r\n [disabled]=\"!canAddNextSegment()\"\r\n [class.hidden]=\"!canAddNextSegment()\"\r\n styleClass=\"flex size-6 shrink-0 items-center justify-center rounded-md bg-primary text-xs font-bold text-white hover:opacity-90 disabled:opacity-50\"\r\n (onClick)=\"nextOperatorPopover.toggle($event)\"\r\n ></mt-button>\r\n </div>\r\n }\r\n <p-popover\r\n #nextOperatorPopover\r\n [style]=\"{ width: 'max-content' }\"\r\n appendTo=\"body\"\r\n >\r\n <div class=\"p-2\">\r\n <div\r\n class=\"mb-2 text-xs font-semibold uppercase text-slate-400\"\r\n >\r\n {{ t(\"properties.add-segment\") }}\r\n </div>\r\n <div\r\n class=\"flex max-h-[min(24rem,calc(100vh-10rem))] flex-col gap-1 overflow-y-auto pr-1\"\r\n >\r\n @for (\r\n option of nextOperatorOptions();\r\n track option.token\r\n ) {\r\n <mt-button\r\n type=\"button\"\r\n [label]=\"getOperatorDisplayName(option.token)\"\r\n icon=\"general.plus\"\r\n [iconPos]=\"'end'\"\r\n size=\"small\"\r\n severity=\"secondary\"\r\n styleClass=\"w-full justify-start rounded-md px-2.5 py-1.5 text-left text-xs font-medium transition-colors text-slate-600 hover:bg-slate-100 dark:text-slate-300 dark:hover:bg-slate-700\"\r\n (onClick)=\"\r\n onAddSegmentSelection(\r\n option.token,\r\n nextOperatorPopover\r\n )\r\n \"\r\n ></mt-button>\r\n }\r\n </div>\r\n </div>\r\n </p-popover>\r\n </div>\r\n </div>\r\n\r\n <!-- Field Selection - Under Path -->\r\n <div\r\n class=\"flex items-center gap-2 border-t border-slate-200 pt-2 dark:border-slate-700\"\r\n >\r\n <span\r\n class=\"shrink-0 text-xs font-semibold uppercase tracking-wider text-slate-400\"\r\n >{{ t(\"properties.field\") }}</span\r\n >\r\n <div\r\n class=\"h-4 w-px shrink-0 bg-slate-200 dark:bg-slate-700\"\r\n ></div>\r\n @if (isPropertyLoading()) {\r\n <p-skeleton\r\n class=\"flex-1\"\r\n height=\"2.5rem\"\r\n styleClass=\"rounded-md\"\r\n />\r\n } @else {\r\n <mt-select-field\r\n class=\"flex-1\"\r\n [label]=\"''\"\r\n [filter]=\"true\"\r\n [hasPlaceholderPrefix]=\"false\"\r\n [placeholder]=\"t('properties.select')\"\r\n [(ngModel)]=\"propertyFieldKey\"\r\n [options]=\"propertyOptions()\"\r\n optionLabel=\"name\"\r\n optionValue=\"key\"\r\n [size]=\"'small'\"\r\n />\r\n }\r\n </div>\r\n <div\r\n class=\"w-full truncate rounded-lg bg-amber-100 px-3 py-2 text-sm font-semibold text-amber-700 shadow-sm hover:bg-amber-200 dark:bg-amber-900/30 dark:text-amber-300 dark:hover:bg-amber-900/50\"\r\n [mtTooltip]=\"\r\n '@' +\r\n propertyTablePath() +\r\n '::' +\r\n (selectedProperty()?.key ?? '...')\r\n \"\r\n tooltipPosition=\"top\"\r\n >\r\n @{{ propertyTablePath() }}::{{\r\n selectedProperty()?.key ?? \"...\"\r\n }}\r\n </div>\r\n <div class=\"flex justify-end\">\r\n <mt-button\r\n type=\"button\"\r\n [label]=\"t('actions.insert')\"\r\n icon=\"general.plus\"\r\n severity=\"primary\"\r\n [disabled]=\"!canInsertProperty()\"\r\n (onClick)=\"insertSelectedProperty(insertBlock)\"\r\n ></mt-button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </ng-template>\r\n </mt-formula-toolbar>\r\n }\r\n\r\n <!-- Editor Area -->\r\n <div class=\"p-3\">\r\n <div\r\n class=\"overflow-hidden rounded-lg border border-surface-200 bg-white dark:border-surface-700 dark:bg-surface-800\"\r\n >\r\n @if (showModeToggle()) {\r\n <div\r\n class=\"flex items-center justify-end border-b border-surface-200 px-3 py-2 dark:border-surface-700\"\r\n >\r\n <mt-toggle-field\r\n [label]=\"t('codeMode')\"\r\n labelPosition=\"end\"\r\n size=\"small\"\r\n [ngModel]=\"isCodeMode()\"\r\n [readonly]=\"isCodeModeLocked()\"\r\n [pInputs]=\"{ disabled: isCodeModeLocked() }\"\r\n (ngModelChange)=\"onModeToggle($event)\"\r\n />\r\n </div>\r\n }\r\n <div class=\"p-0\">\r\n @if (isCodeMode()) {\r\n <mt-formula-editor-code\r\n #formulaEditorCode\r\n [placeholder]=\"placeholder() || t('placeholder')\"\r\n [initialFormula]=\"expression()\"\r\n [borderless]=\"true\"\r\n [autocompleteProvider]=\"autocompleteProvider\"\r\n (formulaChange)=\"onCodeFormulaChange($event)\"\r\n (onFocus)=\"onEditorFocus()\"\r\n (onBlur)=\"onEditorBlur()\"\r\n />\r\n } @else {\r\n <mt-formula-editor\r\n #formulaEditor\r\n [placeholder]=\"placeholder() || t('placeholder')\"\r\n [initialTokens]=\"tokens()\"\r\n [borderless]=\"true\"\r\n (formulaChange)=\"onFormulaChange($event)\"\r\n (tokensChange)=\"onTokensChange($event)\"\r\n (onFocus)=\"onEditorFocus()\"\r\n (onBlur)=\"onEditorBlur()\"\r\n />\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Status Bar - Pass data via inputs (pure component) -->\r\n @if (!hideStatusBar()) {\r\n <mt-formula-status-bar [validation]=\"validation()\" />\r\n }\r\n </div>\r\n</mt-card>\r\n" }]
|
|
1142
1150
|
}], ctorParameters: () => [], propDecorators: { editor: [{ type: i0.ViewChild, args: ['formulaEditor', { isSignal: true }] }], codeEditor: [{ type: i0.ViewChild, args: ['formulaEditorCode', { isSignal: true }] }], propertiesByPath: [{ type: i0.Input, args: [{ isSignal: true, alias: "propertiesByPath", required: false }] }], levelSchemaId: [{ type: i0.Input, args: [{ isSignal: true, alias: "levelSchemaId", required: false }] }], moduleId: [{ type: i0.Input, args: [{ isSignal: true, alias: "moduleId", required: false }] }], contextEntityTypeKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "contextEntityTypeKey", required: false }] }], templateId: [{ type: i0.Input, args: [{ isSignal: true, alias: "templateId", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], hideToolbar: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideToolbar", required: false }] }], hideStatusBar: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideStatusBar", required: false }] }], toolbarTabs: [{ type: i0.Input, args: [{ isSignal: true, alias: "toolbarTabs", required: false }] }], codeOnly: [{ type: i0.Input, args: [{ isSignal: true, alias: "codeOnly", required: false }] }], isProcessBuilder: [{ type: i0.Input, args: [{ isSignal: true, alias: "isProcessBuilder", required: false }] }], validationChange: [{ type: i0.Output, args: ["validationChange"] }], tokensChange: [{ type: i0.Output, args: ["tokensChange"] }] } });
|
|
1143
1151
|
|
|
1144
1152
|
/**
|