ngx-t-forms 2.0.29 → 2.0.31

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-DCKuXHAW.mjs +104 -0
  2. package/fesm2022/ngx-t-forms-auto-complete-input-element.component-DCKuXHAW.mjs.map +1 -0
  3. package/fesm2022/ngx-t-forms-basic-input-input-element.component-Ce4ipSUc.mjs +85 -0
  4. package/fesm2022/ngx-t-forms-basic-input-input-element.component-Ce4ipSUc.mjs.map +1 -0
  5. package/fesm2022/ngx-t-forms-calculated-field-rules.component-C5TPddVe.mjs +643 -0
  6. package/fesm2022/ngx-t-forms-calculated-field-rules.component-C5TPddVe.mjs.map +1 -0
  7. package/fesm2022/ngx-t-forms-chip-options-creator-editor.component-CICQaqz6.mjs +97 -0
  8. package/fesm2022/ngx-t-forms-chip-options-creator-editor.component-CICQaqz6.mjs.map +1 -0
  9. package/fesm2022/ngx-t-forms-config-mscoa-additional-inputs.component-CzisLSIP.mjs +195 -0
  10. package/fesm2022/ngx-t-forms-config-mscoa-additional-inputs.component-CzisLSIP.mjs.map +1 -0
  11. package/fesm2022/ngx-t-forms-data-source-picker.component-Dzz_o6fJ.mjs +261 -0
  12. package/fesm2022/ngx-t-forms-data-source-picker.component-Dzz_o6fJ.mjs.map +1 -0
  13. package/fesm2022/ngx-t-forms-date-picker-input-element.component-CYUbVyzP.mjs +85 -0
  14. package/fesm2022/ngx-t-forms-date-picker-input-element.component-CYUbVyzP.mjs.map +1 -0
  15. package/fesm2022/ngx-t-forms-date-range-picker-input-element.component-CmoquQGV.mjs +156 -0
  16. package/fesm2022/ngx-t-forms-date-range-picker-input-element.component-CmoquQGV.mjs.map +1 -0
  17. package/fesm2022/ngx-t-forms-document-list-label-config-editor.component-CLUOXreG.mjs +368 -0
  18. package/fesm2022/ngx-t-forms-document-list-label-config-editor.component-CLUOXreG.mjs.map +1 -0
  19. package/fesm2022/ngx-t-forms-document-picker.component-qObjcqhE.mjs +704 -0
  20. package/fesm2022/ngx-t-forms-document-picker.component-qObjcqhE.mjs.map +1 -0
  21. package/fesm2022/ngx-t-forms-editor-input-element.component-BLXlfb6F.mjs +294 -0
  22. package/fesm2022/ngx-t-forms-editor-input-element.component-BLXlfb6F.mjs.map +1 -0
  23. package/fesm2022/ngx-t-forms-editor-js-input.component-BQL0AH7H.mjs +240 -0
  24. package/fesm2022/ngx-t-forms-editor-js-input.component-BQL0AH7H.mjs.map +1 -0
  25. package/fesm2022/ngx-t-forms-file-upload-input-element.component-C7mMeEjF.mjs +205 -0
  26. package/fesm2022/ngx-t-forms-file-upload-input-element.component-C7mMeEjF.mjs.map +1 -0
  27. package/fesm2022/ngx-t-forms-form-input-selector.component-C9u8zq9B.mjs +86 -0
  28. package/fesm2022/ngx-t-forms-form-input-selector.component-C9u8zq9B.mjs.map +1 -0
  29. package/fesm2022/ngx-t-forms-form-json-view.component-856Hx1Bg.mjs +22 -0
  30. package/fesm2022/ngx-t-forms-form-json-view.component-856Hx1Bg.mjs.map +1 -0
  31. package/fesm2022/ngx-t-forms-form-payload-projection.component-CDkTuX9S.mjs +179 -0
  32. package/fesm2022/ngx-t-forms-form-payload-projection.component-CDkTuX9S.mjs.map +1 -0
  33. package/fesm2022/ngx-t-forms-form-section-stepper.component-Bs50-nEB.mjs +319 -0
  34. package/fesm2022/ngx-t-forms-form-section-stepper.component-Bs50-nEB.mjs.map +1 -0
  35. package/fesm2022/ngx-t-forms-forms-builder-menu.component-qrhM0jGL.mjs +379 -0
  36. package/fesm2022/ngx-t-forms-forms-builder-menu.component-qrhM0jGL.mjs.map +1 -0
  37. package/fesm2022/ngx-t-forms-geo-location.component-Bosp1UzR.mjs +124 -0
  38. package/fesm2022/ngx-t-forms-geo-location.component-Bosp1UzR.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-C1g7Z0cK.mjs +180 -0
  42. package/fesm2022/ngx-t-forms-image-capture-input-element.component-C1g7Z0cK.mjs.map +1 -0
  43. package/fesm2022/ngx-t-forms-index-dDSobs6A.mjs +2 -0
  44. package/fesm2022/ngx-t-forms-index-dDSobs6A.mjs.map +1 -0
  45. package/fesm2022/ngx-t-forms-input-custom.component-BkbHFAyR.mjs +105 -0
  46. package/fesm2022/ngx-t-forms-input-custom.component-BkbHFAyR.mjs.map +1 -0
  47. package/fesm2022/ngx-t-forms-input-editor.component-BPUOM9kQ.mjs +181 -0
  48. package/fesm2022/ngx-t-forms-input-editor.component-BPUOM9kQ.mjs.map +1 -0
  49. package/fesm2022/{ngx-t-forms-map-mat-options-keys-CbdW82su.mjs → ngx-t-forms-map-mat-options-keys-B6hJ7Io5.mjs} +12 -14
  50. package/fesm2022/ngx-t-forms-map-mat-options-keys-B6hJ7Io5.mjs.map +1 -0
  51. package/fesm2022/ngx-t-forms-mat-chip-list-editor.component-c7uZT1sr.mjs +66 -0
  52. package/fesm2022/ngx-t-forms-mat-chip-list-editor.component-c7uZT1sr.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-DrnH8qdG.mjs +38 -0
  58. package/fesm2022/ngx-t-forms-missing-form-configs.component-DrnH8qdG.mjs.map +1 -0
  59. package/fesm2022/ngx-t-forms-mscoa-chart-toolbar.component-C_abEBQ5.mjs +38 -0
  60. package/fesm2022/ngx-t-forms-mscoa-chart-toolbar.component-C_abEBQ5.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-C0qsMfsq.mjs +336 -0
  64. package/fesm2022/ngx-t-forms-mscoa-segment-config.component-C0qsMfsq.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-C7y1OGPx.mjs +905 -0
  68. package/fesm2022/ngx-t-forms-multiple-input-input-element.component-C7y1OGPx.mjs.map +1 -0
  69. package/fesm2022/ngx-t-forms-ngx-t-forms-u_kigDid.mjs +19461 -0
  70. package/fesm2022/ngx-t-forms-ngx-t-forms-u_kigDid.mjs.map +1 -0
  71. package/fesm2022/ngx-t-forms-paginated-selection-table-AQZSMmhr.mjs +555 -0
  72. package/fesm2022/ngx-t-forms-paginated-selection-table-AQZSMmhr.mjs.map +1 -0
  73. package/fesm2022/ngx-t-forms-pipeline-generator.component-DmNSc5aw.mjs +748 -0
  74. package/fesm2022/ngx-t-forms-pipeline-generator.component-DmNSc5aw.mjs.map +1 -0
  75. package/fesm2022/ngx-t-forms-record-list-manager.component-CUMMvMch.mjs +358 -0
  76. package/fesm2022/ngx-t-forms-record-list-manager.component-CUMMvMch.mjs.map +1 -0
  77. package/fesm2022/ngx-t-forms-required-inputs.component-Ch2yNcIS.mjs +272 -0
  78. package/fesm2022/ngx-t-forms-required-inputs.component-Ch2yNcIS.mjs.map +1 -0
  79. package/fesm2022/ngx-t-forms-rest-api-call-setup.component-C_aFtdvW.mjs +398 -0
  80. package/fesm2022/ngx-t-forms-rest-api-call-setup.component-C_aFtdvW.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-BxOhR6C0.mjs +98 -0
  84. package/fesm2022/ngx-t-forms-section-report.component-BxOhR6C0.mjs.map +1 -0
  85. package/fesm2022/ngx-t-forms-select-input-element.component-DbgZdNoe.mjs +150 -0
  86. package/fesm2022/ngx-t-forms-select-input-element.component-DbgZdNoe.mjs.map +1 -0
  87. package/fesm2022/ngx-t-forms-selection-options-editor.component-Dhln81DL.mjs +169 -0
  88. package/fesm2022/ngx-t-forms-selection-options-editor.component-Dhln81DL.mjs.map +1 -0
  89. package/fesm2022/ngx-t-forms-t-workflow-picker.component-leBokXvM.mjs +204 -0
  90. package/fesm2022/ngx-t-forms-t-workflow-picker.component-leBokXvM.mjs.map +1 -0
  91. package/fesm2022/ngx-t-forms-textarea-input-element.component-BEbXJjFA.mjs +95 -0
  92. package/fesm2022/ngx-t-forms-textarea-input-element.component-BEbXJjFA.mjs.map +1 -0
  93. package/fesm2022/ngx-t-forms-toggle-input-element.component-DDErRUJd.mjs +82 -0
  94. package/fesm2022/ngx-t-forms-toggle-input-element.component-DDErRUJd.mjs.map +1 -0
  95. package/fesm2022/ngx-t-forms-validators-config.component-oGjQVGE2.mjs +733 -0
  96. package/fesm2022/ngx-t-forms-validators-config.component-oGjQVGE2.mjs.map +1 -0
  97. package/fesm2022/ngx-t-forms-workflow-adjudication.component-CtU8dECN.mjs +1303 -0
  98. package/fesm2022/ngx-t-forms-workflow-adjudication.component-CtU8dECN.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 +1767 -621
  107. package/fesm2022/ngx-t-forms-calculated-field-rules.component-D-SBMdYg.mjs +0 -313
  108. package/fesm2022/ngx-t-forms-calculated-field-rules.component-D-SBMdYg.mjs.map +0 -1
  109. package/fesm2022/ngx-t-forms-chip-options-creator-editor.component-1cpszpPN.mjs +0 -191
  110. package/fesm2022/ngx-t-forms-chip-options-creator-editor.component-1cpszpPN.mjs.map +0 -1
  111. package/fesm2022/ngx-t-forms-config-mscoa-additional-inputs.component-DFdAVWTg.mjs +0 -207
  112. package/fesm2022/ngx-t-forms-config-mscoa-additional-inputs.component-DFdAVWTg.mjs.map +0 -1
  113. package/fesm2022/ngx-t-forms-data-source-picker.component-DxORinAD.mjs +0 -204
  114. package/fesm2022/ngx-t-forms-data-source-picker.component-DxORinAD.mjs.map +0 -1
  115. package/fesm2022/ngx-t-forms-document-list-label-config-editor.component-DcWS1txl.mjs +0 -289
  116. package/fesm2022/ngx-t-forms-document-list-label-config-editor.component-DcWS1txl.mjs.map +0 -1
  117. package/fesm2022/ngx-t-forms-form-input-selector.component-B2QEnvkq.mjs +0 -134
  118. package/fesm2022/ngx-t-forms-form-input-selector.component-B2QEnvkq.mjs.map +0 -1
  119. package/fesm2022/ngx-t-forms-form-json-view.component-DePf44w6.mjs +0 -22
  120. package/fesm2022/ngx-t-forms-form-json-view.component-DePf44w6.mjs.map +0 -1
  121. package/fesm2022/ngx-t-forms-form-section-stepper.component-BTkcSjg7.mjs +0 -270
  122. package/fesm2022/ngx-t-forms-form-section-stepper.component-BTkcSjg7.mjs.map +0 -1
  123. package/fesm2022/ngx-t-forms-forms-builder-menu.component-Wamzf_sq.mjs +0 -345
  124. package/fesm2022/ngx-t-forms-forms-builder-menu.component-Wamzf_sq.mjs.map +0 -1
  125. package/fesm2022/ngx-t-forms-input-editor.component-D4xHO76K.mjs +0 -147
  126. package/fesm2022/ngx-t-forms-input-editor.component-D4xHO76K.mjs.map +0 -1
  127. package/fesm2022/ngx-t-forms-map-mat-options-keys-CbdW82su.mjs.map +0 -1
  128. package/fesm2022/ngx-t-forms-mat-chip-list-editor.component-DmTyO9Wi.mjs +0 -105
  129. package/fesm2022/ngx-t-forms-mat-chip-list-editor.component-DmTyO9Wi.mjs.map +0 -1
  130. package/fesm2022/ngx-t-forms-mat-slider-editor.component-DZ4TenrI.mjs +0 -109
  131. package/fesm2022/ngx-t-forms-mat-slider-editor.component-DZ4TenrI.mjs.map +0 -1
  132. package/fesm2022/ngx-t-forms-mat-slider-toggle-editor.component-DPyBYE4p.mjs +0 -155
  133. package/fesm2022/ngx-t-forms-mat-slider-toggle-editor.component-DPyBYE4p.mjs.map +0 -1
  134. package/fesm2022/ngx-t-forms-missing-form-configs.component-BRmnwAK6.mjs +0 -28
  135. package/fesm2022/ngx-t-forms-missing-form-configs.component-BRmnwAK6.mjs.map +0 -1
  136. package/fesm2022/ngx-t-forms-mscoa-chart-toolbar.component-D_umeAPL.mjs +0 -43
  137. package/fesm2022/ngx-t-forms-mscoa-chart-toolbar.component-D_umeAPL.mjs.map +0 -1
  138. package/fesm2022/ngx-t-forms-mscoa-error-display.component-CSX2NCNU.mjs +0 -116
  139. package/fesm2022/ngx-t-forms-mscoa-error-display.component-CSX2NCNU.mjs.map +0 -1
  140. package/fesm2022/ngx-t-forms-mscoa-segment-config.component-B6IF8kGg.mjs +0 -296
  141. package/fesm2022/ngx-t-forms-mscoa-segment-config.component-B6IF8kGg.mjs.map +0 -1
  142. package/fesm2022/ngx-t-forms-mscoa-temporary-hint.component-BPkjsRmH.mjs +0 -83
  143. package/fesm2022/ngx-t-forms-mscoa-temporary-hint.component-BPkjsRmH.mjs.map +0 -1
  144. package/fesm2022/ngx-t-forms-ngx-t-forms-D9qmig6g.mjs +0 -16844
  145. package/fesm2022/ngx-t-forms-ngx-t-forms-D9qmig6g.mjs.map +0 -1
  146. package/fesm2022/ngx-t-forms-pipeline-generator.component-DBJEyCbd.mjs +0 -613
  147. package/fesm2022/ngx-t-forms-pipeline-generator.component-DBJEyCbd.mjs.map +0 -1
  148. package/fesm2022/ngx-t-forms-record-list-manager.component-Dgs9lNSr.mjs +0 -269
  149. package/fesm2022/ngx-t-forms-record-list-manager.component-Dgs9lNSr.mjs.map +0 -1
  150. package/fesm2022/ngx-t-forms-required-inputs.component-CSIJvSHq.mjs +0 -190
  151. package/fesm2022/ngx-t-forms-required-inputs.component-CSIJvSHq.mjs.map +0 -1
  152. package/fesm2022/ngx-t-forms-rest-api-call-setup.component-CY-JSkGs.mjs +0 -291
  153. package/fesm2022/ngx-t-forms-rest-api-call-setup.component-CY-JSkGs.mjs.map +0 -1
  154. package/fesm2022/ngx-t-forms-section-report.component-12-KdKT6.mjs +0 -156
  155. package/fesm2022/ngx-t-forms-section-report.component-12-KdKT6.mjs.map +0 -1
  156. package/fesm2022/ngx-t-forms-selection-options-editor.component-Be3QAG_L.mjs +0 -186
  157. package/fesm2022/ngx-t-forms-selection-options-editor.component-Be3QAG_L.mjs.map +0 -1
  158. package/fesm2022/ngx-t-forms-t-workflow-picker.component-a4f1r8gH.mjs +0 -187
  159. package/fesm2022/ngx-t-forms-t-workflow-picker.component-a4f1r8gH.mjs.map +0 -1
  160. package/fesm2022/ngx-t-forms-validators-config.component-B3j9Dmgu.mjs +0 -215
  161. package/fesm2022/ngx-t-forms-validators-config.component-B3j9Dmgu.mjs.map +0 -1
@@ -0,0 +1,336 @@
1
+ import * as i0 from '@angular/core';
2
+ import { input, output, inject, DestroyRef, signal, computed, effect, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
3
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
4
+ import * as i1 from '@angular/forms';
5
+ import { FormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
6
+ import { take, tap, catchError, of } from 'rxjs';
7
+ import * as i1$1 from '@angular/material/button';
8
+ import { MatButtonModule } from '@angular/material/button';
9
+ import * as i3 from '@angular/material/card';
10
+ import { MatCardModule } from '@angular/material/card';
11
+ import * as i1$2 from '@angular/material/chips';
12
+ import { MatChipsModule } from '@angular/material/chips';
13
+ import * as i2 from '@angular/material/form-field';
14
+ import { MatFormFieldModule } from '@angular/material/form-field';
15
+ import * as i3$1 from '@angular/material/icon';
16
+ import { MatIconModule } from '@angular/material/icon';
17
+ import * as i2$1 from '@angular/material/input';
18
+ import { MatInputModule } from '@angular/material/input';
19
+ import * as i8 from '@angular/material/select';
20
+ import { MatSelectModule } from '@angular/material/select';
21
+ import * as i1$3 from '@angular/material/slide-toggle';
22
+ import { MatSlideToggleModule } from '@angular/material/slide-toggle';
23
+ import { v4 } from 'uuid';
24
+ import { _ as _isEqual, E as EmptyStateComponent } from './ngx-t-forms-ngx-t-forms-u_kigDid.mjs';
25
+
26
+ let nextUniqueId = 0;
27
+ const IDLE = { mode: 'idle' };
28
+ /**
29
+ * Internal editor element for configuring an MSCOA input's included account
30
+ * segments. Child of `t-dynamic-data-edit`, which supplies the field label,
31
+ * hint, and validation errors - so this component owns only the segment chip
32
+ * row and the add/edit panel.
33
+ *
34
+ * The segment list is seeded from the MSCOA tree (`getMscoaTree`); each segment
35
+ * carries flags such as single-select, read-only, VAT-selection and
36
+ * inherit-from-accrual. In cash-segment mode (`isCashSegmentConfig`) every
37
+ * non-`item` segment defaults to inherit-from-accrual + read-only.
38
+ */
39
+ class MscoaSegmentConfigComponent {
40
+ #fb;
41
+ #destroyRef;
42
+ /** Tree-derived segment templates (drives the segment `mat-select`). */
43
+ #treeSegments;
44
+ /** Error raised while fetching the tree (`null` until/unless the fetch fails). */
45
+ #fetchError;
46
+ /** Add/edit panel state. */
47
+ #editState;
48
+ /** Guards single-shot tree load (mirrors the original take(1) one-time fetch). */
49
+ #treeRequested;
50
+ constructor() {
51
+ /**
52
+ * Validation errors passed down by the parent editor. Retained on the contract
53
+ * but not rendered here - `t-dynamic-data-edit` owns error display.
54
+ */
55
+ this.errors = input([], ...(ngDevMode ? [{ debugName: "errors" }] : /* istanbul ignore next */ []));
56
+ /** The full MSCOA input config; supplies the extension-account options. */
57
+ this.dataValue = input(undefined, ...(ngDevMode ? [{ debugName: "dataValue" }] : /* istanbul ignore next */ []));
58
+ /** Disable user interaction. */
59
+ this.disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
60
+ /** Cash-segment mode: non-`item` segments default to inherit + read-only. */
61
+ this.isCashSegmentConfig = input(false, ...(ngDevMode ? [{ debugName: "isCashSegmentConfig" }] : /* istanbul ignore next */ []));
62
+ /** Currently configured segments. */
63
+ this.value = input(undefined, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
64
+ /** When true, render every tree segment read-only (no add/remove). */
65
+ this.showAllSegments = input(false, ...(ngDevMode ? [{ debugName: "showAllSegments" }] : /* istanbul ignore next */ []));
66
+ /**
67
+ * Stream that resolves the MSCOA account tree. Heterogeneous wrapper binding -
68
+ * the parent feeds whatever the editor config holds; narrowing here would force
69
+ * wrapper changes.
70
+ */
71
+ this.getMscoaTree = input(undefined, ...(ngDevMode ? [{ debugName: "getMscoaTree" }] : /* istanbul ignore next */ []));
72
+ /** Emits the mutated segment list whenever the user adds, edits, or removes one. */
73
+ this.valueChanged = output();
74
+ /** Host id attribute - stable, unique per instance. */
75
+ this.hostId = `app-mscoa-segment-config-${nextUniqueId++}`;
76
+ this.#fb = inject(FormBuilder);
77
+ this.#destroyRef = inject(DestroyRef);
78
+ /** Tree-derived segment templates (drives the segment `mat-select`). */
79
+ this.#treeSegments = signal([], ...(ngDevMode ? [{ debugName: "#treeSegments" }] : /* istanbul ignore next */ []));
80
+ /** Error raised while fetching the tree (`null` until/unless the fetch fails). */
81
+ this.#fetchError = signal(null, ...(ngDevMode ? [{ debugName: "#fetchError" }] : /* istanbul ignore next */ []));
82
+ /** True while the tree stream is in flight. */
83
+ this.loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
84
+ /** Add/edit panel state. */
85
+ this.#editState = signal(IDLE, ...(ngDevMode ? [{ debugName: "#editState" }] : /* istanbul ignore next */ []));
86
+ /** Reactive form for the segment currently being added/edited. */
87
+ this.segmentForm = this.#createSegmentForm();
88
+ /** Guards single-shot tree load (mirrors the original take(1) one-time fetch). */
89
+ this.#treeRequested = false;
90
+ /** The configured segments, never null. */
91
+ this.resolvedValue = computed(() => this.value() ?? [], ...(ngDevMode ? [{ debugName: "resolvedValue" }] : /* istanbul ignore next */ []));
92
+ /** Tree-derived segment templates for the picker. */
93
+ this.treeSegments = this.#treeSegments.asReadonly();
94
+ /**
95
+ * Loader/tree error message; `null` when none. A fetch error takes priority,
96
+ * otherwise a missing loader surfaces the "No loader provided" notice.
97
+ */
98
+ this.treeError = computed(() => {
99
+ const fetchError = this.#fetchError();
100
+ if (fetchError) {
101
+ return fetchError;
102
+ }
103
+ return this.getMscoaTree() ? null : 'No loader provided';
104
+ }, ...(ngDevMode ? [{ debugName: "treeError" }] : /* istanbul ignore next */ []));
105
+ /** Whether the add/edit panel is open. */
106
+ this.isEditing = computed(() => this.#editState().mode !== 'idle', ...(ngDevMode ? [{ debugName: "isEditing" }] : /* istanbul ignore next */ []));
107
+ /** Whether the open panel is adding a brand-new segment. */
108
+ this.isAddingNew = computed(() => this.#editState().mode === 'add', ...(ngDevMode ? [{ debugName: "isAddingNew" }] : /* istanbul ignore next */ []));
109
+ /** Whether the "Add new segment" toolbar button should show. */
110
+ this.canAddNew = computed(() => !this.isEditing() && !this.showAllSegments(), ...(ngDevMode ? [{ debugName: "canAddNew" }] : /* istanbul ignore next */ []));
111
+ // One-time tree load. Mirrors the original `take(1)` fetch. The signal
112
+ // writes happen off the reactive tick (microtask) so the effect itself
113
+ // performs no synchronous signal mutation.
114
+ effect(() => {
115
+ const tree$ = this.getMscoaTree();
116
+ if (!tree$ || this.#treeRequested) {
117
+ return;
118
+ }
119
+ this.#treeRequested = true;
120
+ queueMicrotask(() => this.#loadMscoa(tree$));
121
+ });
122
+ // Reflect the full tree as read-only segments when `showAllSegments` is on.
123
+ effect(() => {
124
+ if (this.showAllSegments()) {
125
+ this.#syncAllSegments();
126
+ }
127
+ });
128
+ }
129
+ /** Fetch the tree once, build the segment templates, surface any error. */
130
+ #loadMscoa(tree$) {
131
+ this.#fetchError.set(null);
132
+ this.loading.set(true);
133
+ tree$
134
+ .pipe(take(1), tap((response) => {
135
+ this.#treeSegments.set(this.#buildTreeSegments(response));
136
+ this.loading.set(false);
137
+ }), catchError(() => {
138
+ this.#fetchError.set('Failed to fetch mscoa tree');
139
+ this.loading.set(false);
140
+ return of(undefined);
141
+ }), takeUntilDestroyed(this.#destroyRef))
142
+ .subscribe();
143
+ }
144
+ /** Map the tree account keys into seedable segment templates. */
145
+ #buildTreeSegments(response) {
146
+ const isCash = this.isCashSegmentConfig();
147
+ const current = this.resolvedValue();
148
+ return (response?.accountTreeKeys ?? []).map((treeKey) => {
149
+ const isItem = treeKey.toLocaleLowerCase() === 'item';
150
+ return {
151
+ id: v4(),
152
+ segment: treeKey,
153
+ singleSelect: true,
154
+ additionalAccounts: [],
155
+ inheritValueFromAccrual: isCash ? !isItem : undefined,
156
+ vatSelectonActive: isCash ? false : isItem,
157
+ segmentExtension: false,
158
+ label: this.#toTitleCase(treeKey),
159
+ readOnly: current.find((v) => v.segment === treeKey)?.readOnly ||
160
+ (isCash && !isItem) ||
161
+ false,
162
+ };
163
+ });
164
+ }
165
+ /** Build the per-segment reactive form. */
166
+ #createSegmentForm(segment = {
167
+ segment: '',
168
+ label: '',
169
+ id: v4(),
170
+ singleSelect: true,
171
+ segmentExtension: false,
172
+ additionalAccounts: [],
173
+ readOnly: false,
174
+ }) {
175
+ const isItem = segment.segment?.toLocaleLowerCase() === 'item';
176
+ return this.#fb.group({
177
+ id: [segment.id],
178
+ segment: [segment.segment, Validators.required],
179
+ segmentExtension: [segment.segmentExtension, Validators.required],
180
+ readOnly: [segment.readOnly, Validators.required],
181
+ inheritValueFromAccrual: this.isCashSegmentConfig()
182
+ ? [segment.inheritValueFromAccrual, Validators.required]
183
+ : [segment.inheritValueFromAccrual],
184
+ vatSelectonActive: isItem
185
+ ? [Boolean(segment.vatSelectonActive), Validators.required]
186
+ : [Boolean(segment.vatSelectonActive)],
187
+ additionalAccounts: [segment.additionalAccounts ?? []],
188
+ label: [segment.label, Validators.required],
189
+ singleSelect: [segment.singleSelect, Validators.required],
190
+ });
191
+ }
192
+ startAddNew() {
193
+ this.segmentForm = this.#createSegmentForm();
194
+ this.#editState.set({ mode: 'add' });
195
+ }
196
+ startEdit(index) {
197
+ const segment = this.resolvedValue().at(index);
198
+ if (!segment) {
199
+ return;
200
+ }
201
+ this.segmentForm = this.#createSegmentForm(segment);
202
+ this.#editState.set({ mode: 'edit', index });
203
+ }
204
+ cancelEdit() {
205
+ this.segmentForm.reset();
206
+ this.#editState.set(IDLE);
207
+ }
208
+ saveSegment() {
209
+ if (!this.segmentForm.valid) {
210
+ return;
211
+ }
212
+ const raw = this.segmentForm.getRawValue();
213
+ const label = this.#toTitleCase(String(raw.label ?? ''));
214
+ const newSegment = {
215
+ id: typeof raw.id === 'string' && raw.id ? raw.id : v4(),
216
+ segment: raw.segment,
217
+ // Multi-level segments derive their key from the (upper-cased) label.
218
+ customSegment: raw.segmentExtension ? label.toLocaleUpperCase() : undefined,
219
+ segmentExtension: Boolean(raw.segmentExtension),
220
+ inheritValueFromAccrual: Boolean(raw.inheritValueFromAccrual),
221
+ vatSelectonActive: Boolean(raw.vatSelectonActive),
222
+ additionalAccounts: Array.isArray(raw.additionalAccounts) ? raw.additionalAccounts : [],
223
+ label,
224
+ singleSelect: Boolean(raw.singleSelect),
225
+ readOnly: Boolean(raw.readOnly),
226
+ };
227
+ const state = this.#editState();
228
+ const updated = [...this.resolvedValue()];
229
+ if (state.mode === 'add') {
230
+ updated.push(newSegment);
231
+ }
232
+ else if (state.mode === 'edit') {
233
+ updated[state.index] = newSegment;
234
+ }
235
+ else {
236
+ return;
237
+ }
238
+ this.valueChanged.emit(updated);
239
+ this.cancelEdit();
240
+ }
241
+ readOnlyChanged(event) {
242
+ this.segmentForm.patchValue({ readOnly: event.checked });
243
+ }
244
+ singleSelectChange(event) {
245
+ this.segmentForm.patchValue({ singleSelect: event.checked });
246
+ }
247
+ setVatSelectionActive(event) {
248
+ this.segmentForm.patchValue({ vatSelectonActive: event.checked });
249
+ }
250
+ /** Inherit-from-accrual implies read-only (quirk: toggling on forces read-only). */
251
+ setInheritFromAccrual(event) {
252
+ this.segmentForm.patchValue({ inheritValueFromAccrual: event.checked });
253
+ if (event.checked) {
254
+ this.segmentForm.patchValue({ readOnly: true });
255
+ }
256
+ }
257
+ multiLevelSelectChange(event) {
258
+ this.segmentForm.patchValue({ segmentExtension: event.checked });
259
+ }
260
+ /** Pick a segment; auto-fill the label from it unless this is a multi-level extension. */
261
+ selectSegment(event) {
262
+ this.segmentForm.patchValue({ segment: event.value });
263
+ if (!this.segmentForm.value.segmentExtension) {
264
+ this.segmentForm.patchValue({ label: this.#toTitleCase(String(event.value ?? '')) });
265
+ }
266
+ }
267
+ additionalAccountsChanged(event) {
268
+ this.segmentForm.patchValue({ additionalAccounts: [...event.value] }, { emitEvent: true });
269
+ }
270
+ removeSegment(index) {
271
+ const updated = this.resolvedValue().filter((_, i) => i !== index);
272
+ this.valueChanged.emit(updated);
273
+ }
274
+ /**
275
+ * A tree template is "already used" (and so disabled in the picker) when a
276
+ * segment with the same key is already configured - except for multi-level
277
+ * extensions, which may reuse a key.
278
+ */
279
+ alreadyExists(segment) {
280
+ if (this.segmentForm.value.segmentExtension) {
281
+ return false;
282
+ }
283
+ return this.resolvedValue().some((v) => v.segment === segment.segment);
284
+ }
285
+ /** Extension-account options drawn from the MSCOA config. */
286
+ get extensionAccountsForSegments() {
287
+ return this.dataValue()?.mscoaConfig?.extensionAccountsForSegments ?? [];
288
+ }
289
+ /**
290
+ * When `showAllSegments` is on, reconcile the configured value against the full
291
+ * tree. Preserves the deliberate double-emit sync: emit a reset sentinel first,
292
+ * then the merged list on the next microtask so the parent re-renders cleanly.
293
+ */
294
+ #syncAllSegments() {
295
+ const templates = this.#treeSegments();
296
+ if (!this.#treeRequested || templates.length === 0) {
297
+ return;
298
+ }
299
+ const current = this.resolvedValue();
300
+ const merged = templates.map((segment) => ({
301
+ ...segment,
302
+ ...(current.find((v) => v.segment === segment.segment) ?? {}),
303
+ }));
304
+ if (!_isEqual(merged, current)) {
305
+ // Reset sentinel, then the real value, to force downstream re-binding.
306
+ this.valueChanged.emit([{}]);
307
+ queueMicrotask(() => this.valueChanged.emit(merged));
308
+ }
309
+ }
310
+ #toTitleCase(str) {
311
+ return str.replace(/\w\S*/g, (txt) => txt.charAt(0).toUpperCase() + txt.slice(1).toLowerCase());
312
+ }
313
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: MscoaSegmentConfigComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
314
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: MscoaSegmentConfigComponent, isStandalone: true, selector: "lib-mscoa-segment-config", inputs: { errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null }, dataValue: { classPropertyName: "dataValue", publicName: "dataValue", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, isCashSegmentConfig: { classPropertyName: "isCashSegmentConfig", publicName: "isCashSegmentConfig", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, showAllSegments: { classPropertyName: "showAllSegments", publicName: "showAllSegments", isSignal: true, isRequired: false, transformFunction: null }, getMscoaTree: { classPropertyName: "getMscoaTree", publicName: "getMscoaTree", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChanged: "valueChanged" }, host: { properties: { "attr.id": "hostId" }, classAttribute: "lib-mscoa-segment-config" }, ngImport: i0, template: "@if (loading()) {\n <div class=\"mscoa-segment-config__notice\">\n <mat-icon class=\"mscoa-segment-config__notice-icon\">hourglass_top</mat-icon>\n <span>Loading account segments\u2026</span>\n </div>\n}\n\n@if (treeError(); as error) {\n <div class=\"mscoa-segment-config__notice mscoa-segment-config__notice--error\">\n <mat-icon class=\"mscoa-segment-config__notice-icon\">error_outline</mat-icon>\n <span>{{ error }}</span>\n </div>\n}\n\n@if (resolvedValue().length > 0) {\n <div class=\"mscoa-segment-config__section\">\n <p class=\"mscoa-segment-config__section-label\">Configured segments</p>\n <mat-chip-listbox [disabled]=\"disabled()\" aria-label=\"Configured account segments\">\n @for (segment of resolvedValue(); track segment.id; let i = $index) {\n <mat-chip-option\n (removed)=\"removeSegment(i)\"\n (click)=\"startEdit(i)\"\n [value]=\"segment.segment\"\n [selected]=\"isEditing() && !isAddingNew()\">\n <span class=\"mscoa-segment-config__chip-content\">\n <span class=\"mscoa-segment-config__chip-label\">{{ segment.label }}</span>\n <mat-icon class=\"mscoa-segment-config__chip-icon\">\n {{ segment.singleSelect ? 'done' : 'done_all' }}\n </mat-icon>\n <mat-icon class=\"mscoa-segment-config__chip-icon\">\n {{ segment.readOnly ? 'edit_off' : 'edit' }}\n </mat-icon>\n </span>\n\n @if (showAllSegments() === false) {\n <button matChipRemove aria-label=\"Remove segment\" [disabled]=\"disabled()\">\n <mat-icon>cancel</mat-icon>\n </button>\n }\n </mat-chip-option>\n }\n </mat-chip-listbox>\n </div>\n} @else if (!loading()) {\n <lib-empty-state\n icon=\"account_tree\"\n message=\"No segments configured yet. Add one to begin shaping this MSCOA input.\">\n @if (canAddNew()) {\n <button mat-stroked-button [disabled]=\"disabled()\" (click)=\"startAddNew()\">\n <mat-icon>add</mat-icon>\n Add segment\n </button>\n }\n </lib-empty-state>\n}\n\n@if (canAddNew() && resolvedValue().length > 0) {\n <button\n class=\"mscoa-segment-config__add\"\n mat-stroked-button\n [disabled]=\"disabled()\"\n (click)=\"startAddNew()\">\n <mat-icon>add</mat-icon>\n Add new segment\n </button>\n}\n\n@if (isEditing()) {\n <mat-card class=\"mscoa-segment-config__panel\" appearance=\"outlined\">\n <mat-card-header>\n <mat-card-subtitle>\n {{ isAddingNew() ? 'Add a new' : 'Update' }} segment\n </mat-card-subtitle>\n </mat-card-header>\n\n <mat-card-content>\n <form [formGroup]=\"segmentForm\" (ngSubmit)=\"saveSegment()\">\n <div class=\"mscoa-segment-config__group\">\n <div class=\"mscoa-segment-config__toggle\">\n <mat-slide-toggle\n (change)=\"multiLevelSelectChange($event)\"\n [checked]=\"segmentForm.value.segmentExtension\">\n Enable multi-level segmentation\n </mat-slide-toggle>\n </div>\n <p class=\"mscoa-segment-config__hint\">\n Allows sub-classifications within this segment for more detailed accounting hierarchies.\n </p>\n\n <mat-form-field subscriptSizing=\"dynamic\" floatLabel=\"always\" appearance=\"outline\">\n <mat-label>Segment</mat-label>\n <mat-select\n (selectionChange)=\"selectSegment($event)\"\n formControlName=\"segment\"\n placeholder=\"Select segment\">\n @for (segment of treeSegments(); track segment.id) {\n <mat-option [disabled]=\"alreadyExists(segment)\" [value]=\"segment.segment\">\n {{ segment.label }}\n </mat-option>\n }\n </mat-select>\n <mat-hint>Select an account segment type from your chart of accounts.</mat-hint>\n </mat-form-field>\n </div>\n\n @if (isCashSegmentConfig()) {\n <div class=\"mscoa-segment-config__group\">\n <div class=\"mscoa-segment-config__toggle\">\n <mat-slide-toggle\n (change)=\"setInheritFromAccrual($event)\"\n [checked]=\"segmentForm.value.inheritValueFromAccrual\">\n Inherit from accrual\n </mat-slide-toggle>\n </div>\n <p class=\"mscoa-segment-config__hint\">\n When enabled, changes to the accrual value reflect here automatically.\n </p>\n </div>\n }\n\n <div class=\"mscoa-segment-config__group\">\n <mat-form-field subscriptSizing=\"dynamic\" floatLabel=\"always\" appearance=\"outline\">\n <mat-label>Label</mat-label>\n <input\n matInput\n formControlName=\"label\"\n [readonly]=\"!segmentForm.value.segmentExtension\"\n placeholder=\"Enter label\" />\n <mat-hint>\n A descriptive name for this segment (e.g. 'Department', 'Project', 'Cost Center').\n </mat-hint>\n </mat-form-field>\n </div>\n\n <div class=\"mscoa-segment-config__group\">\n <div class=\"mscoa-segment-config__toggle\">\n <mat-slide-toggle\n (change)=\"singleSelectChange($event)\"\n [checked]=\"segmentForm.value.singleSelect\">\n Single value selection\n </mat-slide-toggle>\n </div>\n <p class=\"mscoa-segment-config__hint\">\n When enabled, transactions are assigned to one value within this segment; when disabled,\n they can be split across multiple values.\n </p>\n </div>\n\n @if (segmentForm.value.segment?.toLocaleLowerCase() === 'item') {\n <div class=\"mscoa-segment-config__group\">\n <div class=\"mscoa-segment-config__toggle\">\n <mat-slide-toggle\n (change)=\"setVatSelectionActive($event)\"\n [checked]=\"segmentForm.value.vatSelectonActive\">\n Require VAT account selection\n </mat-slide-toggle>\n </div>\n <p class=\"mscoa-segment-config__hint\">\n When active, users must specify a VAT account for taxable items.\n </p>\n </div>\n }\n\n <div class=\"mscoa-segment-config__group\">\n <div class=\"mscoa-segment-config__toggle\">\n <mat-slide-toggle\n (change)=\"readOnlyChanged($event)\"\n [checked]=\"segmentForm.value.readOnly\">\n Read-only segment\n </mat-slide-toggle>\n </div>\n <p class=\"mscoa-segment-config__hint\">\n Prevents users from modifying segment values after initial setup. Use for regulatory or\n policy-controlled segments.\n </p>\n </div>\n\n <div class=\"mscoa-segment-config__group\">\n <mat-form-field subscriptSizing=\"dynamic\" floatLabel=\"always\" appearance=\"outline\">\n <mat-label>Additional accounts</mat-label>\n <mat-select\n (selectionChange)=\"additionalAccountsChanged($event)\"\n formControlName=\"additionalAccounts\"\n multiple\n placeholder=\"Select counter accounts\">\n @for (ext of extensionAccountsForSegments; track ext) {\n <mat-option [value]=\"ext\">{{ ext }}</mat-option>\n }\n </mat-select>\n <mat-hint>\n Add supporting accounts for this segment (e.g. VAT or tax accounts).\n </mat-hint>\n </mat-form-field>\n </div>\n\n <mat-card-actions class=\"mscoa-segment-config__actions\">\n <button mat-button type=\"button\" (click)=\"cancelEdit()\">Cancel</button>\n <button mat-flat-button color=\"primary\" type=\"submit\" [disabled]=\"!segmentForm.valid\">\n Save\n </button>\n </mat-card-actions>\n </form>\n </mat-card-content>\n </mat-card>\n}\n", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:column;gap:1.5rem;color:var(--lib-forms-on-surface)}.mscoa-segment-config__notice{display:flex;align-items:center;gap:.5rem;padding:.75rem 1rem;border-radius:var(--lib-forms-radius-md, 10px);background:var(--sem-info-surface);color:var(--lib-forms-on-surface);font-size:.875rem}.mscoa-segment-config__notice--error{background:var(--sem-error-surface)}.mscoa-segment-config__notice-icon{flex:0 0 auto;color:var(--lib-forms-on-surface-variant)}.mscoa-segment-config__notice--error .mscoa-segment-config__notice-icon{color:var(--sem-error)}.mscoa-segment-config__section{display:flex;flex-direction:column;gap:.75rem}.mscoa-segment-config__section-label{margin:0;font-size:.625rem;font-weight:600;letter-spacing:.14em;text-transform:uppercase;color:var(--lib-forms-on-surface-variant)}.mscoa-segment-config__chip-content{display:inline-flex;align-items:center;gap:.375rem}.mscoa-segment-config__chip-label{margin-right:.125rem}.mscoa-segment-config__chip-icon{width:1rem;height:1rem;font-size:1rem;line-height:1;color:var(--lib-forms-on-surface-variant)}.mscoa-segment-config__add{width:100%}.mscoa-segment-config__panel{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:block}.mscoa-segment-config__group{display:flex;flex-direction:column;gap:.5rem;margin-bottom:1.5rem}.mscoa-segment-config__group:last-of-type{margin-bottom:0}.mscoa-segment-config__group mat-form-field{width:100%}.mscoa-segment-config__toggle{display:flex;align-items:center;padding:.5rem 0}.mscoa-segment-config__hint{margin:0;font-size:.75rem;line-height:1.4;color:var(--lib-forms-on-surface-variant)}.mscoa-segment-config__actions{display:flex;justify-content:flex-end;gap:.75rem;margin-top:.5rem}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { 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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { 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: MatCardModule }, { kind: "component", type: i3.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i3.MatCardActions, selector: "mat-card-actions", inputs: ["align"], exportAs: ["matCardActions"] }, { kind: "directive", type: i3.MatCardContent, selector: "mat-card-content" }, { kind: "component", type: i3.MatCardHeader, selector: "mat-card-header" }, { kind: "directive", type: i3.MatCardSubtitle, selector: "mat-card-subtitle, [mat-card-subtitle], [matCardSubtitle]" }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i1$2.MatChipListbox, selector: "mat-chip-listbox", inputs: ["multiple", "aria-orientation", "selectable", "compareWith", "required", "hideSingleSelectionIndicator", "value"], outputs: ["change"] }, { kind: "component", type: i1$2.MatChipOption, selector: "mat-basic-chip-option, [mat-basic-chip-option], mat-chip-option, [mat-chip-option]", inputs: ["selectable", "selected"], outputs: ["selectionChange"] }, { kind: "directive", type: i1$2.MatChipRemove, selector: "[matChipRemove]" }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i2$1.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: MatSlideToggleModule }, { kind: "component", type: i1$3.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "component", type: EmptyStateComponent, selector: "lib-empty-state", inputs: ["icon", "message"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
315
+ }
316
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: MscoaSegmentConfigComponent, decorators: [{
317
+ type: Component,
318
+ args: [{ selector: 'lib-mscoa-segment-config', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.Emulated, host: {
319
+ 'class': 'lib-mscoa-segment-config',
320
+ '[attr.id]': 'hostId',
321
+ }, imports: [
322
+ ReactiveFormsModule,
323
+ MatButtonModule,
324
+ MatCardModule,
325
+ MatChipsModule,
326
+ MatFormFieldModule,
327
+ MatIconModule,
328
+ MatInputModule,
329
+ MatSelectModule,
330
+ MatSlideToggleModule,
331
+ EmptyStateComponent,
332
+ ], template: "@if (loading()) {\n <div class=\"mscoa-segment-config__notice\">\n <mat-icon class=\"mscoa-segment-config__notice-icon\">hourglass_top</mat-icon>\n <span>Loading account segments\u2026</span>\n </div>\n}\n\n@if (treeError(); as error) {\n <div class=\"mscoa-segment-config__notice mscoa-segment-config__notice--error\">\n <mat-icon class=\"mscoa-segment-config__notice-icon\">error_outline</mat-icon>\n <span>{{ error }}</span>\n </div>\n}\n\n@if (resolvedValue().length > 0) {\n <div class=\"mscoa-segment-config__section\">\n <p class=\"mscoa-segment-config__section-label\">Configured segments</p>\n <mat-chip-listbox [disabled]=\"disabled()\" aria-label=\"Configured account segments\">\n @for (segment of resolvedValue(); track segment.id; let i = $index) {\n <mat-chip-option\n (removed)=\"removeSegment(i)\"\n (click)=\"startEdit(i)\"\n [value]=\"segment.segment\"\n [selected]=\"isEditing() && !isAddingNew()\">\n <span class=\"mscoa-segment-config__chip-content\">\n <span class=\"mscoa-segment-config__chip-label\">{{ segment.label }}</span>\n <mat-icon class=\"mscoa-segment-config__chip-icon\">\n {{ segment.singleSelect ? 'done' : 'done_all' }}\n </mat-icon>\n <mat-icon class=\"mscoa-segment-config__chip-icon\">\n {{ segment.readOnly ? 'edit_off' : 'edit' }}\n </mat-icon>\n </span>\n\n @if (showAllSegments() === false) {\n <button matChipRemove aria-label=\"Remove segment\" [disabled]=\"disabled()\">\n <mat-icon>cancel</mat-icon>\n </button>\n }\n </mat-chip-option>\n }\n </mat-chip-listbox>\n </div>\n} @else if (!loading()) {\n <lib-empty-state\n icon=\"account_tree\"\n message=\"No segments configured yet. Add one to begin shaping this MSCOA input.\">\n @if (canAddNew()) {\n <button mat-stroked-button [disabled]=\"disabled()\" (click)=\"startAddNew()\">\n <mat-icon>add</mat-icon>\n Add segment\n </button>\n }\n </lib-empty-state>\n}\n\n@if (canAddNew() && resolvedValue().length > 0) {\n <button\n class=\"mscoa-segment-config__add\"\n mat-stroked-button\n [disabled]=\"disabled()\"\n (click)=\"startAddNew()\">\n <mat-icon>add</mat-icon>\n Add new segment\n </button>\n}\n\n@if (isEditing()) {\n <mat-card class=\"mscoa-segment-config__panel\" appearance=\"outlined\">\n <mat-card-header>\n <mat-card-subtitle>\n {{ isAddingNew() ? 'Add a new' : 'Update' }} segment\n </mat-card-subtitle>\n </mat-card-header>\n\n <mat-card-content>\n <form [formGroup]=\"segmentForm\" (ngSubmit)=\"saveSegment()\">\n <div class=\"mscoa-segment-config__group\">\n <div class=\"mscoa-segment-config__toggle\">\n <mat-slide-toggle\n (change)=\"multiLevelSelectChange($event)\"\n [checked]=\"segmentForm.value.segmentExtension\">\n Enable multi-level segmentation\n </mat-slide-toggle>\n </div>\n <p class=\"mscoa-segment-config__hint\">\n Allows sub-classifications within this segment for more detailed accounting hierarchies.\n </p>\n\n <mat-form-field subscriptSizing=\"dynamic\" floatLabel=\"always\" appearance=\"outline\">\n <mat-label>Segment</mat-label>\n <mat-select\n (selectionChange)=\"selectSegment($event)\"\n formControlName=\"segment\"\n placeholder=\"Select segment\">\n @for (segment of treeSegments(); track segment.id) {\n <mat-option [disabled]=\"alreadyExists(segment)\" [value]=\"segment.segment\">\n {{ segment.label }}\n </mat-option>\n }\n </mat-select>\n <mat-hint>Select an account segment type from your chart of accounts.</mat-hint>\n </mat-form-field>\n </div>\n\n @if (isCashSegmentConfig()) {\n <div class=\"mscoa-segment-config__group\">\n <div class=\"mscoa-segment-config__toggle\">\n <mat-slide-toggle\n (change)=\"setInheritFromAccrual($event)\"\n [checked]=\"segmentForm.value.inheritValueFromAccrual\">\n Inherit from accrual\n </mat-slide-toggle>\n </div>\n <p class=\"mscoa-segment-config__hint\">\n When enabled, changes to the accrual value reflect here automatically.\n </p>\n </div>\n }\n\n <div class=\"mscoa-segment-config__group\">\n <mat-form-field subscriptSizing=\"dynamic\" floatLabel=\"always\" appearance=\"outline\">\n <mat-label>Label</mat-label>\n <input\n matInput\n formControlName=\"label\"\n [readonly]=\"!segmentForm.value.segmentExtension\"\n placeholder=\"Enter label\" />\n <mat-hint>\n A descriptive name for this segment (e.g. 'Department', 'Project', 'Cost Center').\n </mat-hint>\n </mat-form-field>\n </div>\n\n <div class=\"mscoa-segment-config__group\">\n <div class=\"mscoa-segment-config__toggle\">\n <mat-slide-toggle\n (change)=\"singleSelectChange($event)\"\n [checked]=\"segmentForm.value.singleSelect\">\n Single value selection\n </mat-slide-toggle>\n </div>\n <p class=\"mscoa-segment-config__hint\">\n When enabled, transactions are assigned to one value within this segment; when disabled,\n they can be split across multiple values.\n </p>\n </div>\n\n @if (segmentForm.value.segment?.toLocaleLowerCase() === 'item') {\n <div class=\"mscoa-segment-config__group\">\n <div class=\"mscoa-segment-config__toggle\">\n <mat-slide-toggle\n (change)=\"setVatSelectionActive($event)\"\n [checked]=\"segmentForm.value.vatSelectonActive\">\n Require VAT account selection\n </mat-slide-toggle>\n </div>\n <p class=\"mscoa-segment-config__hint\">\n When active, users must specify a VAT account for taxable items.\n </p>\n </div>\n }\n\n <div class=\"mscoa-segment-config__group\">\n <div class=\"mscoa-segment-config__toggle\">\n <mat-slide-toggle\n (change)=\"readOnlyChanged($event)\"\n [checked]=\"segmentForm.value.readOnly\">\n Read-only segment\n </mat-slide-toggle>\n </div>\n <p class=\"mscoa-segment-config__hint\">\n Prevents users from modifying segment values after initial setup. Use for regulatory or\n policy-controlled segments.\n </p>\n </div>\n\n <div class=\"mscoa-segment-config__group\">\n <mat-form-field subscriptSizing=\"dynamic\" floatLabel=\"always\" appearance=\"outline\">\n <mat-label>Additional accounts</mat-label>\n <mat-select\n (selectionChange)=\"additionalAccountsChanged($event)\"\n formControlName=\"additionalAccounts\"\n multiple\n placeholder=\"Select counter accounts\">\n @for (ext of extensionAccountsForSegments; track ext) {\n <mat-option [value]=\"ext\">{{ ext }}</mat-option>\n }\n </mat-select>\n <mat-hint>\n Add supporting accounts for this segment (e.g. VAT or tax accounts).\n </mat-hint>\n </mat-form-field>\n </div>\n\n <mat-card-actions class=\"mscoa-segment-config__actions\">\n <button mat-button type=\"button\" (click)=\"cancelEdit()\">Cancel</button>\n <button mat-flat-button color=\"primary\" type=\"submit\" [disabled]=\"!segmentForm.valid\">\n Save\n </button>\n </mat-card-actions>\n </form>\n </mat-card-content>\n </mat-card>\n}\n", styles: ["@charset \"UTF-8\";:host{display:flex;flex-direction:column;gap:1.5rem;color:var(--lib-forms-on-surface)}.mscoa-segment-config__notice{display:flex;align-items:center;gap:.5rem;padding:.75rem 1rem;border-radius:var(--lib-forms-radius-md, 10px);background:var(--sem-info-surface);color:var(--lib-forms-on-surface);font-size:.875rem}.mscoa-segment-config__notice--error{background:var(--sem-error-surface)}.mscoa-segment-config__notice-icon{flex:0 0 auto;color:var(--lib-forms-on-surface-variant)}.mscoa-segment-config__notice--error .mscoa-segment-config__notice-icon{color:var(--sem-error)}.mscoa-segment-config__section{display:flex;flex-direction:column;gap:.75rem}.mscoa-segment-config__section-label{margin:0;font-size:.625rem;font-weight:600;letter-spacing:.14em;text-transform:uppercase;color:var(--lib-forms-on-surface-variant)}.mscoa-segment-config__chip-content{display:inline-flex;align-items:center;gap:.375rem}.mscoa-segment-config__chip-label{margin-right:.125rem}.mscoa-segment-config__chip-icon{width:1rem;height:1rem;font-size:1rem;line-height:1;color:var(--lib-forms-on-surface-variant)}.mscoa-segment-config__add{width:100%}.mscoa-segment-config__panel{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:block}.mscoa-segment-config__group{display:flex;flex-direction:column;gap:.5rem;margin-bottom:1.5rem}.mscoa-segment-config__group:last-of-type{margin-bottom:0}.mscoa-segment-config__group mat-form-field{width:100%}.mscoa-segment-config__toggle{display:flex;align-items:center;padding:.5rem 0}.mscoa-segment-config__hint{margin:0;font-size:.75rem;line-height:1.4;color:var(--lib-forms-on-surface-variant)}.mscoa-segment-config__actions{display:flex;justify-content:flex-end;gap:.75rem;margin-top:.5rem}\n"] }]
333
+ }], ctorParameters: () => [], propDecorators: { errors: [{ type: i0.Input, args: [{ isSignal: true, alias: "errors", required: false }] }], dataValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "dataValue", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], isCashSegmentConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "isCashSegmentConfig", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], showAllSegments: [{ type: i0.Input, args: [{ isSignal: true, alias: "showAllSegments", required: false }] }], getMscoaTree: [{ type: i0.Input, args: [{ isSignal: true, alias: "getMscoaTree", required: false }] }], valueChanged: [{ type: i0.Output, args: ["valueChanged"] }] } });
334
+
335
+ export { MscoaSegmentConfigComponent };
336
+ //# sourceMappingURL=ngx-t-forms-mscoa-segment-config.component-C0qsMfsq.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ngx-t-forms-mscoa-segment-config.component-C0qsMfsq.mjs","sources":["../../../projects/ngx-t-forms/src/lib/components/t-dynamic-data-edit/elements/mscoa-segment-config/mscoa-segment-config.component.ts","../../../projects/ngx-t-forms/src/lib/components/t-dynamic-data-edit/elements/mscoa-segment-config/mscoa-segment-config.component.html"],"sourcesContent":["import {\r\n ChangeDetectionStrategy,\r\n Component,\r\n DestroyRef,\r\n ViewEncapsulation,\r\n computed,\r\n effect,\r\n inject,\r\n input,\r\n output,\r\n signal,\r\n} from '@angular/core';\r\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\r\nimport {\r\n FormBuilder,\r\n FormGroup,\r\n ReactiveFormsModule,\r\n Validators,\r\n} from '@angular/forms';\r\nimport { Observable, catchError, of, take, tap } from 'rxjs';\r\n\r\nimport { MatButtonModule } from '@angular/material/button';\r\nimport { MatCardModule } from '@angular/material/card';\r\nimport { MatChipsModule } from '@angular/material/chips';\r\nimport { MatFormFieldModule } from '@angular/material/form-field';\r\nimport { MatIconModule } from '@angular/material/icon';\r\nimport { MatInputModule } from '@angular/material/input';\r\nimport { MatSelectChange, MatSelectModule } from '@angular/material/select';\r\nimport { MatSlideToggleChange, MatSlideToggleModule } from '@angular/material/slide-toggle';\r\n\r\nimport type {\r\n IGetTreeResponse,\r\n IIncludedSegmentConfig,\r\n IScoaInput,\r\n} from 'ngx-t-forms-types';\r\nimport { v4 as uuidv4 } from 'uuid';\r\n\r\nimport { _isEqual } from '../../../../shared/functions/isEqual';\r\nimport type { IConfigElementError } from '../../t-dynamic-data-edit.component';\r\nimport { EmptyStateComponent } from '../_shared/empty-state/empty-state.component';\r\n\r\nlet nextUniqueId = 0;\r\n\r\n/** Discriminated edit-panel state: idle, adding a new segment, or editing an existing one. */\r\ntype EditState =\r\n | { readonly mode: 'idle' }\r\n | { readonly mode: 'add' }\r\n | { readonly mode: 'edit'; readonly index: number };\r\n\r\nconst IDLE: EditState = { mode: 'idle' };\r\n\r\n/**\r\n * Internal editor element for configuring an MSCOA input's included account\r\n * segments. Child of `t-dynamic-data-edit`, which supplies the field label,\r\n * hint, and validation errors - so this component owns only the segment chip\r\n * row and the add/edit panel.\r\n *\r\n * The segment list is seeded from the MSCOA tree (`getMscoaTree`); each segment\r\n * carries flags such as single-select, read-only, VAT-selection and\r\n * inherit-from-accrual. In cash-segment mode (`isCashSegmentConfig`) every\r\n * non-`item` segment defaults to inherit-from-accrual + read-only.\r\n */\r\n@Component({\r\n selector: 'lib-mscoa-segment-config',\r\n templateUrl: './mscoa-segment-config.component.html',\r\n styleUrl: './mscoa-segment-config.component.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n encapsulation: ViewEncapsulation.Emulated,\r\n host: {\r\n 'class': 'lib-mscoa-segment-config',\r\n '[attr.id]': 'hostId',\r\n },\r\n imports: [\r\n ReactiveFormsModule,\r\n MatButtonModule,\r\n MatCardModule,\r\n MatChipsModule,\r\n MatFormFieldModule,\r\n MatIconModule,\r\n MatInputModule,\r\n MatSelectModule,\r\n MatSlideToggleModule,\r\n EmptyStateComponent,\r\n ],\r\n})\r\nexport class MscoaSegmentConfigComponent {\r\n /**\r\n * Validation errors passed down by the parent editor. Retained on the contract\r\n * but not rendered here - `t-dynamic-data-edit` owns error display.\r\n */\r\n readonly errors = input<IConfigElementError[] | undefined>([]);\r\n\r\n /** The full MSCOA input config; supplies the extension-account options. */\r\n readonly dataValue = input<IScoaInput | undefined>(undefined);\r\n\r\n /** Disable user interaction. */\r\n readonly disabled = input<boolean>(false);\r\n\r\n /** Cash-segment mode: non-`item` segments default to inherit + read-only. */\r\n readonly isCashSegmentConfig = input<boolean>(false);\r\n\r\n /** Currently configured segments. */\r\n readonly value = input<IIncludedSegmentConfig[] | undefined>(undefined);\r\n\r\n /** When true, render every tree segment read-only (no add/remove). */\r\n readonly showAllSegments = input<boolean>(false);\r\n\r\n /**\r\n * Stream that resolves the MSCOA account tree. Heterogeneous wrapper binding -\r\n * the parent feeds whatever the editor config holds; narrowing here would force\r\n * wrapper changes.\r\n */\r\n readonly getMscoaTree = input<Observable<IGetTreeResponse | undefined> | undefined>(undefined);\r\n\r\n /** Emits the mutated segment list whenever the user adds, edits, or removes one. */\r\n readonly valueChanged = output<IIncludedSegmentConfig[]>();\r\n\r\n /** Host id attribute - stable, unique per instance. */\r\n readonly hostId = `app-mscoa-segment-config-${nextUniqueId++}`;\r\n\r\n readonly #fb = inject(FormBuilder);\r\n readonly #destroyRef = inject(DestroyRef);\r\n\r\n /** Tree-derived segment templates (drives the segment `mat-select`). */\r\n readonly #treeSegments = signal<readonly IIncludedSegmentConfig[]>([]);\r\n\r\n /** Error raised while fetching the tree (`null` until/unless the fetch fails). */\r\n readonly #fetchError = signal<string | null>(null);\r\n\r\n /** True while the tree stream is in flight. */\r\n protected readonly loading = signal<boolean>(false);\r\n\r\n /** Add/edit panel state. */\r\n readonly #editState = signal<EditState>(IDLE);\r\n\r\n /** Reactive form for the segment currently being added/edited. */\r\n protected segmentForm: FormGroup = this.#createSegmentForm();\r\n\r\n /** Guards single-shot tree load (mirrors the original take(1) one-time fetch). */\r\n #treeRequested = false;\r\n\r\n /** The configured segments, never null. */\r\n protected readonly resolvedValue = computed<readonly IIncludedSegmentConfig[]>(\r\n () => this.value() ?? [],\r\n );\r\n\r\n /** Tree-derived segment templates for the picker. */\r\n protected readonly treeSegments = this.#treeSegments.asReadonly();\r\n\r\n /**\r\n * Loader/tree error message; `null` when none. A fetch error takes priority,\r\n * otherwise a missing loader surfaces the \"No loader provided\" notice.\r\n */\r\n protected readonly treeError = computed<string | null>(() => {\r\n const fetchError = this.#fetchError();\r\n if (fetchError) {\r\n return fetchError;\r\n }\r\n return this.getMscoaTree() ? null : 'No loader provided';\r\n });\r\n\r\n /** Whether the add/edit panel is open. */\r\n protected readonly isEditing = computed<boolean>(() => this.#editState().mode !== 'idle');\r\n\r\n /** Whether the open panel is adding a brand-new segment. */\r\n protected readonly isAddingNew = computed<boolean>(() => this.#editState().mode === 'add');\r\n\r\n /** Whether the \"Add new segment\" toolbar button should show. */\r\n protected readonly canAddNew = computed<boolean>(\r\n () => !this.isEditing() && !this.showAllSegments(),\r\n );\r\n\r\n constructor() {\r\n // One-time tree load. Mirrors the original `take(1)` fetch. The signal\r\n // writes happen off the reactive tick (microtask) so the effect itself\r\n // performs no synchronous signal mutation.\r\n effect(() => {\r\n const tree$ = this.getMscoaTree();\r\n if (!tree$ || this.#treeRequested) {\r\n return;\r\n }\r\n this.#treeRequested = true;\r\n queueMicrotask(() => this.#loadMscoa(tree$));\r\n });\r\n\r\n // Reflect the full tree as read-only segments when `showAllSegments` is on.\r\n effect(() => {\r\n if (this.showAllSegments()) {\r\n this.#syncAllSegments();\r\n }\r\n });\r\n }\r\n\r\n /** Fetch the tree once, build the segment templates, surface any error. */\r\n #loadMscoa(tree$: Observable<IGetTreeResponse | undefined>): void {\r\n this.#fetchError.set(null);\r\n this.loading.set(true);\r\n tree$\r\n .pipe(\r\n take(1),\r\n tap((response) => {\r\n this.#treeSegments.set(this.#buildTreeSegments(response));\r\n this.loading.set(false);\r\n }),\r\n catchError(() => {\r\n this.#fetchError.set('Failed to fetch mscoa tree');\r\n this.loading.set(false);\r\n return of(undefined);\r\n }),\r\n takeUntilDestroyed(this.#destroyRef),\r\n )\r\n .subscribe();\r\n }\r\n\r\n /** Map the tree account keys into seedable segment templates. */\r\n #buildTreeSegments(response: IGetTreeResponse | undefined): readonly IIncludedSegmentConfig[] {\r\n const isCash = this.isCashSegmentConfig();\r\n const current = this.resolvedValue();\r\n return (response?.accountTreeKeys ?? []).map((treeKey) => {\r\n const isItem = treeKey.toLocaleLowerCase() === 'item';\r\n return {\r\n id: uuidv4(),\r\n segment: treeKey,\r\n singleSelect: true,\r\n additionalAccounts: [],\r\n inheritValueFromAccrual: isCash ? !isItem : undefined,\r\n vatSelectonActive: isCash ? false : isItem,\r\n segmentExtension: false,\r\n label: this.#toTitleCase(treeKey),\r\n readOnly:\r\n current.find((v) => v.segment === treeKey)?.readOnly ||\r\n (isCash && !isItem) ||\r\n false,\r\n };\r\n });\r\n }\r\n\r\n /** Build the per-segment reactive form. */\r\n #createSegmentForm(\r\n segment: IIncludedSegmentConfig = {\r\n segment: '',\r\n label: '',\r\n id: uuidv4(),\r\n singleSelect: true,\r\n segmentExtension: false,\r\n additionalAccounts: [],\r\n readOnly: false,\r\n },\r\n ): FormGroup {\r\n const isItem = segment.segment?.toLocaleLowerCase() === 'item';\r\n return this.#fb.group({\r\n id: [segment.id],\r\n segment: [segment.segment, Validators.required],\r\n segmentExtension: [segment.segmentExtension, Validators.required],\r\n readOnly: [segment.readOnly, Validators.required],\r\n inheritValueFromAccrual: this.isCashSegmentConfig()\r\n ? [segment.inheritValueFromAccrual, Validators.required]\r\n : [segment.inheritValueFromAccrual],\r\n vatSelectonActive: isItem\r\n ? [Boolean(segment.vatSelectonActive), Validators.required]\r\n : [Boolean(segment.vatSelectonActive)],\r\n additionalAccounts: [segment.additionalAccounts ?? []],\r\n label: [segment.label, Validators.required],\r\n singleSelect: [segment.singleSelect, Validators.required],\r\n });\r\n }\r\n\r\n protected startAddNew(): void {\r\n this.segmentForm = this.#createSegmentForm();\r\n this.#editState.set({ mode: 'add' });\r\n }\r\n\r\n protected startEdit(index: number): void {\r\n const segment = this.resolvedValue().at(index);\r\n if (!segment) {\r\n return;\r\n }\r\n this.segmentForm = this.#createSegmentForm(segment);\r\n this.#editState.set({ mode: 'edit', index });\r\n }\r\n\r\n protected cancelEdit(): void {\r\n this.segmentForm.reset();\r\n this.#editState.set(IDLE);\r\n }\r\n\r\n protected saveSegment(): void {\r\n if (!this.segmentForm.valid) {\r\n return;\r\n }\r\n const raw = this.segmentForm.getRawValue();\r\n const label = this.#toTitleCase(String(raw.label ?? ''));\r\n const newSegment: IIncludedSegmentConfig = {\r\n id: typeof raw.id === 'string' && raw.id ? raw.id : uuidv4(),\r\n segment: raw.segment,\r\n // Multi-level segments derive their key from the (upper-cased) label.\r\n customSegment: raw.segmentExtension ? label.toLocaleUpperCase() : undefined,\r\n segmentExtension: Boolean(raw.segmentExtension),\r\n inheritValueFromAccrual: Boolean(raw.inheritValueFromAccrual),\r\n vatSelectonActive: Boolean(raw.vatSelectonActive),\r\n additionalAccounts: Array.isArray(raw.additionalAccounts) ? raw.additionalAccounts : [],\r\n label,\r\n singleSelect: Boolean(raw.singleSelect),\r\n readOnly: Boolean(raw.readOnly),\r\n };\r\n\r\n const state = this.#editState();\r\n const updated = [...this.resolvedValue()];\r\n if (state.mode === 'add') {\r\n updated.push(newSegment);\r\n } else if (state.mode === 'edit') {\r\n updated[state.index] = newSegment;\r\n } else {\r\n return;\r\n }\r\n\r\n this.valueChanged.emit(updated);\r\n this.cancelEdit();\r\n }\r\n\r\n protected readOnlyChanged(event: MatSlideToggleChange): void {\r\n this.segmentForm.patchValue({ readOnly: event.checked });\r\n }\r\n\r\n protected singleSelectChange(event: MatSlideToggleChange): void {\r\n this.segmentForm.patchValue({ singleSelect: event.checked });\r\n }\r\n\r\n protected setVatSelectionActive(event: MatSlideToggleChange): void {\r\n this.segmentForm.patchValue({ vatSelectonActive: event.checked });\r\n }\r\n\r\n /** Inherit-from-accrual implies read-only (quirk: toggling on forces read-only). */\r\n protected setInheritFromAccrual(event: MatSlideToggleChange): void {\r\n this.segmentForm.patchValue({ inheritValueFromAccrual: event.checked });\r\n if (event.checked) {\r\n this.segmentForm.patchValue({ readOnly: true });\r\n }\r\n }\r\n\r\n protected multiLevelSelectChange(event: MatSlideToggleChange): void {\r\n this.segmentForm.patchValue({ segmentExtension: event.checked });\r\n }\r\n\r\n /** Pick a segment; auto-fill the label from it unless this is a multi-level extension. */\r\n protected selectSegment(event: MatSelectChange): void {\r\n this.segmentForm.patchValue({ segment: event.value });\r\n if (!this.segmentForm.value.segmentExtension) {\r\n this.segmentForm.patchValue({ label: this.#toTitleCase(String(event.value ?? '')) });\r\n }\r\n }\r\n\r\n protected additionalAccountsChanged(event: MatSelectChange): void {\r\n this.segmentForm.patchValue(\r\n { additionalAccounts: [...event.value] },\r\n { emitEvent: true },\r\n );\r\n }\r\n\r\n protected removeSegment(index: number): void {\r\n const updated = this.resolvedValue().filter((_, i) => i !== index);\r\n this.valueChanged.emit(updated);\r\n }\r\n\r\n /**\r\n * A tree template is \"already used\" (and so disabled in the picker) when a\r\n * segment with the same key is already configured - except for multi-level\r\n * extensions, which may reuse a key.\r\n */\r\n protected alreadyExists(segment: IIncludedSegmentConfig): boolean {\r\n if (this.segmentForm.value.segmentExtension) {\r\n return false;\r\n }\r\n return this.resolvedValue().some((v) => v.segment === segment.segment);\r\n }\r\n\r\n /** Extension-account options drawn from the MSCOA config. */\r\n protected get extensionAccountsForSegments(): string[] {\r\n return this.dataValue()?.mscoaConfig?.extensionAccountsForSegments ?? [];\r\n }\r\n\r\n /**\r\n * When `showAllSegments` is on, reconcile the configured value against the full\r\n * tree. Preserves the deliberate double-emit sync: emit a reset sentinel first,\r\n * then the merged list on the next microtask so the parent re-renders cleanly.\r\n */\r\n #syncAllSegments(): void {\r\n const templates = this.#treeSegments();\r\n if (!this.#treeRequested || templates.length === 0) {\r\n return;\r\n }\r\n const current = this.resolvedValue();\r\n const merged = templates.map((segment) => ({\r\n ...segment,\r\n ...(current.find((v) => v.segment === segment.segment) ?? {}),\r\n }));\r\n\r\n if (!_isEqual(merged, current)) {\r\n // Reset sentinel, then the real value, to force downstream re-binding.\r\n this.valueChanged.emit([{} as IIncludedSegmentConfig]);\r\n queueMicrotask(() => this.valueChanged.emit(merged));\r\n }\r\n }\r\n\r\n #toTitleCase(str: string): string {\r\n return str.replace(\r\n /\\w\\S*/g,\r\n (txt) => txt.charAt(0).toUpperCase() + txt.slice(1).toLowerCase(),\r\n );\r\n }\r\n}\r\n","@if (loading()) {\n <div class=\"mscoa-segment-config__notice\">\n <mat-icon class=\"mscoa-segment-config__notice-icon\">hourglass_top</mat-icon>\n <span>Loading account segments…</span>\n </div>\n}\n\n@if (treeError(); as error) {\n <div class=\"mscoa-segment-config__notice mscoa-segment-config__notice--error\">\n <mat-icon class=\"mscoa-segment-config__notice-icon\">error_outline</mat-icon>\n <span>{{ error }}</span>\n </div>\n}\n\n@if (resolvedValue().length > 0) {\n <div class=\"mscoa-segment-config__section\">\n <p class=\"mscoa-segment-config__section-label\">Configured segments</p>\n <mat-chip-listbox [disabled]=\"disabled()\" aria-label=\"Configured account segments\">\n @for (segment of resolvedValue(); track segment.id; let i = $index) {\n <mat-chip-option\n (removed)=\"removeSegment(i)\"\n (click)=\"startEdit(i)\"\n [value]=\"segment.segment\"\n [selected]=\"isEditing() && !isAddingNew()\">\n <span class=\"mscoa-segment-config__chip-content\">\n <span class=\"mscoa-segment-config__chip-label\">{{ segment.label }}</span>\n <mat-icon class=\"mscoa-segment-config__chip-icon\">\n {{ segment.singleSelect ? 'done' : 'done_all' }}\n </mat-icon>\n <mat-icon class=\"mscoa-segment-config__chip-icon\">\n {{ segment.readOnly ? 'edit_off' : 'edit' }}\n </mat-icon>\n </span>\n\n @if (showAllSegments() === false) {\n <button matChipRemove aria-label=\"Remove segment\" [disabled]=\"disabled()\">\n <mat-icon>cancel</mat-icon>\n </button>\n }\n </mat-chip-option>\n }\n </mat-chip-listbox>\n </div>\n} @else if (!loading()) {\n <lib-empty-state\n icon=\"account_tree\"\n message=\"No segments configured yet. Add one to begin shaping this MSCOA input.\">\n @if (canAddNew()) {\n <button mat-stroked-button [disabled]=\"disabled()\" (click)=\"startAddNew()\">\n <mat-icon>add</mat-icon>\n Add segment\n </button>\n }\n </lib-empty-state>\n}\n\n@if (canAddNew() && resolvedValue().length > 0) {\n <button\n class=\"mscoa-segment-config__add\"\n mat-stroked-button\n [disabled]=\"disabled()\"\n (click)=\"startAddNew()\">\n <mat-icon>add</mat-icon>\n Add new segment\n </button>\n}\n\n@if (isEditing()) {\n <mat-card class=\"mscoa-segment-config__panel\" appearance=\"outlined\">\n <mat-card-header>\n <mat-card-subtitle>\n {{ isAddingNew() ? 'Add a new' : 'Update' }} segment\n </mat-card-subtitle>\n </mat-card-header>\n\n <mat-card-content>\n <form [formGroup]=\"segmentForm\" (ngSubmit)=\"saveSegment()\">\n <div class=\"mscoa-segment-config__group\">\n <div class=\"mscoa-segment-config__toggle\">\n <mat-slide-toggle\n (change)=\"multiLevelSelectChange($event)\"\n [checked]=\"segmentForm.value.segmentExtension\">\n Enable multi-level segmentation\n </mat-slide-toggle>\n </div>\n <p class=\"mscoa-segment-config__hint\">\n Allows sub-classifications within this segment for more detailed accounting hierarchies.\n </p>\n\n <mat-form-field subscriptSizing=\"dynamic\" floatLabel=\"always\" appearance=\"outline\">\n <mat-label>Segment</mat-label>\n <mat-select\n (selectionChange)=\"selectSegment($event)\"\n formControlName=\"segment\"\n placeholder=\"Select segment\">\n @for (segment of treeSegments(); track segment.id) {\n <mat-option [disabled]=\"alreadyExists(segment)\" [value]=\"segment.segment\">\n {{ segment.label }}\n </mat-option>\n }\n </mat-select>\n <mat-hint>Select an account segment type from your chart of accounts.</mat-hint>\n </mat-form-field>\n </div>\n\n @if (isCashSegmentConfig()) {\n <div class=\"mscoa-segment-config__group\">\n <div class=\"mscoa-segment-config__toggle\">\n <mat-slide-toggle\n (change)=\"setInheritFromAccrual($event)\"\n [checked]=\"segmentForm.value.inheritValueFromAccrual\">\n Inherit from accrual\n </mat-slide-toggle>\n </div>\n <p class=\"mscoa-segment-config__hint\">\n When enabled, changes to the accrual value reflect here automatically.\n </p>\n </div>\n }\n\n <div class=\"mscoa-segment-config__group\">\n <mat-form-field subscriptSizing=\"dynamic\" floatLabel=\"always\" appearance=\"outline\">\n <mat-label>Label</mat-label>\n <input\n matInput\n formControlName=\"label\"\n [readonly]=\"!segmentForm.value.segmentExtension\"\n placeholder=\"Enter label\" />\n <mat-hint>\n A descriptive name for this segment (e.g. 'Department', 'Project', 'Cost Center').\n </mat-hint>\n </mat-form-field>\n </div>\n\n <div class=\"mscoa-segment-config__group\">\n <div class=\"mscoa-segment-config__toggle\">\n <mat-slide-toggle\n (change)=\"singleSelectChange($event)\"\n [checked]=\"segmentForm.value.singleSelect\">\n Single value selection\n </mat-slide-toggle>\n </div>\n <p class=\"mscoa-segment-config__hint\">\n When enabled, transactions are assigned to one value within this segment; when disabled,\n they can be split across multiple values.\n </p>\n </div>\n\n @if (segmentForm.value.segment?.toLocaleLowerCase() === 'item') {\n <div class=\"mscoa-segment-config__group\">\n <div class=\"mscoa-segment-config__toggle\">\n <mat-slide-toggle\n (change)=\"setVatSelectionActive($event)\"\n [checked]=\"segmentForm.value.vatSelectonActive\">\n Require VAT account selection\n </mat-slide-toggle>\n </div>\n <p class=\"mscoa-segment-config__hint\">\n When active, users must specify a VAT account for taxable items.\n </p>\n </div>\n }\n\n <div class=\"mscoa-segment-config__group\">\n <div class=\"mscoa-segment-config__toggle\">\n <mat-slide-toggle\n (change)=\"readOnlyChanged($event)\"\n [checked]=\"segmentForm.value.readOnly\">\n Read-only segment\n </mat-slide-toggle>\n </div>\n <p class=\"mscoa-segment-config__hint\">\n Prevents users from modifying segment values after initial setup. Use for regulatory or\n policy-controlled segments.\n </p>\n </div>\n\n <div class=\"mscoa-segment-config__group\">\n <mat-form-field subscriptSizing=\"dynamic\" floatLabel=\"always\" appearance=\"outline\">\n <mat-label>Additional accounts</mat-label>\n <mat-select\n (selectionChange)=\"additionalAccountsChanged($event)\"\n formControlName=\"additionalAccounts\"\n multiple\n placeholder=\"Select counter accounts\">\n @for (ext of extensionAccountsForSegments; track ext) {\n <mat-option [value]=\"ext\">{{ ext }}</mat-option>\n }\n </mat-select>\n <mat-hint>\n Add supporting accounts for this segment (e.g. VAT or tax accounts).\n </mat-hint>\n </mat-form-field>\n </div>\n\n <mat-card-actions class=\"mscoa-segment-config__actions\">\n <button mat-button type=\"button\" (click)=\"cancelEdit()\">Cancel</button>\n <button mat-flat-button color=\"primary\" type=\"submit\" [disabled]=\"!segmentForm.valid\">\n Save\n </button>\n </mat-card-actions>\n </form>\n </mat-card-content>\n </mat-card>\n}\n"],"names":["uuidv4","i2","i5","i6","i9"],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ import * as i0 from '@angular/core';
2
+ import { input, signal, inject, DestroyRef, effect, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
3
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
4
+ import * as i1 from '@angular/material/button';
5
+ import { MatButtonModule } from '@angular/material/button';
6
+ import * as i3 from '@angular/material/icon';
7
+ import { MatIconModule } from '@angular/material/icon';
8
+ import { Subject, timer } from 'rxjs';
9
+ import { takeUntil } from 'rxjs/operators';
10
+
11
+ /**
12
+ * Displays a transient hint message inside the MSCOA chart UI.
13
+ * Auto-hides after the configured duration; can be dismissed manually.
14
+ */
15
+ class MscoaTemporaryHintComponent {
16
+ #destroyRef;
17
+ #hideTimer$;
18
+ #previousMessage;
19
+ constructor() {
20
+ /** Message text to display. */
21
+ this.message = input('', ...(ngDevMode ? [{ debugName: "message" }] : /* istanbul ignore next */ []));
22
+ /** Auto-hide duration in milliseconds. */
23
+ this.duration = input(5000, ...(ngDevMode ? [{ debugName: "duration" }] : /* istanbul ignore next */ []));
24
+ /** Whether to show the dismiss button. */
25
+ this.showDismiss = input(true, ...(ngDevMode ? [{ debugName: "showDismiss" }] : /* istanbul ignore next */ []));
26
+ /** Visual variant. */
27
+ this.type = input('info', ...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
28
+ this.visible = signal(false, ...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
29
+ this.#destroyRef = inject(DestroyRef);
30
+ this.#hideTimer$ = new Subject();
31
+ this.#previousMessage = '';
32
+ // React to message changes (replaces ngOnInit + ngOnChanges).
33
+ effect(() => {
34
+ const current = this.message();
35
+ const previous = this.#previousMessage;
36
+ this.#previousMessage = current;
37
+ if (current && current !== previous) {
38
+ this.show();
39
+ }
40
+ else if (!current && previous) {
41
+ this.hide();
42
+ }
43
+ });
44
+ this.#destroyRef.onDestroy(() => {
45
+ this.#hideTimer$.next();
46
+ this.#hideTimer$.complete();
47
+ });
48
+ }
49
+ show() {
50
+ // Cancel any existing timer.
51
+ this.#hideTimer$.next();
52
+ this.visible.set(true);
53
+ // Auto-hide after duration.
54
+ timer(this.duration())
55
+ .pipe(takeUntil(this.#hideTimer$), takeUntilDestroyed(this.#destroyRef))
56
+ .subscribe(() => this.hide());
57
+ }
58
+ hide() {
59
+ this.#hideTimer$.next();
60
+ this.visible.set(false);
61
+ }
62
+ dismiss() {
63
+ this.hide();
64
+ }
65
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: MscoaTemporaryHintComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
66
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: MscoaTemporaryHintComponent, isStandalone: true, selector: "lib-mscoa-temporary-hint", inputs: { message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: false, transformFunction: null }, duration: { classPropertyName: "duration", publicName: "duration", isSignal: true, isRequired: false, transformFunction: null }, showDismiss: { classPropertyName: "showDismiss", publicName: "showDismiss", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (visible() && message()) {\r\n <div\r\n class=\"temporary-hint\"\r\n [class.temporary-hint--info]=\"type() === 'info'\"\r\n [class.temporary-hint--guidance]=\"type() === 'guidance'\"\r\n role=\"status\"\r\n aria-live=\"polite\"\r\n [attr.aria-label]=\"'Hint: ' + message()\">\r\n\r\n <mat-icon class=\"temporary-hint__icon\" aria-hidden=\"true\">info</mat-icon>\r\n\r\n <div class=\"temporary-hint__content\">\r\n <p class=\"temporary-hint__message\">{{ message() }}</p>\r\n </div>\r\n\r\n @if (showDismiss()) {\r\n <button\r\n class=\"temporary-hint__dismiss\"\r\n (click)=\"dismiss()\"\r\n [attr.aria-label]=\"'Dismiss hint'\"\r\n mat-icon-button\r\n type=\"button\">\r\n <mat-icon aria-hidden=\"true\">close</mat-icon>\r\n </button>\r\n }\r\n </div>\r\n}\r\n", styles: [".temporary-hint{display:flex;align-items:flex-start;gap:var(--mscoa-chart-spacing-sm, 8px);padding:var(--mscoa-chart-spacing-sm, 8px) var(--mscoa-chart-spacing-md, 16px);margin-top:var(--mscoa-chart-spacing-sm, 8px);border-radius:var(--mscoa-chart-border-radius, 4px);font-size:13px;line-height:1.5;animation:slideInFade var(--mscoa-chart-transition, .2s ease);transition:opacity var(--lib-forms-duration-hover) var(--lib-forms-easing)}.temporary-hint--info{background-color:var(--sem-info-surface);color:var(--sem-info);border-left:3px solid var(--sem-info)}.temporary-hint--guidance{background-color:var(--sem-warning-surface);color:var(--lib-forms-on-surface);border-left:3px solid var(--sem-warning)}.temporary-hint__icon{flex-shrink:0;width:18px;height:18px;font-size:18px;margin-top:2px;color:var(--sem-info)}.temporary-hint--guidance .temporary-hint__icon{color:var(--sem-warning)}.temporary-hint__content{flex:1;min-width:0}.temporary-hint__message{margin:0;font-weight:400}.temporary-hint__dismiss{flex-shrink:0;width:24px;height:24px;opacity:.7;transition:opacity var(--lib-forms-duration-hover) var(--lib-forms-easing)}.temporary-hint__dismiss:hover{opacity:1}.temporary-hint__dismiss mat-icon{font-size:18px;width:18px;height:18px}@keyframes slideInFade{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}.temporary-hint.ng-leave{animation:slideOutFade var(--mscoa-chart-transition, .2s ease)}@keyframes slideOutFade{0%{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(-4px)}}\n"], dependencies: [{ kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
67
+ }
68
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: MscoaTemporaryHintComponent, decorators: [{
69
+ type: Component,
70
+ args: [{ selector: 'lib-mscoa-temporary-hint', imports: [MatButtonModule, MatIconModule], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.Emulated, template: "@if (visible() && message()) {\r\n <div\r\n class=\"temporary-hint\"\r\n [class.temporary-hint--info]=\"type() === 'info'\"\r\n [class.temporary-hint--guidance]=\"type() === 'guidance'\"\r\n role=\"status\"\r\n aria-live=\"polite\"\r\n [attr.aria-label]=\"'Hint: ' + message()\">\r\n\r\n <mat-icon class=\"temporary-hint__icon\" aria-hidden=\"true\">info</mat-icon>\r\n\r\n <div class=\"temporary-hint__content\">\r\n <p class=\"temporary-hint__message\">{{ message() }}</p>\r\n </div>\r\n\r\n @if (showDismiss()) {\r\n <button\r\n class=\"temporary-hint__dismiss\"\r\n (click)=\"dismiss()\"\r\n [attr.aria-label]=\"'Dismiss hint'\"\r\n mat-icon-button\r\n type=\"button\">\r\n <mat-icon aria-hidden=\"true\">close</mat-icon>\r\n </button>\r\n }\r\n </div>\r\n}\r\n", styles: [".temporary-hint{display:flex;align-items:flex-start;gap:var(--mscoa-chart-spacing-sm, 8px);padding:var(--mscoa-chart-spacing-sm, 8px) var(--mscoa-chart-spacing-md, 16px);margin-top:var(--mscoa-chart-spacing-sm, 8px);border-radius:var(--mscoa-chart-border-radius, 4px);font-size:13px;line-height:1.5;animation:slideInFade var(--mscoa-chart-transition, .2s ease);transition:opacity var(--lib-forms-duration-hover) var(--lib-forms-easing)}.temporary-hint--info{background-color:var(--sem-info-surface);color:var(--sem-info);border-left:3px solid var(--sem-info)}.temporary-hint--guidance{background-color:var(--sem-warning-surface);color:var(--lib-forms-on-surface);border-left:3px solid var(--sem-warning)}.temporary-hint__icon{flex-shrink:0;width:18px;height:18px;font-size:18px;margin-top:2px;color:var(--sem-info)}.temporary-hint--guidance .temporary-hint__icon{color:var(--sem-warning)}.temporary-hint__content{flex:1;min-width:0}.temporary-hint__message{margin:0;font-weight:400}.temporary-hint__dismiss{flex-shrink:0;width:24px;height:24px;opacity:.7;transition:opacity var(--lib-forms-duration-hover) var(--lib-forms-easing)}.temporary-hint__dismiss:hover{opacity:1}.temporary-hint__dismiss mat-icon{font-size:18px;width:18px;height:18px}@keyframes slideInFade{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}.temporary-hint.ng-leave{animation:slideOutFade var(--mscoa-chart-transition, .2s ease)}@keyframes slideOutFade{0%{opacity:1;transform:translateY(0)}to{opacity:0;transform:translateY(-4px)}}\n"] }]
71
+ }], ctorParameters: () => [], propDecorators: { message: [{ type: i0.Input, args: [{ isSignal: true, alias: "message", required: false }] }], duration: [{ type: i0.Input, args: [{ isSignal: true, alias: "duration", required: false }] }], showDismiss: [{ type: i0.Input, args: [{ isSignal: true, alias: "showDismiss", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }] } });
72
+
73
+ export { MscoaTemporaryHintComponent };
74
+ //# sourceMappingURL=ngx-t-forms-mscoa-temporary-hint.component-B1Z-IXSL.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ngx-t-forms-mscoa-temporary-hint.component-B1Z-IXSL.mjs","sources":["../../../projects/ngx-t-forms/src/lib/components/t-form-input/elements/mscoa-form-input/elements/mscoa-chart/components/mscoa-temporary-hint/mscoa-temporary-hint.component.ts","../../../projects/ngx-t-forms/src/lib/components/t-form-input/elements/mscoa-form-input/elements/mscoa-chart/components/mscoa-temporary-hint/mscoa-temporary-hint.component.html"],"sourcesContent":["import {\r\n ChangeDetectionStrategy,\r\n Component,\r\n DestroyRef,\r\n ViewEncapsulation,\r\n effect,\r\n inject,\r\n input,\r\n signal,\r\n} from '@angular/core';\r\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\r\nimport { MatButtonModule } from '@angular/material/button';\r\nimport { MatIconModule } from '@angular/material/icon';\r\nimport { Subject, timer } from 'rxjs';\r\nimport { takeUntil } from 'rxjs/operators';\r\n\r\n/**\r\n * Displays a transient hint message inside the MSCOA chart UI.\r\n * Auto-hides after the configured duration; can be dismissed manually.\r\n */\r\n@Component({\r\n selector: 'lib-mscoa-temporary-hint',\r\n imports: [MatButtonModule, MatIconModule],\r\n templateUrl: './mscoa-temporary-hint.component.html',\r\n styleUrls: ['./mscoa-temporary-hint.component.scss'],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n encapsulation: ViewEncapsulation.Emulated,\r\n})\r\nexport class MscoaTemporaryHintComponent {\r\n /** Message text to display. */\r\n readonly message = input<string>('');\r\n /** Auto-hide duration in milliseconds. */\r\n readonly duration = input<number>(5000);\r\n /** Whether to show the dismiss button. */\r\n readonly showDismiss = input<boolean>(true);\r\n /** Visual variant. */\r\n readonly type = input<'info' | 'guidance'>('info');\r\n\r\n protected readonly visible = signal<boolean>(false);\r\n\r\n readonly #destroyRef = inject(DestroyRef);\r\n readonly #hideTimer$ = new Subject<void>();\r\n #previousMessage = '';\r\n\r\n constructor() {\r\n // React to message changes (replaces ngOnInit + ngOnChanges).\r\n effect(() => {\r\n const current = this.message();\r\n const previous = this.#previousMessage;\r\n this.#previousMessage = current;\r\n\r\n if (current && current !== previous) {\r\n this.show();\r\n } else if (!current && previous) {\r\n this.hide();\r\n }\r\n });\r\n\r\n this.#destroyRef.onDestroy(() => {\r\n this.#hideTimer$.next();\r\n this.#hideTimer$.complete();\r\n });\r\n }\r\n\r\n show(): void {\r\n // Cancel any existing timer.\r\n this.#hideTimer$.next();\r\n\r\n this.visible.set(true);\r\n\r\n // Auto-hide after duration.\r\n timer(this.duration())\r\n .pipe(takeUntil(this.#hideTimer$), takeUntilDestroyed(this.#destroyRef))\r\n .subscribe(() => this.hide());\r\n }\r\n\r\n hide(): void {\r\n this.#hideTimer$.next();\r\n this.visible.set(false);\r\n }\r\n\r\n dismiss(): void {\r\n this.hide();\r\n }\r\n}\r\n","@if (visible() && message()) {\r\n <div\r\n class=\"temporary-hint\"\r\n [class.temporary-hint--info]=\"type() === 'info'\"\r\n [class.temporary-hint--guidance]=\"type() === 'guidance'\"\r\n role=\"status\"\r\n aria-live=\"polite\"\r\n [attr.aria-label]=\"'Hint: ' + message()\">\r\n\r\n <mat-icon class=\"temporary-hint__icon\" aria-hidden=\"true\">info</mat-icon>\r\n\r\n <div class=\"temporary-hint__content\">\r\n <p class=\"temporary-hint__message\">{{ message() }}</p>\r\n </div>\r\n\r\n @if (showDismiss()) {\r\n <button\r\n class=\"temporary-hint__dismiss\"\r\n (click)=\"dismiss()\"\r\n [attr.aria-label]=\"'Dismiss hint'\"\r\n mat-icon-button\r\n type=\"button\">\r\n <mat-icon aria-hidden=\"true\">close</mat-icon>\r\n </button>\r\n }\r\n </div>\r\n}\r\n"],"names":["i2"],"mappings":"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"}