ngx-t-forms 2.0.30 → 2.0.32

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.
Files changed (161) hide show
  1. package/fesm2022/ngx-t-forms-auto-complete-input-element.component-CaXs4561.mjs +104 -0
  2. package/fesm2022/ngx-t-forms-auto-complete-input-element.component-CaXs4561.mjs.map +1 -0
  3. package/fesm2022/ngx-t-forms-basic-input-input-element.component-Dotyd-Qs.mjs +85 -0
  4. package/fesm2022/ngx-t-forms-basic-input-input-element.component-Dotyd-Qs.mjs.map +1 -0
  5. package/fesm2022/ngx-t-forms-calculated-field-rules.component-BhxT6tRq.mjs +643 -0
  6. package/fesm2022/ngx-t-forms-calculated-field-rules.component-BhxT6tRq.mjs.map +1 -0
  7. package/fesm2022/ngx-t-forms-chip-options-creator-editor.component-d4QeVhsp.mjs +97 -0
  8. package/fesm2022/ngx-t-forms-chip-options-creator-editor.component-d4QeVhsp.mjs.map +1 -0
  9. package/fesm2022/ngx-t-forms-config-mscoa-additional-inputs.component-Gn8exJ9a.mjs +195 -0
  10. package/fesm2022/ngx-t-forms-config-mscoa-additional-inputs.component-Gn8exJ9a.mjs.map +1 -0
  11. package/fesm2022/ngx-t-forms-data-source-picker.component-Ebf_if9j.mjs +261 -0
  12. package/fesm2022/ngx-t-forms-data-source-picker.component-Ebf_if9j.mjs.map +1 -0
  13. package/fesm2022/ngx-t-forms-date-picker-input-element.component-kdinBGRA.mjs +85 -0
  14. package/fesm2022/ngx-t-forms-date-picker-input-element.component-kdinBGRA.mjs.map +1 -0
  15. package/fesm2022/ngx-t-forms-date-range-picker-input-element.component-4W6uvrDU.mjs +156 -0
  16. package/fesm2022/ngx-t-forms-date-range-picker-input-element.component-4W6uvrDU.mjs.map +1 -0
  17. package/fesm2022/ngx-t-forms-document-list-label-config-editor.component-CR6EvgJO.mjs +368 -0
  18. package/fesm2022/ngx-t-forms-document-list-label-config-editor.component-CR6EvgJO.mjs.map +1 -0
  19. package/fesm2022/ngx-t-forms-document-picker.component-BThdRFec.mjs +704 -0
  20. package/fesm2022/ngx-t-forms-document-picker.component-BThdRFec.mjs.map +1 -0
  21. package/fesm2022/ngx-t-forms-editor-input-element.component-1X6uAPeZ.mjs +294 -0
  22. package/fesm2022/ngx-t-forms-editor-input-element.component-1X6uAPeZ.mjs.map +1 -0
  23. package/fesm2022/ngx-t-forms-editor-js-input.component-5MD8wRj0.mjs +240 -0
  24. package/fesm2022/ngx-t-forms-editor-js-input.component-5MD8wRj0.mjs.map +1 -0
  25. package/fesm2022/ngx-t-forms-file-upload-input-element.component-BAtuymMY.mjs +205 -0
  26. package/fesm2022/ngx-t-forms-file-upload-input-element.component-BAtuymMY.mjs.map +1 -0
  27. package/fesm2022/ngx-t-forms-form-input-selector.component-B42xP3jh.mjs +86 -0
  28. package/fesm2022/ngx-t-forms-form-input-selector.component-B42xP3jh.mjs.map +1 -0
  29. package/fesm2022/ngx-t-forms-form-json-view.component-DnnLXqR0.mjs +22 -0
  30. package/fesm2022/ngx-t-forms-form-json-view.component-DnnLXqR0.mjs.map +1 -0
  31. package/fesm2022/ngx-t-forms-form-payload-projection.component-Ip9ewB18.mjs +179 -0
  32. package/fesm2022/ngx-t-forms-form-payload-projection.component-Ip9ewB18.mjs.map +1 -0
  33. package/fesm2022/ngx-t-forms-form-section-stepper.component-BPgPfZSy.mjs +319 -0
  34. package/fesm2022/ngx-t-forms-form-section-stepper.component-BPgPfZSy.mjs.map +1 -0
  35. package/fesm2022/ngx-t-forms-forms-builder-menu.component-Dv0Dfw79.mjs +379 -0
  36. package/fesm2022/ngx-t-forms-forms-builder-menu.component-Dv0Dfw79.mjs.map +1 -0
  37. package/fesm2022/ngx-t-forms-geo-location.component-Bmd84Gcb.mjs +124 -0
  38. package/fesm2022/ngx-t-forms-geo-location.component-Bmd84Gcb.mjs.map +1 -0
  39. package/fesm2022/ngx-t-forms-getInputIcon-B4ADgevZ.mjs +31 -0
  40. package/fesm2022/ngx-t-forms-getInputIcon-B4ADgevZ.mjs.map +1 -0
  41. package/fesm2022/ngx-t-forms-image-capture-input-element.component-CUd04Ghl.mjs +180 -0
  42. package/fesm2022/ngx-t-forms-image-capture-input-element.component-CUd04Ghl.mjs.map +1 -0
  43. package/fesm2022/ngx-t-forms-index-BcrQ01DQ.mjs +2 -0
  44. package/fesm2022/ngx-t-forms-index-BcrQ01DQ.mjs.map +1 -0
  45. package/fesm2022/ngx-t-forms-input-custom.component-Cn-KH0Lb.mjs +105 -0
  46. package/fesm2022/ngx-t-forms-input-custom.component-Cn-KH0Lb.mjs.map +1 -0
  47. package/fesm2022/ngx-t-forms-input-editor.component-DLru1Ezu.mjs +193 -0
  48. package/fesm2022/ngx-t-forms-input-editor.component-DLru1Ezu.mjs.map +1 -0
  49. package/fesm2022/{ngx-t-forms-map-mat-options-keys-SM5XM9uy.mjs → ngx-t-forms-map-mat-options-keys-CVlPdrCO.mjs} +12 -14
  50. package/fesm2022/ngx-t-forms-map-mat-options-keys-CVlPdrCO.mjs.map +1 -0
  51. package/fesm2022/ngx-t-forms-mat-chip-list-editor.component-BWisS3Em.mjs +66 -0
  52. package/fesm2022/ngx-t-forms-mat-chip-list-editor.component-BWisS3Em.mjs.map +1 -0
  53. package/fesm2022/ngx-t-forms-mat-slider-editor.component-CTSBrM-j.mjs +211 -0
  54. package/fesm2022/ngx-t-forms-mat-slider-editor.component-CTSBrM-j.mjs.map +1 -0
  55. package/fesm2022/ngx-t-forms-mat-slider-toggle-editor.component-CcYiwx-8.mjs +165 -0
  56. package/fesm2022/ngx-t-forms-mat-slider-toggle-editor.component-CcYiwx-8.mjs.map +1 -0
  57. package/fesm2022/ngx-t-forms-missing-form-configs.component-DxdynZY6.mjs +38 -0
  58. package/fesm2022/ngx-t-forms-missing-form-configs.component-DxdynZY6.mjs.map +1 -0
  59. package/fesm2022/ngx-t-forms-mscoa-chart-toolbar.component-D4Xa_Yi0.mjs +38 -0
  60. package/fesm2022/ngx-t-forms-mscoa-chart-toolbar.component-D4Xa_Yi0.mjs.map +1 -0
  61. package/fesm2022/ngx-t-forms-mscoa-error-display.component-99DpVSy7.mjs +126 -0
  62. package/fesm2022/ngx-t-forms-mscoa-error-display.component-99DpVSy7.mjs.map +1 -0
  63. package/fesm2022/ngx-t-forms-mscoa-segment-config.component-Bo0aDEMy.mjs +447 -0
  64. package/fesm2022/ngx-t-forms-mscoa-segment-config.component-Bo0aDEMy.mjs.map +1 -0
  65. package/fesm2022/ngx-t-forms-mscoa-temporary-hint.component-B1Z-IXSL.mjs +74 -0
  66. package/fesm2022/ngx-t-forms-mscoa-temporary-hint.component-B1Z-IXSL.mjs.map +1 -0
  67. package/fesm2022/ngx-t-forms-multiple-input-input-element.component-C8JP3D6r.mjs +905 -0
  68. package/fesm2022/ngx-t-forms-multiple-input-input-element.component-C8JP3D6r.mjs.map +1 -0
  69. package/fesm2022/ngx-t-forms-ngx-t-forms-C2G8_WQk.mjs +20310 -0
  70. package/fesm2022/ngx-t-forms-ngx-t-forms-C2G8_WQk.mjs.map +1 -0
  71. package/fesm2022/ngx-t-forms-paginated-selection-table-0OI1ikWW.mjs +555 -0
  72. package/fesm2022/ngx-t-forms-paginated-selection-table-0OI1ikWW.mjs.map +1 -0
  73. package/fesm2022/ngx-t-forms-pipeline-generator.component-CZ21sd77.mjs +748 -0
  74. package/fesm2022/ngx-t-forms-pipeline-generator.component-CZ21sd77.mjs.map +1 -0
  75. package/fesm2022/ngx-t-forms-record-list-manager.component-CykBq_nW.mjs +358 -0
  76. package/fesm2022/ngx-t-forms-record-list-manager.component-CykBq_nW.mjs.map +1 -0
  77. package/fesm2022/ngx-t-forms-required-inputs.component-ONbhxVSH.mjs +272 -0
  78. package/fesm2022/ngx-t-forms-required-inputs.component-ONbhxVSH.mjs.map +1 -0
  79. package/fesm2022/ngx-t-forms-rest-api-call-setup.component-WPUxtY7Q.mjs +398 -0
  80. package/fesm2022/ngx-t-forms-rest-api-call-setup.component-WPUxtY7Q.mjs.map +1 -0
  81. package/fesm2022/ngx-t-forms-search-field.component-B2ZO7lqO.mjs +38 -0
  82. package/fesm2022/ngx-t-forms-search-field.component-B2ZO7lqO.mjs.map +1 -0
  83. package/fesm2022/ngx-t-forms-section-report.component-C1w16LYm.mjs +98 -0
  84. package/fesm2022/ngx-t-forms-section-report.component-C1w16LYm.mjs.map +1 -0
  85. package/fesm2022/ngx-t-forms-select-input-element.component-CWcywuS6.mjs +150 -0
  86. package/fesm2022/ngx-t-forms-select-input-element.component-CWcywuS6.mjs.map +1 -0
  87. package/fesm2022/ngx-t-forms-selection-options-editor.component-KjbZhc2u.mjs +169 -0
  88. package/fesm2022/ngx-t-forms-selection-options-editor.component-KjbZhc2u.mjs.map +1 -0
  89. package/fesm2022/ngx-t-forms-t-workflow-picker.component-CtavFAUq.mjs +204 -0
  90. package/fesm2022/ngx-t-forms-t-workflow-picker.component-CtavFAUq.mjs.map +1 -0
  91. package/fesm2022/ngx-t-forms-textarea-input-element.component-DkJkBQif.mjs +95 -0
  92. package/fesm2022/ngx-t-forms-textarea-input-element.component-DkJkBQif.mjs.map +1 -0
  93. package/fesm2022/ngx-t-forms-toggle-input-element.component-Dr7MNli8.mjs +82 -0
  94. package/fesm2022/ngx-t-forms-toggle-input-element.component-Dr7MNli8.mjs.map +1 -0
  95. package/fesm2022/ngx-t-forms-validators-config.component-BknyAmV_.mjs +574 -0
  96. package/fesm2022/ngx-t-forms-validators-config.component-BknyAmV_.mjs.map +1 -0
  97. package/fesm2022/ngx-t-forms-workflow-adjudication.component-CPvwm7f4.mjs +1303 -0
  98. package/fesm2022/ngx-t-forms-workflow-adjudication.component-CPvwm7f4.mjs.map +1 -0
  99. package/fesm2022/ngx-t-forms.mjs +2 -1
  100. package/fesm2022/ngx-t-forms.mjs.map +1 -1
  101. package/package.json +20 -18
  102. package/styles/_editor-mixins.scss +62 -0
  103. package/styles/_json-editor-syntax.scss +26 -0
  104. package/styles/_signature-pad.scss +26 -0
  105. package/styles/_tokens.scss +148 -0
  106. package/types/ngx-t-forms.d.ts +1921 -733
  107. package/fesm2022/ngx-t-forms-calculated-field-rules.component-Ct6_c_Lj.mjs +0 -313
  108. package/fesm2022/ngx-t-forms-calculated-field-rules.component-Ct6_c_Lj.mjs.map +0 -1
  109. package/fesm2022/ngx-t-forms-chip-options-creator-editor.component-yuM1KHho.mjs +0 -191
  110. package/fesm2022/ngx-t-forms-chip-options-creator-editor.component-yuM1KHho.mjs.map +0 -1
  111. package/fesm2022/ngx-t-forms-config-mscoa-additional-inputs.component-BptpYSe-.mjs +0 -207
  112. package/fesm2022/ngx-t-forms-config-mscoa-additional-inputs.component-BptpYSe-.mjs.map +0 -1
  113. package/fesm2022/ngx-t-forms-data-source-picker.component-Badna1Rl.mjs +0 -204
  114. package/fesm2022/ngx-t-forms-data-source-picker.component-Badna1Rl.mjs.map +0 -1
  115. package/fesm2022/ngx-t-forms-document-list-label-config-editor.component-2_8XzUgD.mjs +0 -289
  116. package/fesm2022/ngx-t-forms-document-list-label-config-editor.component-2_8XzUgD.mjs.map +0 -1
  117. package/fesm2022/ngx-t-forms-form-input-selector.component-DV4Sts9F.mjs +0 -134
  118. package/fesm2022/ngx-t-forms-form-input-selector.component-DV4Sts9F.mjs.map +0 -1
  119. package/fesm2022/ngx-t-forms-form-json-view.component-B8seYzMQ.mjs +0 -22
  120. package/fesm2022/ngx-t-forms-form-json-view.component-B8seYzMQ.mjs.map +0 -1
  121. package/fesm2022/ngx-t-forms-form-section-stepper.component-x_83iAWA.mjs +0 -281
  122. package/fesm2022/ngx-t-forms-form-section-stepper.component-x_83iAWA.mjs.map +0 -1
  123. package/fesm2022/ngx-t-forms-forms-builder-menu.component-UWo_dyVt.mjs +0 -345
  124. package/fesm2022/ngx-t-forms-forms-builder-menu.component-UWo_dyVt.mjs.map +0 -1
  125. package/fesm2022/ngx-t-forms-input-editor.component-B_kkOoEO.mjs +0 -147
  126. package/fesm2022/ngx-t-forms-input-editor.component-B_kkOoEO.mjs.map +0 -1
  127. package/fesm2022/ngx-t-forms-map-mat-options-keys-SM5XM9uy.mjs.map +0 -1
  128. package/fesm2022/ngx-t-forms-mat-chip-list-editor.component-C41AL9Et.mjs +0 -105
  129. package/fesm2022/ngx-t-forms-mat-chip-list-editor.component-C41AL9Et.mjs.map +0 -1
  130. package/fesm2022/ngx-t-forms-mat-slider-editor.component-BWe8U-sI.mjs +0 -109
  131. package/fesm2022/ngx-t-forms-mat-slider-editor.component-BWe8U-sI.mjs.map +0 -1
  132. package/fesm2022/ngx-t-forms-mat-slider-toggle-editor.component-B_XlkHuK.mjs +0 -155
  133. package/fesm2022/ngx-t-forms-mat-slider-toggle-editor.component-B_XlkHuK.mjs.map +0 -1
  134. package/fesm2022/ngx-t-forms-missing-form-configs.component-DPNNyKkt.mjs +0 -28
  135. package/fesm2022/ngx-t-forms-missing-form-configs.component-DPNNyKkt.mjs.map +0 -1
  136. package/fesm2022/ngx-t-forms-mscoa-chart-toolbar.component-DY1QnG08.mjs +0 -43
  137. package/fesm2022/ngx-t-forms-mscoa-chart-toolbar.component-DY1QnG08.mjs.map +0 -1
  138. package/fesm2022/ngx-t-forms-mscoa-error-display.component-CRc_4l3l.mjs +0 -116
  139. package/fesm2022/ngx-t-forms-mscoa-error-display.component-CRc_4l3l.mjs.map +0 -1
  140. package/fesm2022/ngx-t-forms-mscoa-segment-config.component-Ckr_nuZF.mjs +0 -296
  141. package/fesm2022/ngx-t-forms-mscoa-segment-config.component-Ckr_nuZF.mjs.map +0 -1
  142. package/fesm2022/ngx-t-forms-mscoa-temporary-hint.component-GYxT-56Y.mjs +0 -83
  143. package/fesm2022/ngx-t-forms-mscoa-temporary-hint.component-GYxT-56Y.mjs.map +0 -1
  144. package/fesm2022/ngx-t-forms-ngx-t-forms-DP2koSL5.mjs +0 -17401
  145. package/fesm2022/ngx-t-forms-ngx-t-forms-DP2koSL5.mjs.map +0 -1
  146. package/fesm2022/ngx-t-forms-pipeline-generator.component-BxHetD_Q.mjs +0 -613
  147. package/fesm2022/ngx-t-forms-pipeline-generator.component-BxHetD_Q.mjs.map +0 -1
  148. package/fesm2022/ngx-t-forms-record-list-manager.component-BQuMkoXo.mjs +0 -269
  149. package/fesm2022/ngx-t-forms-record-list-manager.component-BQuMkoXo.mjs.map +0 -1
  150. package/fesm2022/ngx-t-forms-required-inputs.component-CLyq9dIR.mjs +0 -190
  151. package/fesm2022/ngx-t-forms-required-inputs.component-CLyq9dIR.mjs.map +0 -1
  152. package/fesm2022/ngx-t-forms-rest-api-call-setup.component-CWeIUKLz.mjs +0 -291
  153. package/fesm2022/ngx-t-forms-rest-api-call-setup.component-CWeIUKLz.mjs.map +0 -1
  154. package/fesm2022/ngx-t-forms-section-report.component-BtaF39WD.mjs +0 -156
  155. package/fesm2022/ngx-t-forms-section-report.component-BtaF39WD.mjs.map +0 -1
  156. package/fesm2022/ngx-t-forms-selection-options-editor.component-B4cEGWrK.mjs +0 -186
  157. package/fesm2022/ngx-t-forms-selection-options-editor.component-B4cEGWrK.mjs.map +0 -1
  158. package/fesm2022/ngx-t-forms-t-workflow-picker.component-BkVN4Wdk.mjs +0 -187
  159. package/fesm2022/ngx-t-forms-t-workflow-picker.component-BkVN4Wdk.mjs.map +0 -1
  160. package/fesm2022/ngx-t-forms-validators-config.component-Cq07Er-G.mjs +0 -215
  161. package/fesm2022/ngx-t-forms-validators-config.component-Cq07Er-G.mjs.map +0 -1
@@ -0,0 +1,643 @@
1
+ import * as i0 from '@angular/core';
2
+ import { input, computed, inject, ElementRef, PLATFORM_ID, effect, ViewEncapsulation, ChangeDetectionStrategy, Component, output, signal, viewChild, Input } from '@angular/core';
3
+ import { isPlatformBrowser, CommonModule } from '@angular/common';
4
+ import * as i1 from '@angular/forms';
5
+ import { NgControl, FormsModule } from '@angular/forms';
6
+ import * as i8 from '@angular/material/select';
7
+ import { MatSelectModule } from '@angular/material/select';
8
+ import * as i2$1 from '@angular/material/form-field';
9
+ import { MatFormFieldModule, MatFormFieldControl } from '@angular/material/form-field';
10
+ import * as i2$2 from '@angular/material/input';
11
+ import { MatInputModule } from '@angular/material/input';
12
+ import * as i3 from '@angular/material/icon';
13
+ import { MatIconModule } from '@angular/material/icon';
14
+ import * as i3$1 from '@angular/material/card';
15
+ import { MatCardModule } from '@angular/material/card';
16
+ import * as i1$1 from '@angular/material/button';
17
+ import { MatButtonModule } from '@angular/material/button';
18
+ import * as i4 from '@angular/material/chips';
19
+ import { MatChipsModule } from '@angular/material/chips';
20
+ import * as i2 from '@angular/cdk/overlay';
21
+ import { OverlayModule } from '@angular/cdk/overlay';
22
+ import { Subject } from 'rxjs';
23
+ import { v4 } from 'uuid';
24
+ import { CalculationFunctions } from 'ngx-t-forms-types';
25
+ import { _ as _isEqual } from './ngx-t-forms-ngx-t-forms-C2G8_WQk.mjs';
26
+ import katex from 'katex';
27
+ import { parse } from 'mathjs';
28
+
29
+ /**
30
+ * Parses a strictly-infix expression (the format `math.evaluate` consumes) and,
31
+ * when it is syntactically valid, returns its LaTeX form for KaTeX to render.
32
+ *
33
+ * The expression is never rewritten — what the user types is what gets stored
34
+ * and later evaluated by mathjs. This only *reads* it to derive a preview and a
35
+ * friendly validity message; an empty expression is treated as "not yet valid"
36
+ * rather than an error.
37
+ */
38
+ function parseInfixFormula(expression) {
39
+ const trimmed = expression.trim();
40
+ if (!trimmed) {
41
+ return { tex: null, error: null };
42
+ }
43
+ try {
44
+ return { tex: parse(trimmed).toTex(), error: null };
45
+ }
46
+ catch (error) {
47
+ return { tex: null, error: friendlyMessage(error) };
48
+ }
49
+ }
50
+ /** Maps mathjs' technical parser errors onto guidance a non-technical user can act on. */
51
+ function friendlyMessage(error) {
52
+ const raw = error instanceof Error ? error.message : '';
53
+ if (/end of expression/i.test(raw)) {
54
+ return 'The equation looks unfinished — add the missing number or variable.';
55
+ }
56
+ if (/parenthesis|bracket/i.test(raw)) {
57
+ return 'Check that every opening bracket "(" has a matching closing bracket ")".';
58
+ }
59
+ if (/value expected/i.test(raw)) {
60
+ return 'An operator (like + or ×) is missing a number or variable next to it.';
61
+ }
62
+ if (/unexpected/i.test(raw)) {
63
+ return 'There is an unexpected symbol in the equation.';
64
+ }
65
+ return 'This equation is not valid yet.';
66
+ }
67
+
68
+ /**
69
+ * Read-only "natural maths" preview of a strictly-infix expression.
70
+ *
71
+ * It parses the expression with mathjs and renders the result as MathML via
72
+ * KaTeX (no stylesheet required — the browser draws the glyphs natively). The
73
+ * expression itself is never modified, so what is previewed is exactly what
74
+ * `math.evaluate` will later consume.
75
+ *
76
+ * Internal to `t-dynamic-data-edit` — not part of the library's public surface.
77
+ */
78
+ class MathPreviewComponent {
79
+ #host;
80
+ #isBrowser;
81
+ constructor() {
82
+ /** Strictly-infix expression to render (mathjs syntax, e.g. `((a+2)/(b-1))*2`). */
83
+ this.expression = input('', ...(ngDevMode ? [{ debugName: "expression" }] : /* istanbul ignore next */ []));
84
+ /** Text shown when there is nothing to preview. */
85
+ this.placeholder = input('Nothing to preview yet', ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
86
+ /** `'empty'` when no expression is set, otherwise `'rendered'`. */
87
+ this.state = computed(() => this.expression().trim() ? 'rendered' : 'empty', ...(ngDevMode ? [{ debugName: "state" }] : /* istanbul ignore next */ []));
88
+ this.#host = inject(ElementRef);
89
+ this.#isBrowser = isPlatformBrowser(inject(PLATFORM_ID));
90
+ effect(() => {
91
+ const expression = this.expression().trim();
92
+ const placeholder = this.placeholder();
93
+ const element = this.#host.nativeElement;
94
+ // On the server KaTeX has no DOM to render into — fall back to plain text.
95
+ if (!this.#isBrowser) {
96
+ element.textContent = expression || placeholder;
97
+ return;
98
+ }
99
+ if (!expression) {
100
+ element.textContent = placeholder;
101
+ return;
102
+ }
103
+ const { tex } = parseInfixFormula(expression);
104
+ if (tex == null) {
105
+ // Mid-edit / not yet valid: show the raw infix until it parses cleanly.
106
+ element.textContent = expression;
107
+ return;
108
+ }
109
+ katex.render(tex, element, {
110
+ output: 'mathml',
111
+ throwOnError: false,
112
+ displayMode: true,
113
+ });
114
+ });
115
+ }
116
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: MathPreviewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
117
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.12", type: MathPreviewComponent, isStandalone: true, selector: "lib-math-preview", inputs: { expression: { classPropertyName: "expression", publicName: "expression", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-state": "state()" }, classAttribute: "lib-math-preview" }, ngImport: i0, template: '', isInline: true, styles: [":host{display:flex;align-items:center;justify-content:center;min-height:3rem;padding:.5rem .75rem;overflow-x:auto;color:var(--lib-forms-on-surface);font-size:1.375rem;line-height:1.4;text-align:center}:host([data-state=empty]){color:var(--lib-forms-on-surface-variant);font-size:.9375rem;font-style:italic}:host ::ng-deep math{max-width:100%}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
118
+ }
119
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: MathPreviewComponent, decorators: [{
120
+ type: Component,
121
+ args: [{ selector: 'lib-math-preview', template: '', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.Emulated, host: {
122
+ 'class': 'lib-math-preview',
123
+ '[attr.data-state]': 'state()',
124
+ }, styles: [":host{display:flex;align-items:center;justify-content:center;min-height:3rem;padding:.5rem .75rem;overflow-x:auto;color:var(--lib-forms-on-surface);font-size:1.375rem;line-height:1.4;text-align:center}:host([data-state=empty]){color:var(--lib-forms-on-surface-variant);font-size:.9375rem;font-style:italic}:host ::ng-deep math{max-width:100%}\n"] }]
125
+ }], ctorParameters: () => [], propDecorators: { expression: [{ type: i0.Input, args: [{ isSignal: true, alias: "expression", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }] } });
126
+
127
+ /** Escapes a string for safe inclusion as a literal inside a `RegExp`. */
128
+ function escapeRegExp(value) {
129
+ return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
130
+ }
131
+ /**
132
+ * Internal calculated-field-rules editor implementing
133
+ * `MatFormFieldControl<CalculatedFieldRules | undefined>` and
134
+ * `ControlValueAccessor`.
135
+ *
136
+ * Rendered by `t-dynamic-data-edit`, which supplies the surrounding field label,
137
+ * hint, and validation errors — so this component owns only its two modes: a
138
+ * read-only formula summary (view) and a sectioned editor (edit) for the
139
+ * formula, its variables, the optional formula source link, and the rounding
140
+ * settings.
141
+ *
142
+ * NOTE: `MatFormFieldControl<T>` and `ControlValueAccessor` mandate plain
143
+ * mutable `value` / `placeholder` / `required` / `disabled` / `id` members,
144
+ * `@Input()` decorators on them, the `focused` / `touched` / `stateChanges` /
145
+ * `onChange` / `onTouched` members, and the `useExisting` provider. These are
146
+ * framework wiring, not defects — the CLAUDE.md bans on `@Input()` /
147
+ * `useExisting` do not apply to MatFormFieldControl integration. Genuinely
148
+ * internal state is signal-based.
149
+ */
150
+ class CalculatedFieldRulesComponent {
151
+ static { this.nextId = 0; }
152
+ /** Index of the `$` that opened the picker, and the caret at that moment. */
153
+ #dollarIndex;
154
+ #cursorPosition;
155
+ #elementRef;
156
+ constructor() {
157
+ // #region MatFormFieldControl framework members (plain mutable — not signals)
158
+ this.placeholder = '';
159
+ this.required = false;
160
+ this.disabled = false;
161
+ this.stateChanges = new Subject();
162
+ this.controlType = 'app-calculated-field-rules';
163
+ this.id = `app-calculated-field-rules-${CalculatedFieldRulesComponent.nextId++}`;
164
+ this.focused = false;
165
+ this.touched = false;
166
+ this.describedBy = '';
167
+ // #endregion
168
+ // #region Non-MFC inputs / outputs (contract preserved exactly)
169
+ /** Owning input definition; supplies table mode and the formula-source map. */
170
+ this.mapToData = input(undefined, ...(ngDevMode ? [{ debugName: "mapToData" }] : /* istanbul ignore next */ []));
171
+ /** All form inputs available to bind as calculation variables. */
172
+ this.formInputs = input([], ...(ngDevMode ? [{ debugName: "formInputs" }] : /* istanbul ignore next */ []));
173
+ /** Validation errors surfaced by the parent for error-state derivation. */
174
+ this.errors = input([], ...(ngDevMode ? [{ debugName: "errors" }] : /* istanbul ignore next */ []));
175
+ /** Retained on the contract; reserved for path-scoped value emission. */
176
+ this.valueChange2dWithPath = output();
177
+ /** Emits the persisted rules whenever the editor commits a new value. */
178
+ this.valueChanged = output();
179
+ // #endregion
180
+ // #region Internal signal state
181
+ /** Whether the editor card is open (edit mode) versus the summary (view). */
182
+ this.isEditing = signal(false, ...(ngDevMode ? [{ debugName: "isEditing" }] : /* istanbul ignore next */ []));
183
+ /** Working copy edited in the card; committed to `value` on save. */
184
+ this.tempValue = signal({}, ...(ngDevMode ? [{ debugName: "tempValue" }] : /* istanbul ignore next */ []));
185
+ /** Whether the inline `$` field-picker is open. */
186
+ this.pickerOpen = signal(false, ...(ngDevMode ? [{ debugName: "pickerOpen" }] : /* istanbul ignore next */ []));
187
+ /** Text typed after `$`, used to filter the field-picker. */
188
+ this.pickerQuery = signal('', ...(ngDevMode ? [{ debugName: "pickerQuery" }] : /* istanbul ignore next */ []));
189
+ /** Keyboard-highlighted result in the field-picker. */
190
+ this.pickerActiveIndex = signal(0, ...(ngDevMode ? [{ debugName: "pickerActiveIndex" }] : /* istanbul ignore next */ []));
191
+ /** Index of the `$` that opened the picker, and the caret at that moment. */
192
+ this.#dollarIndex = -1;
193
+ this.#cursorPosition = 0;
194
+ // #endregion
195
+ this.roundingType = [
196
+ { value: 'ROUND', label: 'Nearest' },
197
+ { value: 'FLOOR', label: 'Round down' },
198
+ { value: 'CEIL', label: 'Round up' },
199
+ ];
200
+ /** Operator palette inserted into the equation; glyphs are friendly, tokens are infix. */
201
+ this.operatorKeys = [
202
+ { label: '+', token: ' + ', caretBack: 0, aria: 'Add' },
203
+ { label: '−', token: ' - ', caretBack: 0, aria: 'Subtract' },
204
+ { label: '×', token: ' * ', caretBack: 0, aria: 'Multiply' },
205
+ { label: '÷', token: ' / ', caretBack: 0, aria: 'Divide' },
206
+ { label: '( )', token: '()', caretBack: 1, aria: 'Brackets' },
207
+ { label: 'xⁿ', token: '^', caretBack: 0, aria: 'Power' },
208
+ ];
209
+ /** The equation textarea, used for caret-aware token insertion. */
210
+ this.formulaInputRef = viewChild('formulaInput', ...(ngDevMode ? [{ debugName: "formulaInputRef" }] : /* istanbul ignore next */ []));
211
+ /** Live, non-technical validity of the working equation (drives the preview banner). */
212
+ this.formulaStatus = computed(() => {
213
+ const formula = (this.tempValue().formula ?? '').trim();
214
+ if (!formula) {
215
+ return { kind: 'empty', message: 'Start building your equation below.' };
216
+ }
217
+ const { error } = parseInfixFormula(formula);
218
+ return error
219
+ ? { kind: 'invalid', message: error }
220
+ : { kind: 'valid', message: 'This equation is valid.' };
221
+ }, ...(ngDevMode ? [{ debugName: "formulaStatus" }] : /* istanbul ignore next */ []));
222
+ /** Number-typed inputs that may back a calculation variable. */
223
+ this.cachedNumberInputs = computed(() => this.formInputs().filter((input) => input.dataType === 'number' || input.type === 'number'), ...(ngDevMode ? [{ debugName: "cachedNumberInputs" }] : /* istanbul ignore next */ []));
224
+ /** Field-picker results: number inputs filtered by the text typed after `$`. */
225
+ this.pickerResults = computed(() => {
226
+ const query = this.pickerQuery().trim().toLowerCase();
227
+ const inputs = this.cachedNumberInputs();
228
+ if (!query) {
229
+ return inputs;
230
+ }
231
+ return inputs.filter((input) => input.label?.toLowerCase().includes(query) ||
232
+ input.formControlName?.toLowerCase().includes(query));
233
+ }, ...(ngDevMode ? [{ debugName: "pickerResults" }] : /* istanbul ignore next */ []));
234
+ /** Every calculation function offered as a list-aggregation chip. */
235
+ this.allCalculationFunction = computed(() => Object.values(CalculationFunctions), ...(ngDevMode ? [{ debugName: "allCalculationFunction" }] : /* istanbul ignore next */ []));
236
+ /** True when this editor targets a table column rather than a scalar input. */
237
+ this.tableMode = computed(() => !!this.mapToData()?.tableConfig, ...(ngDevMode ? [{ debugName: "tableMode" }] : /* istanbul ignore next */ []));
238
+ /** Table configuration when in table mode. */
239
+ this.tableConfig = computed(() => this.mapToData()?.tableConfig, ...(ngDevMode ? [{ debugName: "tableConfig" }] : /* istanbul ignore next */ []));
240
+ this.ngControl = inject(NgControl, { self: true, optional: true });
241
+ this.#elementRef = inject(ElementRef);
242
+ // ControlValueAccessor — Angular registers an untyped change callback.
243
+ this.onChange = () => { };
244
+ this.onTouched = () => { };
245
+ if (this.ngControl != null) {
246
+ this.ngControl.valueAccessor = this;
247
+ }
248
+ }
249
+ ngOnDestroy() {
250
+ this.stateChanges.next();
251
+ this.stateChanges.complete();
252
+ }
253
+ // #region Value accessor & MatFormFieldControl logic
254
+ #value;
255
+ get value() {
256
+ return this.#value;
257
+ }
258
+ set value(val) {
259
+ if (_isEqual(this.#value, val)) {
260
+ return;
261
+ }
262
+ this.#value = val ? { ...val } : undefined;
263
+ this.stateChanges.next();
264
+ this.valueChanged.emit(this.#value ?? null);
265
+ this.onChange(this.#value);
266
+ }
267
+ // MatFormFieldControl reads these as plain getters during its own change
268
+ // detection, so they stay getters rather than `computed()` signals.
269
+ get empty() {
270
+ return !this.#value;
271
+ }
272
+ get shouldLabelFloat() {
273
+ return this.focused || !this.empty;
274
+ }
275
+ get errorState() {
276
+ const hasCustomError = (this.errors() ?? []).length > 0;
277
+ const hasControlError = this.ngControl?.control?.errors != null;
278
+ return ((this.touched && (hasControlError || hasCustomError)) ||
279
+ (this.required && !this.#value));
280
+ }
281
+ writeValue(value) {
282
+ this.value = value;
283
+ }
284
+ registerOnChange(fn) {
285
+ this.onChange = fn;
286
+ }
287
+ registerOnTouched(fn) {
288
+ this.onTouched = fn;
289
+ }
290
+ setDisabledState(isDisabled) {
291
+ this.disabled = isDisabled;
292
+ this.stateChanges.next();
293
+ }
294
+ setDescribedByIds(ids) {
295
+ const controlElement = this.#elementRef.nativeElement.querySelector('.app-calculated-field-rules');
296
+ controlElement?.setAttribute('aria-describedby', ids.join(' '));
297
+ this.describedBy = ids.join(' ');
298
+ this.stateChanges.next();
299
+ }
300
+ onContainerClick() {
301
+ if (!this.focused) {
302
+ this.focused = true;
303
+ this.stateChanges.next();
304
+ }
305
+ this.markAsTouched();
306
+ }
307
+ markAsTouched() {
308
+ if (!this.touched) {
309
+ this.onTouched();
310
+ this.touched = true;
311
+ this.stateChanges.next();
312
+ }
313
+ }
314
+ // #endregion
315
+ // #region Edit-mode lifecycle
316
+ startEdit() {
317
+ this.tempValue.set(this.#value ? structuredClone(this.#value) : {});
318
+ this.isEditing.set(true);
319
+ this.markAsTouched();
320
+ }
321
+ saveEdit() {
322
+ this.value = this.tempValue();
323
+ this.isEditing.set(false);
324
+ }
325
+ cancelEdit() {
326
+ this.isEditing.set(false);
327
+ this.tempValue.set({});
328
+ }
329
+ // #endregion
330
+ // #region Formula / variable editing (operates on tempValue)
331
+ checkIfInputCanBeLinkedToCalVariable(currentInput, inputToDisable) {
332
+ if (!currentInput) {
333
+ return false;
334
+ }
335
+ if (currentInput.formControlName === inputToDisable.formControlName) {
336
+ return true;
337
+ }
338
+ if (!currentInput.multipleInputInEditId) {
339
+ return !!inputToDisable.parentInput || !!inputToDisable.multipleInputInEditId;
340
+ }
341
+ return false;
342
+ }
343
+ linkFormulaSource(event) {
344
+ // Resetting formula to undefined intentionally during edit; persisted value
345
+ // re-validates on save.
346
+ this.tempValue.update((current) => ({
347
+ ...current,
348
+ formControlWithFormula: event.value,
349
+ formula: '',
350
+ }));
351
+ }
352
+ removeVariable(variableId) {
353
+ const current = this.tempValue();
354
+ const variables = current.variables ?? [];
355
+ const target = variables.find((v) => v.id === variableId);
356
+ let formula = current.formula ?? '';
357
+ if (target?.variable) {
358
+ formula = formula
359
+ .replace(new RegExp(`\\b${escapeRegExp(target.variable)}\\b`, 'g'), '')
360
+ .replace(/\s{2,}/g, ' ')
361
+ .trim();
362
+ }
363
+ this.tempValue.set({
364
+ ...current,
365
+ variables: variables.filter((v) => v.id !== variableId),
366
+ formula,
367
+ });
368
+ }
369
+ appendVariableToFormula(variableName) {
370
+ // A variable carries no spacing of its own, so pad it only where it would
371
+ // otherwise fuse with an adjacent token (e.g. `ab` instead of `a b`).
372
+ const { before, after } = this.#caretSlices();
373
+ const lead = before.length > 0 && !/[\s(]$/.test(before) ? ' ' : '';
374
+ const trail = after.length > 0 && !/^[\s)]/.test(after) ? ' ' : '';
375
+ this.insertToken(`${lead}${variableName}${trail}`, trail ? 1 : 0);
376
+ }
377
+ setFormula(formula) {
378
+ this.tempValue.update((current) => ({ ...current, formula }));
379
+ }
380
+ /**
381
+ * Inserts an infix token at the caret (or appends it when the textarea is not
382
+ * focused), then restores the caret just after the insertion. Used by both the
383
+ * operator palette and the variable chips so the equation reads naturally while
384
+ * staying strictly infix.
385
+ */
386
+ insertToken(token, caretBack = 0) {
387
+ const element = this.formulaInputRef()?.nativeElement;
388
+ const { before, after } = this.#caretSlices();
389
+ const next = before + token + after;
390
+ this.setFormula(next);
391
+ if (!element) {
392
+ return;
393
+ }
394
+ const caret = before.length + token.length - caretBack;
395
+ // Restore focus + caret after Angular has written the new value back to the DOM.
396
+ setTimeout(() => {
397
+ element.focus();
398
+ element.setSelectionRange(caret, caret);
399
+ });
400
+ }
401
+ /** The formula split around the current caret/selection (end-of-string when unfocused). */
402
+ #caretSlices() {
403
+ const current = this.tempValue().formula ?? '';
404
+ const element = this.formulaInputRef()?.nativeElement;
405
+ const start = element?.selectionStart ?? current.length;
406
+ const end = element?.selectionEnd ?? current.length;
407
+ return { before: current.slice(0, start), after: current.slice(end) };
408
+ }
409
+ setDecimalPlaces(value) {
410
+ const parsed = value === null || value === '' ? undefined : Number(value);
411
+ this.tempValue.update((current) => ({
412
+ ...current,
413
+ decimalPlaces: parsed !== undefined && Number.isFinite(parsed) ? parsed : undefined,
414
+ }));
415
+ }
416
+ setRoundingMode(mode) {
417
+ this.tempValue.update((current) => ({ ...current, roundingMode: mode }));
418
+ }
419
+ /** Friendly label for a stored rounding mode, used in the read-only summary. */
420
+ roundingLabel(mode) {
421
+ return this.roundingType.find((option) => option.value === mode)?.label ?? 'nearest';
422
+ }
423
+ // #endregion
424
+ // #region Inline `$` field-picker & variable binding
425
+ /** Formula text changed: persist it and re-evaluate whether the `$` picker should show. */
426
+ onFormulaChange(value) {
427
+ this.setFormula(value);
428
+ this.#syncPicker();
429
+ }
430
+ /** Caret moved (click / arrow keys / focus): re-evaluate the `$` picker against the new caret. */
431
+ onFormulaCaret() {
432
+ this.#syncPicker();
433
+ }
434
+ /** Closes the picker shortly after blur, leaving time for a result click to register. */
435
+ onFormulaBlur() {
436
+ setTimeout(() => this.closePicker(), 150);
437
+ }
438
+ /** Keyboard control for the open picker: navigate, select, dismiss. */
439
+ onFormulaKeydown(event) {
440
+ if (!this.pickerOpen()) {
441
+ return;
442
+ }
443
+ const results = this.pickerResults();
444
+ switch (event.key) {
445
+ case 'ArrowDown':
446
+ event.preventDefault();
447
+ this.pickerActiveIndex.update((i) => Math.min(i + 1, results.length - 1));
448
+ break;
449
+ case 'ArrowUp':
450
+ event.preventDefault();
451
+ this.pickerActiveIndex.update((i) => Math.max(i - 1, 0));
452
+ break;
453
+ case 'Enter': {
454
+ const item = results[this.pickerActiveIndex()];
455
+ if (item) {
456
+ event.preventDefault();
457
+ this.selectField(item);
458
+ }
459
+ break;
460
+ }
461
+ case 'Escape':
462
+ event.preventDefault();
463
+ this.closePicker();
464
+ break;
465
+ }
466
+ }
467
+ closePicker() {
468
+ this.pickerOpen.set(false);
469
+ this.pickerActiveIndex.set(0);
470
+ this.#dollarIndex = -1;
471
+ }
472
+ /**
473
+ * Binds a form field to a calculation variable and drops its short token into
474
+ * the equation. Reuses an existing scalar binding for the same field; otherwise
475
+ * mints the next free short name (a, b, c, …). When opened from `$`, the typed
476
+ * `$query` is replaced in place; otherwise the token is appended.
477
+ */
478
+ selectField(input) {
479
+ const current = this.tempValue();
480
+ const variables = current.variables ?? [];
481
+ const existing = variables.find((v) => v.formControlName === input.formControlName && !v.function && !v.parentInputId);
482
+ const token = existing ? existing.variable : this.#nextShortName();
483
+ const nextVars = existing ? variables : [...variables, this.#makeVariable(input, token)];
484
+ const formula = current.formula ?? '';
485
+ let nextFormula;
486
+ let caret;
487
+ if (this.pickerOpen() && this.#dollarIndex >= 0) {
488
+ const before = formula.slice(0, this.#dollarIndex);
489
+ const after = formula.slice(this.#cursorPosition);
490
+ const lead = before.length > 0 && !/[\s(]$/.test(before) ? ' ' : '';
491
+ const insert = `${lead}${token} `;
492
+ nextFormula = before + insert + after;
493
+ caret = (before + insert).length;
494
+ }
495
+ else {
496
+ const lead = formula.length > 0 && !/[\s(]$/.test(formula) ? ' ' : '';
497
+ nextFormula = `${formula}${lead}${token} `;
498
+ caret = nextFormula.length;
499
+ }
500
+ this.tempValue.set({ ...current, formula: nextFormula, variables: nextVars });
501
+ this.closePicker();
502
+ const element = this.formulaInputRef()?.nativeElement;
503
+ if (element) {
504
+ setTimeout(() => {
505
+ element.focus();
506
+ element.setSelectionRange(caret, caret);
507
+ });
508
+ }
509
+ }
510
+ /**
511
+ * Renames a variable's short token, updating every whole-word occurrence in the
512
+ * formula. An empty name is ignored so the token never desyncs from the formula
513
+ * (the field repopulates with the current name on the next render).
514
+ */
515
+ setVariableShortName(id, rawName) {
516
+ const name = rawName.trim();
517
+ const current = this.tempValue();
518
+ const variables = current.variables ?? [];
519
+ const target = variables.find((v) => v.id === id);
520
+ if (!target || !name || name === target.variable) {
521
+ return;
522
+ }
523
+ const formula = target.variable
524
+ ? (current.formula ?? '').replace(new RegExp(`\\b${escapeRegExp(target.variable)}\\b`, 'g'), name)
525
+ : (current.formula ?? '');
526
+ this.tempValue.set({
527
+ ...current,
528
+ formula,
529
+ variables: variables.map((v) => (v.id === id ? { ...v, variable: name } : v)),
530
+ });
531
+ }
532
+ /** Toggles a list-aggregation function (sum/avg/…) on a sub-item variable. */
533
+ setVariableFunction(id, func) {
534
+ this.tempValue.update((current) => ({
535
+ ...current,
536
+ variables: (current.variables ?? []).map((v) => {
537
+ if (v.id !== id) {
538
+ return v;
539
+ }
540
+ if (v.function === func) {
541
+ return {
542
+ ...v,
543
+ function: undefined,
544
+ applyFunctionToCol: undefined,
545
+ applyFunctionToLabel: undefined,
546
+ };
547
+ }
548
+ return {
549
+ ...v,
550
+ function: func,
551
+ applyFunctionToCol: v.formControlName,
552
+ applyFunctionToLabel: v.label,
553
+ };
554
+ }),
555
+ }));
556
+ }
557
+ /** Recomputes the picker visibility/query from the current formula and caret. */
558
+ #syncPicker() {
559
+ const element = this.formulaInputRef()?.nativeElement;
560
+ if (!element) {
561
+ this.closePicker();
562
+ return;
563
+ }
564
+ const position = element.selectionStart ?? 0;
565
+ this.#cursorPosition = position;
566
+ const formula = this.tempValue().formula ?? '';
567
+ const lastDollar = formula.slice(0, position).lastIndexOf('$');
568
+ if (lastDollar === -1) {
569
+ this.closePicker();
570
+ return;
571
+ }
572
+ const query = formula.slice(lastDollar + 1, position);
573
+ // Only a run of letters/digits/spaces keeps the picker open; anything else
574
+ // (an operator, a newline) means the `$` was not a field trigger.
575
+ if (!/^[a-zA-Z0-9 ]*$/.test(query)) {
576
+ this.closePicker();
577
+ return;
578
+ }
579
+ this.#dollarIndex = lastDollar;
580
+ this.pickerQuery.set(query);
581
+ this.pickerActiveIndex.set(0);
582
+ this.pickerOpen.set(true);
583
+ }
584
+ /** Builds a calculation variable bound to a form field, carrying the list parent when present. */
585
+ #makeVariable(input, token) {
586
+ return {
587
+ id: v4(),
588
+ variable: token,
589
+ formControlName: input.formControlName,
590
+ inputId: input.id,
591
+ label: input.label,
592
+ ...(input.multipleInputInEditId ? { parentInputId: input.multipleInputInEditId } : {}),
593
+ };
594
+ }
595
+ /** Next free single-letter token (a, b, c, …), skipping mathjs constants and falling back to v1, v2…. */
596
+ #nextShortName() {
597
+ const used = new Set((this.tempValue().variables ?? []).map((v) => v.variable));
598
+ const reserved = new Set(['e', 'i']); // mathjs constants
599
+ for (let code = 97; code <= 122; code++) {
600
+ const char = String.fromCharCode(code);
601
+ if (!used.has(char) && !reserved.has(char)) {
602
+ return char;
603
+ }
604
+ }
605
+ let n = 1;
606
+ while (used.has(`v${n}`)) {
607
+ n++;
608
+ }
609
+ return `v${n}`;
610
+ }
611
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: CalculatedFieldRulesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
612
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: CalculatedFieldRulesComponent, isStandalone: true, selector: "lib-calculated-field-rules", inputs: { placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: false, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: false, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: false, isRequired: false, transformFunction: null }, mapToData: { classPropertyName: "mapToData", publicName: "mapToData", isSignal: true, isRequired: false, transformFunction: null }, formInputs: { classPropertyName: "formInputs", publicName: "formInputs", isSignal: true, isRequired: false, transformFunction: null }, errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { valueChange2dWithPath: "valueChange2dWithPath", valueChanged: "valueChanged" }, host: { properties: { "attr.aria-describedby": "describedBy" }, classAttribute: "lib-calculated-field-rules" }, providers: [{ provide: MatFormFieldControl, useExisting: CalculatedFieldRulesComponent }], viewQueries: [{ propertyName: "formulaInputRef", first: true, predicate: ["formulaInput"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- View mode: read-only calculation summary -->\n@if (!isEditing()) {\n<div class=\"cfr-summary\">\n @if (!!value && !mapToData()?.id && !tableMode()) {\n <div class=\"cfr-hint\">\n <mat-icon class=\"cfr-hint__icon\" color=\"primary\">info</mat-icon>\n <span>Save the input first to enable calculated field configurations</span>\n </div>\n }\n\n <div class=\"cfr-formula-card\">\n <span class=\"cfr-section__label\">Calculation</span>\n <lib-math-preview class=\"cfr-formula-card__preview\" [expression]=\"value?.formula || ''\"\n placeholder=\"No calculation set up yet\" />\n @if (value?.decimalPlaces) {\n <div class=\"cfr-formula-card__meta\">\n <mat-icon class=\"cfr-formula-card__meta-icon\">tune</mat-icon>\n <span>Shown to {{ value?.decimalPlaces }} decimal place(s) \u00B7 {{ value?.roundingMode ? roundingLabel(value?.roundingMode) : 'nearest' }}</span>\n </div>\n }\n </div>\n\n <button class=\"cfr-edit-trigger\" mat-stroked-button color=\"primary\" [disabled]=\"disabled\"\n (click)=\"startEdit()\">\n <mat-icon>edit</mat-icon>\n {{ !!value?.formula ? 'Edit calculation' : 'Set up calculation' }}\n </button>\n</div>\n}\n\n<!-- Edit mode: guided calculation builder -->\n@else {\n<mat-card appearance=\"outlined\" class=\"cfr-editor\">\n <header class=\"cfr-editor__head\">\n <h3 class=\"cfr-editor__title\">\n <mat-icon>functions</mat-icon>\n Build the calculation\n </h3>\n <p class=\"cfr-editor__subtitle\">\n Combine your form fields with operators to work out this value automatically.\n </p>\n </header>\n\n <!-- Live preview + validity -->\n <div class=\"cfr-preview\" [attr.data-state]=\"formulaStatus().kind\">\n <span class=\"cfr-section__label\">Live preview</span>\n <lib-math-preview class=\"cfr-preview__render\" [expression]=\"tempValue().formula || ''\"\n placeholder=\"Your equation will appear here\" />\n <p class=\"cfr-preview__status\">\n <mat-icon class=\"cfr-preview__status-icon\">\n {{ formulaStatus().kind === 'valid' ? 'check_circle' : formulaStatus().kind === 'invalid' ? 'error' : 'lightbulb' }}\n </mat-icon>\n <span>{{ formulaStatus().message }}</span>\n </p>\n </div>\n\n <section class=\"cfr-section\">\n <!-- Equation input + inline field-picker + operator keypad -->\n <div class=\"cfr-equation\">\n <div class=\"cfr-equation__field\">\n <mat-form-field class=\"cfr-field\" [subscriptSizing]=\"'dynamic'\" [floatLabel]=\"'always'\"\n appearance=\"outline\">\n <mat-label>Equation</mat-label>\n <textarea #formulaInput matInput [ngModel]=\"tempValue().formula\"\n (ngModelChange)=\"onFormulaChange($event)\" (keyup)=\"onFormulaCaret()\"\n (click)=\"onFormulaCaret()\" (focus)=\"onFormulaCaret()\"\n (keydown)=\"onFormulaKeydown($event)\" (blur)=\"onFormulaBlur()\"\n placeholder=\"e.g. (a + 2) / b\" rows=\"2\" spellcheck=\"false\" autocapitalize=\"off\"\n autocomplete=\"off\"></textarea>\n <mat-hint>Type <strong>$</strong> to add a form field, then join fields with the operator keys.</mat-hint>\n </mat-form-field>\n\n @if (pickerOpen()) {\n <div class=\"cfr-picker\" role=\"listbox\" aria-label=\"Form fields\">\n <div class=\"cfr-picker__head\">Insert a field</div>\n @if (pickerResults().length === 0) {\n <div class=\"cfr-picker__empty\">No matching number fields</div>\n } @else {\n @for (item of pickerResults(); track item.id; let idx = $index) {\n <button type=\"button\" role=\"option\" class=\"cfr-picker__item\"\n [class.cfr-picker__item--active]=\"idx === pickerActiveIndex()\"\n [attr.aria-selected]=\"idx === pickerActiveIndex()\"\n (mousedown)=\"$event.preventDefault()\" (click)=\"selectField(item)\">\n <mat-icon class=\"cfr-picker__icon\">{{ item.multipleInputInEditId ? 'format_list_numbered' : 'tag' }}</mat-icon>\n <span class=\"cfr-picker__label\">{{ item.label }}</span>\n <span class=\"cfr-picker__meta\">{{ item.formControlName }}</span>\n </button>\n }\n }\n </div>\n }\n </div>\n\n <div class=\"cfr-keypad\" role=\"group\" aria-label=\"Operators\">\n @for (key of operatorKeys; track key.token) {\n <button type=\"button\" class=\"cfr-key\" [attr.aria-label]=\"key.aria\"\n (click)=\"insertToken(key.token, key.caretBack)\">\n {{ key.label }}\n </button>\n }\n </div>\n </div>\n\n <!-- Optional equation source link -->\n @if (!!tempValue().getFormulaFromAFormInput) {\n <mat-form-field class=\"cfr-field\" [subscriptSizing]=\"'dynamic'\" [floatLabel]=\"'always'\"\n appearance=\"outline\">\n <mat-label>Equation source</mat-label>\n <mat-select [value]=\"tempValue().formControlWithFormula\"\n (selectionChange)=\"linkFormulaSource($event)\" placeholder=\"Select an input that holds a formula\">\n @for (input of formInputs(); track input.id) {\n <mat-option\n [disabled]=\"checkIfInputCanBeLinkedToCalVariable(mapToData(), input) || input.element !== 'select'\"\n [value]=\"input.formControlName\">\n {{ input.label }}\n </mat-option>\n }\n </mat-select>\n <mat-hint>Pull the equation from another input's value</mat-hint>\n </mat-form-field>\n }\n\n <!-- Bound fields legend -->\n <div class=\"cfr-variables\">\n <div class=\"cfr-block-head\">\n <span class=\"cfr-section__label\">Fields in this calculation</span>\n <span class=\"cfr-block-head__hint\">Rename a letter, or type $ above to add another</span>\n </div>\n\n @if ((tempValue().variables || []).length === 0) {\n <p class=\"cfr-variables__empty\">\n Type <strong>$</strong> in the equation above to add a form field \u2014 each becomes a short\n letter you can use in the equation.\n </p>\n } @else {\n <ul class=\"cfr-legend\">\n @for (variable of (tempValue().variables || []); track variable.id) {\n <li class=\"cfr-legend__row\">\n <div class=\"cfr-legend__main\">\n <input class=\"cfr-legend__token\" [ngModel]=\"variable.variable\"\n (ngModelChange)=\"setVariableShortName(variable.id, $event)\" aria-label=\"Short name\"\n maxlength=\"12\" spellcheck=\"false\" autocomplete=\"off\" autocapitalize=\"off\">\n <mat-icon class=\"cfr-legend__arrow\">arrow_right_alt</mat-icon>\n <button type=\"button\" class=\"cfr-legend__field\"\n [attr.aria-label]=\"'Insert ' + variable.label + ' into the equation'\"\n (click)=\"appendVariableToFormula(variable.variable)\">\n {{ variable.label }}\n </button>\n <button type=\"button\" class=\"cfr-legend__remove\"\n [attr.aria-label]=\"'Remove ' + variable.variable\"\n (click)=\"removeVariable(variable.id)\">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n\n @if (variable.parentInputId) {\n <div class=\"cfr-legend__fns\" role=\"group\" aria-label=\"Combine list values with\">\n <span class=\"cfr-legend__fns-label\" aria-hidden=\"true\">\u0192</span>\n @for (func of allCalculationFunction(); track func) {\n <button type=\"button\" class=\"cfr-legend__fn\"\n [class.cfr-legend__fn--active]=\"variable.function === func\"\n (click)=\"setVariableFunction(variable.id, func)\">\n {{ func }}\n </button>\n }\n </div>\n }\n </li>\n }\n </ul>\n }\n </div>\n\n <!-- Result formatting -->\n <div class=\"cfr-rounding\">\n <div class=\"cfr-block-head\">\n <span class=\"cfr-section__label\">Result formatting</span>\n <span class=\"cfr-block-head__hint\">Optional \u2014 how the answer is rounded</span>\n </div>\n\n <div class=\"cfr-rounding__row\">\n <mat-form-field class=\"cfr-field cfr-rounding__decimals\" [subscriptSizing]=\"'dynamic'\"\n [floatLabel]=\"'always'\" appearance=\"outline\">\n <mat-label>Decimal places</mat-label>\n <input matInput [ngModel]=\"tempValue().decimalPlaces\"\n (ngModelChange)=\"setDecimalPlaces($event)\" placeholder=\"0\" type=\"number\" min=\"0\">\n </mat-form-field>\n\n @if (tempValue().decimalPlaces) {\n <div class=\"cfr-rounding__mode\">\n <label class=\"cfr-section__label\">Rounding</label>\n <mat-chip-listbox aria-label=\"Rounding method\">\n @for (type of roundingType; track type.value) {\n <mat-chip-option (click)=\"setRoundingMode(type.value)\"\n [selected]=\"tempValue().roundingMode === type.value\">\n {{ type.label }}\n </mat-chip-option>\n }\n </mat-chip-listbox>\n </div>\n }\n </div>\n </div>\n </section>\n\n <div class=\"cfr-editor__actions\">\n <button mat-button (click)=\"cancelEdit()\">Cancel</button>\n <button mat-flat-button color=\"primary\" [disabled]=\"formulaStatus().kind === 'invalid'\"\n (click)=\"saveEdit()\">\n Save calculation\n </button>\n </div>\n</mat-card>\n}\n\n<!-- Disabled overlay -->\n<ng-template cdkConnectedOverlay [cdkConnectedOverlayOpen]=\"disabled\">\n <div class=\"cfr-disabled-overlay\"></div>\n</ng-template>\n", styles: [":host{display:block;position:relative}.cfr-hint{display:flex;align-items:center;gap:.5rem;padding:.875rem 1rem;background:var(--sem-info-surface);border-radius:var(--lib-forms-radius-sm, 8px);color:var(--lib-forms-on-surface);font-size:.875rem}.cfr-hint__icon{flex:0 0 auto}.cfr-section__label{display:block;font-size:.625rem;font-weight:600;letter-spacing:.14em;text-transform:uppercase;color:var(--lib-forms-on-surface-variant)}.cfr-field{width:100%}.cfr-block-head{display:flex;flex-wrap:wrap;align-items:baseline;gap:.5rem .75rem;margin-bottom:.75rem}.cfr-block-head__hint{font-size:.8125rem;color:var(--lib-forms-on-surface-variant)}.cfr-summary{display:flex;flex-direction:column;gap:1.5rem}.cfr-formula-card{background:var(--lib-forms-surface);border:1px solid color-mix(in srgb,var(--lib-forms-outline) 15%,transparent);border-radius:var(--lib-forms-radius-lg, 12px);box-shadow:var(--lib-forms-shadow-resting);display:flex;flex-direction:column;gap:1rem;padding:2rem}.cfr-formula-card__preview{display:block;border-radius:var(--lib-forms-radius-md, 10px);background:var(--lib-forms-surface-container-low)}.cfr-formula-card__meta{display:flex;align-items:center;gap:.5rem;font-size:.8125rem;color:var(--lib-forms-on-surface-variant)}.cfr-formula-card__meta-icon{font-size:1.125rem;width:1.125rem;height:1.125rem}.cfr-edit-trigger{width:100%}.cfr-editor{display:flex;flex-direction:column;gap:1.5rem;padding:1.5rem;border-color:color-mix(in srgb,var(--lib-forms-primary) 30%,transparent)}.cfr-editor__head{display:flex;flex-direction:column;gap:.5rem}.cfr-editor__title{display:flex;align-items:center;gap:.5rem;margin:0;font-size:1.25rem;font-weight:500;letter-spacing:-.01em;color:var(--lib-forms-on-surface)}.cfr-editor__subtitle{margin:0;font-size:.9375rem;color:var(--lib-forms-on-surface-variant)}.cfr-preview{display:flex;flex-direction:column;gap:.875rem;padding:1.25rem 1.5rem;border-radius:var(--lib-forms-radius-lg, 12px);background:var(--lib-forms-surface-container-low);border:1px solid color-mix(in srgb,var(--lib-forms-outline) 15%,transparent);transition:border-color var(--lib-forms-duration, .4s) var(--lib-forms-easing)}.cfr-preview[data-state=valid]{border-color:color-mix(in srgb,var(--sem-success) 45%,transparent)}.cfr-preview[data-state=invalid]{border-color:color-mix(in srgb,var(--sem-error) 45%,transparent)}.cfr-preview__render{display:block}.cfr-preview__status{display:flex;align-items:center;gap:.5rem;margin:0;font-size:.875rem;color:var(--lib-forms-on-surface-variant)}.cfr-preview__status-icon{flex:0 0 auto;font-size:1.125rem;width:1.125rem;height:1.125rem}.cfr-preview[data-state=valid] .cfr-preview__status{color:var(--sem-success)}.cfr-preview[data-state=invalid] .cfr-preview__status{color:var(--sem-error)}.cfr-section{display:flex;flex-direction:column;gap:1.5rem}.cfr-equation{display:flex;flex-direction:column;gap:.625rem}.cfr-equation__field{position:relative}.cfr-keypad{display:flex;flex-wrap:wrap;gap:.375rem}.cfr-key{display:inline-flex;align-items:center;justify-content:center;min-width:2.5rem;height:2.25rem;padding:0 .625rem;border:1px solid var(--lib-forms-outline-variant);border-radius:var(--lib-forms-radius-sm, 8px);background:var(--lib-forms-surface);color:var(--lib-forms-on-surface);font-size:1rem;font-weight:500;cursor:pointer;transition:border-color var(--lib-forms-duration-hover, .3s) var(--lib-forms-easing),background-color var(--lib-forms-duration-hover, .3s) var(--lib-forms-easing),transform var(--lib-forms-duration-hover, .3s) var(--lib-forms-easing)}.cfr-key:hover{border-color:var(--lib-forms-primary);background:color-mix(in srgb,var(--lib-forms-primary) 8%,transparent)}.cfr-key:active{transform:translateY(1px)}.cfr-picker{position:absolute;z-index:20;left:0;right:0;top:calc(100% - 1.25rem);max-height:16rem;overflow-y:auto;padding:.5rem;border-radius:var(--lib-forms-radius-md, 10px);background:var(--lib-forms-surface);border:1px solid color-mix(in srgb,var(--lib-forms-outline) 20%,transparent);box-shadow:var(--lib-forms-shadow-elevated, var(--lib-forms-shadow-resting))}.cfr-picker__head{padding:.25rem .5rem .5rem;font-size:.625rem;font-weight:600;letter-spacing:.14em;text-transform:uppercase;color:var(--lib-forms-on-surface-variant)}.cfr-picker__empty{padding:.75rem .5rem;font-size:.875rem;color:var(--lib-forms-on-surface-variant)}.cfr-picker__item{display:flex;align-items:center;gap:.625rem;width:100%;padding:.5rem .625rem;border:none;border-radius:var(--lib-forms-radius-sm, 8px);background:transparent;color:var(--lib-forms-on-surface);font-size:.9375rem;text-align:left;cursor:pointer;transition:background-color var(--lib-forms-duration-hover, .3s) var(--lib-forms-easing)}.cfr-picker__item:hover,.cfr-picker__item--active{background:color-mix(in srgb,var(--lib-forms-primary) 12%,transparent)}.cfr-picker__icon{flex:0 0 auto;font-size:1.125rem;width:1.125rem;height:1.125rem;color:var(--lib-forms-on-surface-variant)}.cfr-picker__label{flex:1 1 auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.cfr-picker__meta{flex:0 0 auto;font-size:.75rem;color:var(--lib-forms-on-surface-variant)}.cfr-variables{display:flex;flex-direction:column;gap:.75rem}.cfr-variables__empty{margin:0;font-size:.875rem;color:var(--lib-forms-on-surface-variant)}.cfr-legend{display:flex;flex-direction:column;gap:.5rem;margin:0;padding:0;list-style:none}.cfr-legend__row{display:flex;flex-direction:column;gap:.5rem;padding:.5rem .625rem;border-radius:var(--lib-forms-radius-md, 10px);background:var(--lib-forms-surface-container-low);border:1px solid color-mix(in srgb,var(--lib-forms-outline) 12%,transparent)}.cfr-legend__main{display:flex;align-items:center;gap:.5rem}.cfr-legend__token{flex:0 0 auto;width:2.5rem;height:1.875rem;padding:0 .25rem;text-align:center;font-family:JetBrains Mono,SF Mono,ui-monospace,monospace;font-size:.9375rem;font-weight:600;color:var(--lib-forms-primary);background:color-mix(in srgb,var(--lib-forms-primary) 8%,var(--lib-forms-surface));border:1px solid color-mix(in srgb,var(--lib-forms-primary) 30%,transparent);border-radius:var(--lib-forms-radius-sm, 8px);transition:border-color var(--lib-forms-duration-hover, .3s) var(--lib-forms-easing),box-shadow var(--lib-forms-duration-hover, .3s) var(--lib-forms-easing)}.cfr-legend__token:focus{outline:none;border-color:var(--lib-forms-primary);box-shadow:0 0 0 2px color-mix(in srgb,var(--lib-forms-primary) 25%,transparent)}.cfr-legend__arrow{flex:0 0 auto;font-size:1.125rem;width:1.125rem;height:1.125rem;color:var(--lib-forms-on-surface-variant)}.cfr-legend__field{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding:.3125rem .625rem;border:1px solid transparent;border-radius:var(--lib-forms-radius-sm, 8px);background:transparent;color:var(--lib-forms-on-surface);font-size:.875rem;text-align:left;cursor:pointer;transition:border-color var(--lib-forms-duration-hover, .3s) var(--lib-forms-easing),background-color var(--lib-forms-duration-hover, .3s) var(--lib-forms-easing)}.cfr-legend__field:hover{border-color:var(--lib-forms-outline-variant);background:color-mix(in srgb,var(--lib-forms-primary) 6%,transparent)}.cfr-legend__remove{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;width:1.75rem;height:1.75rem;border:none;border-radius:50%;background:transparent;color:var(--lib-forms-on-surface-variant);cursor:pointer;transition:color var(--lib-forms-duration-hover, .3s) var(--lib-forms-easing),background-color var(--lib-forms-duration-hover, .3s) var(--lib-forms-easing)}.cfr-legend__remove mat-icon{font-size:1.125rem;width:1.125rem;height:1.125rem}.cfr-legend__remove:hover{color:var(--sem-error);background:var(--sem-error-surface)}.cfr-legend__fns{display:flex;flex-wrap:wrap;align-items:center;gap:.25rem;padding-left:3rem}.cfr-legend__fns-label{margin-right:.125rem;font-style:italic;font-size:.8125rem;color:var(--lib-forms-on-surface-variant)}.cfr-legend__fn{padding:.1875rem .5rem;border:1px solid var(--lib-forms-outline-variant);border-radius:var(--lib-forms-radius-pill, 999px);background:transparent;color:var(--lib-forms-on-surface-variant);font-size:.6875rem;font-weight:500;letter-spacing:.02em;cursor:pointer;transition:border-color var(--lib-forms-duration-hover, .3s) var(--lib-forms-easing),background-color var(--lib-forms-duration-hover, .3s) var(--lib-forms-easing),color var(--lib-forms-duration-hover, .3s) var(--lib-forms-easing)}.cfr-legend__fn:hover{border-color:var(--lib-forms-primary);color:var(--lib-forms-on-surface)}.cfr-legend__fn--active{border-color:transparent;background:var(--lib-forms-primary);color:var(--lib-forms-on-primary)}.cfr-rounding{display:flex;flex-direction:column}.cfr-rounding__row{display:flex;gap:1.5rem;flex-wrap:wrap}.cfr-rounding__decimals{flex:1 1 150px;min-width:150px}.cfr-rounding__mode{flex:2 1 220px;display:flex;flex-direction:column;gap:.5rem}.cfr-editor__actions{display:flex;justify-content:flex-end;gap:.75rem}.cfr-disabled-overlay{position:absolute;inset:0;background:color-mix(in srgb,var(--lib-forms-shadow-color) 50%,transparent);z-index:10}mat-chip{cursor:pointer}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: MathPreviewComponent, selector: "lib-math-preview", inputs: ["expression", "placeholder"] }, { kind: "ngmodule", type: OverlayModule }, { kind: "directive", type: i2.CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation", "cdkConnectedOverlayUsePopover", "cdkConnectedOverlayMatchWidth", "cdkConnectedOverlay"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$1.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i2$2.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i8.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i8.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatCardModule }, { kind: "component", type: i3$1.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$1.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i4.MatChipListbox, selector: "mat-chip-listbox", inputs: ["multiple", "aria-orientation", "selectable", "compareWith", "required", "hideSingleSelectionIndicator", "value"], outputs: ["change"] }, { kind: "component", type: i4.MatChipOption, selector: "mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]", inputs: ["selectable", "selected"], outputs: ["selectionChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
613
+ }
614
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: CalculatedFieldRulesComponent, decorators: [{
615
+ type: Component,
616
+ args: [{ selector: 'lib-calculated-field-rules', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.Emulated, imports: [
617
+ CommonModule,
618
+ FormsModule,
619
+ MathPreviewComponent,
620
+ OverlayModule,
621
+ MatFormFieldModule,
622
+ MatInputModule,
623
+ MatSelectModule,
624
+ MatIconModule,
625
+ MatCardModule,
626
+ MatButtonModule,
627
+ MatChipsModule,
628
+ ], providers: [{ provide: MatFormFieldControl, useExisting: CalculatedFieldRulesComponent }], host: {
629
+ 'class': 'lib-calculated-field-rules',
630
+ '[attr.aria-describedby]': 'describedBy',
631
+ }, template: "<!-- View mode: read-only calculation summary -->\n@if (!isEditing()) {\n<div class=\"cfr-summary\">\n @if (!!value && !mapToData()?.id && !tableMode()) {\n <div class=\"cfr-hint\">\n <mat-icon class=\"cfr-hint__icon\" color=\"primary\">info</mat-icon>\n <span>Save the input first to enable calculated field configurations</span>\n </div>\n }\n\n <div class=\"cfr-formula-card\">\n <span class=\"cfr-section__label\">Calculation</span>\n <lib-math-preview class=\"cfr-formula-card__preview\" [expression]=\"value?.formula || ''\"\n placeholder=\"No calculation set up yet\" />\n @if (value?.decimalPlaces) {\n <div class=\"cfr-formula-card__meta\">\n <mat-icon class=\"cfr-formula-card__meta-icon\">tune</mat-icon>\n <span>Shown to {{ value?.decimalPlaces }} decimal place(s) \u00B7 {{ value?.roundingMode ? roundingLabel(value?.roundingMode) : 'nearest' }}</span>\n </div>\n }\n </div>\n\n <button class=\"cfr-edit-trigger\" mat-stroked-button color=\"primary\" [disabled]=\"disabled\"\n (click)=\"startEdit()\">\n <mat-icon>edit</mat-icon>\n {{ !!value?.formula ? 'Edit calculation' : 'Set up calculation' }}\n </button>\n</div>\n}\n\n<!-- Edit mode: guided calculation builder -->\n@else {\n<mat-card appearance=\"outlined\" class=\"cfr-editor\">\n <header class=\"cfr-editor__head\">\n <h3 class=\"cfr-editor__title\">\n <mat-icon>functions</mat-icon>\n Build the calculation\n </h3>\n <p class=\"cfr-editor__subtitle\">\n Combine your form fields with operators to work out this value automatically.\n </p>\n </header>\n\n <!-- Live preview + validity -->\n <div class=\"cfr-preview\" [attr.data-state]=\"formulaStatus().kind\">\n <span class=\"cfr-section__label\">Live preview</span>\n <lib-math-preview class=\"cfr-preview__render\" [expression]=\"tempValue().formula || ''\"\n placeholder=\"Your equation will appear here\" />\n <p class=\"cfr-preview__status\">\n <mat-icon class=\"cfr-preview__status-icon\">\n {{ formulaStatus().kind === 'valid' ? 'check_circle' : formulaStatus().kind === 'invalid' ? 'error' : 'lightbulb' }}\n </mat-icon>\n <span>{{ formulaStatus().message }}</span>\n </p>\n </div>\n\n <section class=\"cfr-section\">\n <!-- Equation input + inline field-picker + operator keypad -->\n <div class=\"cfr-equation\">\n <div class=\"cfr-equation__field\">\n <mat-form-field class=\"cfr-field\" [subscriptSizing]=\"'dynamic'\" [floatLabel]=\"'always'\"\n appearance=\"outline\">\n <mat-label>Equation</mat-label>\n <textarea #formulaInput matInput [ngModel]=\"tempValue().formula\"\n (ngModelChange)=\"onFormulaChange($event)\" (keyup)=\"onFormulaCaret()\"\n (click)=\"onFormulaCaret()\" (focus)=\"onFormulaCaret()\"\n (keydown)=\"onFormulaKeydown($event)\" (blur)=\"onFormulaBlur()\"\n placeholder=\"e.g. (a + 2) / b\" rows=\"2\" spellcheck=\"false\" autocapitalize=\"off\"\n autocomplete=\"off\"></textarea>\n <mat-hint>Type <strong>$</strong> to add a form field, then join fields with the operator keys.</mat-hint>\n </mat-form-field>\n\n @if (pickerOpen()) {\n <div class=\"cfr-picker\" role=\"listbox\" aria-label=\"Form fields\">\n <div class=\"cfr-picker__head\">Insert a field</div>\n @if (pickerResults().length === 0) {\n <div class=\"cfr-picker__empty\">No matching number fields</div>\n } @else {\n @for (item of pickerResults(); track item.id; let idx = $index) {\n <button type=\"button\" role=\"option\" class=\"cfr-picker__item\"\n [class.cfr-picker__item--active]=\"idx === pickerActiveIndex()\"\n [attr.aria-selected]=\"idx === pickerActiveIndex()\"\n (mousedown)=\"$event.preventDefault()\" (click)=\"selectField(item)\">\n <mat-icon class=\"cfr-picker__icon\">{{ item.multipleInputInEditId ? 'format_list_numbered' : 'tag' }}</mat-icon>\n <span class=\"cfr-picker__label\">{{ item.label }}</span>\n <span class=\"cfr-picker__meta\">{{ item.formControlName }}</span>\n </button>\n }\n }\n </div>\n }\n </div>\n\n <div class=\"cfr-keypad\" role=\"group\" aria-label=\"Operators\">\n @for (key of operatorKeys; track key.token) {\n <button type=\"button\" class=\"cfr-key\" [attr.aria-label]=\"key.aria\"\n (click)=\"insertToken(key.token, key.caretBack)\">\n {{ key.label }}\n </button>\n }\n </div>\n </div>\n\n <!-- Optional equation source link -->\n @if (!!tempValue().getFormulaFromAFormInput) {\n <mat-form-field class=\"cfr-field\" [subscriptSizing]=\"'dynamic'\" [floatLabel]=\"'always'\"\n appearance=\"outline\">\n <mat-label>Equation source</mat-label>\n <mat-select [value]=\"tempValue().formControlWithFormula\"\n (selectionChange)=\"linkFormulaSource($event)\" placeholder=\"Select an input that holds a formula\">\n @for (input of formInputs(); track input.id) {\n <mat-option\n [disabled]=\"checkIfInputCanBeLinkedToCalVariable(mapToData(), input) || input.element !== 'select'\"\n [value]=\"input.formControlName\">\n {{ input.label }}\n </mat-option>\n }\n </mat-select>\n <mat-hint>Pull the equation from another input's value</mat-hint>\n </mat-form-field>\n }\n\n <!-- Bound fields legend -->\n <div class=\"cfr-variables\">\n <div class=\"cfr-block-head\">\n <span class=\"cfr-section__label\">Fields in this calculation</span>\n <span class=\"cfr-block-head__hint\">Rename a letter, or type $ above to add another</span>\n </div>\n\n @if ((tempValue().variables || []).length === 0) {\n <p class=\"cfr-variables__empty\">\n Type <strong>$</strong> in the equation above to add a form field \u2014 each becomes a short\n letter you can use in the equation.\n </p>\n } @else {\n <ul class=\"cfr-legend\">\n @for (variable of (tempValue().variables || []); track variable.id) {\n <li class=\"cfr-legend__row\">\n <div class=\"cfr-legend__main\">\n <input class=\"cfr-legend__token\" [ngModel]=\"variable.variable\"\n (ngModelChange)=\"setVariableShortName(variable.id, $event)\" aria-label=\"Short name\"\n maxlength=\"12\" spellcheck=\"false\" autocomplete=\"off\" autocapitalize=\"off\">\n <mat-icon class=\"cfr-legend__arrow\">arrow_right_alt</mat-icon>\n <button type=\"button\" class=\"cfr-legend__field\"\n [attr.aria-label]=\"'Insert ' + variable.label + ' into the equation'\"\n (click)=\"appendVariableToFormula(variable.variable)\">\n {{ variable.label }}\n </button>\n <button type=\"button\" class=\"cfr-legend__remove\"\n [attr.aria-label]=\"'Remove ' + variable.variable\"\n (click)=\"removeVariable(variable.id)\">\n <mat-icon>close</mat-icon>\n </button>\n </div>\n\n @if (variable.parentInputId) {\n <div class=\"cfr-legend__fns\" role=\"group\" aria-label=\"Combine list values with\">\n <span class=\"cfr-legend__fns-label\" aria-hidden=\"true\">\u0192</span>\n @for (func of allCalculationFunction(); track func) {\n <button type=\"button\" class=\"cfr-legend__fn\"\n [class.cfr-legend__fn--active]=\"variable.function === func\"\n (click)=\"setVariableFunction(variable.id, func)\">\n {{ func }}\n </button>\n }\n </div>\n }\n </li>\n }\n </ul>\n }\n </div>\n\n <!-- Result formatting -->\n <div class=\"cfr-rounding\">\n <div class=\"cfr-block-head\">\n <span class=\"cfr-section__label\">Result formatting</span>\n <span class=\"cfr-block-head__hint\">Optional \u2014 how the answer is rounded</span>\n </div>\n\n <div class=\"cfr-rounding__row\">\n <mat-form-field class=\"cfr-field cfr-rounding__decimals\" [subscriptSizing]=\"'dynamic'\"\n [floatLabel]=\"'always'\" appearance=\"outline\">\n <mat-label>Decimal places</mat-label>\n <input matInput [ngModel]=\"tempValue().decimalPlaces\"\n (ngModelChange)=\"setDecimalPlaces($event)\" placeholder=\"0\" type=\"number\" min=\"0\">\n </mat-form-field>\n\n @if (tempValue().decimalPlaces) {\n <div class=\"cfr-rounding__mode\">\n <label class=\"cfr-section__label\">Rounding</label>\n <mat-chip-listbox aria-label=\"Rounding method\">\n @for (type of roundingType; track type.value) {\n <mat-chip-option (click)=\"setRoundingMode(type.value)\"\n [selected]=\"tempValue().roundingMode === type.value\">\n {{ type.label }}\n </mat-chip-option>\n }\n </mat-chip-listbox>\n </div>\n }\n </div>\n </div>\n </section>\n\n <div class=\"cfr-editor__actions\">\n <button mat-button (click)=\"cancelEdit()\">Cancel</button>\n <button mat-flat-button color=\"primary\" [disabled]=\"formulaStatus().kind === 'invalid'\"\n (click)=\"saveEdit()\">\n Save calculation\n </button>\n </div>\n</mat-card>\n}\n\n<!-- Disabled overlay -->\n<ng-template cdkConnectedOverlay [cdkConnectedOverlayOpen]=\"disabled\">\n <div class=\"cfr-disabled-overlay\"></div>\n</ng-template>\n", styles: [":host{display:block;position:relative}.cfr-hint{display:flex;align-items:center;gap:.5rem;padding:.875rem 1rem;background:var(--sem-info-surface);border-radius:var(--lib-forms-radius-sm, 8px);color:var(--lib-forms-on-surface);font-size:.875rem}.cfr-hint__icon{flex:0 0 auto}.cfr-section__label{display:block;font-size:.625rem;font-weight:600;letter-spacing:.14em;text-transform:uppercase;color:var(--lib-forms-on-surface-variant)}.cfr-field{width:100%}.cfr-block-head{display:flex;flex-wrap:wrap;align-items:baseline;gap:.5rem .75rem;margin-bottom:.75rem}.cfr-block-head__hint{font-size:.8125rem;color:var(--lib-forms-on-surface-variant)}.cfr-summary{display:flex;flex-direction:column;gap:1.5rem}.cfr-formula-card{background:var(--lib-forms-surface);border:1px solid color-mix(in srgb,var(--lib-forms-outline) 15%,transparent);border-radius:var(--lib-forms-radius-lg, 12px);box-shadow:var(--lib-forms-shadow-resting);display:flex;flex-direction:column;gap:1rem;padding:2rem}.cfr-formula-card__preview{display:block;border-radius:var(--lib-forms-radius-md, 10px);background:var(--lib-forms-surface-container-low)}.cfr-formula-card__meta{display:flex;align-items:center;gap:.5rem;font-size:.8125rem;color:var(--lib-forms-on-surface-variant)}.cfr-formula-card__meta-icon{font-size:1.125rem;width:1.125rem;height:1.125rem}.cfr-edit-trigger{width:100%}.cfr-editor{display:flex;flex-direction:column;gap:1.5rem;padding:1.5rem;border-color:color-mix(in srgb,var(--lib-forms-primary) 30%,transparent)}.cfr-editor__head{display:flex;flex-direction:column;gap:.5rem}.cfr-editor__title{display:flex;align-items:center;gap:.5rem;margin:0;font-size:1.25rem;font-weight:500;letter-spacing:-.01em;color:var(--lib-forms-on-surface)}.cfr-editor__subtitle{margin:0;font-size:.9375rem;color:var(--lib-forms-on-surface-variant)}.cfr-preview{display:flex;flex-direction:column;gap:.875rem;padding:1.25rem 1.5rem;border-radius:var(--lib-forms-radius-lg, 12px);background:var(--lib-forms-surface-container-low);border:1px solid color-mix(in srgb,var(--lib-forms-outline) 15%,transparent);transition:border-color var(--lib-forms-duration, .4s) var(--lib-forms-easing)}.cfr-preview[data-state=valid]{border-color:color-mix(in srgb,var(--sem-success) 45%,transparent)}.cfr-preview[data-state=invalid]{border-color:color-mix(in srgb,var(--sem-error) 45%,transparent)}.cfr-preview__render{display:block}.cfr-preview__status{display:flex;align-items:center;gap:.5rem;margin:0;font-size:.875rem;color:var(--lib-forms-on-surface-variant)}.cfr-preview__status-icon{flex:0 0 auto;font-size:1.125rem;width:1.125rem;height:1.125rem}.cfr-preview[data-state=valid] .cfr-preview__status{color:var(--sem-success)}.cfr-preview[data-state=invalid] .cfr-preview__status{color:var(--sem-error)}.cfr-section{display:flex;flex-direction:column;gap:1.5rem}.cfr-equation{display:flex;flex-direction:column;gap:.625rem}.cfr-equation__field{position:relative}.cfr-keypad{display:flex;flex-wrap:wrap;gap:.375rem}.cfr-key{display:inline-flex;align-items:center;justify-content:center;min-width:2.5rem;height:2.25rem;padding:0 .625rem;border:1px solid var(--lib-forms-outline-variant);border-radius:var(--lib-forms-radius-sm, 8px);background:var(--lib-forms-surface);color:var(--lib-forms-on-surface);font-size:1rem;font-weight:500;cursor:pointer;transition:border-color var(--lib-forms-duration-hover, .3s) var(--lib-forms-easing),background-color var(--lib-forms-duration-hover, .3s) var(--lib-forms-easing),transform var(--lib-forms-duration-hover, .3s) var(--lib-forms-easing)}.cfr-key:hover{border-color:var(--lib-forms-primary);background:color-mix(in srgb,var(--lib-forms-primary) 8%,transparent)}.cfr-key:active{transform:translateY(1px)}.cfr-picker{position:absolute;z-index:20;left:0;right:0;top:calc(100% - 1.25rem);max-height:16rem;overflow-y:auto;padding:.5rem;border-radius:var(--lib-forms-radius-md, 10px);background:var(--lib-forms-surface);border:1px solid color-mix(in srgb,var(--lib-forms-outline) 20%,transparent);box-shadow:var(--lib-forms-shadow-elevated, var(--lib-forms-shadow-resting))}.cfr-picker__head{padding:.25rem .5rem .5rem;font-size:.625rem;font-weight:600;letter-spacing:.14em;text-transform:uppercase;color:var(--lib-forms-on-surface-variant)}.cfr-picker__empty{padding:.75rem .5rem;font-size:.875rem;color:var(--lib-forms-on-surface-variant)}.cfr-picker__item{display:flex;align-items:center;gap:.625rem;width:100%;padding:.5rem .625rem;border:none;border-radius:var(--lib-forms-radius-sm, 8px);background:transparent;color:var(--lib-forms-on-surface);font-size:.9375rem;text-align:left;cursor:pointer;transition:background-color var(--lib-forms-duration-hover, .3s) var(--lib-forms-easing)}.cfr-picker__item:hover,.cfr-picker__item--active{background:color-mix(in srgb,var(--lib-forms-primary) 12%,transparent)}.cfr-picker__icon{flex:0 0 auto;font-size:1.125rem;width:1.125rem;height:1.125rem;color:var(--lib-forms-on-surface-variant)}.cfr-picker__label{flex:1 1 auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.cfr-picker__meta{flex:0 0 auto;font-size:.75rem;color:var(--lib-forms-on-surface-variant)}.cfr-variables{display:flex;flex-direction:column;gap:.75rem}.cfr-variables__empty{margin:0;font-size:.875rem;color:var(--lib-forms-on-surface-variant)}.cfr-legend{display:flex;flex-direction:column;gap:.5rem;margin:0;padding:0;list-style:none}.cfr-legend__row{display:flex;flex-direction:column;gap:.5rem;padding:.5rem .625rem;border-radius:var(--lib-forms-radius-md, 10px);background:var(--lib-forms-surface-container-low);border:1px solid color-mix(in srgb,var(--lib-forms-outline) 12%,transparent)}.cfr-legend__main{display:flex;align-items:center;gap:.5rem}.cfr-legend__token{flex:0 0 auto;width:2.5rem;height:1.875rem;padding:0 .25rem;text-align:center;font-family:JetBrains Mono,SF Mono,ui-monospace,monospace;font-size:.9375rem;font-weight:600;color:var(--lib-forms-primary);background:color-mix(in srgb,var(--lib-forms-primary) 8%,var(--lib-forms-surface));border:1px solid color-mix(in srgb,var(--lib-forms-primary) 30%,transparent);border-radius:var(--lib-forms-radius-sm, 8px);transition:border-color var(--lib-forms-duration-hover, .3s) var(--lib-forms-easing),box-shadow var(--lib-forms-duration-hover, .3s) var(--lib-forms-easing)}.cfr-legend__token:focus{outline:none;border-color:var(--lib-forms-primary);box-shadow:0 0 0 2px color-mix(in srgb,var(--lib-forms-primary) 25%,transparent)}.cfr-legend__arrow{flex:0 0 auto;font-size:1.125rem;width:1.125rem;height:1.125rem;color:var(--lib-forms-on-surface-variant)}.cfr-legend__field{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding:.3125rem .625rem;border:1px solid transparent;border-radius:var(--lib-forms-radius-sm, 8px);background:transparent;color:var(--lib-forms-on-surface);font-size:.875rem;text-align:left;cursor:pointer;transition:border-color var(--lib-forms-duration-hover, .3s) var(--lib-forms-easing),background-color var(--lib-forms-duration-hover, .3s) var(--lib-forms-easing)}.cfr-legend__field:hover{border-color:var(--lib-forms-outline-variant);background:color-mix(in srgb,var(--lib-forms-primary) 6%,transparent)}.cfr-legend__remove{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;width:1.75rem;height:1.75rem;border:none;border-radius:50%;background:transparent;color:var(--lib-forms-on-surface-variant);cursor:pointer;transition:color var(--lib-forms-duration-hover, .3s) var(--lib-forms-easing),background-color var(--lib-forms-duration-hover, .3s) var(--lib-forms-easing)}.cfr-legend__remove mat-icon{font-size:1.125rem;width:1.125rem;height:1.125rem}.cfr-legend__remove:hover{color:var(--sem-error);background:var(--sem-error-surface)}.cfr-legend__fns{display:flex;flex-wrap:wrap;align-items:center;gap:.25rem;padding-left:3rem}.cfr-legend__fns-label{margin-right:.125rem;font-style:italic;font-size:.8125rem;color:var(--lib-forms-on-surface-variant)}.cfr-legend__fn{padding:.1875rem .5rem;border:1px solid var(--lib-forms-outline-variant);border-radius:var(--lib-forms-radius-pill, 999px);background:transparent;color:var(--lib-forms-on-surface-variant);font-size:.6875rem;font-weight:500;letter-spacing:.02em;cursor:pointer;transition:border-color var(--lib-forms-duration-hover, .3s) var(--lib-forms-easing),background-color var(--lib-forms-duration-hover, .3s) var(--lib-forms-easing),color var(--lib-forms-duration-hover, .3s) var(--lib-forms-easing)}.cfr-legend__fn:hover{border-color:var(--lib-forms-primary);color:var(--lib-forms-on-surface)}.cfr-legend__fn--active{border-color:transparent;background:var(--lib-forms-primary);color:var(--lib-forms-on-primary)}.cfr-rounding{display:flex;flex-direction:column}.cfr-rounding__row{display:flex;gap:1.5rem;flex-wrap:wrap}.cfr-rounding__decimals{flex:1 1 150px;min-width:150px}.cfr-rounding__mode{flex:2 1 220px;display:flex;flex-direction:column;gap:.5rem}.cfr-editor__actions{display:flex;justify-content:flex-end;gap:.75rem}.cfr-disabled-overlay{position:absolute;inset:0;background:color-mix(in srgb,var(--lib-forms-shadow-color) 50%,transparent);z-index:10}mat-chip{cursor:pointer}\n"] }]
632
+ }], ctorParameters: () => [], propDecorators: { placeholder: [{
633
+ type: Input
634
+ }], required: [{
635
+ type: Input
636
+ }], disabled: [{
637
+ type: Input
638
+ }], mapToData: [{ type: i0.Input, args: [{ isSignal: true, alias: "mapToData", required: false }] }], formInputs: [{ type: i0.Input, args: [{ isSignal: true, alias: "formInputs", required: false }] }], errors: [{ type: i0.Input, args: [{ isSignal: true, alias: "errors", required: false }] }], valueChange2dWithPath: [{ type: i0.Output, args: ["valueChange2dWithPath"] }], valueChanged: [{ type: i0.Output, args: ["valueChanged"] }], formulaInputRef: [{ type: i0.ViewChild, args: ['formulaInput', { isSignal: true }] }], value: [{
639
+ type: Input
640
+ }] } });
641
+
642
+ export { CalculatedFieldRulesComponent };
643
+ //# sourceMappingURL=ngx-t-forms-calculated-field-rules.component-BhxT6tRq.mjs.map