@masterteam/formula-builder 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/*! tailwindcss v4.1.18 | MIT License | https://tailwindcss.com */
|
|
2
|
-
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style:solid;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-500:oklch(63.7% .237 25.331);--color-red-600:oklch(57.7% .245 27.325);--color-amber-100:oklch(96.2% .059 95.617);--color-amber-200:oklch(92.4% .12 95.746);--color-amber-300:oklch(87.9% .169 91.605);--color-amber-700:oklch(55.5% .163 48.998);--color-amber-900:oklch(41.4% .112 45.904);--color-emerald-100:oklch(95% .052 163.051);--color-emerald-400:oklch(76.5% .177 163.223);--color-emerald-600:oklch(59.6% .145 163.225);--color-emerald-900:oklch(37.8% .077 168.94);--color-slate-50:oklch(98.4% .003 247.858);--color-slate-100:oklch(96.8% .007 247.896);--color-slate-200:oklch(92.9% .013 255.508);--color-slate-300:oklch(86.9% .022 252.894);--color-slate-400:oklch(70.4% .04 256.788);--color-slate-600:oklch(44.6% .043 257.281);--color-slate-700:oklch(37.2% .044 257.287);--color-slate-800:oklch(27.9% .041 260.031);--color-white:#fff;--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-wider:.05em;--radius-md:.375rem;--radius-lg:.5rem;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.absolute{position:absolute}.static{position:static}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.mt-2{margin-top:calc(var(--spacing)*2)}.mb-2{margin-bottom:calc(var(--spacing)*2)}.block{display:block}.flex{display:flex}.hidden{display:none}.inline{display:inline}.table{display:table}.size-5{width:calc(var(--spacing)*5);height:calc(var(--spacing)*5)}.size-6{width:calc(var(--spacing)*6);height:calc(var(--spacing)*6)}.h-4{height:calc(var(--spacing)*4)}.min-h-11{min-height:calc(var(--spacing)*11)}.w-full{width:100%}.w-px{width:1px}.min-w-0{min-width:calc(var(--spacing)*0)}.flex-1{flex:1}.shrink-0{flex-shrink:0}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.justify-start{justify-content:flex-start}.gap-1{gap:calc(var(--spacing)*1)}.gap-1\.5{gap:calc(var(--spacing)*1.5)}.gap-2{gap:calc(var(--spacing)*2)}.gap-4{gap:calc(var(--spacing)*4)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-slate-200{border-color:var(--color-slate-200)}.bg-amber-100{background-color:var(--color-amber-100)}.bg-emerald-100{background-color:var(--color-emerald-100)}.bg-primary{background-color:var(--p-primary-color)}@supports (color:color-mix(in lab, red, red)){.bg-primary{background-color:color-mix(in srgb,var(--p-primary-color)calc(100%*1),transparent)}}.bg-red-500{background-color:var(--color-red-500)}.bg-slate-50{background-color:var(--color-slate-50)}.bg-slate-200{background-color:var(--color-slate-200)}.p-2{padding:calc(var(--spacing)*2)}.p-3{padding:calc(var(--spacing)*3)}.p-4{padding:calc(var(--spacing)*4)}.px-2\.5{padding-inline:calc(var(--spacing)*2.5)}.px-3{padding-inline:calc(var(--spacing)*3)}.py-1{padding-block:calc(var(--spacing)*1)}.py-1\.5{padding-block:calc(var(--spacing)*1.5)}.py-2{padding-block:calc(var(--spacing)*2)}.pt-2{padding-top:calc(var(--spacing)*2)}.text-left{text-align:left}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.text-amber-700{color:var(--color-amber-700)}.text-emerald-600{color:var(--color-emerald-600)}.text-slate-300{color:var(--color-slate-300)}.text-slate-400{color:var(--color-slate-400)}.text-slate-600{color:var(--color-slate-600)}.text-white{color:var(--color-white)}.uppercase{text-transform:uppercase}.italic{font-style:italic}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring-2{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring-primary{--tw-ring-color:var(--p-primary-color)}@supports (color:color-mix(in lab, red, red)){.ring-primary{--tw-ring-color:color-mix(in srgb,var(--p-primary-color)calc(100%*1),transparent)}}.filter{filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}@media (hover:hover){.hover\:bg-amber-200:hover{background-color:var(--color-amber-200)}.hover\:bg-red-600:hover{background-color:var(--color-red-600)}.hover\:bg-slate-50:hover{background-color:var(--color-slate-50)}.hover\:bg-slate-100:hover{background-color:var(--color-slate-100)}.hover\:opacity-90:hover{opacity:.9}}.disabled\:opacity-50:disabled{opacity:.5}.dark\:border-slate-700:where(.dark,.dark *){border-color:var(--color-slate-700)}.dark\:bg-amber-900\/30:where(.dark,.dark *){background-color:#7b33064d}@supports (color:color-mix(in lab, red, red)){.dark\:bg-amber-900\/30:where(.dark,.dark *){background-color:color-mix(in oklab,var(--color-amber-900)30%,transparent)}}.dark\:bg-emerald-900\/30:where(.dark,.dark *){background-color:#004e3b4d}@supports (color:color-mix(in lab, red, red)){.dark\:bg-emerald-900\/30:where(.dark,.dark *){background-color:color-mix(in oklab,var(--color-emerald-900)30%,transparent)}}.dark\:bg-slate-700:where(.dark,.dark *){background-color:var(--color-slate-700)}.dark\:bg-slate-800\/50:where(.dark,.dark *){background-color:#1d293d80}@supports (color:color-mix(in lab, red, red)){.dark\:bg-slate-800\/50:where(.dark,.dark *){background-color:color-mix(in oklab,var(--color-slate-800)50%,transparent)}}.dark\:text-amber-300:where(.dark,.dark *){color:var(--color-amber-300)}.dark\:text-emerald-400:where(.dark,.dark *){color:var(--color-emerald-400)}.dark\:text-slate-300:where(.dark,.dark *){color:var(--color-slate-300)}.dark\:text-slate-600:where(.dark,.dark *){color:var(--color-slate-600)}@media (hover:hover){.dark\:hover\:bg-amber-900\/50:where(.dark,.dark *):hover{background-color:#7b330680}@supports (color:color-mix(in lab, red, red)){.dark\:hover\:bg-amber-900\/50:where(.dark,.dark *):hover{background-color:color-mix(in oklab,var(--color-amber-900)50%,transparent)}}.dark\:hover\:bg-slate-700:where(.dark,.dark *):hover{background-color:var(--color-slate-700)}}}@keyframes enter{0%{opacity:var(--p-enter-opacity,1);transform:translate3d(var(--p-enter-translate-x,0),var(--p-enter-translate-y,0),0)scale3d(var(--p-enter-scale,1),var(--p-enter-scale,1),var(--p-enter-scale,1))rotate(var(--p-enter-rotate,0))}}@keyframes leave{to{opacity:var(--p-leave-opacity,1);transform:translate3d(var(--p-leave-translate-x,0),var(--p-leave-translate-y,0),0)scale3d(var(--p-leave-scale,1),var(--p-leave-scale,1),var(--p-leave-scale,1))rotate(var(--p-leave-rotate,0))}}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}
|
|
2
|
+
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style:solid;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-500:oklch(63.7% .237 25.331);--color-red-600:oklch(57.7% .245 27.325);--color-amber-100:oklch(96.2% .059 95.617);--color-amber-200:oklch(92.4% .12 95.746);--color-amber-300:oklch(87.9% .169 91.605);--color-amber-700:oklch(55.5% .163 48.998);--color-amber-900:oklch(41.4% .112 45.904);--color-emerald-100:oklch(95% .052 163.051);--color-emerald-400:oklch(76.5% .177 163.223);--color-emerald-600:oklch(59.6% .145 163.225);--color-emerald-900:oklch(37.8% .077 168.94);--color-slate-50:oklch(98.4% .003 247.858);--color-slate-100:oklch(96.8% .007 247.896);--color-slate-200:oklch(92.9% .013 255.508);--color-slate-300:oklch(86.9% .022 252.894);--color-slate-400:oklch(70.4% .04 256.788);--color-slate-600:oklch(44.6% .043 257.281);--color-slate-700:oklch(37.2% .044 257.287);--color-slate-800:oklch(27.9% .041 260.031);--color-white:#fff;--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-wider:.05em;--radius-md:.375rem;--radius-lg:.5rem;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.absolute{position:absolute}.static{position:static}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.mt-2{margin-top:calc(var(--spacing)*2)}.mb-2{margin-bottom:calc(var(--spacing)*2)}.block{display:block}.flex{display:flex}.hidden{display:none}.inline{display:inline}.table{display:table}.size-5{width:calc(var(--spacing)*5);height:calc(var(--spacing)*5)}.size-6{width:calc(var(--spacing)*6);height:calc(var(--spacing)*6)}.h-4{height:calc(var(--spacing)*4)}.min-h-11{min-height:calc(var(--spacing)*11)}.w-full{width:100%}.w-px{width:1px}.min-w-0{min-width:calc(var(--spacing)*0)}.flex-1{flex:1}.shrink-0{flex-shrink:0}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.justify-start{justify-content:flex-start}.gap-1{gap:calc(var(--spacing)*1)}.gap-1\.5{gap:calc(var(--spacing)*1.5)}.gap-2{gap:calc(var(--spacing)*2)}.gap-4{gap:calc(var(--spacing)*4)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-slate-200{border-color:var(--color-slate-200)}.border-surface-200{border-color:var(--p-surface-200)}@supports (color:color-mix(in lab, red, red)){.border-surface-200{border-color:color-mix(in srgb,var(--p-surface-200)calc(100%*1),transparent)}}.bg-amber-100{background-color:var(--color-amber-100)}.bg-emerald-100{background-color:var(--color-emerald-100)}.bg-primary{background-color:var(--p-primary-color)}@supports (color:color-mix(in lab, red, red)){.bg-primary{background-color:color-mix(in srgb,var(--p-primary-color)calc(100%*1),transparent)}}.bg-red-500{background-color:var(--color-red-500)}.bg-slate-50{background-color:var(--color-slate-50)}.bg-slate-200{background-color:var(--color-slate-200)}.bg-white{background-color:var(--color-white)}.p-0{padding:calc(var(--spacing)*0)}.p-2{padding:calc(var(--spacing)*2)}.p-3{padding:calc(var(--spacing)*3)}.p-4{padding:calc(var(--spacing)*4)}.px-2\.5{padding-inline:calc(var(--spacing)*2.5)}.px-3{padding-inline:calc(var(--spacing)*3)}.py-1{padding-block:calc(var(--spacing)*1)}.py-1\.5{padding-block:calc(var(--spacing)*1.5)}.py-2{padding-block:calc(var(--spacing)*2)}.pt-2{padding-top:calc(var(--spacing)*2)}.text-left{text-align:left}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.text-amber-700{color:var(--color-amber-700)}.text-emerald-600{color:var(--color-emerald-600)}.text-slate-300{color:var(--color-slate-300)}.text-slate-400{color:var(--color-slate-400)}.text-slate-600{color:var(--color-slate-600)}.text-white{color:var(--color-white)}.uppercase{text-transform:uppercase}.italic{font-style:italic}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring-2{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring-primary{--tw-ring-color:var(--p-primary-color)}@supports (color:color-mix(in lab, red, red)){.ring-primary{--tw-ring-color:color-mix(in srgb,var(--p-primary-color)calc(100%*1),transparent)}}.filter{filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}@media (hover:hover){.hover\:bg-amber-200:hover{background-color:var(--color-amber-200)}.hover\:bg-red-600:hover{background-color:var(--color-red-600)}.hover\:bg-slate-50:hover{background-color:var(--color-slate-50)}.hover\:bg-slate-100:hover{background-color:var(--color-slate-100)}.hover\:opacity-90:hover{opacity:.9}}.disabled\:opacity-50:disabled{opacity:.5}.dark\:border-slate-700:where(.dark,.dark *){border-color:var(--color-slate-700)}.dark\:border-surface-700:where(.dark,.dark *){border-color:var(--p-surface-700)}@supports (color:color-mix(in lab, red, red)){.dark\:border-surface-700:where(.dark,.dark *){border-color:color-mix(in srgb,var(--p-surface-700)calc(100%*1),transparent)}}.dark\:bg-amber-900\/30:where(.dark,.dark *){background-color:#7b33064d}@supports (color:color-mix(in lab, red, red)){.dark\:bg-amber-900\/30:where(.dark,.dark *){background-color:color-mix(in oklab,var(--color-amber-900)30%,transparent)}}.dark\:bg-emerald-900\/30:where(.dark,.dark *){background-color:#004e3b4d}@supports (color:color-mix(in lab, red, red)){.dark\:bg-emerald-900\/30:where(.dark,.dark *){background-color:color-mix(in oklab,var(--color-emerald-900)30%,transparent)}}.dark\:bg-slate-700:where(.dark,.dark *){background-color:var(--color-slate-700)}.dark\:bg-slate-800\/50:where(.dark,.dark *){background-color:#1d293d80}@supports (color:color-mix(in lab, red, red)){.dark\:bg-slate-800\/50:where(.dark,.dark *){background-color:color-mix(in oklab,var(--color-slate-800)50%,transparent)}}.dark\:bg-surface-800:where(.dark,.dark *){background-color:var(--p-surface-800)}@supports (color:color-mix(in lab, red, red)){.dark\:bg-surface-800:where(.dark,.dark *){background-color:color-mix(in srgb,var(--p-surface-800)calc(100%*1),transparent)}}.dark\:text-amber-300:where(.dark,.dark *){color:var(--color-amber-300)}.dark\:text-emerald-400:where(.dark,.dark *){color:var(--color-emerald-400)}.dark\:text-slate-300:where(.dark,.dark *){color:var(--color-slate-300)}.dark\:text-slate-600:where(.dark,.dark *){color:var(--color-slate-600)}@media (hover:hover){.dark\:hover\:bg-amber-900\/50:where(.dark,.dark *):hover{background-color:#7b330680}@supports (color:color-mix(in lab, red, red)){.dark\:hover\:bg-amber-900\/50:where(.dark,.dark *):hover{background-color:color-mix(in oklab,var(--color-amber-900)50%,transparent)}}.dark\:hover\:bg-slate-700:where(.dark,.dark *):hover{background-color:var(--color-slate-700)}}}@keyframes enter{0%{opacity:var(--p-enter-opacity,1);transform:translate3d(var(--p-enter-translate-x,0),var(--p-enter-translate-y,0),0)scale3d(var(--p-enter-scale,1),var(--p-enter-scale,1),var(--p-enter-scale,1))rotate(var(--p-enter-rotate,0))}}@keyframes leave{to{opacity:var(--p-leave-opacity,1);transform:translate3d(var(--p-leave-translate-x,0),var(--p-leave-translate-y,0),0)scale3d(var(--p-leave-scale,1),var(--p-leave-scale,1),var(--p-leave-scale,1))rotate(var(--p-leave-rotate,0))}}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}
|
|
@@ -9,13 +9,14 @@ import { Button } from '@masterteam/components/button';
|
|
|
9
9
|
import { SelectField } from '@masterteam/components/select-field';
|
|
10
10
|
import { Tooltip } from '@masterteam/components/tooltip';
|
|
11
11
|
import { RadioCards } from '@masterteam/components/radio-cards';
|
|
12
|
+
import { ToggleField } from '@masterteam/components/toggle-field';
|
|
12
13
|
import * as i2 from 'primeng/popover';
|
|
13
14
|
import { PopoverModule } from 'primeng/popover';
|
|
14
15
|
import { Skeleton } from 'primeng/skeleton';
|
|
15
|
-
import { createPropertyBlock, FormulaToolbar, FormulaStatusBar, FormulaEditor } from '@masterteam/components/formula';
|
|
16
|
+
import { createPropertyBlock, FormulaToolbar, FormulaStatusBar, FormulaEditor, FormulaEditorCode } from '@masterteam/components/formula';
|
|
16
17
|
export { createFunctionBlock, createLiteralBlock, createOperatorBlock, createPropertyBlock } from '@masterteam/components/formula';
|
|
17
18
|
import { HttpClient } from '@angular/common/http';
|
|
18
|
-
import { Subject, debounceTime, distinctUntilChanged, tap, switchMap, of, catchError } from 'rxjs';
|
|
19
|
+
import { Subject, debounceTime, distinctUntilChanged, tap, switchMap, of, map, catchError } from 'rxjs';
|
|
19
20
|
|
|
20
21
|
/**
|
|
21
22
|
* Formula Validator Service
|
|
@@ -50,6 +51,14 @@ class FormulaValidatorService {
|
|
|
50
51
|
_isValidating = signal(false, ...(ngDevMode ? [{ debugName: "_isValidating" }] : []));
|
|
51
52
|
/** Validation subject for debouncing */
|
|
52
53
|
validateSubject = new Subject();
|
|
54
|
+
unwrapResponse(response) {
|
|
55
|
+
if (!response)
|
|
56
|
+
return null;
|
|
57
|
+
if (typeof response === 'object' && response !== null && 'data' in response) {
|
|
58
|
+
return response.data ?? null;
|
|
59
|
+
}
|
|
60
|
+
return response;
|
|
61
|
+
}
|
|
53
62
|
/** Public signals */
|
|
54
63
|
validation = this._validation.asReadonly();
|
|
55
64
|
isValidating = this._isValidating.asReadonly();
|
|
@@ -102,7 +111,7 @@ class FormulaValidatorService {
|
|
|
102
111
|
callValidateApi(request) {
|
|
103
112
|
return this.http
|
|
104
113
|
.post(`${this.apiUrl}/validate`, request)
|
|
105
|
-
.pipe(catchError((error) => {
|
|
114
|
+
.pipe(map((response) => this.unwrapResponse(response) ?? ERROR_VALIDATION), catchError((error) => {
|
|
106
115
|
console.error('Validation API error:', error);
|
|
107
116
|
// Try to extract error message
|
|
108
117
|
const apiError = error.error;
|
|
@@ -155,6 +164,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
|
|
|
155
164
|
class FormulaContextService {
|
|
156
165
|
http = inject(HttpClient);
|
|
157
166
|
apiUrl = '/formulas';
|
|
167
|
+
unwrapResponse(response) {
|
|
168
|
+
if (!response)
|
|
169
|
+
return null;
|
|
170
|
+
if (typeof response === 'object' && response !== null && 'data' in response) {
|
|
171
|
+
return response.data ?? null;
|
|
172
|
+
}
|
|
173
|
+
return response;
|
|
174
|
+
}
|
|
158
175
|
contextCache = new Map();
|
|
159
176
|
propertiesCache = new Map();
|
|
160
177
|
nextTokensCache = new Map();
|
|
@@ -171,9 +188,9 @@ class FormulaContextService {
|
|
|
171
188
|
: '';
|
|
172
189
|
return this.http
|
|
173
190
|
.get(`${this.apiUrl}/builder/context/${schemaId}${query}`)
|
|
174
|
-
.pipe(
|
|
175
|
-
if (
|
|
176
|
-
this.contextCache.set(cacheKey,
|
|
191
|
+
.pipe(map((response) => this.unwrapResponse(response)), tap((context) => {
|
|
192
|
+
if (context) {
|
|
193
|
+
this.contextCache.set(cacheKey, context);
|
|
177
194
|
}
|
|
178
195
|
}), catchError((error) => {
|
|
179
196
|
console.warn('Failed to load formula builder context:', error);
|
|
@@ -195,8 +212,8 @@ class FormulaContextService {
|
|
|
195
212
|
});
|
|
196
213
|
return this.http
|
|
197
214
|
.get(`${this.apiUrl}/builder/properties?${params.toString()}`)
|
|
198
|
-
.pipe(tap((response) => {
|
|
199
|
-
this.propertiesCache.set(cacheKey, response
|
|
215
|
+
.pipe(map((response) => this.unwrapResponse(response) ?? []), tap((response) => {
|
|
216
|
+
this.propertiesCache.set(cacheKey, response);
|
|
200
217
|
}), catchError((error) => {
|
|
201
218
|
console.warn('Failed to load formula properties:', error);
|
|
202
219
|
return of([]);
|
|
@@ -217,9 +234,9 @@ class FormulaContextService {
|
|
|
217
234
|
});
|
|
218
235
|
return this.http
|
|
219
236
|
.get(`${this.apiUrl}/builder/next-tokens?${params.toString()}`)
|
|
220
|
-
.pipe(
|
|
221
|
-
if (
|
|
222
|
-
this.nextTokensCache.set(cacheKey,
|
|
237
|
+
.pipe(map((response) => this.unwrapResponse(response)), tap((payload) => {
|
|
238
|
+
if (payload) {
|
|
239
|
+
this.nextTokensCache.set(cacheKey, payload);
|
|
223
240
|
}
|
|
224
241
|
}), catchError((error) => {
|
|
225
242
|
console.warn('Failed to load formula next tokens:', error);
|
|
@@ -234,6 +251,40 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
|
|
|
234
251
|
args: [{ providedIn: 'root' }]
|
|
235
252
|
}] });
|
|
236
253
|
|
|
254
|
+
class FormulaAutocompleteService {
|
|
255
|
+
http = inject(HttpClient);
|
|
256
|
+
apiUrl = '/formulas';
|
|
257
|
+
unwrapResponse(response) {
|
|
258
|
+
if (!response)
|
|
259
|
+
return null;
|
|
260
|
+
if (typeof response === 'object' && response !== null && 'data' in response) {
|
|
261
|
+
return response.data ?? null;
|
|
262
|
+
}
|
|
263
|
+
return response;
|
|
264
|
+
}
|
|
265
|
+
getSuggestions(request) {
|
|
266
|
+
if (!request) {
|
|
267
|
+
return of(null);
|
|
268
|
+
}
|
|
269
|
+
const normalized = {
|
|
270
|
+
...request,
|
|
271
|
+
formula: request.formula ?? '',
|
|
272
|
+
};
|
|
273
|
+
return this.http
|
|
274
|
+
.post(`${this.apiUrl}/autocomplete`, normalized)
|
|
275
|
+
.pipe(map((response) => this.unwrapResponse(response)), catchError((error) => {
|
|
276
|
+
console.warn('Autocomplete API error:', error);
|
|
277
|
+
return of(null);
|
|
278
|
+
}));
|
|
279
|
+
}
|
|
280
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: FormulaAutocompleteService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
281
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: FormulaAutocompleteService, providedIn: 'root' });
|
|
282
|
+
}
|
|
283
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: FormulaAutocompleteService, decorators: [{
|
|
284
|
+
type: Injectable,
|
|
285
|
+
args: [{ providedIn: 'root' }]
|
|
286
|
+
}] });
|
|
287
|
+
|
|
237
288
|
function resolveSegmentsMeta({ scope, segments, operators, baseRule, rulesByPath, }) {
|
|
238
289
|
if (!scope || segments.length === 0) {
|
|
239
290
|
return [];
|
|
@@ -334,8 +385,10 @@ const SCOPE_ICON_MAP = {
|
|
|
334
385
|
class FormulaBuilder {
|
|
335
386
|
validatorService = inject(FormulaValidatorService);
|
|
336
387
|
contextService = inject(FormulaContextService);
|
|
388
|
+
autocompleteService = inject(FormulaAutocompleteService);
|
|
337
389
|
/** Reference to the formula editor */
|
|
338
390
|
editor = viewChild('formulaEditor', ...(ngDevMode ? [{ debugName: "editor" }] : []));
|
|
391
|
+
codeEditor = viewChild('formulaEditorCode', ...(ngDevMode ? [{ debugName: "codeEditor" }] : []));
|
|
339
392
|
// ===== INPUTS =====
|
|
340
393
|
/** Properties per table path (e.g., "Current", "Children.Project") */
|
|
341
394
|
propertiesByPath = input({}, ...(ngDevMode ? [{ debugName: "propertiesByPath" }] : []));
|
|
@@ -362,8 +415,22 @@ class FormulaBuilder {
|
|
|
362
415
|
builderValue = signal([], ...(ngDevMode ? [{ debugName: "builderValue" }] : []));
|
|
363
416
|
/** Tokens for the editor */
|
|
364
417
|
tokens = signal([], ...(ngDevMode ? [{ debugName: "tokens" }] : []));
|
|
418
|
+
expression = computed(() => this.expressionValue(), ...(ngDevMode ? [{ debugName: "expression" }] : []));
|
|
419
|
+
autocompleteProvider = (request) => {
|
|
420
|
+
return this.autocompleteService.getSuggestions({
|
|
421
|
+
...request,
|
|
422
|
+
levelSchemaId: this.levelSchemaId(),
|
|
423
|
+
contextEntityTypeKey: this.builderContext()?.contextEntityTypeKey,
|
|
424
|
+
});
|
|
425
|
+
};
|
|
365
426
|
/** Track last synced builder JSON to avoid loops */
|
|
366
427
|
lastBuilderJson = '';
|
|
428
|
+
/** Editor mode */
|
|
429
|
+
editorMode = signal('builder', ...(ngDevMode ? [{ debugName: "editorMode" }] : []));
|
|
430
|
+
isCodeMode = computed(() => this.editorMode() === 'code', ...(ngDevMode ? [{ debugName: "isCodeMode" }] : []));
|
|
431
|
+
isCodeModeLocked = signal(false, ...(ngDevMode ? [{ debugName: "isCodeModeLocked" }] : []));
|
|
432
|
+
codeModeSnapshotTokens = [];
|
|
433
|
+
codeModeSnapshotExpression = '';
|
|
367
434
|
/** ControlValueAccessor callbacks */
|
|
368
435
|
onChange = () => { };
|
|
369
436
|
onTouched = () => { };
|
|
@@ -555,10 +622,18 @@ class FormulaBuilder {
|
|
|
555
622
|
if (editor) {
|
|
556
623
|
editor.writeValue([]);
|
|
557
624
|
}
|
|
625
|
+
const codeEditor = this.codeEditor();
|
|
626
|
+
if (codeEditor) {
|
|
627
|
+
codeEditor.writeValue('');
|
|
628
|
+
}
|
|
558
629
|
this.validatorService.reset();
|
|
559
630
|
return;
|
|
560
631
|
}
|
|
561
632
|
this.expressionValue.set(value.expression ?? '');
|
|
633
|
+
const codeEditor = this.codeEditor();
|
|
634
|
+
if (codeEditor) {
|
|
635
|
+
codeEditor.writeValue(this.expressionValue());
|
|
636
|
+
}
|
|
562
637
|
const builder = Array.isArray(value.builder) ? value.builder : [];
|
|
563
638
|
this.builderValue.set(builder);
|
|
564
639
|
if (builder.length === 0) {
|
|
@@ -595,8 +670,25 @@ class FormulaBuilder {
|
|
|
595
670
|
this.expressionValue.set(newFormula);
|
|
596
671
|
this.emitValueChange();
|
|
597
672
|
}
|
|
673
|
+
/** Handle formula change from code editor */
|
|
674
|
+
onCodeFormulaChange(newFormula) {
|
|
675
|
+
this.expressionValue.set(newFormula);
|
|
676
|
+
if (!this.isCodeModeLocked() &&
|
|
677
|
+
newFormula !== this.codeModeSnapshotExpression) {
|
|
678
|
+
this.isCodeModeLocked.set(true);
|
|
679
|
+
this.clearBuilderTokens();
|
|
680
|
+
}
|
|
681
|
+
this.emitValueChange();
|
|
682
|
+
}
|
|
598
683
|
/** Handle block insert from toolbar */
|
|
599
684
|
onBlockInsert(block) {
|
|
685
|
+
if (this.isCodeMode()) {
|
|
686
|
+
const editor = this.codeEditor();
|
|
687
|
+
if (editor) {
|
|
688
|
+
editor.addBlock(block);
|
|
689
|
+
}
|
|
690
|
+
return;
|
|
691
|
+
}
|
|
600
692
|
const editor = this.editor();
|
|
601
693
|
if (editor) {
|
|
602
694
|
editor.addBlock(block);
|
|
@@ -624,6 +716,61 @@ class FormulaBuilder {
|
|
|
624
716
|
builder: this.builderValue(),
|
|
625
717
|
});
|
|
626
718
|
}
|
|
719
|
+
onModeToggle(value) {
|
|
720
|
+
const nextMode = value ? 'code' : 'builder';
|
|
721
|
+
this.setEditorMode(nextMode);
|
|
722
|
+
}
|
|
723
|
+
setEditorMode(mode) {
|
|
724
|
+
if (this.editorMode() === mode)
|
|
725
|
+
return;
|
|
726
|
+
if (mode === 'code') {
|
|
727
|
+
this.enterCodeMode();
|
|
728
|
+
return;
|
|
729
|
+
}
|
|
730
|
+
if (this.isCodeModeLocked()) {
|
|
731
|
+
return;
|
|
732
|
+
}
|
|
733
|
+
this.exitCodeMode();
|
|
734
|
+
}
|
|
735
|
+
enterCodeMode() {
|
|
736
|
+
this.codeModeSnapshotTokens = this.tokens().slice();
|
|
737
|
+
this.codeModeSnapshotExpression = this.expressionValue();
|
|
738
|
+
const editor = this.editor();
|
|
739
|
+
if (editor) {
|
|
740
|
+
const formula = editor.serialize();
|
|
741
|
+
this.codeModeSnapshotExpression = formula;
|
|
742
|
+
this.expressionValue.set(formula);
|
|
743
|
+
this.emitValueChange();
|
|
744
|
+
}
|
|
745
|
+
this.isCodeModeLocked.set(false);
|
|
746
|
+
this.editorMode.set('code');
|
|
747
|
+
}
|
|
748
|
+
exitCodeMode() {
|
|
749
|
+
this.editorMode.set('builder');
|
|
750
|
+
if (this.codeModeSnapshotTokens.length > 0) {
|
|
751
|
+
const restored = this.codeModeSnapshotTokens.slice();
|
|
752
|
+
this.tokens.set(restored);
|
|
753
|
+
this.builderValue.set(restored);
|
|
754
|
+
this.lastBuilderJson = JSON.stringify(restored);
|
|
755
|
+
const editor = this.editor();
|
|
756
|
+
if (editor) {
|
|
757
|
+
editor.writeValue(restored);
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
if (this.codeModeSnapshotExpression) {
|
|
761
|
+
this.expressionValue.set(this.codeModeSnapshotExpression);
|
|
762
|
+
}
|
|
763
|
+
this.isCodeModeLocked.set(false);
|
|
764
|
+
}
|
|
765
|
+
clearBuilderTokens() {
|
|
766
|
+
if (this.tokens().length === 0 && this.builderValue().length === 0) {
|
|
767
|
+
return;
|
|
768
|
+
}
|
|
769
|
+
this.tokens.set([]);
|
|
770
|
+
this.builderValue.set([]);
|
|
771
|
+
this.lastBuilderJson = '';
|
|
772
|
+
this.tokensChange.emit([]);
|
|
773
|
+
}
|
|
627
774
|
// ===== PUBLIC METHODS =====
|
|
628
775
|
/** Clear the formula */
|
|
629
776
|
clear() {
|
|
@@ -631,10 +778,17 @@ class FormulaBuilder {
|
|
|
631
778
|
this.tokens.set([]);
|
|
632
779
|
this.builderValue.set([]);
|
|
633
780
|
this.lastBuilderJson = '';
|
|
781
|
+
this.codeModeSnapshotTokens = [];
|
|
782
|
+
this.codeModeSnapshotExpression = '';
|
|
783
|
+
this.isCodeModeLocked.set(false);
|
|
634
784
|
const editor = this.editor();
|
|
635
785
|
if (editor) {
|
|
636
786
|
editor.writeValue([]);
|
|
637
787
|
}
|
|
788
|
+
const codeEditor = this.codeEditor();
|
|
789
|
+
if (codeEditor) {
|
|
790
|
+
codeEditor.writeValue('');
|
|
791
|
+
}
|
|
638
792
|
this.validatorService.reset();
|
|
639
793
|
this.emitValueChange();
|
|
640
794
|
}
|
|
@@ -823,7 +977,7 @@ class FormulaBuilder {
|
|
|
823
977
|
useExisting: forwardRef(() => FormulaBuilder),
|
|
824
978
|
multi: true,
|
|
825
979
|
},
|
|
826
|
-
], viewQueries: [{ propertyName: "editor", first: true, predicate: ["formulaEditor"], 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 (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 >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 Direct Access\r\n </span>\r\n } @else if (pathSegments().length === 0) {\r\n <span class=\"text-xs italic text-slate-400\"\r\n >No path configured</span\r\n >\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 'Select ' + 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 Select {{ segment.operatorToken }}\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=\"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 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]=\"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 >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=\"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=\"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 <mt-formula-editor\r\n #formulaEditor\r\n [placeholder]=\"placeholder()\"\r\n [initialTokens]=\"tokens()\"\r\n (formulaChange)=\"onFormulaChange($event)\"\r\n (tokensChange)=\"onTokensChange($event)\"\r\n (onFocus)=\"onEditorFocus()\"\r\n (onBlur)=\"onEditorBlur()\"\r\n />\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"], 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: "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", "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"], outputs: ["formulaChange", "tokensChange", "onBlur", "onFocus"] }] });
|
|
980
|
+
], 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 (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 >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 Direct Access\r\n </span>\r\n } @else if (pathSegments().length === 0) {\r\n <span class=\"text-xs italic text-slate-400\"\r\n >No path configured</span\r\n >\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 'Select ' + 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 Select {{ segment.operatorToken }}\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=\"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 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]=\"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 >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=\"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=\"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 <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=\"Code mode\"\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 <div class=\"p-0\">\r\n @if (isCodeMode()) {\r\n <mt-formula-editor-code\r\n #formulaEditorCode\r\n [placeholder]=\"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()\"\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"], 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", "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", "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"] }] });
|
|
827
981
|
}
|
|
828
982
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: FormulaBuilder, decorators: [{
|
|
829
983
|
type: Component,
|
|
@@ -836,11 +990,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
|
|
|
836
990
|
SelectField,
|
|
837
991
|
Tooltip,
|
|
838
992
|
RadioCards,
|
|
993
|
+
ToggleField,
|
|
839
994
|
PopoverModule,
|
|
840
995
|
Skeleton,
|
|
841
996
|
FormulaToolbar,
|
|
842
997
|
FormulaStatusBar,
|
|
843
998
|
FormulaEditor,
|
|
999
|
+
FormulaEditorCode,
|
|
844
1000
|
], host: {
|
|
845
1001
|
class: 'block',
|
|
846
1002
|
}, providers: [
|
|
@@ -849,8 +1005,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
|
|
|
849
1005
|
useExisting: forwardRef(() => FormulaBuilder),
|
|
850
1006
|
multi: true,
|
|
851
1007
|
},
|
|
852
|
-
], 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 (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 >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 Direct Access\r\n </span>\r\n } @else if (pathSegments().length === 0) {\r\n <span class=\"text-xs italic text-slate-400\"\r\n >No path configured</span\r\n >\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 'Select ' + 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 Select {{ segment.operatorToken }}\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=\"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 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]=\"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 >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=\"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=\"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 <mt-formula-editor\r\n #formulaEditor\r\n [placeholder]=\"placeholder()\"\r\n [initialTokens]=\"tokens()\"\r\n (formulaChange)=\"onFormulaChange($event)\"\r\n (tokensChange)=\"onTokensChange($event)\"\r\n (onFocus)=\"onEditorFocus()\"\r\n (onBlur)=\"onEditorBlur()\"\r\n />\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" }]
|
|
853
|
-
}], ctorParameters: () => [], propDecorators: { editor: [{ type: i0.ViewChild, args: ['formulaEditor', { isSignal: true }] }], propertiesByPath: [{ type: i0.Input, args: [{ isSignal: true, alias: "propertiesByPath", required: false }] }], levelSchemaId: [{ type: i0.Input, args: [{ isSignal: true, alias: "levelSchemaId", 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 }] }], validationChange: [{ type: i0.Output, args: ["validationChange"] }], tokensChange: [{ type: i0.Output, args: ["tokensChange"] }] } });
|
|
1008
|
+
], 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 (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 >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 Direct Access\r\n </span>\r\n } @else if (pathSegments().length === 0) {\r\n <span class=\"text-xs italic text-slate-400\"\r\n >No path configured</span\r\n >\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 'Select ' + 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 Select {{ segment.operatorToken }}\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=\"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 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]=\"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 >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=\"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=\"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 <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=\"Code mode\"\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 <div class=\"p-0\">\r\n @if (isCodeMode()) {\r\n <mt-formula-editor-code\r\n #formulaEditorCode\r\n [placeholder]=\"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()\"\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" }]
|
|
1009
|
+
}], 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 }] }], 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 }] }], validationChange: [{ type: i0.Output, args: ["validationChange"] }], tokensChange: [{ type: i0.Output, args: ["tokensChange"] }] } });
|
|
854
1010
|
|
|
855
1011
|
/**
|
|
856
1012
|
* Services barrel export
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"masterteam-formula-builder.mjs","sources":["../../../../packages/masterteam/formula-builder/src/lib/services/formula-validator.service.ts","../../../../packages/masterteam/formula-builder/src/lib/services/formula-context.service.ts","../../../../packages/masterteam/formula-builder/src/lib/utils/formula-path-builder.ts","../../../../packages/masterteam/formula-builder/src/lib/formula-builder.ts","../../../../packages/masterteam/formula-builder/src/lib/formula-builder.html","../../../../packages/masterteam/formula-builder/src/lib/services/index.ts","../../../../packages/masterteam/formula-builder/src/public-api.ts","../../../../packages/masterteam/formula-builder/src/masterteam-formula-builder.ts"],"sourcesContent":["/**\r\n * Formula Validator Service\r\n * Handles real-time validation via API\r\n */\r\n\r\nimport { Injectable, inject, signal } from '@angular/core';\r\nimport { HttpClient, HttpErrorResponse } from '@angular/common/http';\r\nimport {\r\n Observable,\r\n Subject,\r\n of,\r\n catchError,\r\n debounceTime,\r\n distinctUntilChanged,\r\n switchMap,\r\n tap,\r\n} from 'rxjs';\r\nimport {\r\n ValidationResult,\r\n ValidationRequest,\r\n ApiErrorResponse,\r\n} from '../models/validation-result.model';\r\n\r\n/** Default validation result for empty formulas */\r\nconst EMPTY_VALIDATION: ValidationResult = {\r\n isValid: true,\r\n errors: [],\r\n warnings: [],\r\n dependencies: [],\r\n complexity: 0,\r\n};\r\n\r\n/** Error validation result */\r\nconst ERROR_VALIDATION: ValidationResult = {\r\n isValid: false,\r\n errors: [\r\n { message: 'Validation failed', line: 1, column: 1, severity: 'Error' },\r\n ],\r\n warnings: [],\r\n dependencies: [],\r\n complexity: 0,\r\n};\r\n\r\n@Injectable({ providedIn: 'root' })\r\nexport class FormulaValidatorService {\r\n private readonly http = inject(HttpClient);\r\n private readonly apiUrl = '/formulas';\r\n\r\n /** Debounce time in ms */\r\n private readonly DEBOUNCE_MS = 300;\r\n\r\n /** Current validation result */\r\n private readonly _validation = signal<ValidationResult>(EMPTY_VALIDATION);\r\n\r\n /** Loading state */\r\n private readonly _isValidating = signal(false);\r\n\r\n /** Validation subject for debouncing */\r\n private readonly validateSubject = new Subject<ValidationRequest>();\r\n\r\n /** Public signals */\r\n readonly validation = this._validation.asReadonly();\r\n readonly isValidating = this._isValidating.asReadonly();\r\n\r\n constructor() {\r\n this.setupValidationStream();\r\n }\r\n\r\n /** Setup debounced validation stream */\r\n private setupValidationStream(): void {\r\n this.validateSubject\r\n .pipe(\r\n debounceTime(this.DEBOUNCE_MS),\r\n distinctUntilChanged(\r\n (a, b) =>\r\n a.formula === b.formula &&\r\n JSON.stringify(a.knownProperties) ===\r\n JSON.stringify(b.knownProperties),\r\n ),\r\n tap(() => this._isValidating.set(true)),\r\n switchMap((request) => this.callValidateApi(request)),\r\n )\r\n .subscribe((result) => {\r\n this._validation.set(result);\r\n this._isValidating.set(false);\r\n });\r\n }\r\n\r\n /** Validate formula (debounced) */\r\n validate(\r\n formula: string,\r\n knownProperties?: string[],\r\n levelSchemaId?: number,\r\n templateId?: number,\r\n ): void {\r\n // Handle empty formula\r\n if (!formula || formula.trim() === '') {\r\n this._validation.set(EMPTY_VALIDATION);\r\n return;\r\n }\r\n\r\n // Push to debounced stream\r\n this.validateSubject.next({\r\n formula,\r\n knownProperties,\r\n levelSchemaId,\r\n templateId,\r\n });\r\n }\r\n\r\n /** Validate formula immediately (no debounce) */\r\n validateImmediate(\r\n formula: string,\r\n knownProperties?: string[],\r\n levelSchemaId?: number,\r\n templateId?: number,\r\n ): Observable<ValidationResult> {\r\n if (!formula || formula.trim() === '') {\r\n return of(EMPTY_VALIDATION);\r\n }\r\n\r\n this._isValidating.set(true);\r\n\r\n return this.callValidateApi({\r\n formula,\r\n knownProperties,\r\n levelSchemaId,\r\n templateId,\r\n }).pipe(\r\n tap((result) => {\r\n this._validation.set(result);\r\n this._isValidating.set(false);\r\n }),\r\n );\r\n }\r\n\r\n /** Call validation API */\r\n private callValidateApi(\r\n request: ValidationRequest,\r\n ): Observable<ValidationResult> {\r\n return this.http\r\n .post<ValidationResult>(`${this.apiUrl}/validate`, request)\r\n .pipe(\r\n catchError((error: HttpErrorResponse) => {\r\n console.error('Validation API error:', error);\r\n\r\n // Try to extract error message\r\n const apiError = error.error as ApiErrorResponse;\r\n const message =\r\n apiError?.message ?? apiError?.error ?? 'Validation failed';\r\n\r\n return of({\r\n ...ERROR_VALIDATION,\r\n errors: [\r\n { message, line: 1, column: 1, severity: 'Error' as const },\r\n ],\r\n });\r\n }),\r\n );\r\n }\r\n\r\n /** Reset validation state */\r\n reset(): void {\r\n this._validation.set(EMPTY_VALIDATION);\r\n this._isValidating.set(false);\r\n }\r\n\r\n /** Get current validation result */\r\n getCurrentValidation(): ValidationResult {\r\n return this._validation();\r\n }\r\n\r\n /** Check if formula is valid */\r\n isValid(): boolean {\r\n return this._validation().isValid;\r\n }\r\n\r\n /** Get validation errors */\r\n getErrors() {\r\n return this._validation().errors;\r\n }\r\n\r\n /** Get validation warnings */\r\n getWarnings() {\r\n return this._validation().warnings;\r\n }\r\n\r\n /** Get formula dependencies */\r\n getDependencies() {\r\n return this._validation().dependencies;\r\n }\r\n\r\n /** Get formula complexity */\r\n getComplexity() {\r\n return this._validation().complexity;\r\n }\r\n}\r\n","import { Injectable, inject } from '@angular/core';\r\nimport { HttpClient } from '@angular/common/http';\r\nimport { Observable, of, catchError, tap } from 'rxjs';\r\n\r\nimport type {\r\n FormulaBuilderContextResponse,\r\n FormulaBuilderNextTokensResponse,\r\n FormulaPropertyDescriptor,\r\n} from '../models/formula-context.model';\r\n\r\n@Injectable({ providedIn: 'root' })\r\nexport class FormulaContextService {\r\n private readonly http = inject(HttpClient);\r\n private readonly apiUrl = '/formulas';\r\n\r\n private readonly contextCache = new Map<\r\n string,\r\n FormulaBuilderContextResponse\r\n >();\r\n private readonly propertiesCache = new Map<\r\n string,\r\n FormulaPropertyDescriptor[]\r\n >();\r\n private readonly nextTokensCache = new Map<\r\n string,\r\n FormulaBuilderNextTokensResponse\r\n >();\r\n\r\n loadContext(\r\n schemaId: number,\r\n contextEntityTypeKey?: string,\r\n ): Observable<FormulaBuilderContextResponse | null> {\r\n if (!schemaId) return of(null);\r\n\r\n const cacheKey = `${schemaId}:${contextEntityTypeKey ?? ''}`;\r\n const cached = this.contextCache.get(cacheKey);\r\n if (cached) {\r\n return of(cached);\r\n }\r\n\r\n const query = contextEntityTypeKey\r\n ? `?contextEntityTypeKey=${encodeURIComponent(contextEntityTypeKey)}`\r\n : '';\r\n\r\n return this.http\r\n .get<FormulaBuilderContextResponse>(\r\n `${this.apiUrl}/builder/context/${schemaId}${query}`,\r\n )\r\n .pipe(\r\n tap((response) => {\r\n if (response) {\r\n this.contextCache.set(cacheKey, response);\r\n }\r\n }),\r\n catchError((error) => {\r\n console.warn('Failed to load formula builder context:', error);\r\n return of(null);\r\n }),\r\n );\r\n }\r\n\r\n getScopeProperties(\r\n schemaId: number,\r\n component: string,\r\n tablePath: string,\r\n ): Observable<FormulaPropertyDescriptor[]> {\r\n if (!schemaId || !component || !tablePath) return of([]);\r\n\r\n const cacheKey = `${schemaId}:${component}:${tablePath}`;\r\n const cached = this.propertiesCache.get(cacheKey);\r\n if (cached) {\r\n return of(cached);\r\n }\r\n\r\n const params = new URLSearchParams({\r\n schemaId: schemaId.toString(),\r\n component,\r\n tablePath,\r\n });\r\n\r\n return this.http\r\n .get<\r\n FormulaPropertyDescriptor[]\r\n >(`${this.apiUrl}/builder/properties?${params.toString()}`)\r\n .pipe(\r\n tap((response) => {\r\n this.propertiesCache.set(cacheKey, response ?? []);\r\n }),\r\n catchError((error) => {\r\n console.warn('Failed to load formula properties:', error);\r\n return of([]);\r\n }),\r\n );\r\n }\r\n\r\n getNextTokens(\r\n schemaId: number,\r\n component: string,\r\n tablePath: string,\r\n ): Observable<FormulaBuilderNextTokensResponse | null> {\r\n if (!schemaId || !component || !tablePath) return of(null);\r\n\r\n const cacheKey = `${schemaId}:${component}:${tablePath}`;\r\n const cached = this.nextTokensCache.get(cacheKey);\r\n if (cached) {\r\n return of(cached);\r\n }\r\n\r\n const params = new URLSearchParams({\r\n schemaId: schemaId.toString(),\r\n component,\r\n tablePath,\r\n });\r\n\r\n return this.http\r\n .get<FormulaBuilderNextTokensResponse>(\r\n `${this.apiUrl}/builder/next-tokens?${params.toString()}`,\r\n )\r\n .pipe(\r\n tap((response) => {\r\n if (response) {\r\n this.nextTokensCache.set(cacheKey, response);\r\n }\r\n }),\r\n catchError((error) => {\r\n console.warn('Failed to load formula next tokens:', error);\r\n return of(null);\r\n }),\r\n );\r\n }\r\n}\r\n","import type {\r\n NextTokenRule,\r\n OperatorDescriptor,\r\n} from '../models/formula-context.model';\r\n\r\nexport type PathSegment = {\r\n operatorToken: string;\r\n value: string;\r\n};\r\n\r\nexport type SegmentMeta = PathSegment & {\r\n parameterKind?: string | null;\r\n requiresParameter: boolean;\r\n allowedValues: string[];\r\n optional: boolean;\r\n canRemove: boolean;\r\n};\r\n\r\nexport type ResolveSegmentsParams = {\r\n scope: string;\r\n segments: PathSegment[];\r\n operators: OperatorDescriptor[];\r\n baseRule?: NextTokenRule;\r\n rulesByPath: Record<string, Record<string, NextTokenRule>>;\r\n};\r\n\r\nexport function resolveSegmentsMeta({\r\n scope,\r\n segments,\r\n operators,\r\n baseRule,\r\n rulesByPath,\r\n}: ResolveSegmentsParams): SegmentMeta[] {\r\n if (!scope || segments.length === 0) {\r\n return [];\r\n }\r\n\r\n let pathBefore = scope;\r\n let blocked = false;\r\n\r\n return segments.map((segment, index) => {\r\n const isBase = index === 0 && segment.operatorToken === scope;\r\n const operator = operators.find((op) => op.token === segment.operatorToken);\r\n const rule = blocked\r\n ? undefined\r\n : isBase\r\n ? baseRule\r\n : rulesByPath[pathBefore]?.[segment.operatorToken];\r\n const parameterKind =\r\n rule?.parameterKind ?? operator?.parameterKind ?? null;\r\n const requiresParameter =\r\n operator?.requiresParameter ?? Boolean(parameterKind);\r\n const allowedValues = getAllowedValues(rule);\r\n const normalizedValue = segment.value;\r\n const isComplete = !requiresParameter || Boolean(normalizedValue);\r\n\r\n if (!blocked && isComplete) {\r\n pathBefore = appendToPath(\r\n pathBefore,\r\n segment.operatorToken,\r\n normalizedValue,\r\n isBase,\r\n );\r\n } else {\r\n blocked = true;\r\n }\r\n\r\n return {\r\n operatorToken: segment.operatorToken,\r\n value: normalizedValue,\r\n parameterKind,\r\n requiresParameter,\r\n allowedValues,\r\n optional: !requiresParameter,\r\n canRemove: !isBase,\r\n };\r\n });\r\n}\r\n\r\nexport function buildInitialSegments(\r\n scope: string,\r\n operator: OperatorDescriptor | undefined,\r\n rule: NextTokenRule | undefined,\r\n): PathSegment[] {\r\n if (!operator || !scope) return [];\r\n const parameterKind = operator.parameterKind ?? rule?.parameterKind ?? null;\r\n const requiresParameter =\r\n operator.requiresParameter ?? Boolean(parameterKind);\r\n const shouldHaveSegment = Boolean(parameterKind) || requiresParameter;\r\n if (!shouldHaveSegment) return [];\r\n\r\n return [{ operatorToken: scope, value: '' }];\r\n}\r\n\r\nexport function buildTablePath(\r\n scope: string,\r\n segments: SegmentMeta[],\r\n baseOperator: OperatorDescriptor | undefined,\r\n stopOnIncomplete: boolean,\r\n): string {\r\n if (!scope) return '';\r\n\r\n if (\r\n stopOnIncomplete &&\r\n segments.length === 0 &&\r\n (baseOperator?.requiresParameter || baseOperator?.parameterKind)\r\n ) {\r\n return '';\r\n }\r\n\r\n let path = scope;\r\n for (let index = 0; index < segments.length; index += 1) {\r\n const segment = segments[index];\r\n const isBase = index === 0 && segment.operatorToken === scope;\r\n if (!isBase) {\r\n path += `.${segment.operatorToken}`;\r\n }\r\n if (segment.value) {\r\n path += `.${segment.value}`;\r\n } else if (segment.requiresParameter && stopOnIncomplete) {\r\n return '';\r\n }\r\n }\r\n\r\n return path;\r\n}\r\n\r\nexport function getAllowedValues(rule: NextTokenRule | undefined): string[] {\r\n return rule?.allowedValues ?? [];\r\n}\r\n\r\nfunction appendToPath(\r\n basePath: string,\r\n operatorToken: string,\r\n value: string,\r\n isBase: boolean,\r\n): string {\r\n if (isBase) {\r\n if (!value) return basePath;\r\n if (!basePath) return value;\r\n return `${basePath}.${value}`;\r\n }\r\n if (!basePath) {\r\n return value ? `${operatorToken}.${value}` : operatorToken;\r\n }\r\n const withOperator = `${basePath}.${operatorToken}`;\r\n return value ? `${withOperator}.${value}` : withOperator;\r\n}\r\n","import {\r\n Component,\r\n forwardRef,\r\n input,\r\n output,\r\n signal,\r\n computed,\r\n inject,\r\n effect,\r\n OnDestroy,\r\n viewChild,\r\n} from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { TranslocoDirective } from '@jsverse/transloco';\r\nimport {\r\n ControlValueAccessor,\r\n FormsModule,\r\n NG_VALUE_ACCESSOR,\r\n} from '@angular/forms';\r\nimport { Card } from '@masterteam/components/card';\r\nimport { Button } from '@masterteam/components/button';\r\nimport { SelectField } from '@masterteam/components/select-field';\r\nimport { Tooltip } from '@masterteam/components/tooltip';\r\nimport { RadioCards, type RadioItem } from '@masterteam/components/radio-cards';\r\nimport type { MTIcon } from '@masterteam/icons';\r\nimport { PopoverModule } from 'primeng/popover';\r\nimport { Skeleton } from 'primeng/skeleton';\r\n\r\n// Import pure UI components from @masterteam/components/formula\r\nimport {\r\n FormulaToolbar,\r\n FormulaEditor,\r\n FormulaStatusBar,\r\n type SmartBlock,\r\n type FormulaToken,\r\n createPropertyBlock,\r\n} from '@masterteam/components/formula';\r\n\r\n// Services are kept in formula-builder (backend logic)\r\nimport { FormulaValidatorService } from './services/formula-validator.service';\r\nimport { FormulaContextService } from './services/formula-context.service';\r\nimport { ValidationResult } from './models/validation-result.model';\r\nimport type {\r\n FormulaBuilderContextResponse,\r\n FormulaPropertyDescriptor,\r\n NextTokenRule,\r\n OperatorDescriptor,\r\n} from './models/formula-context.model';\r\nimport type { FormulaBuilderValue } from './models/formula-builder-value.model';\r\nimport {\r\n buildInitialSegments,\r\n buildTablePath,\r\n getAllowedValues,\r\n resolveSegmentsMeta,\r\n type PathSegment,\r\n type SegmentMeta,\r\n} from './utils/formula-path-builder';\r\n\r\nconst DEFAULT_SCOPE_ICON: MTIcon = 'general.placeholder';\r\nconst SCOPE_ICON_MAP: Record<string, MTIcon> = {\r\n Current: 'map.marker-pin-01',\r\n Level: 'map.marker-pin-01',\r\n Parent: 'arrow.arrow-up',\r\n Children: 'user.users-01',\r\n Descendants: 'custom.hierarchy-structure',\r\n Modules: 'file.folder-closed',\r\n};\r\n\r\n@Component({\r\n selector: 'mt-formula-builder',\r\n standalone: true,\r\n imports: [\r\n CommonModule,\r\n TranslocoDirective,\r\n FormsModule,\r\n Card,\r\n Button,\r\n SelectField,\r\n Tooltip,\r\n RadioCards,\r\n PopoverModule,\r\n Skeleton,\r\n FormulaToolbar,\r\n FormulaStatusBar,\r\n FormulaEditor,\r\n ],\r\n templateUrl: './formula-builder.html',\r\n host: {\r\n class: 'block',\r\n },\r\n providers: [\r\n {\r\n provide: NG_VALUE_ACCESSOR,\r\n useExisting: forwardRef(() => FormulaBuilder),\r\n multi: true,\r\n },\r\n ],\r\n})\r\nexport class FormulaBuilder implements ControlValueAccessor, OnDestroy {\r\n private readonly validatorService = inject(FormulaValidatorService);\r\n private readonly contextService = inject(FormulaContextService);\r\n\r\n /** Reference to the formula editor */\r\n private readonly editor = viewChild<FormulaEditor>('formulaEditor');\r\n\r\n // ===== INPUTS =====\r\n\r\n /** Properties per table path (e.g., \"Current\", \"Children.Project\") */\r\n readonly propertiesByPath = input<\r\n Record<string, { key: string; name?: string }[]>\r\n >({});\r\n\r\n /** Level schema ID for validation context */\r\n readonly levelSchemaId = input<number>();\r\n\r\n /** Template ID for validation context */\r\n readonly templateId = input<number>();\r\n\r\n /** Placeholder text */\r\n readonly placeholder = input('Enter formula...');\r\n\r\n /** Hide the top toolbar */\r\n readonly hideToolbar = input(false);\r\n\r\n /** Hide the status bar */\r\n readonly hideStatusBar = input(false);\r\n\r\n // ===== OUTPUTS =====\r\n\r\n /** Emits validation result on change */\r\n readonly validationChange = output<ValidationResult>();\r\n\r\n /** Emits when tokens change */\r\n readonly tokensChange = output<FormulaToken[]>();\r\n\r\n // ===== STATE =====\r\n\r\n /** Editor focus state */\r\n readonly hasFocus = signal(false);\r\n\r\n /** Form control value */\r\n private readonly expressionValue = signal('');\r\n private readonly builderValue = signal<FormulaToken[]>([]);\r\n\r\n /** Tokens for the editor */\r\n readonly tokens = signal<FormulaToken[]>([]);\r\n\r\n /** Track last synced builder JSON to avoid loops */\r\n private lastBuilderJson = '';\r\n\r\n /** ControlValueAccessor callbacks */\r\n private onChange: (value: FormulaBuilderValue) => void = () => {};\r\n private onTouched: () => void = () => {};\r\n\r\n /** Disabled state */\r\n private readonly isDisabled = signal(false);\r\n\r\n /** Validation result from service */\r\n readonly validation = this.validatorService.validation;\r\n\r\n /** Is validation in progress */\r\n readonly isValidating = this.validatorService.isValidating;\r\n\r\n /** Builder context from API */\r\n readonly builderContext = signal<FormulaBuilderContextResponse | null>(null);\r\n\r\n /** Function categories from context */\r\n readonly functionCategories = computed(\r\n () => this.builderContext()?.functions?.categories ?? [],\r\n );\r\n\r\n /** Is builder context loading */\r\n readonly isContextLoading = signal(false);\r\n\r\n private contextRequestId = 0;\r\n\r\n /** Properties loaded from API */\r\n private readonly propertiesByPathApi = signal<\r\n Record<string, FormulaPropertyDescriptor[]>\r\n >({});\r\n\r\n /** Current property list loading path */\r\n private readonly propertyLoadingPath = signal<string | null>(null);\r\n\r\n constructor() {\r\n // Validate when formula changes\r\n effect(() => {\r\n const formula = this.expressionValue();\r\n if (formula && formula.trim().length > 0) {\r\n this.validatorService.validate(\r\n formula,\r\n undefined,\r\n this.levelSchemaId(),\r\n this.templateId(),\r\n );\r\n }\r\n });\r\n\r\n // Emit validation changes\r\n effect(() => {\r\n const validation = this.validation();\r\n this.validationChange.emit(validation);\r\n });\r\n\r\n // Load builder context when schema changes\r\n effect(() => {\r\n const schemaId = this.levelSchemaId();\r\n\r\n if (!schemaId) {\r\n this.builderContext.set(null);\r\n this.propertiesByPathApi.set({});\r\n this.nextTokenRulesByPath.set({});\r\n this.isContextLoading.set(false);\r\n return;\r\n }\r\n\r\n const requestId = ++this.contextRequestId;\r\n this.isContextLoading.set(true);\r\n this.nextTokenRulesByPath.set({});\r\n this.contextService.loadContext(schemaId).subscribe((context) => {\r\n if (requestId !== this.contextRequestId) {\r\n return;\r\n }\r\n\r\n this.builderContext.set(context);\r\n this.isContextLoading.set(false);\r\n\r\n if (!context) {\r\n return;\r\n }\r\n\r\n if (context.currentProperties?.length) {\r\n const scalarOperators =\r\n context.schemaDescriptor?.operators?.filter(\r\n (operator) =>\r\n operator.cardinality === 'scalar' &&\r\n !operator.requiresParameter &&\r\n !operator.parameterKind,\r\n ) ?? [];\r\n const scopedProperties = scalarOperators.reduce(\r\n (acc, operator) => ({\r\n ...acc,\r\n [operator.token]: context.currentProperties,\r\n }),\r\n {} as Record<string, FormulaPropertyDescriptor[]>,\r\n );\r\n this.propertiesByPathApi.update((current) => ({\r\n ...current,\r\n ...scopedProperties,\r\n }));\r\n }\r\n });\r\n });\r\n\r\n // Ensure selected scope exists in available options\r\n effect(() => {\r\n const scopes = this.availableScopes();\r\n if (scopes.length === 0) return;\r\n const current = this.propertyScope();\r\n if (!scopes.some((scope) => scope.key === current)) {\r\n this.setPropertyScope(scopes[0].key);\r\n }\r\n });\r\n\r\n // Fetch properties for the selected table path\r\n effect(() => {\r\n const schemaId = this.levelSchemaId();\r\n const tablePath = this.resolvedTablePath();\r\n const component = this.propertiesComponent();\r\n const context = this.builderContext();\r\n\r\n if (!schemaId || !tablePath || !component || !context) {\r\n this.propertyLoadingPath.set(null);\r\n return;\r\n }\r\n\r\n const existing = this.propertiesByPathApi()[tablePath];\r\n if (existing !== undefined) {\r\n this.propertyLoadingPath.set(null);\r\n return;\r\n }\r\n\r\n this.propertyLoadingPath.set(tablePath);\r\n this.contextService\r\n .getScopeProperties(schemaId, component, tablePath)\r\n .subscribe((props) => {\r\n this.propertiesByPathApi.update((current) => ({\r\n ...current,\r\n [tablePath]: props ?? [],\r\n }));\r\n if (this.propertyLoadingPath() === tablePath) {\r\n this.propertyLoadingPath.set(null);\r\n }\r\n });\r\n });\r\n\r\n // Fetch next-token rules for the current table path\r\n effect(() => {\r\n const schemaId = this.levelSchemaId();\r\n const tablePath = this.resolvedTablePath();\r\n const component = this.propertiesComponent();\r\n\r\n if (!schemaId || !tablePath || !component) return;\r\n\r\n if (this.nextTokenRulesByPath()[tablePath]) return;\r\n\r\n this.contextService\r\n .getNextTokens(schemaId, component, tablePath)\r\n .subscribe((response) => {\r\n if (!response) return;\r\n this.nextTokenRulesByPath.update((current) => ({\r\n ...current,\r\n [tablePath]: response.nextTokenRules ?? {},\r\n }));\r\n });\r\n });\r\n\r\n // Keep base segment in sync with scope metadata\r\n effect(() => {\r\n const scope = this.propertyScope();\r\n const operator = this.baseOperator();\r\n const shouldHaveSegment =\r\n Boolean(operator?.parameterKind) ||\r\n Boolean(operator?.requiresParameter);\r\n const segments = this.propertyPathSegments();\r\n const hasBase = segments[0]?.operatorToken === scope;\r\n\r\n if (shouldHaveSegment && !hasBase) {\r\n this.propertyPathSegments.set(\r\n buildInitialSegments(scope, operator, this.baseRule()),\r\n );\r\n return;\r\n }\r\n\r\n if (!shouldHaveSegment && hasBase) {\r\n this.propertyPathSegments.set(segments.slice(1));\r\n }\r\n });\r\n\r\n // Normalize segment values when allowed values change\r\n effect(() => {\r\n const meta = this.pathSegments();\r\n const segments = this.propertyPathSegments();\r\n if (meta.length !== segments.length) return;\r\n\r\n let changed = false;\r\n const next = segments.map((segment, index) => {\r\n const normalized = meta[index]?.value ?? segment.value;\r\n if (segment.value !== normalized) {\r\n changed = true;\r\n return { ...segment, value: normalized };\r\n }\r\n return segment;\r\n });\r\n\r\n if (changed) {\r\n this.propertyPathSegments.set(next);\r\n }\r\n });\r\n\r\n // Ensure selected field exists in current options\r\n effect(() => {\r\n const options = this.propertyOptions();\r\n const current = this.propertyFieldKey();\r\n\r\n if (options.length === 0) {\r\n if (current) this.propertyFieldKey.set('');\r\n return;\r\n }\r\n\r\n if (current && !options.some((prop) => prop.key === current)) {\r\n this.propertyFieldKey.set('');\r\n }\r\n });\r\n }\r\n\r\n ngOnDestroy(): void {\r\n this.validatorService.reset();\r\n }\r\n\r\n // ===== ControlValueAccessor =====\r\n\r\n writeValue(value: FormulaBuilderValue | null): void {\r\n if (!value) {\r\n this.expressionValue.set('');\r\n this.builderValue.set([]);\r\n this.tokens.set([]);\r\n this.lastBuilderJson = '';\r\n const editor = this.editor();\r\n if (editor) {\r\n editor.writeValue([]);\r\n }\r\n this.validatorService.reset();\r\n return;\r\n }\r\n\r\n this.expressionValue.set(value.expression ?? '');\r\n const builder = Array.isArray(value.builder) ? value.builder : [];\r\n this.builderValue.set(builder);\r\n\r\n if (builder.length === 0) {\r\n this.tokens.set([]);\r\n this.lastBuilderJson = '';\r\n const editor = this.editor();\r\n if (editor) {\r\n editor.writeValue([]);\r\n }\r\n return;\r\n }\r\n\r\n const serialized = JSON.stringify(builder);\r\n if (serialized === this.lastBuilderJson) {\r\n return;\r\n }\r\n\r\n this.tokens.set(builder);\r\n const editor = this.editor();\r\n if (editor) {\r\n editor.writeValue(builder);\r\n }\r\n this.lastBuilderJson = serialized;\r\n }\r\n\r\n registerOnChange(fn: (value: FormulaBuilderValue) => void): void {\r\n this.onChange = fn;\r\n }\r\n\r\n registerOnTouched(fn: () => void): void {\r\n this.onTouched = fn;\r\n }\r\n\r\n setDisabledState(isDisabled: boolean): void {\r\n this.isDisabled.set(isDisabled);\r\n }\r\n\r\n /** Handle formula change from editor */\r\n onFormulaChange(newFormula: string): void {\r\n this.expressionValue.set(newFormula);\r\n this.emitValueChange();\r\n }\r\n\r\n /** Handle block insert from toolbar */\r\n onBlockInsert(block: SmartBlock): void {\r\n const editor = this.editor();\r\n if (editor) {\r\n editor.addBlock(block);\r\n }\r\n }\r\n\r\n /** Handle tokens change */\r\n onTokensChange(newTokens: FormulaToken[]): void {\r\n this.tokens.set(newTokens);\r\n const json = JSON.stringify(newTokens);\r\n this.lastBuilderJson = json;\r\n this.builderValue.set(newTokens);\r\n this.tokensChange.emit(newTokens);\r\n this.emitValueChange();\r\n }\r\n\r\n onEditorFocus(): void {\r\n this.hasFocus.set(true);\r\n }\r\n\r\n onEditorBlur(): void {\r\n this.hasFocus.set(false);\r\n this.onTouched();\r\n }\r\n\r\n private emitValueChange(): void {\r\n this.onChange({\r\n expression: this.expressionValue(),\r\n builder: this.builderValue(),\r\n });\r\n }\r\n\r\n // ===== PUBLIC METHODS =====\r\n\r\n /** Clear the formula */\r\n clear(): void {\r\n this.expressionValue.set('');\r\n this.tokens.set([]);\r\n this.builderValue.set([]);\r\n this.lastBuilderJson = '';\r\n const editor = this.editor();\r\n if (editor) {\r\n editor.writeValue([]);\r\n }\r\n this.validatorService.reset();\r\n this.emitValueChange();\r\n }\r\n\r\n // ===== PROPERTY COMPOSER =====\r\n\r\n readonly propertyScope = signal<string>('');\r\n\r\n readonly propertyPathSegments = signal<PathSegment[]>([]);\r\n\r\n readonly propertyFieldKey = signal('');\r\n\r\n private readonly nextTokenRulesByPath = signal<\r\n Record<string, Record<string, NextTokenRule>>\r\n >({});\r\n\r\n readonly contextOperators = computed<OperatorDescriptor[]>(() => {\r\n return this.builderContext()?.schemaDescriptor?.operators ?? [];\r\n });\r\n\r\n readonly baseOperator = computed(() =>\r\n this.contextOperators().find((op) => op.token === this.propertyScope()),\r\n );\r\n\r\n readonly baseRule = computed(() => {\r\n const scope = this.propertyScope();\r\n return this.builderContext()?.schemaDescriptor?.nextTokenRules?.[scope];\r\n });\r\n\r\n readonly availableScopes = computed(() => {\r\n const operators = this.contextOperators();\r\n if (operators.length === 0) return [];\r\n return operators.map((operator) => ({\r\n key: operator.token,\r\n label: `@${operator.token}`,\r\n requiresParam: operator.requiresParameter ?? false,\r\n optional: !operator.requiresParameter,\r\n }));\r\n });\r\n\r\n /** Radio card options for scope selection */\r\n readonly scopeOptions = computed<RadioItem[]>(() =>\r\n this.availableScopes().map((scope) => ({\r\n id: scope.key,\r\n name: scope.key,\r\n icon: SCOPE_ICON_MAP[scope.key] ?? DEFAULT_SCOPE_ICON,\r\n })),\r\n );\r\n\r\n /** Handle scope selection from radio cards */\r\n onScopeChange(item: RadioItem): void {\r\n this.setPropertyScope(String(item.id));\r\n }\r\n\r\n readonly pathSegments = computed<SegmentMeta[]>(() => {\r\n const scope = this.propertyScope();\r\n return resolveSegmentsMeta({\r\n scope,\r\n segments: this.propertyPathSegments(),\r\n operators: this.contextOperators(),\r\n baseRule: this.baseRule(),\r\n rulesByPath: this.nextTokenRulesByPath(),\r\n });\r\n });\r\n\r\n readonly isDirectAccess = computed(() => {\r\n const operator = this.baseOperator();\r\n const needsParameter =\r\n Boolean(operator?.parameterKind) || Boolean(operator?.requiresParameter);\r\n return !needsParameter && this.pathSegments().length === 0;\r\n });\r\n\r\n readonly propertyTablePath = computed(() =>\r\n buildTablePath(\r\n this.propertyScope(),\r\n this.pathSegments(),\r\n this.baseOperator(),\r\n false,\r\n ),\r\n );\r\n\r\n readonly resolvedTablePath = computed(() =>\r\n buildTablePath(\r\n this.propertyScope(),\r\n this.pathSegments(),\r\n this.baseOperator(),\r\n true,\r\n ),\r\n );\r\n\r\n readonly currentNextTokenRules = computed(() => {\r\n const path = this.resolvedTablePath();\r\n if (!path) return {};\r\n return this.nextTokenRulesByPath()[path] ?? {};\r\n });\r\n\r\n readonly nextOperatorOptions = computed(() => {\r\n const rules = this.currentNextTokenRules();\r\n const operators = this.contextOperators();\r\n return Object.keys(rules)\r\n .map((token) => {\r\n const rule = rules[token];\r\n const operator = operators.find((item) => item.token === token);\r\n const parameterKind =\r\n rule?.parameterKind ?? operator?.parameterKind ?? null;\r\n const requiresParameter =\r\n operator?.requiresParameter ?? Boolean(parameterKind);\r\n const allowedValues = getAllowedValues(rule);\r\n return {\r\n token,\r\n rule,\r\n requiresParameter,\r\n allowedValues,\r\n };\r\n })\r\n .filter(\r\n (option) =>\r\n option.allowedValues.length > 0 || !option.requiresParameter,\r\n );\r\n });\r\n\r\n readonly canAddNextSegment = computed(() => {\r\n if (this.nextOperatorOptions().length === 0) return false;\r\n const segments = this.pathSegments();\r\n if (segments.length === 0 || !segments[0].value) {\r\n return false;\r\n }\r\n return segments.every(\r\n (segment) => !segment.requiresParameter || Boolean(segment.value),\r\n );\r\n });\r\n\r\n readonly propertiesComponent = computed(() => {\r\n const contextKey = this.builderContext()?.contextEntityTypeKey;\r\n return contextKey;\r\n });\r\n\r\n readonly mergedPropertiesByPath = computed<\r\n Record<string, FormulaPropertyDescriptor[]>\r\n >(() => {\r\n const merged: Record<string, FormulaPropertyDescriptor[]> = {\r\n ...this.propertiesByPath(),\r\n };\r\n const apiProps = this.propertiesByPathApi();\r\n Object.entries(apiProps).forEach(([path, props]) => {\r\n if (props && props.length > 0) {\r\n merged[path] = props;\r\n }\r\n });\r\n return merged;\r\n });\r\n\r\n readonly isPropertyLoading = computed(() => {\r\n const path = this.resolvedTablePath();\r\n return Boolean(path) && this.propertyLoadingPath() === path;\r\n });\r\n\r\n readonly propertyOptions = computed(() => {\r\n const path = this.resolvedTablePath();\r\n if (!path) return [];\r\n const byPath = this.mergedPropertiesByPath()[path];\r\n const list = byPath && byPath.length > 0 ? byPath : [];\r\n return list.map((prop) => ({\r\n key: prop.key,\r\n name: prop.name ?? prop.key,\r\n }));\r\n });\r\n\r\n readonly selectedProperty = computed(() => {\r\n const key = this.propertyFieldKey();\r\n return this.propertyOptions().find((prop) => prop.key === key) ?? null;\r\n });\r\n\r\n readonly canInsertProperty = computed(() => {\r\n if (!this.selectedProperty()) return false;\r\n return Boolean(this.resolvedTablePath());\r\n });\r\n\r\n setPropertyScope(scope: string): void {\r\n if (this.propertyScope() === scope) {\r\n return;\r\n }\r\n this.propertyScope.set(scope);\r\n this.propertyPathSegments.set(\r\n buildInitialSegments(\r\n scope,\r\n this.contextOperators().find((op) => op.token === scope),\r\n this.builderContext()?.schemaDescriptor?.nextTokenRules?.[scope],\r\n ),\r\n );\r\n this.propertyFieldKey.set('');\r\n }\r\n\r\n setPathSegmentValue(index: number, value: string | null): void {\r\n this.propertyPathSegments.update((segments) => {\r\n // Update the segment at the given index and remove all segments after it\r\n // because subsequent segments depend on previous values\r\n const updated = segments.slice(0, index + 1);\r\n updated[index] = { ...updated[index], value: value ?? '' };\r\n return updated;\r\n });\r\n }\r\n\r\n addNextSegment(operatorToken: string): void {\r\n const value = '';\r\n\r\n this.propertyPathSegments.update((segments) => [\r\n ...segments,\r\n { operatorToken, value },\r\n ]);\r\n }\r\n\r\n onAddSegmentSelection(\r\n operatorToken: string,\r\n popover: { hide: () => void },\r\n ): void {\r\n popover.hide();\r\n this.addNextSegment(operatorToken);\r\n }\r\n\r\n removePathSegment(index: number): void {\r\n this.propertyPathSegments.update((segments) =>\r\n segments.filter((_, i) => i !== index),\r\n );\r\n }\r\n\r\n segmentOptions(index: number): { key: string; name: string }[] {\r\n const segment = this.pathSegments()[index];\r\n if (!segment) return [];\r\n return segment.allowedValues.map((value) => ({\r\n key: value,\r\n name: value,\r\n }));\r\n }\r\n\r\n insertSelectedProperty(insertBlock: (block: SmartBlock) => void): void {\r\n const prop = this.selectedProperty();\r\n if (!prop) return;\r\n\r\n if (!this.canInsertProperty()) return;\r\n\r\n const tablePath = this.resolvedTablePath();\r\n if (!tablePath) return;\r\n const display = prop.name ?? prop.key;\r\n const block = createPropertyBlock(\r\n `@${tablePath}::${prop.key}`,\r\n 'current',\r\n display,\r\n );\r\n insertBlock(block);\r\n }\r\n}\r\n","<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 (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 >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 ✓ Direct Access\r\n </span>\r\n } @else if (pathSegments().length === 0) {\r\n <span class=\"text-xs italic text-slate-400\"\r\n >No path configured</span\r\n >\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 >›</span\r\n >\r\n }\r\n <mt-button\r\n type=\"button\"\r\n [label]=\"\r\n segment.value ||\r\n 'Select ' + 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 Select {{ segment.operatorToken }}\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=\"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 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]=\"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 >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=\"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=\"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 <mt-formula-editor\r\n #formulaEditor\r\n [placeholder]=\"placeholder()\"\r\n [initialTokens]=\"tokens()\"\r\n (formulaChange)=\"onFormulaChange($event)\"\r\n (tokensChange)=\"onTokensChange($event)\"\r\n (onFocus)=\"onEditorFocus()\"\r\n (onBlur)=\"onEditorBlur()\"\r\n />\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","/**\r\n * Services barrel export\r\n */\r\n\r\nexport * from './formula-context.service';\r\nexport * from './formula-validator.service';\r\n","/**\r\n * Public API Surface of @masterteam/formula-builder\r\n *\r\n * This package provides the FormulaBuilder component which wraps\r\n * pure UI components from @masterteam/components/formula with\r\n * backend services for validation and context loading.\r\n *\r\n * Architecture:\r\n * - UI Components: imported from @masterteam/components/formula (pure, no services)\r\n * - Services: FormulaContextService, FormulaValidatorService (backend logic)\r\n * - FormulaBuilder: Main wrapper that connects UI with services\r\n */\r\n\r\n// Main component\r\nexport * from './lib/formula-builder';\r\n\r\n// Services (backend logic only)\r\nexport * from './lib/services/index';\r\n\r\n// Re-export models from base package for convenience\r\nexport {\r\n type SmartBlock,\r\n type BlockType,\r\n type ArgumentSlot,\r\n type FormulaToken,\r\n type TokenType,\r\n type DragBehavior,\r\n type ValidationResult,\r\n type ValidationError,\r\n type FunctionDefinition,\r\n type FunctionCategoryGroup,\r\n type OperatorDefinition,\r\n createFunctionBlock,\r\n createPropertyBlock,\r\n createOperatorBlock,\r\n createLiteralBlock,\r\n} from '@masterteam/components/formula';\r\n\r\n// Export validation-specific models\r\nexport type {\r\n ValidationRequest,\r\n FunctionCatalogResponse,\r\n ApiErrorResponse,\r\n} from './lib/models/validation-result.model';\r\n\r\n// Export value model for ControlValueAccessor usage\r\nexport type { FormulaBuilderValue } from './lib/models/formula-builder-value.model';\r\n\r\n// Export builder context models\r\nexport type {\r\n FormulaBuilderContextResponse,\r\n FormulaPropertyDescriptor,\r\n FormulaEngineSchemaDescriptor,\r\n OperatorDescriptor,\r\n NextTokenRule,\r\n} from './lib/models/formula-context.model';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"masterteam-formula-builder.mjs","sources":["../../../../packages/masterteam/formula-builder/src/lib/services/formula-validator.service.ts","../../../../packages/masterteam/formula-builder/src/lib/services/formula-context.service.ts","../../../../packages/masterteam/formula-builder/src/lib/services/formula-autocomplete.service.ts","../../../../packages/masterteam/formula-builder/src/lib/utils/formula-path-builder.ts","../../../../packages/masterteam/formula-builder/src/lib/formula-builder.ts","../../../../packages/masterteam/formula-builder/src/lib/formula-builder.html","../../../../packages/masterteam/formula-builder/src/lib/services/index.ts","../../../../packages/masterteam/formula-builder/src/public-api.ts","../../../../packages/masterteam/formula-builder/src/masterteam-formula-builder.ts"],"sourcesContent":["/**\r\n * Formula Validator Service\r\n * Handles real-time validation via API\r\n */\r\n\r\nimport { Injectable, inject, signal } from '@angular/core';\r\nimport { HttpClient, HttpErrorResponse } from '@angular/common/http';\r\nimport {\r\n Observable,\r\n Subject,\r\n of,\r\n catchError,\r\n debounceTime,\r\n distinctUntilChanged,\r\n map,\r\n switchMap,\r\n tap,\r\n} from 'rxjs';\r\nimport {\r\n ValidationResult,\r\n ValidationRequest,\r\n ApiErrorResponse,\r\n} from '../models/validation-result.model';\r\n\r\n/** Default validation result for empty formulas */\r\nconst EMPTY_VALIDATION: ValidationResult = {\r\n isValid: true,\r\n errors: [],\r\n warnings: [],\r\n dependencies: [],\r\n complexity: 0,\r\n};\r\n\r\n/** Error validation result */\r\nconst ERROR_VALIDATION: ValidationResult = {\r\n isValid: false,\r\n errors: [\r\n { message: 'Validation failed', line: 1, column: 1, severity: 'Error' },\r\n ],\r\n warnings: [],\r\n dependencies: [],\r\n complexity: 0,\r\n};\r\n\r\n@Injectable({ providedIn: 'root' })\r\nexport class FormulaValidatorService {\r\n private readonly http = inject(HttpClient);\r\n private readonly apiUrl = '/formulas';\r\n\r\n /** Debounce time in ms */\r\n private readonly DEBOUNCE_MS = 300;\r\n\r\n /** Current validation result */\r\n private readonly _validation = signal<ValidationResult>(EMPTY_VALIDATION);\r\n\r\n /** Loading state */\r\n private readonly _isValidating = signal(false);\r\n\r\n /** Validation subject for debouncing */\r\n private readonly validateSubject = new Subject<ValidationRequest>();\r\n\r\n private unwrapResponse<T>(response: T | { data: T } | null): T | null {\r\n if (!response) return null;\r\n if (typeof response === 'object' && response !== null && 'data' in response) {\r\n return (response as { data: T }).data ?? null;\r\n }\r\n return response as T;\r\n }\r\n\r\n /** Public signals */\r\n readonly validation = this._validation.asReadonly();\r\n readonly isValidating = this._isValidating.asReadonly();\r\n\r\n constructor() {\r\n this.setupValidationStream();\r\n }\r\n\r\n /** Setup debounced validation stream */\r\n private setupValidationStream(): void {\r\n this.validateSubject\r\n .pipe(\r\n debounceTime(this.DEBOUNCE_MS),\r\n distinctUntilChanged(\r\n (a, b) =>\r\n a.formula === b.formula &&\r\n JSON.stringify(a.knownProperties) ===\r\n JSON.stringify(b.knownProperties),\r\n ),\r\n tap(() => this._isValidating.set(true)),\r\n switchMap((request) => this.callValidateApi(request)),\r\n )\r\n .subscribe((result) => {\r\n this._validation.set(result);\r\n this._isValidating.set(false);\r\n });\r\n }\r\n\r\n /** Validate formula (debounced) */\r\n validate(\r\n formula: string,\r\n knownProperties?: string[],\r\n levelSchemaId?: number,\r\n templateId?: number,\r\n ): void {\r\n // Handle empty formula\r\n if (!formula || formula.trim() === '') {\r\n this._validation.set(EMPTY_VALIDATION);\r\n return;\r\n }\r\n\r\n // Push to debounced stream\r\n this.validateSubject.next({\r\n formula,\r\n knownProperties,\r\n levelSchemaId,\r\n templateId,\r\n });\r\n }\r\n\r\n /** Validate formula immediately (no debounce) */\r\n validateImmediate(\r\n formula: string,\r\n knownProperties?: string[],\r\n levelSchemaId?: number,\r\n templateId?: number,\r\n ): Observable<ValidationResult> {\r\n if (!formula || formula.trim() === '') {\r\n return of(EMPTY_VALIDATION);\r\n }\r\n\r\n this._isValidating.set(true);\r\n\r\n return this.callValidateApi({\r\n formula,\r\n knownProperties,\r\n levelSchemaId,\r\n templateId,\r\n }).pipe(\r\n tap((result) => {\r\n this._validation.set(result);\r\n this._isValidating.set(false);\r\n }),\r\n );\r\n }\r\n\r\n /** Call validation API */\r\n private callValidateApi(\r\n request: ValidationRequest,\r\n ): Observable<ValidationResult> {\r\n return this.http\r\n .post<ValidationResult | { data: ValidationResult }>(\r\n `${this.apiUrl}/validate`,\r\n request,\r\n )\r\n .pipe(\r\n map((response) => this.unwrapResponse(response) ?? ERROR_VALIDATION),\r\n catchError((error: HttpErrorResponse) => {\r\n console.error('Validation API error:', error);\r\n\r\n // Try to extract error message\r\n const apiError = error.error as ApiErrorResponse;\r\n const message =\r\n apiError?.message ?? apiError?.error ?? 'Validation failed';\r\n\r\n return of({\r\n ...ERROR_VALIDATION,\r\n errors: [\r\n { message, line: 1, column: 1, severity: 'Error' as const },\r\n ],\r\n });\r\n }),\r\n );\r\n }\r\n\r\n /** Reset validation state */\r\n reset(): void {\r\n this._validation.set(EMPTY_VALIDATION);\r\n this._isValidating.set(false);\r\n }\r\n\r\n /** Get current validation result */\r\n getCurrentValidation(): ValidationResult {\r\n return this._validation();\r\n }\r\n\r\n /** Check if formula is valid */\r\n isValid(): boolean {\r\n return this._validation().isValid;\r\n }\r\n\r\n /** Get validation errors */\r\n getErrors() {\r\n return this._validation().errors;\r\n }\r\n\r\n /** Get validation warnings */\r\n getWarnings() {\r\n return this._validation().warnings;\r\n }\r\n\r\n /** Get formula dependencies */\r\n getDependencies() {\r\n return this._validation().dependencies;\r\n }\r\n\r\n /** Get formula complexity */\r\n getComplexity() {\r\n return this._validation().complexity;\r\n }\r\n}\r\n","import { Injectable, inject } from '@angular/core';\r\nimport { HttpClient } from '@angular/common/http';\r\nimport { Observable, of, catchError, tap, map } from 'rxjs';\r\n\r\nimport type {\r\n FormulaBuilderContextResponse,\r\n FormulaBuilderNextTokensResponse,\r\n FormulaPropertyDescriptor,\r\n} from '../models/formula-context.model';\r\n\r\n@Injectable({ providedIn: 'root' })\r\nexport class FormulaContextService {\r\n private readonly http = inject(HttpClient);\r\n private readonly apiUrl = '/formulas';\r\n\r\n private unwrapResponse<T>(response: T | { data: T } | null): T | null {\r\n if (!response) return null;\r\n if (typeof response === 'object' && response !== null && 'data' in response) {\r\n return (response as { data: T }).data ?? null;\r\n }\r\n return response as T;\r\n }\r\n\r\n private readonly contextCache = new Map<\r\n string,\r\n FormulaBuilderContextResponse\r\n >();\r\n private readonly propertiesCache = new Map<\r\n string,\r\n FormulaPropertyDescriptor[]\r\n >();\r\n private readonly nextTokensCache = new Map<\r\n string,\r\n FormulaBuilderNextTokensResponse\r\n >();\r\n\r\n loadContext(\r\n schemaId: number,\r\n contextEntityTypeKey?: string,\r\n ): Observable<FormulaBuilderContextResponse | null> {\r\n if (!schemaId) return of(null);\r\n\r\n const cacheKey = `${schemaId}:${contextEntityTypeKey ?? ''}`;\r\n const cached = this.contextCache.get(cacheKey);\r\n if (cached) {\r\n return of(cached);\r\n }\r\n\r\n const query = contextEntityTypeKey\r\n ? `?contextEntityTypeKey=${encodeURIComponent(contextEntityTypeKey)}`\r\n : '';\r\n\r\n return this.http\r\n .get<FormulaBuilderContextResponse | { data: FormulaBuilderContextResponse }>(\r\n `${this.apiUrl}/builder/context/${schemaId}${query}`,\r\n )\r\n .pipe(\r\n map((response) => this.unwrapResponse(response)),\r\n tap((context) => {\r\n if (context) {\r\n this.contextCache.set(cacheKey, context);\r\n }\r\n }),\r\n catchError((error) => {\r\n console.warn('Failed to load formula builder context:', error);\r\n return of(null);\r\n }),\r\n );\r\n }\r\n\r\n getScopeProperties(\r\n schemaId: number,\r\n component: string,\r\n tablePath: string,\r\n ): Observable<FormulaPropertyDescriptor[]> {\r\n if (!schemaId || !component || !tablePath) return of([]);\r\n\r\n const cacheKey = `${schemaId}:${component}:${tablePath}`;\r\n const cached = this.propertiesCache.get(cacheKey);\r\n if (cached) {\r\n return of(cached);\r\n }\r\n\r\n const params = new URLSearchParams({\r\n schemaId: schemaId.toString(),\r\n component,\r\n tablePath,\r\n });\r\n\r\n return this.http\r\n .get<\r\n FormulaPropertyDescriptor[] | { data: FormulaPropertyDescriptor[] }\r\n >(`${this.apiUrl}/builder/properties?${params.toString()}`)\r\n .pipe(\r\n map((response) => this.unwrapResponse(response) ?? []),\r\n tap((response) => {\r\n this.propertiesCache.set(cacheKey, response);\r\n }),\r\n catchError((error) => {\r\n console.warn('Failed to load formula properties:', error);\r\n return of([]);\r\n }),\r\n );\r\n }\r\n\r\n getNextTokens(\r\n schemaId: number,\r\n component: string,\r\n tablePath: string,\r\n ): Observable<FormulaBuilderNextTokensResponse | null> {\r\n if (!schemaId || !component || !tablePath) return of(null);\r\n\r\n const cacheKey = `${schemaId}:${component}:${tablePath}`;\r\n const cached = this.nextTokensCache.get(cacheKey);\r\n if (cached) {\r\n return of(cached);\r\n }\r\n\r\n const params = new URLSearchParams({\r\n schemaId: schemaId.toString(),\r\n component,\r\n tablePath,\r\n });\r\n\r\n return this.http\r\n .get<\r\n | FormulaBuilderNextTokensResponse\r\n | { data: FormulaBuilderNextTokensResponse }\r\n >(`${this.apiUrl}/builder/next-tokens?${params.toString()}`)\r\n .pipe(\r\n map((response) => this.unwrapResponse(response)),\r\n tap((payload) => {\r\n if (payload) {\r\n this.nextTokensCache.set(cacheKey, payload);\r\n }\r\n }),\r\n catchError((error) => {\r\n console.warn('Failed to load formula next tokens:', error);\r\n return of(null);\r\n }),\r\n );\r\n }\r\n}\r\n","import { Injectable, inject } from '@angular/core';\r\nimport { HttpClient } from '@angular/common/http';\r\nimport { Observable, of, catchError, map } from 'rxjs';\r\nimport type {\r\n AutocompleteRequest,\r\n AutocompleteResponse,\r\n} from '../models/validation-result.model';\r\n\r\n@Injectable({ providedIn: 'root' })\r\nexport class FormulaAutocompleteService {\r\n private readonly http = inject(HttpClient);\r\n private readonly apiUrl = '/formulas';\r\n\r\n private unwrapResponse<T>(response: T | { data: T } | null): T | null {\r\n if (!response) return null;\r\n if (typeof response === 'object' && response !== null && 'data' in response) {\r\n return (response as { data: T }).data ?? null;\r\n }\r\n return response as T;\r\n }\r\n\r\n getSuggestions(\r\n request: AutocompleteRequest,\r\n ): Observable<AutocompleteResponse | null> {\r\n if (!request) {\r\n return of(null);\r\n }\r\n\r\n const normalized: AutocompleteRequest = {\r\n ...request,\r\n formula: request.formula ?? '',\r\n };\r\n\r\n return this.http\r\n .post<AutocompleteResponse | { data: AutocompleteResponse }>(\r\n `${this.apiUrl}/autocomplete`,\r\n normalized,\r\n )\r\n .pipe(\r\n map((response) => this.unwrapResponse(response)),\r\n catchError((error) => {\r\n console.warn('Autocomplete API error:', error);\r\n return of(null);\r\n }),\r\n );\r\n }\r\n}\r\n","import type {\r\n NextTokenRule,\r\n OperatorDescriptor,\r\n} from '../models/formula-context.model';\r\n\r\nexport type PathSegment = {\r\n operatorToken: string;\r\n value: string;\r\n};\r\n\r\nexport type SegmentMeta = PathSegment & {\r\n parameterKind?: string | null;\r\n requiresParameter: boolean;\r\n allowedValues: string[];\r\n optional: boolean;\r\n canRemove: boolean;\r\n};\r\n\r\nexport type ResolveSegmentsParams = {\r\n scope: string;\r\n segments: PathSegment[];\r\n operators: OperatorDescriptor[];\r\n baseRule?: NextTokenRule;\r\n rulesByPath: Record<string, Record<string, NextTokenRule>>;\r\n};\r\n\r\nexport function resolveSegmentsMeta({\r\n scope,\r\n segments,\r\n operators,\r\n baseRule,\r\n rulesByPath,\r\n}: ResolveSegmentsParams): SegmentMeta[] {\r\n if (!scope || segments.length === 0) {\r\n return [];\r\n }\r\n\r\n let pathBefore = scope;\r\n let blocked = false;\r\n\r\n return segments.map((segment, index) => {\r\n const isBase = index === 0 && segment.operatorToken === scope;\r\n const operator = operators.find((op) => op.token === segment.operatorToken);\r\n const rule = blocked\r\n ? undefined\r\n : isBase\r\n ? baseRule\r\n : rulesByPath[pathBefore]?.[segment.operatorToken];\r\n const parameterKind =\r\n rule?.parameterKind ?? operator?.parameterKind ?? null;\r\n const requiresParameter =\r\n operator?.requiresParameter ?? Boolean(parameterKind);\r\n const allowedValues = getAllowedValues(rule);\r\n const normalizedValue = segment.value;\r\n const isComplete = !requiresParameter || Boolean(normalizedValue);\r\n\r\n if (!blocked && isComplete) {\r\n pathBefore = appendToPath(\r\n pathBefore,\r\n segment.operatorToken,\r\n normalizedValue,\r\n isBase,\r\n );\r\n } else {\r\n blocked = true;\r\n }\r\n\r\n return {\r\n operatorToken: segment.operatorToken,\r\n value: normalizedValue,\r\n parameterKind,\r\n requiresParameter,\r\n allowedValues,\r\n optional: !requiresParameter,\r\n canRemove: !isBase,\r\n };\r\n });\r\n}\r\n\r\nexport function buildInitialSegments(\r\n scope: string,\r\n operator: OperatorDescriptor | undefined,\r\n rule: NextTokenRule | undefined,\r\n): PathSegment[] {\r\n if (!operator || !scope) return [];\r\n const parameterKind = operator.parameterKind ?? rule?.parameterKind ?? null;\r\n const requiresParameter =\r\n operator.requiresParameter ?? Boolean(parameterKind);\r\n const shouldHaveSegment = Boolean(parameterKind) || requiresParameter;\r\n if (!shouldHaveSegment) return [];\r\n\r\n return [{ operatorToken: scope, value: '' }];\r\n}\r\n\r\nexport function buildTablePath(\r\n scope: string,\r\n segments: SegmentMeta[],\r\n baseOperator: OperatorDescriptor | undefined,\r\n stopOnIncomplete: boolean,\r\n): string {\r\n if (!scope) return '';\r\n\r\n if (\r\n stopOnIncomplete &&\r\n segments.length === 0 &&\r\n (baseOperator?.requiresParameter || baseOperator?.parameterKind)\r\n ) {\r\n return '';\r\n }\r\n\r\n let path = scope;\r\n for (let index = 0; index < segments.length; index += 1) {\r\n const segment = segments[index];\r\n const isBase = index === 0 && segment.operatorToken === scope;\r\n if (!isBase) {\r\n path += `.${segment.operatorToken}`;\r\n }\r\n if (segment.value) {\r\n path += `.${segment.value}`;\r\n } else if (segment.requiresParameter && stopOnIncomplete) {\r\n return '';\r\n }\r\n }\r\n\r\n return path;\r\n}\r\n\r\nexport function getAllowedValues(rule: NextTokenRule | undefined): string[] {\r\n return rule?.allowedValues ?? [];\r\n}\r\n\r\nfunction appendToPath(\r\n basePath: string,\r\n operatorToken: string,\r\n value: string,\r\n isBase: boolean,\r\n): string {\r\n if (isBase) {\r\n if (!value) return basePath;\r\n if (!basePath) return value;\r\n return `${basePath}.${value}`;\r\n }\r\n if (!basePath) {\r\n return value ? `${operatorToken}.${value}` : operatorToken;\r\n }\r\n const withOperator = `${basePath}.${operatorToken}`;\r\n return value ? `${withOperator}.${value}` : withOperator;\r\n}\r\n","import {\r\n Component,\r\n forwardRef,\r\n input,\r\n output,\r\n signal,\r\n computed,\r\n inject,\r\n effect,\r\n OnDestroy,\r\n viewChild,\r\n} from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { TranslocoDirective } from '@jsverse/transloco';\r\nimport {\r\n ControlValueAccessor,\r\n FormsModule,\r\n NG_VALUE_ACCESSOR,\r\n} from '@angular/forms';\r\nimport { Card } from '@masterteam/components/card';\r\nimport { Button } from '@masterteam/components/button';\r\nimport { SelectField } from '@masterteam/components/select-field';\r\nimport { Tooltip } from '@masterteam/components/tooltip';\r\nimport { RadioCards, type RadioItem } from '@masterteam/components/radio-cards';\r\nimport { ToggleField } from '@masterteam/components/toggle-field';\r\nimport type { MTIcon } from '@masterteam/icons';\r\nimport { PopoverModule } from 'primeng/popover';\r\nimport { Skeleton } from 'primeng/skeleton';\r\nimport { Observable } from 'rxjs';\r\n\r\n// Import pure UI components from @masterteam/components/formula\r\nimport {\r\n FormulaToolbar,\r\n FormulaEditor,\r\n FormulaEditorCode,\r\n FormulaStatusBar,\r\n type SmartBlock,\r\n type FormulaToken,\r\n createPropertyBlock,\r\n} from '@masterteam/components/formula';\r\n\r\n// Services are kept in formula-builder (backend logic)\r\nimport { FormulaValidatorService } from './services/formula-validator.service';\r\nimport { FormulaContextService } from './services/formula-context.service';\r\nimport { FormulaAutocompleteService } from './services/formula-autocomplete.service';\r\nimport type {\r\n ValidationResult,\r\n AutocompleteRequest,\r\n AutocompleteResponse,\r\n} from './models/validation-result.model';\r\nimport type {\r\n FormulaBuilderContextResponse,\r\n FormulaPropertyDescriptor,\r\n NextTokenRule,\r\n OperatorDescriptor,\r\n} from './models/formula-context.model';\r\nimport type { FormulaBuilderValue } from './models/formula-builder-value.model';\r\nimport {\r\n buildInitialSegments,\r\n buildTablePath,\r\n getAllowedValues,\r\n resolveSegmentsMeta,\r\n type PathSegment,\r\n type SegmentMeta,\r\n} from './utils/formula-path-builder';\r\n\r\nconst DEFAULT_SCOPE_ICON: MTIcon = 'general.placeholder';\r\nconst SCOPE_ICON_MAP: Record<string, MTIcon> = {\r\n Current: 'map.marker-pin-01',\r\n Level: 'map.marker-pin-01',\r\n Parent: 'arrow.arrow-up',\r\n Children: 'user.users-01',\r\n Descendants: 'custom.hierarchy-structure',\r\n Modules: 'file.folder-closed',\r\n};\r\n\r\n@Component({\r\n selector: 'mt-formula-builder',\r\n standalone: true,\r\n imports: [\r\n CommonModule,\r\n TranslocoDirective,\r\n FormsModule,\r\n Card,\r\n Button,\r\n SelectField,\r\n Tooltip,\r\n RadioCards,\r\n ToggleField,\r\n PopoverModule,\r\n Skeleton,\r\n FormulaToolbar,\r\n FormulaStatusBar,\r\n FormulaEditor,\r\n FormulaEditorCode,\r\n ],\r\n templateUrl: './formula-builder.html',\r\n host: {\r\n class: 'block',\r\n },\r\n providers: [\r\n {\r\n provide: NG_VALUE_ACCESSOR,\r\n useExisting: forwardRef(() => FormulaBuilder),\r\n multi: true,\r\n },\r\n ],\r\n})\r\nexport class FormulaBuilder implements ControlValueAccessor, OnDestroy {\r\n private readonly validatorService = inject(FormulaValidatorService);\r\n private readonly contextService = inject(FormulaContextService);\r\n private readonly autocompleteService = inject(FormulaAutocompleteService);\r\n\r\n /** Reference to the formula editor */\r\n private readonly editor = viewChild<FormulaEditor>('formulaEditor');\r\n private readonly codeEditor = viewChild<FormulaEditorCode>(\r\n 'formulaEditorCode',\r\n );\r\n\r\n // ===== INPUTS =====\r\n\r\n /** Properties per table path (e.g., \"Current\", \"Children.Project\") */\r\n readonly propertiesByPath = input<\r\n Record<string, { key: string; name?: string }[]>\r\n >({});\r\n\r\n /** Level schema ID for validation context */\r\n readonly levelSchemaId = input<number>();\r\n\r\n /** Template ID for validation context */\r\n readonly templateId = input<number>();\r\n\r\n /** Placeholder text */\r\n readonly placeholder = input('Enter formula...');\r\n\r\n /** Hide the top toolbar */\r\n readonly hideToolbar = input(false);\r\n\r\n /** Hide the status bar */\r\n readonly hideStatusBar = input(false);\r\n\r\n // ===== OUTPUTS =====\r\n\r\n /** Emits validation result on change */\r\n readonly validationChange = output<ValidationResult>();\r\n\r\n /** Emits when tokens change */\r\n readonly tokensChange = output<FormulaToken[]>();\r\n\r\n // ===== STATE =====\r\n\r\n /** Editor focus state */\r\n readonly hasFocus = signal(false);\r\n\r\n /** Form control value */\r\n private readonly expressionValue = signal('');\r\n private readonly builderValue = signal<FormulaToken[]>([]);\r\n\r\n /** Tokens for the editor */\r\n readonly tokens = signal<FormulaToken[]>([]);\r\n readonly expression = computed(() => this.expressionValue());\r\n\r\n readonly autocompleteProvider = (\r\n request: AutocompleteRequest,\r\n ): Observable<AutocompleteResponse | null> => {\r\n return this.autocompleteService.getSuggestions({\r\n ...request,\r\n levelSchemaId: this.levelSchemaId(),\r\n contextEntityTypeKey: this.builderContext()?.contextEntityTypeKey,\r\n });\r\n };\r\n\r\n /** Track last synced builder JSON to avoid loops */\r\n private lastBuilderJson = '';\r\n\r\n /** Editor mode */\r\n readonly editorMode = signal<'builder' | 'code'>('builder');\r\n readonly isCodeMode = computed(() => this.editorMode() === 'code');\r\n readonly isCodeModeLocked = signal(false);\r\n private codeModeSnapshotTokens: FormulaToken[] = [];\r\n private codeModeSnapshotExpression = '';\r\n\r\n /** ControlValueAccessor callbacks */\r\n private onChange: (value: FormulaBuilderValue) => void = () => {};\r\n private onTouched: () => void = () => {};\r\n\r\n /** Disabled state */\r\n private readonly isDisabled = signal(false);\r\n\r\n /** Validation result from service */\r\n readonly validation = this.validatorService.validation;\r\n\r\n /** Is validation in progress */\r\n readonly isValidating = this.validatorService.isValidating;\r\n\r\n /** Builder context from API */\r\n readonly builderContext = signal<FormulaBuilderContextResponse | null>(null);\r\n\r\n /** Function categories from context */\r\n readonly functionCategories = computed(\r\n () => this.builderContext()?.functions?.categories ?? [],\r\n );\r\n\r\n /** Is builder context loading */\r\n readonly isContextLoading = signal(false);\r\n\r\n private contextRequestId = 0;\r\n\r\n /** Properties loaded from API */\r\n private readonly propertiesByPathApi = signal<\r\n Record<string, FormulaPropertyDescriptor[]>\r\n >({});\r\n\r\n /** Current property list loading path */\r\n private readonly propertyLoadingPath = signal<string | null>(null);\r\n\r\n constructor() {\r\n // Validate when formula changes\r\n effect(() => {\r\n const formula = this.expressionValue();\r\n if (formula && formula.trim().length > 0) {\r\n this.validatorService.validate(\r\n formula,\r\n undefined,\r\n this.levelSchemaId(),\r\n this.templateId(),\r\n );\r\n }\r\n });\r\n\r\n // Emit validation changes\r\n effect(() => {\r\n const validation = this.validation();\r\n this.validationChange.emit(validation);\r\n });\r\n\r\n // Load builder context when schema changes\r\n effect(() => {\r\n const schemaId = this.levelSchemaId();\r\n\r\n if (!schemaId) {\r\n this.builderContext.set(null);\r\n this.propertiesByPathApi.set({});\r\n this.nextTokenRulesByPath.set({});\r\n this.isContextLoading.set(false);\r\n return;\r\n }\r\n\r\n const requestId = ++this.contextRequestId;\r\n this.isContextLoading.set(true);\r\n this.nextTokenRulesByPath.set({});\r\n this.contextService.loadContext(schemaId).subscribe((context) => {\r\n if (requestId !== this.contextRequestId) {\r\n return;\r\n }\r\n\r\n this.builderContext.set(context);\r\n this.isContextLoading.set(false);\r\n\r\n if (!context) {\r\n return;\r\n }\r\n\r\n if (context.currentProperties?.length) {\r\n const scalarOperators =\r\n context.schemaDescriptor?.operators?.filter(\r\n (operator) =>\r\n operator.cardinality === 'scalar' &&\r\n !operator.requiresParameter &&\r\n !operator.parameterKind,\r\n ) ?? [];\r\n const scopedProperties = scalarOperators.reduce(\r\n (acc, operator) => ({\r\n ...acc,\r\n [operator.token]: context.currentProperties,\r\n }),\r\n {} as Record<string, FormulaPropertyDescriptor[]>,\r\n );\r\n this.propertiesByPathApi.update((current) => ({\r\n ...current,\r\n ...scopedProperties,\r\n }));\r\n }\r\n });\r\n });\r\n\r\n // Ensure selected scope exists in available options\r\n effect(() => {\r\n const scopes = this.availableScopes();\r\n if (scopes.length === 0) return;\r\n const current = this.propertyScope();\r\n if (!scopes.some((scope) => scope.key === current)) {\r\n this.setPropertyScope(scopes[0].key);\r\n }\r\n });\r\n\r\n // Fetch properties for the selected table path\r\n effect(() => {\r\n const schemaId = this.levelSchemaId();\r\n const tablePath = this.resolvedTablePath();\r\n const component = this.propertiesComponent();\r\n const context = this.builderContext();\r\n\r\n if (!schemaId || !tablePath || !component || !context) {\r\n this.propertyLoadingPath.set(null);\r\n return;\r\n }\r\n\r\n const existing = this.propertiesByPathApi()[tablePath];\r\n if (existing !== undefined) {\r\n this.propertyLoadingPath.set(null);\r\n return;\r\n }\r\n\r\n this.propertyLoadingPath.set(tablePath);\r\n this.contextService\r\n .getScopeProperties(schemaId, component, tablePath)\r\n .subscribe((props) => {\r\n this.propertiesByPathApi.update((current) => ({\r\n ...current,\r\n [tablePath]: props ?? [],\r\n }));\r\n if (this.propertyLoadingPath() === tablePath) {\r\n this.propertyLoadingPath.set(null);\r\n }\r\n });\r\n });\r\n\r\n // Fetch next-token rules for the current table path\r\n effect(() => {\r\n const schemaId = this.levelSchemaId();\r\n const tablePath = this.resolvedTablePath();\r\n const component = this.propertiesComponent();\r\n\r\n if (!schemaId || !tablePath || !component) return;\r\n\r\n if (this.nextTokenRulesByPath()[tablePath]) return;\r\n\r\n this.contextService\r\n .getNextTokens(schemaId, component, tablePath)\r\n .subscribe((response) => {\r\n if (!response) return;\r\n this.nextTokenRulesByPath.update((current) => ({\r\n ...current,\r\n [tablePath]: response.nextTokenRules ?? {},\r\n }));\r\n });\r\n });\r\n\r\n // Keep base segment in sync with scope metadata\r\n effect(() => {\r\n const scope = this.propertyScope();\r\n const operator = this.baseOperator();\r\n const shouldHaveSegment =\r\n Boolean(operator?.parameterKind) ||\r\n Boolean(operator?.requiresParameter);\r\n const segments = this.propertyPathSegments();\r\n const hasBase = segments[0]?.operatorToken === scope;\r\n\r\n if (shouldHaveSegment && !hasBase) {\r\n this.propertyPathSegments.set(\r\n buildInitialSegments(scope, operator, this.baseRule()),\r\n );\r\n return;\r\n }\r\n\r\n if (!shouldHaveSegment && hasBase) {\r\n this.propertyPathSegments.set(segments.slice(1));\r\n }\r\n });\r\n\r\n // Normalize segment values when allowed values change\r\n effect(() => {\r\n const meta = this.pathSegments();\r\n const segments = this.propertyPathSegments();\r\n if (meta.length !== segments.length) return;\r\n\r\n let changed = false;\r\n const next = segments.map((segment, index) => {\r\n const normalized = meta[index]?.value ?? segment.value;\r\n if (segment.value !== normalized) {\r\n changed = true;\r\n return { ...segment, value: normalized };\r\n }\r\n return segment;\r\n });\r\n\r\n if (changed) {\r\n this.propertyPathSegments.set(next);\r\n }\r\n });\r\n\r\n // Ensure selected field exists in current options\r\n effect(() => {\r\n const options = this.propertyOptions();\r\n const current = this.propertyFieldKey();\r\n\r\n if (options.length === 0) {\r\n if (current) this.propertyFieldKey.set('');\r\n return;\r\n }\r\n\r\n if (current && !options.some((prop) => prop.key === current)) {\r\n this.propertyFieldKey.set('');\r\n }\r\n });\r\n }\r\n\r\n ngOnDestroy(): void {\r\n this.validatorService.reset();\r\n }\r\n\r\n // ===== ControlValueAccessor =====\r\n\r\n writeValue(value: FormulaBuilderValue | null): void {\r\n if (!value) {\r\n this.expressionValue.set('');\r\n this.builderValue.set([]);\r\n this.tokens.set([]);\r\n this.lastBuilderJson = '';\r\n const editor = this.editor();\r\n if (editor) {\r\n editor.writeValue([]);\r\n }\r\n const codeEditor = this.codeEditor();\r\n if (codeEditor) {\r\n codeEditor.writeValue('');\r\n }\r\n this.validatorService.reset();\r\n return;\r\n }\r\n\r\n this.expressionValue.set(value.expression ?? '');\r\n const codeEditor = this.codeEditor();\r\n if (codeEditor) {\r\n codeEditor.writeValue(this.expressionValue());\r\n }\r\n const builder = Array.isArray(value.builder) ? value.builder : [];\r\n this.builderValue.set(builder);\r\n\r\n if (builder.length === 0) {\r\n this.tokens.set([]);\r\n this.lastBuilderJson = '';\r\n const editor = this.editor();\r\n if (editor) {\r\n editor.writeValue([]);\r\n }\r\n return;\r\n }\r\n\r\n const serialized = JSON.stringify(builder);\r\n if (serialized === this.lastBuilderJson) {\r\n return;\r\n }\r\n\r\n this.tokens.set(builder);\r\n const editor = this.editor();\r\n if (editor) {\r\n editor.writeValue(builder);\r\n }\r\n this.lastBuilderJson = serialized;\r\n }\r\n\r\n registerOnChange(fn: (value: FormulaBuilderValue) => void): void {\r\n this.onChange = fn;\r\n }\r\n\r\n registerOnTouched(fn: () => void): void {\r\n this.onTouched = fn;\r\n }\r\n\r\n setDisabledState(isDisabled: boolean): void {\r\n this.isDisabled.set(isDisabled);\r\n }\r\n\r\n /** Handle formula change from editor */\r\n onFormulaChange(newFormula: string): void {\r\n this.expressionValue.set(newFormula);\r\n this.emitValueChange();\r\n }\r\n\r\n /** Handle formula change from code editor */\r\n onCodeFormulaChange(newFormula: string): void {\r\n this.expressionValue.set(newFormula);\r\n if (\r\n !this.isCodeModeLocked() &&\r\n newFormula !== this.codeModeSnapshotExpression\r\n ) {\r\n this.isCodeModeLocked.set(true);\r\n this.clearBuilderTokens();\r\n }\r\n this.emitValueChange();\r\n }\r\n\r\n /** Handle block insert from toolbar */\r\n onBlockInsert(block: SmartBlock): void {\r\n if (this.isCodeMode()) {\r\n const editor = this.codeEditor();\r\n if (editor) {\r\n editor.addBlock(block);\r\n }\r\n return;\r\n }\r\n const editor = this.editor();\r\n if (editor) {\r\n editor.addBlock(block);\r\n }\r\n }\r\n\r\n /** Handle tokens change */\r\n onTokensChange(newTokens: FormulaToken[]): void {\r\n this.tokens.set(newTokens);\r\n const json = JSON.stringify(newTokens);\r\n this.lastBuilderJson = json;\r\n this.builderValue.set(newTokens);\r\n this.tokensChange.emit(newTokens);\r\n this.emitValueChange();\r\n }\r\n\r\n onEditorFocus(): void {\r\n this.hasFocus.set(true);\r\n }\r\n\r\n onEditorBlur(): void {\r\n this.hasFocus.set(false);\r\n this.onTouched();\r\n }\r\n\r\n private emitValueChange(): void {\r\n this.onChange({\r\n expression: this.expressionValue(),\r\n builder: this.builderValue(),\r\n });\r\n }\r\n\r\n onModeToggle(value: boolean): void {\r\n const nextMode: 'builder' | 'code' = value ? 'code' : 'builder';\r\n this.setEditorMode(nextMode);\r\n }\r\n\r\n private setEditorMode(mode: 'builder' | 'code'): void {\r\n if (this.editorMode() === mode) return;\r\n\r\n if (mode === 'code') {\r\n this.enterCodeMode();\r\n return;\r\n }\r\n\r\n if (this.isCodeModeLocked()) {\r\n return;\r\n }\r\n\r\n this.exitCodeMode();\r\n }\r\n\r\n private enterCodeMode(): void {\r\n this.codeModeSnapshotTokens = this.tokens().slice();\r\n this.codeModeSnapshotExpression = this.expressionValue();\r\n const editor = this.editor();\r\n if (editor) {\r\n const formula = editor.serialize();\r\n this.codeModeSnapshotExpression = formula;\r\n this.expressionValue.set(formula);\r\n this.emitValueChange();\r\n }\r\n this.isCodeModeLocked.set(false);\r\n this.editorMode.set('code');\r\n }\r\n\r\n private exitCodeMode(): void {\r\n this.editorMode.set('builder');\r\n if (this.codeModeSnapshotTokens.length > 0) {\r\n const restored = this.codeModeSnapshotTokens.slice();\r\n this.tokens.set(restored);\r\n this.builderValue.set(restored);\r\n this.lastBuilderJson = JSON.stringify(restored);\r\n const editor = this.editor();\r\n if (editor) {\r\n editor.writeValue(restored);\r\n }\r\n }\r\n if (this.codeModeSnapshotExpression) {\r\n this.expressionValue.set(this.codeModeSnapshotExpression);\r\n }\r\n this.isCodeModeLocked.set(false);\r\n }\r\n\r\n private clearBuilderTokens(): void {\r\n if (this.tokens().length === 0 && this.builderValue().length === 0) {\r\n return;\r\n }\r\n this.tokens.set([]);\r\n this.builderValue.set([]);\r\n this.lastBuilderJson = '';\r\n this.tokensChange.emit([]);\r\n }\r\n\r\n // ===== PUBLIC METHODS =====\r\n\r\n /** Clear the formula */\r\n clear(): void {\r\n this.expressionValue.set('');\r\n this.tokens.set([]);\r\n this.builderValue.set([]);\r\n this.lastBuilderJson = '';\r\n this.codeModeSnapshotTokens = [];\r\n this.codeModeSnapshotExpression = '';\r\n this.isCodeModeLocked.set(false);\r\n const editor = this.editor();\r\n if (editor) {\r\n editor.writeValue([]);\r\n }\r\n const codeEditor = this.codeEditor();\r\n if (codeEditor) {\r\n codeEditor.writeValue('');\r\n }\r\n this.validatorService.reset();\r\n this.emitValueChange();\r\n }\r\n\r\n // ===== PROPERTY COMPOSER =====\r\n\r\n readonly propertyScope = signal<string>('');\r\n\r\n readonly propertyPathSegments = signal<PathSegment[]>([]);\r\n\r\n readonly propertyFieldKey = signal('');\r\n\r\n private readonly nextTokenRulesByPath = signal<\r\n Record<string, Record<string, NextTokenRule>>\r\n >({});\r\n\r\n readonly contextOperators = computed<OperatorDescriptor[]>(() => {\r\n return this.builderContext()?.schemaDescriptor?.operators ?? [];\r\n });\r\n\r\n readonly baseOperator = computed(() =>\r\n this.contextOperators().find((op) => op.token === this.propertyScope()),\r\n );\r\n\r\n readonly baseRule = computed(() => {\r\n const scope = this.propertyScope();\r\n return this.builderContext()?.schemaDescriptor?.nextTokenRules?.[scope];\r\n });\r\n\r\n readonly availableScopes = computed(() => {\r\n const operators = this.contextOperators();\r\n if (operators.length === 0) return [];\r\n return operators.map((operator) => ({\r\n key: operator.token,\r\n label: `@${operator.token}`,\r\n requiresParam: operator.requiresParameter ?? false,\r\n optional: !operator.requiresParameter,\r\n }));\r\n });\r\n\r\n /** Radio card options for scope selection */\r\n readonly scopeOptions = computed<RadioItem[]>(() =>\r\n this.availableScopes().map((scope) => ({\r\n id: scope.key,\r\n name: scope.key,\r\n icon: SCOPE_ICON_MAP[scope.key] ?? DEFAULT_SCOPE_ICON,\r\n })),\r\n );\r\n\r\n /** Handle scope selection from radio cards */\r\n onScopeChange(item: RadioItem): void {\r\n this.setPropertyScope(String(item.id));\r\n }\r\n\r\n readonly pathSegments = computed<SegmentMeta[]>(() => {\r\n const scope = this.propertyScope();\r\n return resolveSegmentsMeta({\r\n scope,\r\n segments: this.propertyPathSegments(),\r\n operators: this.contextOperators(),\r\n baseRule: this.baseRule(),\r\n rulesByPath: this.nextTokenRulesByPath(),\r\n });\r\n });\r\n\r\n readonly isDirectAccess = computed(() => {\r\n const operator = this.baseOperator();\r\n const needsParameter =\r\n Boolean(operator?.parameterKind) || Boolean(operator?.requiresParameter);\r\n return !needsParameter && this.pathSegments().length === 0;\r\n });\r\n\r\n readonly propertyTablePath = computed(() =>\r\n buildTablePath(\r\n this.propertyScope(),\r\n this.pathSegments(),\r\n this.baseOperator(),\r\n false,\r\n ),\r\n );\r\n\r\n readonly resolvedTablePath = computed(() =>\r\n buildTablePath(\r\n this.propertyScope(),\r\n this.pathSegments(),\r\n this.baseOperator(),\r\n true,\r\n ),\r\n );\r\n\r\n readonly currentNextTokenRules = computed(() => {\r\n const path = this.resolvedTablePath();\r\n if (!path) return {};\r\n return this.nextTokenRulesByPath()[path] ?? {};\r\n });\r\n\r\n readonly nextOperatorOptions = computed(() => {\r\n const rules = this.currentNextTokenRules();\r\n const operators = this.contextOperators();\r\n return Object.keys(rules)\r\n .map((token) => {\r\n const rule = rules[token];\r\n const operator = operators.find((item) => item.token === token);\r\n const parameterKind =\r\n rule?.parameterKind ?? operator?.parameterKind ?? null;\r\n const requiresParameter =\r\n operator?.requiresParameter ?? Boolean(parameterKind);\r\n const allowedValues = getAllowedValues(rule);\r\n return {\r\n token,\r\n rule,\r\n requiresParameter,\r\n allowedValues,\r\n };\r\n })\r\n .filter(\r\n (option) =>\r\n option.allowedValues.length > 0 || !option.requiresParameter,\r\n );\r\n });\r\n\r\n readonly canAddNextSegment = computed(() => {\r\n if (this.nextOperatorOptions().length === 0) return false;\r\n const segments = this.pathSegments();\r\n if (segments.length === 0 || !segments[0].value) {\r\n return false;\r\n }\r\n return segments.every(\r\n (segment) => !segment.requiresParameter || Boolean(segment.value),\r\n );\r\n });\r\n\r\n readonly propertiesComponent = computed(() => {\r\n const contextKey = this.builderContext()?.contextEntityTypeKey;\r\n return contextKey;\r\n });\r\n\r\n readonly mergedPropertiesByPath = computed<\r\n Record<string, FormulaPropertyDescriptor[]>\r\n >(() => {\r\n const merged: Record<string, FormulaPropertyDescriptor[]> = {\r\n ...this.propertiesByPath(),\r\n };\r\n const apiProps = this.propertiesByPathApi();\r\n Object.entries(apiProps).forEach(([path, props]) => {\r\n if (props && props.length > 0) {\r\n merged[path] = props;\r\n }\r\n });\r\n return merged;\r\n });\r\n\r\n readonly isPropertyLoading = computed(() => {\r\n const path = this.resolvedTablePath();\r\n return Boolean(path) && this.propertyLoadingPath() === path;\r\n });\r\n\r\n readonly propertyOptions = computed(() => {\r\n const path = this.resolvedTablePath();\r\n if (!path) return [];\r\n const byPath = this.mergedPropertiesByPath()[path];\r\n const list = byPath && byPath.length > 0 ? byPath : [];\r\n return list.map((prop) => ({\r\n key: prop.key,\r\n name: prop.name ?? prop.key,\r\n }));\r\n });\r\n\r\n readonly selectedProperty = computed(() => {\r\n const key = this.propertyFieldKey();\r\n return this.propertyOptions().find((prop) => prop.key === key) ?? null;\r\n });\r\n\r\n readonly canInsertProperty = computed(() => {\r\n if (!this.selectedProperty()) return false;\r\n return Boolean(this.resolvedTablePath());\r\n });\r\n\r\n setPropertyScope(scope: string): void {\r\n if (this.propertyScope() === scope) {\r\n return;\r\n }\r\n this.propertyScope.set(scope);\r\n this.propertyPathSegments.set(\r\n buildInitialSegments(\r\n scope,\r\n this.contextOperators().find((op) => op.token === scope),\r\n this.builderContext()?.schemaDescriptor?.nextTokenRules?.[scope],\r\n ),\r\n );\r\n this.propertyFieldKey.set('');\r\n }\r\n\r\n setPathSegmentValue(index: number, value: string | null): void {\r\n this.propertyPathSegments.update((segments) => {\r\n // Update the segment at the given index and remove all segments after it\r\n // because subsequent segments depend on previous values\r\n const updated = segments.slice(0, index + 1);\r\n updated[index] = { ...updated[index], value: value ?? '' };\r\n return updated;\r\n });\r\n }\r\n\r\n addNextSegment(operatorToken: string): void {\r\n const value = '';\r\n\r\n this.propertyPathSegments.update((segments) => [\r\n ...segments,\r\n { operatorToken, value },\r\n ]);\r\n }\r\n\r\n onAddSegmentSelection(\r\n operatorToken: string,\r\n popover: { hide: () => void },\r\n ): void {\r\n popover.hide();\r\n this.addNextSegment(operatorToken);\r\n }\r\n\r\n removePathSegment(index: number): void {\r\n this.propertyPathSegments.update((segments) =>\r\n segments.filter((_, i) => i !== index),\r\n );\r\n }\r\n\r\n segmentOptions(index: number): { key: string; name: string }[] {\r\n const segment = this.pathSegments()[index];\r\n if (!segment) return [];\r\n return segment.allowedValues.map((value) => ({\r\n key: value,\r\n name: value,\r\n }));\r\n }\r\n\r\n insertSelectedProperty(insertBlock: (block: SmartBlock) => void): void {\r\n const prop = this.selectedProperty();\r\n if (!prop) return;\r\n\r\n if (!this.canInsertProperty()) return;\r\n\r\n const tablePath = this.resolvedTablePath();\r\n if (!tablePath) return;\r\n const display = prop.name ?? prop.key;\r\n const block = createPropertyBlock(\r\n `@${tablePath}::${prop.key}`,\r\n 'current',\r\n display,\r\n );\r\n insertBlock(block);\r\n }\r\n}\r\n","<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 (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 >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 ✓ Direct Access\r\n </span>\r\n } @else if (pathSegments().length === 0) {\r\n <span class=\"text-xs italic text-slate-400\"\r\n >No path configured</span\r\n >\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 >›</span\r\n >\r\n }\r\n <mt-button\r\n type=\"button\"\r\n [label]=\"\r\n segment.value ||\r\n 'Select ' + 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 Select {{ segment.operatorToken }}\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=\"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 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]=\"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 >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=\"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=\"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 <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=\"Code mode\"\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 <div class=\"p-0\">\r\n @if (isCodeMode()) {\r\n <mt-formula-editor-code\r\n #formulaEditorCode\r\n [placeholder]=\"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()\"\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","/**\r\n * Services barrel export\r\n */\r\n\r\nexport * from './formula-context.service';\r\nexport * from './formula-validator.service';\r\n","/**\r\n * Public API Surface of @masterteam/formula-builder\r\n *\r\n * This package provides the FormulaBuilder component which wraps\r\n * pure UI components from @masterteam/components/formula with\r\n * backend services for validation and context loading.\r\n *\r\n * Architecture:\r\n * - UI Components: imported from @masterteam/components/formula (pure, no services)\r\n * - Services: FormulaContextService, FormulaValidatorService (backend logic)\r\n * - FormulaBuilder: Main wrapper that connects UI with services\r\n */\r\n\r\n// Main component\r\nexport * from './lib/formula-builder';\r\n\r\n// Services (backend logic only)\r\nexport * from './lib/services/index';\r\n\r\n// Re-export models from base package for convenience\r\nexport {\r\n type SmartBlock,\r\n type BlockType,\r\n type ArgumentSlot,\r\n type FormulaToken,\r\n type TokenType,\r\n type DragBehavior,\r\n type ValidationResult,\r\n type ValidationError,\r\n type FunctionDefinition,\r\n type FunctionCategoryGroup,\r\n type OperatorDefinition,\r\n createFunctionBlock,\r\n createPropertyBlock,\r\n createOperatorBlock,\r\n createLiteralBlock,\r\n} from '@masterteam/components/formula';\r\n\r\n// Export validation-specific models\r\nexport type {\r\n ValidationRequest,\r\n FunctionCatalogResponse,\r\n ApiErrorResponse,\r\n} from './lib/models/validation-result.model';\r\n\r\n// Export value model for ControlValueAccessor usage\r\nexport type { FormulaBuilderValue } from './lib/models/formula-builder-value.model';\r\n\r\n// Export builder context models\r\nexport type {\r\n FormulaBuilderContextResponse,\r\n FormulaPropertyDescriptor,\r\n FormulaEngineSchemaDescriptor,\r\n OperatorDescriptor,\r\n NextTokenRule,\r\n} from './lib/models/formula-context.model';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@masterteam/formula-builder",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"directory": "../../../dist/masterteam/formula-builder",
|
|
6
6
|
"linkDirectory": true,
|
|
@@ -19,8 +19,8 @@
|
|
|
19
19
|
"rxjs": "^7.8.2",
|
|
20
20
|
"tailwindcss": "^4.1.17",
|
|
21
21
|
"tailwindcss-primeui": "^0.6.1",
|
|
22
|
-
"@masterteam/components": "^0.0.
|
|
23
|
-
"@masterteam/icons": "^0.0.
|
|
22
|
+
"@masterteam/components": "^0.0.86",
|
|
23
|
+
"@masterteam/icons": "^0.0.13"
|
|
24
24
|
},
|
|
25
25
|
"sideEffects": false,
|
|
26
26
|
"exports": {
|
|
@@ -3,9 +3,9 @@ import * as _angular_core from '@angular/core';
|
|
|
3
3
|
import { OnDestroy } from '@angular/core';
|
|
4
4
|
import { ControlValueAccessor } from '@angular/forms';
|
|
5
5
|
import { RadioItem } from '@masterteam/components/radio-cards';
|
|
6
|
-
import { FunctionCategoryGroup, FormulaToken, ValidationResult, SmartBlock } from '@masterteam/components/formula';
|
|
7
|
-
export { ArgumentSlot, BlockType, DragBehavior, FormulaToken, FunctionCategoryGroup, FunctionDefinition, OperatorDefinition, SmartBlock, TokenType, ValidationError, ValidationResult, createFunctionBlock, createLiteralBlock, createOperatorBlock, createPropertyBlock } from '@masterteam/components/formula';
|
|
8
6
|
import { Observable } from 'rxjs';
|
|
7
|
+
import { FunctionCategoryGroup, FormulaToken, ValidationResult, AutocompleteRequest, AutocompleteResponse, SmartBlock } from '@masterteam/components/formula';
|
|
8
|
+
export { ArgumentSlot, BlockType, DragBehavior, FormulaToken, FunctionCategoryGroup, FunctionDefinition, OperatorDefinition, SmartBlock, TokenType, ValidationError, ValidationResult, createFunctionBlock, createLiteralBlock, createOperatorBlock, createPropertyBlock } from '@masterteam/components/formula';
|
|
9
9
|
|
|
10
10
|
/** Validation request payload (for API calls) */
|
|
11
11
|
interface ValidationRequest {
|
|
@@ -89,8 +89,10 @@ type SegmentMeta = PathSegment & {
|
|
|
89
89
|
declare class FormulaBuilder implements ControlValueAccessor, OnDestroy {
|
|
90
90
|
private readonly validatorService;
|
|
91
91
|
private readonly contextService;
|
|
92
|
+
private readonly autocompleteService;
|
|
92
93
|
/** Reference to the formula editor */
|
|
93
94
|
private readonly editor;
|
|
95
|
+
private readonly codeEditor;
|
|
94
96
|
/** Properties per table path (e.g., "Current", "Children.Project") */
|
|
95
97
|
readonly propertiesByPath: _angular_core.InputSignal<Record<string, {
|
|
96
98
|
key: string;
|
|
@@ -117,8 +119,16 @@ declare class FormulaBuilder implements ControlValueAccessor, OnDestroy {
|
|
|
117
119
|
private readonly builderValue;
|
|
118
120
|
/** Tokens for the editor */
|
|
119
121
|
readonly tokens: _angular_core.WritableSignal<FormulaToken[]>;
|
|
122
|
+
readonly expression: _angular_core.Signal<string>;
|
|
123
|
+
readonly autocompleteProvider: (request: AutocompleteRequest) => Observable<AutocompleteResponse | null>;
|
|
120
124
|
/** Track last synced builder JSON to avoid loops */
|
|
121
125
|
private lastBuilderJson;
|
|
126
|
+
/** Editor mode */
|
|
127
|
+
readonly editorMode: _angular_core.WritableSignal<"builder" | "code">;
|
|
128
|
+
readonly isCodeMode: _angular_core.Signal<boolean>;
|
|
129
|
+
readonly isCodeModeLocked: _angular_core.WritableSignal<boolean>;
|
|
130
|
+
private codeModeSnapshotTokens;
|
|
131
|
+
private codeModeSnapshotExpression;
|
|
122
132
|
/** ControlValueAccessor callbacks */
|
|
123
133
|
private onChange;
|
|
124
134
|
private onTouched;
|
|
@@ -147,6 +157,8 @@ declare class FormulaBuilder implements ControlValueAccessor, OnDestroy {
|
|
|
147
157
|
setDisabledState(isDisabled: boolean): void;
|
|
148
158
|
/** Handle formula change from editor */
|
|
149
159
|
onFormulaChange(newFormula: string): void;
|
|
160
|
+
/** Handle formula change from code editor */
|
|
161
|
+
onCodeFormulaChange(newFormula: string): void;
|
|
150
162
|
/** Handle block insert from toolbar */
|
|
151
163
|
onBlockInsert(block: SmartBlock): void;
|
|
152
164
|
/** Handle tokens change */
|
|
@@ -154,6 +166,11 @@ declare class FormulaBuilder implements ControlValueAccessor, OnDestroy {
|
|
|
154
166
|
onEditorFocus(): void;
|
|
155
167
|
onEditorBlur(): void;
|
|
156
168
|
private emitValueChange;
|
|
169
|
+
onModeToggle(value: boolean): void;
|
|
170
|
+
private setEditorMode;
|
|
171
|
+
private enterCodeMode;
|
|
172
|
+
private exitCodeMode;
|
|
173
|
+
private clearBuilderTokens;
|
|
157
174
|
/** Clear the formula */
|
|
158
175
|
clear(): void;
|
|
159
176
|
readonly propertyScope: _angular_core.WritableSignal<string>;
|
|
@@ -216,6 +233,7 @@ declare class FormulaBuilder implements ControlValueAccessor, OnDestroy {
|
|
|
216
233
|
declare class FormulaContextService {
|
|
217
234
|
private readonly http;
|
|
218
235
|
private readonly apiUrl;
|
|
236
|
+
private unwrapResponse;
|
|
219
237
|
private readonly contextCache;
|
|
220
238
|
private readonly propertiesCache;
|
|
221
239
|
private readonly nextTokensCache;
|
|
@@ -237,6 +255,7 @@ declare class FormulaValidatorService {
|
|
|
237
255
|
private readonly _isValidating;
|
|
238
256
|
/** Validation subject for debouncing */
|
|
239
257
|
private readonly validateSubject;
|
|
258
|
+
private unwrapResponse;
|
|
240
259
|
/** Public signals */
|
|
241
260
|
readonly validation: _angular_core.Signal<ValidationResult>;
|
|
242
261
|
readonly isValidating: _angular_core.Signal<boolean>;
|