ngx-t-forms 2.0.30 → 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-SM5XM9uy.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 +1747 -746
  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,704 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, Injectable, ElementRef, input, viewChild, ChangeDetectorRef, DestroyRef, effect, ChangeDetectionStrategy, Component, output, computed } from '@angular/core';
3
+ import * as i1 from '@angular/forms';
4
+ import { NgControl, FormControl, ReactiveFormsModule } from '@angular/forms';
5
+ import * as i2 from '@angular/material/form-field';
6
+ import { MatFormFieldModule, MatFormFieldControl } from '@angular/material/form-field';
7
+ import * as i3$1 from '@angular/material/icon';
8
+ import { MatIconModule } from '@angular/material/icon';
9
+ import * as i1$1 from '@angular/material/button';
10
+ import { MatButtonModule } from '@angular/material/button';
11
+ import * as i5 from '@angular/material/tooltip';
12
+ import { MatTooltipModule } from '@angular/material/tooltip';
13
+ import { N as NGX_T_FORMS_CONFIG_TOKEN, B as BaseCustomInput, _ as _isEqual, w as returnMappedPathValue, x as FormatDataPipe, m as getInputErrorMessage, n as TFormInputStatusComponent } from './ngx-t-forms-ngx-t-forms-u_kigDid.mjs';
14
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
15
+ import { of, throwError, debounceTime, map as map$1, distinctUntilChanged, tap, take as take$1, catchError as catchError$1, finalize } from 'rxjs';
16
+ import { take, map, catchError } from 'rxjs/operators';
17
+ import { DataSources, DocumentLitsLabelConfigInterfaceValueType } from 'ngx-t-forms-types';
18
+ import * as i11 from '@angular/material/paginator';
19
+ import { MatPaginator, MatPaginatorModule } from '@angular/material/paginator';
20
+ import * as i10 from '@angular/material/sort';
21
+ import { MatSort, MatSortModule } from '@angular/material/sort';
22
+ import * as i5$1 from '@angular/material/table';
23
+ import { MatTableDataSource, MatTableModule } from '@angular/material/table';
24
+ import * as i3 from '@angular/material/card';
25
+ import { MatCardModule } from '@angular/material/card';
26
+ import * as i3$2 from '@angular/material/progress-spinner';
27
+ import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
28
+ import * as i2$1 from '@angular/material/input';
29
+ import { MatInputModule } from '@angular/material/input';
30
+ import { MatDividerModule } from '@angular/material/divider';
31
+ import * as i3$3 from '@angular/material/checkbox';
32
+ import { MatCheckboxModule } from '@angular/material/checkbox';
33
+ import * as i13 from '@angular/material/radio';
34
+ import { MatRadioModule } from '@angular/material/radio';
35
+
36
+ /** Default sort when none provided: updatedAt descending. */
37
+ const DEFAULT_SORT = { updatedAt: -1 };
38
+ /**
39
+ * Abstracts document fetching from different data sources (API, MongoDB, default).
40
+ * For default source with getWorkflowDocuments, supports server-side pagination, sort, and search
41
+ * (aligned with getTransactionsWithSchema / getWorkflowDocuments).
42
+ */
43
+ class DocumentLoaderService {
44
+ constructor() {
45
+ this.formsConfig = inject(NGX_T_FORMS_CONFIG_TOKEN, { optional: true });
46
+ }
47
+ loadDocuments(params) {
48
+ const { sourceType, documentsSource, workflowId } = params;
49
+ if (sourceType === DataSources.Api && documentsSource) {
50
+ return this.loadFromApi(params);
51
+ }
52
+ if (sourceType === DataSources.MongoDb && documentsSource) {
53
+ return this.loadFromMongoDb(params);
54
+ }
55
+ if (sourceType === 'default') {
56
+ return this.loadFromDefault(workflowId, params);
57
+ }
58
+ return of({ documents: [] });
59
+ }
60
+ /**
61
+ * Normalizes API/MongoDB/default responses to LoadDocumentsResult.
62
+ * Extracts documents from formValues, documents, results, or raw array.
63
+ * Validates footerConfig. Returns empty documents + error on malformed response.
64
+ */
65
+ normalizeToLoadDocumentsResult(response) {
66
+ if (response == null) {
67
+ return { documents: [] };
68
+ }
69
+ const res = response;
70
+ const rawDocs = res['formValues'] ?? res['documents'] ?? res['results'] ?? (Array.isArray(response) ? response : undefined);
71
+ if (!Array.isArray(rawDocs)) {
72
+ return {
73
+ documents: [],
74
+ error: 'Invalid response format: expected formValues, documents, or results array',
75
+ };
76
+ }
77
+ const documents = this.flattenListDocuments(rawDocs);
78
+ const footerConfig = this.validateFooterConfig(res['footerConfig']);
79
+ return { documents, footerConfig };
80
+ }
81
+ validateFooterConfig(fc) {
82
+ if (!fc || typeof fc !== 'object')
83
+ return undefined;
84
+ const o = fc;
85
+ const totalPages = o['totalPages'];
86
+ const totalItems = o['totalItems'];
87
+ const itemsPerPage = o['itemsPerPage'];
88
+ if (typeof totalPages !== 'number' || typeof totalItems !== 'number' || typeof itemsPerPage !== 'number') {
89
+ return undefined;
90
+ }
91
+ return {
92
+ totalPages,
93
+ totalItems,
94
+ itemsPerPage,
95
+ currentPage: typeof o['currentPage'] === 'number' ? o['currentPage'] : undefined,
96
+ sortBy: (o['sortBy'] && typeof o['sortBy'] === 'object')
97
+ ? o['sortBy']
98
+ : undefined,
99
+ };
100
+ }
101
+ loadFromApi(params) {
102
+ const { documentsSource, workflowId, parentFormValue, formBuilder } = params;
103
+ const config = documentsSource;
104
+ const missingInputs = [];
105
+ const postData = (config.backEndConfig?.minimumInputRequired ?? []).reduce((acc, curr) => {
106
+ if (curr.type === 'default') {
107
+ acc[curr.name] = curr.defaultValue;
108
+ return acc;
109
+ }
110
+ if (curr.type === 'mapto' && parentFormValue[curr.name] !== undefined) {
111
+ acc[curr.name] = parentFormValue[curr.name];
112
+ return acc;
113
+ }
114
+ missingInputs.push(curr.name);
115
+ return acc;
116
+ }, {});
117
+ postData['workflowId'] = workflowId;
118
+ postData['page'] = params.page ?? 1;
119
+ postData['itemsPerPage'] = params.itemsPerPage ?? 10;
120
+ postData['sort'] = (params.sort && Object.keys(params.sort).length > 0) ? params.sort : DEFAULT_SORT;
121
+ postData['searchKey'] = params.searchKey;
122
+ if (params.filter && Object.keys(params.filter).length > 0) {
123
+ postData['filter'] = params.filter;
124
+ }
125
+ if (missingInputs.length > 0) {
126
+ return throwError(() => new Error(`Missing inputs: ${missingInputs.join(', ')}`));
127
+ }
128
+ return formBuilder.httpPostDataFunction(config.httpEndPoint, postData).pipe(take(1), map((response) => this.normalizeToLoadDocumentsResult(response)), catchError((err) => {
129
+ const msg = err?.error?.message ?? (err instanceof Error ? err.message : 'Unknown error');
130
+ return of({ documents: [], error: msg });
131
+ }));
132
+ }
133
+ loadFromMongoDb(params) {
134
+ const { documentsSource, formBuilder } = params;
135
+ const config = documentsSource;
136
+ if (!config.pipeline || config.pipeline.length === 0) {
137
+ return throwError(() => new Error('No pipeline found'));
138
+ }
139
+ if (!config.workflowId) {
140
+ return throwError(() => new Error('No workflow id found'));
141
+ }
142
+ const paginationParams = {
143
+ page: params.page ?? 1,
144
+ itemsPerPage: params.itemsPerPage ?? 10,
145
+ sort: (params.sort && Object.keys(params.sort).length > 0) ? params.sort : DEFAULT_SORT,
146
+ searchKey: params.searchKey,
147
+ ...(params.filter && Object.keys(params.filter).length > 0 ? { filter: params.filter } : {}),
148
+ };
149
+ const runPipeline = formBuilder.runMongoDbPipeLine;
150
+ return runPipeline(config.pipeline, config.workflowId, paginationParams).pipe(take(1), map((data) => this.normalizeToLoadDocumentsResult(data)), catchError((err) => {
151
+ const msg = err?.error?.message ?? (err instanceof Error ? err.message : 'Unknown error');
152
+ return of({ documents: [], error: msg });
153
+ }));
154
+ }
155
+ loadFromDefault(workflowId, params) {
156
+ // Prefer formBuilder from params; fallback to injected config when params.formBuilder
157
+ // lacks getWorkflowDocuments (e.g. form builder preview, test-app, or partial config)
158
+ const getWorkflowDocuments = this.formsConfig?.formBuilder?.getWorkflowDocuments;
159
+ if (typeof getWorkflowDocuments !== 'function') {
160
+ return of({ documents: [] });
161
+ }
162
+ const page = params.page ?? 1;
163
+ const itemsPerPage = params.itemsPerPage ?? 10;
164
+ const sort = (params.sort && Object.keys(params.sort).length > 0) ? params.sort : DEFAULT_SORT;
165
+ const searchKey = params.searchKey;
166
+ const filter = params.filter;
167
+ return getWorkflowDocuments(workflowId, page, itemsPerPage, sort, searchKey, filter).pipe(take(1), map((res) => this.normalizeToLoadDocumentsResult(res)));
168
+ }
169
+ /**
170
+ * Flatten WorkFlowDocumentInterface list rows so form fields are at top level.
171
+ * Matches getSelectedDocument structure so row[col.formControlName] works for all columns.
172
+ * Attaches _originalDoc so primaryIdentifierKey can resolve against the original nested structure
173
+ * (e.g. { _id, reference, form: { customId } }) when the flattened row has form keys at top level.
174
+ */
175
+ flattenListDocuments(docs) {
176
+ return docs.map((doc) => {
177
+ const form = doc['form'];
178
+ if (!form || typeof form !== 'object')
179
+ return { ...doc, _originalDoc: doc };
180
+ const { form: _f, ...rest } = doc;
181
+ return { ...rest, ...form, _originalDoc: doc };
182
+ });
183
+ }
184
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: DocumentLoaderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
185
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: DocumentLoaderService, providedIn: 'root' }); }
186
+ }
187
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: DocumentLoaderService, decorators: [{
188
+ type: Injectable,
189
+ args: [{ providedIn: 'root' }]
190
+ }] });
191
+
192
+ const customInputConfig = {
193
+ controlType: 'lib-document-picker-reactive-input',
194
+ nextId: 0,
195
+ };
196
+ /**
197
+ * Document Picker: Link workflow transactions via search, sort, and selection.
198
+ *
199
+ * User Story: As a Process Coordinator, I want to search, sort, and select specific workflow
200
+ * transactions from a paginated list, so that I can accurately link related records.
201
+ *
202
+ * AC1 Dynamic loading: Reloads when workflowId/inputConfig changes.
203
+ * AC2 Search: Refreshes list and resets to page 1 on keyword change; restores full list when cleared.
204
+ * AC3 Sort/Pagination: Sort resets to page 1; pagination fetches subset while preserving search/sort.
205
+ * AC4 Selection: Selected transaction shown clearly; deselect restores paginated view.
206
+ * AC5 Empty/Error: "No transactions found" when empty; error state with retry option.
207
+ */
208
+ class DocumentPickerReactiveInputComponent extends BaseCustomInput {
209
+ #formsConfig;
210
+ #documentLoader;
211
+ #cdr;
212
+ #destroyRef;
213
+ #pickerConfig;
214
+ #lastInputConfig;
215
+ /** Documents loaded in memory. For client-side: full list; for server-side: current page only. */
216
+ #documentOptions;
217
+ /** Last loaded workflowId/sourceType - only reload when these change. */
218
+ #lastLoadedWorkflowId;
219
+ #lastLoadedSourceType;
220
+ constructor() {
221
+ super(inject(NgControl, { self: true, optional: true }), inject(ElementRef), customInputConfig);
222
+ this.formBuilderFunctions = input(undefined, ...(ngDevMode ? [{ debugName: "formBuilderFunctions" }] : /* istanbul ignore next */ []));
223
+ this.searchPlaceholder = input('Search transactions…', ...(ngDevMode ? [{ debugName: "searchPlaceholder" }] : /* istanbul ignore next */ []));
224
+ this.emptyMessage = input('No transactions found', ...(ngDevMode ? [{ debugName: "emptyMessage" }] : /* istanbul ignore next */ []));
225
+ this.inputConfig = input(undefined, ...(ngDevMode ? [{ debugName: "inputConfig" }] : /* istanbul ignore next */ []));
226
+ this.searchFormControl = new FormControl('');
227
+ this.dataSource = new MatTableDataSource([]);
228
+ this.sort = viewChild(MatSort, ...(ngDevMode ? [{ debugName: "sort" }] : /* istanbul ignore next */ []));
229
+ this.paginator = viewChild(MatPaginator, ...(ngDevMode ? [{ debugName: "paginator" }] : /* istanbul ignore next */ []));
230
+ this.#formsConfig = inject(NGX_T_FORMS_CONFIG_TOKEN);
231
+ this.#documentLoader = inject(DocumentLoaderService);
232
+ this.#cdr = inject(ChangeDetectorRef);
233
+ this.#destroyRef = inject(DestroyRef);
234
+ this._cols = [];
235
+ this._loadingCols = false;
236
+ /** Documents loaded in memory. For client-side: full list; for server-side: current page only. */
237
+ this.#documentOptions = [];
238
+ this.serverPage = 1;
239
+ this.serverPageSize = 5;
240
+ this.serverSort = { ...DEFAULT_SORT };
241
+ this.loadingData = false;
242
+ this.selectedDocument = undefined;
243
+ this.#listenToStateChanges();
244
+ this.#setupFilterPredicate();
245
+ this.#setupSearchSubscription();
246
+ // Replaces the previous @Input setter side-effect: react to inputConfig changes.
247
+ effect(() => {
248
+ const value = this.inputConfig();
249
+ if (_isEqual(this.#lastInputConfig, value))
250
+ return;
251
+ this.#lastInputConfig = value;
252
+ this.loadCols();
253
+ });
254
+ }
255
+ get isMultiSelect() {
256
+ return this.inputConfig()?.allowMultipleSelection === true;
257
+ }
258
+ get primaryIdentifierKey() {
259
+ return this.inputConfig()?.workflowPickerConfig?.primaryIdentifierKey;
260
+ }
261
+ /**
262
+ * Returns the row identifier. Uses returnMappedPathValue when primaryIdentifierKey is set,
263
+ * resolving against the original document (row._originalDoc) for nested paths like form.customId,
264
+ * since the table row is flattened. Fallback: _id or id.
265
+ */
266
+ getRowId(row) {
267
+ const pk = this.primaryIdentifierKey;
268
+ if (pk != null && pk !== '') {
269
+ const doc = row['_originalDoc'] ?? row;
270
+ return returnMappedPathValue(pk, doc);
271
+ }
272
+ return row['_id'] ?? row['id'];
273
+ }
274
+ /**
275
+ * Builds a filter object for the selected value.
276
+ * Key: dot-joined path from primaryIdentifierKey (e.g. form.customId) or '_id' when not set.
277
+ * Value: the current value.
278
+ */
279
+ #buildFilterForValue() {
280
+ const val = this.value;
281
+ if (val == null || val === '')
282
+ return undefined;
283
+ const pk = this.primaryIdentifierKey;
284
+ let filterKey = '_id';
285
+ if (pk != null && pk !== '') {
286
+ if (typeof pk === 'string') {
287
+ filterKey = pk;
288
+ }
289
+ else if (Array.isArray(pk) && pk.length > 0) {
290
+ filterKey = pk
291
+ .map((n) => (typeof n === 'object' && n != null && (n).key != null ? String((n).key) : String(n)))
292
+ .join('.');
293
+ }
294
+ }
295
+ return { [filterKey]: val };
296
+ }
297
+ /** Builds a minimal row from an id for fallback when the row is not in documentOptions/dataSource. */
298
+ #buildFallbackRowFromId(id) {
299
+ const pk = this.primaryIdentifierKey;
300
+ if (!pk || !Array.isArray(pk) || pk.length === 0) {
301
+ return { _id: id, id };
302
+ }
303
+ const obj = {};
304
+ let current = obj;
305
+ for (let i = 0; i < pk.length; i++) {
306
+ const node = pk[i];
307
+ const key = typeof node === 'object' && node != null && node.key != null ? String(node.key) : String(node);
308
+ const isLast = i === pk.length - 1;
309
+ if (isLast) {
310
+ current[key] = id;
311
+ }
312
+ else {
313
+ current[key] = {};
314
+ current = current[key];
315
+ }
316
+ }
317
+ return obj;
318
+ }
319
+ /** Returns selected id(s) as strings. Handles value from form/API (string, number, ObjectId, etc.). */
320
+ getSelectedIds() {
321
+ const v = this.value;
322
+ if (v == null || v === '')
323
+ return [];
324
+ if (Array.isArray(v))
325
+ return v.map((x) => (x != null ? String(x) : '')).filter(Boolean);
326
+ return [String(v)];
327
+ }
328
+ isRowSelected(row) {
329
+ const id = this.getRowId(row);
330
+ return this.getSelectedIds().some((sid) => sid == id || String(id) === sid);
331
+ }
332
+ get empty() {
333
+ const n = this.value;
334
+ if (n === null || n === undefined)
335
+ return true;
336
+ if (this.isMultiSelect) {
337
+ return Array.isArray(n) && n.length === 0;
338
+ }
339
+ return n === '';
340
+ }
341
+ get shouldLabelFloat() {
342
+ return true;
343
+ }
344
+ ngAfterViewInit() {
345
+ const sortRef = this.sort();
346
+ if (sortRef) {
347
+ this.dataSource.sort = sortRef;
348
+ sortRef.sortChange.pipe(takeUntilDestroyed(this.#destroyRef)).subscribe((s) => {
349
+ if (this.footerConfig && s.active && s.direction) {
350
+ this.onSortChange(s.active, s.direction);
351
+ }
352
+ });
353
+ }
354
+ this.#attachPaginatorIfNeeded();
355
+ }
356
+ /** Attach paginator when client-side (not server-side). Server-side uses length from footerConfig. */
357
+ #attachPaginatorIfNeeded() {
358
+ if (this.footerConfig)
359
+ return; // Server-side: paginator length handled by template
360
+ const paginatorRef = this.paginator();
361
+ if (paginatorRef && this.dataSource.paginator !== paginatorRef) {
362
+ this.dataSource.paginator = paginatorRef;
363
+ this.#cdr.markForCheck();
364
+ }
365
+ }
366
+ #setupFilterPredicate() {
367
+ this.dataSource.filterPredicate = (doc, filter) => {
368
+ const term = filter?.trim();
369
+ if (!term)
370
+ return true;
371
+ if (typeof doc !== 'object' || doc === null)
372
+ return false;
373
+ const regex = new RegExp(term.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'), 'i');
374
+ return Object.values(doc).some(value => typeof value === 'string' && regex.test(value));
375
+ };
376
+ }
377
+ #setupSearchSubscription() {
378
+ this.searchFormControl.valueChanges.pipe(debounceTime(400), map$1((term) => term?.trim() ?? ''), distinctUntilChanged((a, b) => a === b), takeUntilDestroyed(this.#destroyRef)).subscribe((filter) => {
379
+ if (this.footerConfig) {
380
+ this.serverPage = 1;
381
+ this.loadDocumentOptions(true);
382
+ }
383
+ else {
384
+ this.dataSource.filter = filter;
385
+ this.dataSource.paginator?.firstPage();
386
+ }
387
+ });
388
+ }
389
+ get parentFormGroup() {
390
+ return this.ngControl?.control?.parent;
391
+ }
392
+ get displayedColumns() {
393
+ return this._cols.map((col) => col.formControlName);
394
+ }
395
+ /** Page index for paginator: server-side uses serverPage; client-side uses paginator's current page. */
396
+ get pageIndexForDisplay() {
397
+ return this.footerConfig ? this.serverPage - 1 : (this.paginator()?.pageIndex ?? 0);
398
+ }
399
+ /** Page size for paginator: server-side uses serverPageSize; client-side uses paginator's current size. */
400
+ get pageSizeForDisplay() {
401
+ return this.footerConfig ? this.serverPageSize : (this.paginator()?.pageSize ?? 5);
402
+ }
403
+ /** True when server echoes sort in footerConfig; false when sortBy is empty → use local sort. */
404
+ get serverMaintainsSort() {
405
+ const sb = this.footerConfig?.sortBy;
406
+ return !!(sb && typeof sb === 'object' && Object.keys(sb).length > 0);
407
+ }
408
+ /**
409
+ * Documents load only when workflowId or documentSourceType changes.
410
+ * Search, pagination, sorting operate client-side on already-loaded data.
411
+ */
412
+ #shouldLoadDocuments(forceRefresh) {
413
+ if (forceRefresh)
414
+ return true;
415
+ const pickerConfig = this.inputConfig()?.workflowPickerConfig;
416
+ const workflowId = pickerConfig?.workflowId ?? '';
417
+ const sourceType = pickerConfig?.documentSourceType ?? 'default';
418
+ if (!workflowId || !sourceType)
419
+ return false;
420
+ return (this.#lastLoadedWorkflowId !== workflowId || this.#lastLoadedSourceType !== sourceType);
421
+ }
422
+ #listenToStateChanges() {
423
+ this.stateChanges.pipe(takeUntilDestroyed(this.#destroyRef), tap(() => {
424
+ if (this.isMultiSelect) {
425
+ this.dataSource.data = [...this.#documentOptions];
426
+ this.#cdr.markForCheck();
427
+ return;
428
+ }
429
+ const hasValue = !!this.value;
430
+ const docIdMatches = this.selectedDocument != null && this.getRowId(this.selectedDocument) == this.value;
431
+ if (!docIdMatches && hasValue) {
432
+ // Use filter so the selected document appears on the first page
433
+ this.serverPage = 1;
434
+ this.loadDocumentOptions(true);
435
+ }
436
+ else if (!docIdMatches && !hasValue) {
437
+ this.restoreDocumentList();
438
+ }
439
+ })).subscribe();
440
+ }
441
+ /** Restore list view from memory (no API call). Use when value is cleared or user deselects. */
442
+ restoreDocumentList() {
443
+ this.selectedDocument = undefined;
444
+ this.dataSource.data = [...this.#documentOptions];
445
+ this.loadingData = false;
446
+ this.dataLoadingError = undefined;
447
+ setTimeout(() => this.#attachPaginatorIfNeeded(), 0);
448
+ this.#cdr.markForCheck();
449
+ }
450
+ loadCols() {
451
+ const newConfig = this.#lastInputConfig?.workflowPickerConfig;
452
+ if (_isEqual(this.#pickerConfig, newConfig))
453
+ return;
454
+ if (!newConfig?.workflowId) {
455
+ this.#pickerConfig = newConfig;
456
+ this._cols = [];
457
+ this.#documentOptions = [];
458
+ this.dataSource.data = [];
459
+ this.#lastLoadedWorkflowId = undefined;
460
+ this.#lastLoadedSourceType = undefined;
461
+ this.footerConfig = undefined;
462
+ this.serverPage = 1;
463
+ this.serverPageSize = 10;
464
+ this.serverSort = { ...DEFAULT_SORT };
465
+ this.selectedDocument = undefined;
466
+ this.dataLoadingError = undefined;
467
+ this.#cdr.markForCheck();
468
+ return;
469
+ }
470
+ this.#pickerConfig = newConfig;
471
+ this.#lastLoadedWorkflowId = undefined;
472
+ this.#lastLoadedSourceType = undefined;
473
+ this.footerConfig = undefined;
474
+ this.serverPage = 1;
475
+ this._loadingCols = true;
476
+ this.#cdr.markForCheck();
477
+ this.#formsConfig.formBuilder.getWorkflowCols(newConfig.workflowId).pipe(take$1(1), tap((cols) => {
478
+ this._cols = [
479
+ { label: '', formControlName: 'icons' },
480
+ { label: 'reference', formControlName: 'reference' },
481
+ { label: 'Updated', formControlName: 'updatedAt', type: DocumentLitsLabelConfigInterfaceValueType.date },
482
+ ...cols,
483
+ { label: '', formControlName: 'actions' },
484
+ ];
485
+ this.loadDocumentOptions();
486
+ }), catchError$1(() => {
487
+ this._cols = [];
488
+ return of([]);
489
+ }), finalize(() => {
490
+ this._loadingCols = false;
491
+ this.#cdr.markForCheck();
492
+ }), takeUntilDestroyed(this.#destroyRef)).subscribe();
493
+ }
494
+ /**
495
+ * Load documents only when workflowId or documentSourceType changes.
496
+ * Called from: loadCols (config change), refreshDocuments (user refresh).
497
+ */
498
+ loadDocumentOptions(forceRefresh = false) {
499
+ const pickerConfig = this.inputConfig()?.workflowPickerConfig;
500
+ const workflowId = pickerConfig?.workflowId ?? '';
501
+ const sourceType = pickerConfig?.documentSourceType ?? 'default';
502
+ const newSource = pickerConfig?.documentsSource;
503
+ if (!sourceType)
504
+ return;
505
+ if (!forceRefresh && !this.#shouldLoadDocuments(false))
506
+ return;
507
+ this.#lastLoadedWorkflowId = workflowId;
508
+ this.#lastLoadedSourceType = sourceType;
509
+ this.loadingData = true;
510
+ this.dataLoadingError = undefined;
511
+ this.#cdr.markForCheck();
512
+ const effectiveSort = (this.serverSort && Object.keys(this.serverSort).length > 0) ? this.serverSort : DEFAULT_SORT;
513
+ const filter = !this.isMultiSelect && this.value ? this.#buildFilterForValue() : undefined;
514
+ const parentFormValue = {
515
+ ...(this.parentFormGroup?.value ?? {}),
516
+ page: this.serverPage,
517
+ itemsPerPage: this.serverPageSize,
518
+ sort: effectiveSort,
519
+ searchKey: this.searchFormControl.value?.trim() || undefined,
520
+ ...(filter ? { filter } : {}),
521
+ };
522
+ const params = {
523
+ sourceType,
524
+ documentsSource: newSource,
525
+ workflowId,
526
+ parentFormValue,
527
+ formBuilder: this.#formsConfig.formBuilder,
528
+ page: this.serverPage,
529
+ itemsPerPage: this.serverPageSize,
530
+ sort: effectiveSort,
531
+ searchKey: this.searchFormControl.value?.trim() || undefined,
532
+ filter,
533
+ };
534
+ this.#documentLoader.loadDocuments(params).pipe(take$1(1), tap((result) => {
535
+ const documents = result.documents;
536
+ this.#documentOptions = documents;
537
+ this.footerConfig = result.footerConfig;
538
+ this.dataLoadingError = result.error;
539
+ if (this.isMultiSelect) {
540
+ this.dataSource.data = [...this.#documentOptions];
541
+ setTimeout(() => this.#attachPaginatorIfNeeded(), 0);
542
+ }
543
+ else if (this.value) {
544
+ const matchingDoc = documents.find((d) => this.getRowId(d) == this.value);
545
+ const rowFromCurrent = !matchingDoc && this.dataSource.data?.length
546
+ ? this.dataSource.data.find((d) => this.getRowId(d) == this.value)
547
+ : null;
548
+ const displayDoc = matchingDoc ?? rowFromCurrent ?? this.#buildFallbackRowFromId(this.value);
549
+ this.selectedDocument = matchingDoc ?? rowFromCurrent ?? undefined;
550
+ this.dataSource.data = [displayDoc];
551
+ setTimeout(() => this.#attachPaginatorIfNeeded(), 0);
552
+ }
553
+ else {
554
+ this.selectedDocument = undefined;
555
+ this.dataSource.data = [...this.#documentOptions];
556
+ setTimeout(() => this.#attachPaginatorIfNeeded(), 0);
557
+ }
558
+ }), catchError$1((error) => {
559
+ this.dataLoadingError =
560
+ error?.error?.message ?? (error instanceof Error ? error.message : 'Unknown error');
561
+ this.#documentOptions = [];
562
+ this.footerConfig = undefined;
563
+ this.dataSource.data = [];
564
+ return of({ documents: [] });
565
+ }), finalize(() => {
566
+ this.loadingData = false;
567
+ this.#cdr.markForCheck();
568
+ }), takeUntilDestroyed(this.#destroyRef)).subscribe();
569
+ }
570
+ refreshDocuments() {
571
+ this.#lastLoadedWorkflowId = undefined;
572
+ this.#lastLoadedSourceType = undefined;
573
+ this.loadDocumentOptions(true);
574
+ }
575
+ /** Server-side: handle paginator page/pageSize change. */
576
+ onPageChange(event) {
577
+ if (!this.footerConfig)
578
+ return;
579
+ this.serverPage = event.pageIndex + 1;
580
+ this.serverPageSize = event.pageSize;
581
+ this.loadDocumentOptions(true);
582
+ }
583
+ /** Server-side: handle sort change. */
584
+ onSortChange(active, direction) {
585
+ if (!this.footerConfig || !active)
586
+ return;
587
+ this.serverSort = { [active]: direction === 'asc' ? 1 : -1 };
588
+ this.serverPage = 1;
589
+ this.loadDocumentOptions(true);
590
+ }
591
+ clearSearch() {
592
+ this.searchFormControl.setValue('');
593
+ }
594
+ onRadioChange(event) {
595
+ const id = event?.value;
596
+ if (id == null)
597
+ return;
598
+ const row = this.#documentOptions.find((r) => this.getRowId(r) == id) ??
599
+ this.dataSource.data.find((r) => this.getRowId(r) == id);
600
+ this.selectRow(row ?? this.#buildFallbackRowFromId(id));
601
+ }
602
+ /** Handle click on radio: if already selected, deselect (radios don't fire change when re-clicked). */
603
+ onRadioClick(row, event) {
604
+ if (this.isRowSelected(row)) {
605
+ event.preventDefault();
606
+ event.stopPropagation();
607
+ this.selectRow(row);
608
+ }
609
+ }
610
+ /** Handle click on row: toggle selection (select or deselect). Ignores clicks on buttons/controls. */
611
+ onRowClick(row, event) {
612
+ const cfg = this.inputConfig();
613
+ if (!!cfg?.disabled || !!cfg?.readonly)
614
+ return;
615
+ const target = event.target;
616
+ if (target.closest('button, [mat-icon-button], .mat-mdc-radio-button'))
617
+ return;
618
+ this.selectRow(row);
619
+ }
620
+ // Row parameter mirrors `getRowId` / `isRowSelected` which use `Record<string, any>` to match
621
+ // the upstream `MatTableDataSource<Record<string, any>>` declaration.
622
+ selectRow(row) {
623
+ const id = this.getRowId(row);
624
+ const idStr = id != null ? String(id) : undefined;
625
+ if (this.isMultiSelect) {
626
+ const ids = [...this.getSelectedIds()];
627
+ const idx = ids.indexOf(idStr ?? '');
628
+ if (idx >= 0) {
629
+ ids.splice(idx, 1);
630
+ }
631
+ else if (idStr != null) {
632
+ ids.push(idStr);
633
+ }
634
+ this.value = ids.length ? ids : null;
635
+ this.onChange(this.value);
636
+ this.onTouched();
637
+ this.#cdr.markForCheck();
638
+ return;
639
+ }
640
+ const isDeselecting = this.isRowSelected(row);
641
+ this.selectedDocument = undefined;
642
+ this.value = isDeselecting ? null : (idStr ?? null);
643
+ this.onChange(this.value);
644
+ this.onTouched();
645
+ if (isDeselecting) {
646
+ this.serverPage = 1;
647
+ this.loadDocumentOptions(true);
648
+ }
649
+ }
650
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: DocumentPickerReactiveInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
651
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: DocumentPickerReactiveInputComponent, isStandalone: true, selector: "lib-document-picker-reactive-input", inputs: { formBuilderFunctions: { classPropertyName: "formBuilderFunctions", publicName: "formBuilderFunctions", isSignal: true, isRequired: false, transformFunction: null }, searchPlaceholder: { classPropertyName: "searchPlaceholder", publicName: "searchPlaceholder", isSignal: true, isRequired: false, transformFunction: null }, emptyMessage: { classPropertyName: "emptyMessage", publicName: "emptyMessage", isSignal: true, isRequired: false, transformFunction: null }, inputConfig: { classPropertyName: "inputConfig", publicName: "inputConfig", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.floating": "shouldLabelFloat", "id": "id" } }, providers: [{ provide: MatFormFieldControl, useExisting: DocumentPickerReactiveInputComponent }], viewQueries: [{ propertyName: "sort", first: true, predicate: MatSort, descendants: true, isSignal: true }, { propertyName: "paginator", first: true, predicate: MatPaginator, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<mat-card class=\"doc-picker-card\">\r\n <header class=\"doc-picker-header\">\r\n @if (!inputConfig()?.disabled && !inputConfig()?.readonly && !selectedDocument && !dataLoadingError) {\r\n <div class=\"doc-picker-toolbar\">\r\n <mat-form-field subscriptSizing=\"dynamic\" class=\"doc-picker-search\">\r\n <input matInput [placeholder]=\"searchPlaceholder()\" [formControl]=\"searchFormControl\"\r\n [attr.aria-label]=\"searchPlaceholder()\">\r\n @if (searchFormControl.value) {\r\n <button mat-icon-button matSuffix (click)=\"clearSearch()\" type=\"button\"\r\n aria-label=\"Clear search\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n } @else {\r\n <mat-icon matSuffix>search</mat-icon>\r\n }\r\n </mat-form-field>\r\n @if (isMultiSelect && getSelectedIds().length > 0) {\r\n <span class=\"doc-picker-selection-badge\" role=\"status\" aria-live=\"polite\">\r\n {{ getSelectedIds().length }} selected\r\n </span>\r\n }\r\n </div>\r\n }\r\n </header>\r\n\r\n @if (dataLoadingError) {\r\n <div class=\"doc-picker-error\">\r\n <mat-icon color=\"warn\">error</mat-icon>\r\n <span class=\"doc-picker-error-text\">{{ dataLoadingError }}</span>\r\n @if (!inputConfig()?.disabled && !inputConfig()?.readonly) {\r\n <button mat-stroked-button color=\"warn\" (click)=\"refreshDocuments()\" class=\"doc-picker-retry\"\r\n aria-label=\"Retry loading documents\">\r\n <mat-icon>refresh</mat-icon>\r\n Retry\r\n </button>\r\n }\r\n </div>\r\n } @else {\r\n <div class=\"doc-picker-body\">\r\n @if (!inputConfig()?.disabled && !inputConfig()?.readonly && !selectedDocument) {\r\n <div class=\"doc-picker-helper\">\r\n <mat-icon class=\"doc-picker-helper-icon\" color=\"primary\">info</mat-icon>\r\n <span><strong>{{ isMultiSelect ? 'Link transactions' : 'Link a transaction' }}</strong> \u2014 Search or sort to find {{ isMultiSelect ? 'them' : 'one' }}, then {{ isMultiSelect ? 'check the box' : 'select the radio' }} to select {{ isMultiSelect ? 'them' : 'it' }}.</span>\r\n </div>\r\n }\r\n <div class=\"doc-picker-content-area\">\r\n @if (_loadingCols || loadingData) {\r\n <div class=\"doc-picker-loading doc-picker-loading-overlay\">\r\n <mat-spinner [diameter]=\"40\" aria-label=\"Loading documents\"></mat-spinner>\r\n </div>\r\n }\r\n @if (dataSource.filteredData.length === 0 && !loadingData && !_loadingCols) {\r\n <div class=\"doc-picker-empty\">\r\n <mat-icon>folder_open</mat-icon>\r\n <span>{{ emptyMessage() }}</span>\r\n <button mat-stroked-button color=\"warn\" (click)=\"refreshDocuments()\" class=\"doc-picker-retry\"\r\n aria-label=\"Retry loading documents\">\r\n <mat-icon>refresh</mat-icon>\r\n Retry\r\n </button>\r\n </div>\r\n }\r\n @if (dataSource.filteredData.length > 0 && _cols.length > 0) {\r\n @if (isMultiSelect) {\r\n <div class=\"doc-picker-table-wrapper\">\r\n <table mat-table [dataSource]=\"dataSource\" class=\"doc-picker-table\" matSort matSortActive=\"updatedAt\"\r\n matSortDisableClear matSortDirection=\"desc\" role=\"grid\" aria-label=\"Transaction list\">\r\n @for (col of _cols; track col.formControlName) {\r\n <ng-container [matColumnDef]=\"col.formControlName\" [stickyEnd]=\"$last\">\r\n <th mat-header-cell *matHeaderCellDef mat-sort-header\r\n [disabled]=\"col.formControlName === 'icons' || col.formControlName === 'actions'\"\r\n [class.text-right-align]=\"col.type === 'currency' || col.type === 'number'\"\r\n [class.doc-picker-col-icons]=\"col.formControlName === 'icons'\"\r\n [class.doc-picker-col-actions]=\"col.formControlName === 'actions'\"\r\n [class.doc-picker-col-text]=\"col.formControlName !== 'icons' && col.formControlName !== 'actions' && col.type !== 'currency' && col.type !== 'number'\"\r\n [class.doc-picker-col-numeric]=\"col.type === 'currency' || col.type === 'number'\">\r\n @if (col.formControlName === 'actions') {\r\n <button mat-icon-button (click)=\"refreshDocuments()\" class=\"doc-picker-refresh\"\r\n matTooltip=\"Refresh list\" matTooltipPosition=\"below\" aria-label=\"Refresh document list\">\r\n <mat-icon>sync</mat-icon>\r\n </button>\r\n }@else {\r\n {{ col.label }}\r\n }\r\n </th>\r\n <td mat-cell *matCellDef=\"let row\"\r\n [class.text-right-align]=\"col.type === 'currency' || col.type === 'number'\"\r\n [class.doc-picker-col-icons]=\"col.formControlName === 'icons'\"\r\n [class.doc-picker-col-actions]=\"col.formControlName === 'actions'\"\r\n [class.doc-picker-col-text]=\"col.formControlName !== 'icons' && col.formControlName !== 'actions' && col.type !== 'currency' && col.type !== 'number'\"\r\n [class.doc-picker-col-numeric]=\"col.type === 'currency' || col.type === 'number'\">\r\n @if (col.formControlName === 'icons') {\r\n <mat-icon class=\"doc-picker-row-icon\">description</mat-icon>\r\n } @else if (col.formControlName === 'actions') {\r\n <mat-checkbox\r\n [checked]=\"isRowSelected(row)\"\r\n [disabled]=\"!!inputConfig()?.disabled || !!inputConfig()?.readonly\"\r\n (change)=\"selectRow(row)\"\r\n [matTooltip]=\"isRowSelected(row) ? 'Clear selection' : 'Select ' + (row['reference'] ?? 'document')\"\r\n matTooltipPosition=\"below\"\r\n [attr.aria-label]=\"isRowSelected(row) ? 'Clear selection' : 'Select ' + (row['reference'] ?? 'document')\">\r\n </mat-checkbox>\r\n } @else {\r\n <span class=\"doc-picker-cell-value doc-picker-cell-text\"\r\n [class.doc-picker-cell-selected]=\"isRowSelected(row)\"\r\n [matTooltip]=\"row[col.formControlName] | formatData:col.type\"\r\n matTooltipPosition=\"above\">\r\n {{ row[col.formControlName] | formatData:col.type }}\r\n </span>\r\n }\r\n </td>\r\n </ng-container>\r\n }\r\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns; sticky: true\"></tr>\r\n <tr mat-row class=\"doc-picker-row\" *matRowDef=\"let row; columns: displayedColumns;\"\r\n [class.doc-picker-row-selected]=\"isRowSelected(row)\"\r\n [attr.aria-label]=\"'Row: ' + (row['reference'] ?? 'document')\"\r\n [attr.aria-selected]=\"isRowSelected(row)\"></tr>\r\n </table>\r\n </div>\r\n } @else {\r\n <mat-radio-group [value]=\"value\" (change)=\"onRadioChange($event)\" class=\"doc-picker-radio-group\">\r\n <div class=\"doc-picker-table-wrapper\">\r\n <table mat-table [dataSource]=\"dataSource\" class=\"doc-picker-table\" matSort matSortActive=\"updatedAt\"\r\n matSortDisableClear matSortDirection=\"desc\" role=\"grid\" aria-label=\"Transaction list\">\r\n @for (col of _cols; track col.formControlName) {\r\n <ng-container [matColumnDef]=\"col.formControlName\" [stickyEnd]=\"$last\">\r\n <th mat-header-cell *matHeaderCellDef mat-sort-header\r\n [disabled]=\"col.formControlName === 'icons' || col.formControlName === 'actions'\"\r\n [class.text-right-align]=\"col.type === 'currency' || col.type === 'number'\"\r\n [class.doc-picker-col-icons]=\"col.formControlName === 'icons'\"\r\n [class.doc-picker-col-actions]=\"col.formControlName === 'actions'\"\r\n [class.doc-picker-col-text]=\"col.formControlName !== 'icons' && col.formControlName !== 'actions' && col.type !== 'currency' && col.type !== 'number'\"\r\n [class.doc-picker-col-numeric]=\"col.type === 'currency' || col.type === 'number'\">\r\n \r\n\r\n @if (col.formControlName === 'actions') {\r\n <button mat-icon-button (click)=\"refreshDocuments()\" class=\"doc-picker-refresh\"\r\n matTooltip=\"Refresh list\" matTooltipPosition=\"below\" aria-label=\"Refresh document list\">\r\n <mat-icon>sync</mat-icon>\r\n </button>\r\n }@else {\r\n {{ col.label }}\r\n }\r\n \r\n </th>\r\n <td mat-cell *matCellDef=\"let row\"\r\n [class.text-right-align]=\"col.type === 'currency' || col.type === 'number'\"\r\n [class.doc-picker-col-icons]=\"col.formControlName === 'icons'\"\r\n [class.doc-picker-col-actions]=\"col.formControlName === 'actions'\"\r\n [class.doc-picker-col-text]=\"col.formControlName !== 'icons' && col.formControlName !== 'actions' && col.type !== 'currency' && col.type !== 'number'\"\r\n [class.doc-picker-col-numeric]=\"col.type === 'currency' || col.type === 'number'\">\r\n @if (col.formControlName === 'icons') {\r\n <mat-icon class=\"doc-picker-row-icon\">description</mat-icon>\r\n } @else if (col.formControlName === 'actions') {\r\n <mat-radio-button\r\n [value]=\"getRowId(row)\"\r\n [disabled]=\"!!inputConfig()?.disabled || !!inputConfig()?.readonly\"\r\n (click)=\"onRadioClick(row, $event)\"\r\n [matTooltip]=\"isRowSelected(row) ? 'Clear selection' : 'Select ' + (row['reference'] ?? 'document')\"\r\n matTooltipPosition=\"below\"\r\n [attr.aria-label]=\"isRowSelected(row) ? 'Clear selection' : 'Select ' + (row['reference'] ?? 'document')\">\r\n </mat-radio-button>\r\n } @else {\r\n <span class=\"doc-picker-cell-value doc-picker-cell-text\"\r\n [class.doc-picker-cell-selected]=\"isRowSelected(row)\"\r\n [matTooltip]=\"row[col.formControlName] | formatData:col.type\"\r\n matTooltipPosition=\"above\">\r\n {{ row[col.formControlName] | formatData:col.type }}\r\n </span>\r\n }\r\n </td>\r\n </ng-container>\r\n }\r\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns; sticky: true\"></tr>\r\n <tr mat-row class=\"doc-picker-row\" *matRowDef=\"let row; columns: displayedColumns;\"\r\n [class.doc-picker-row-selected]=\"isRowSelected(row)\"\r\n [attr.aria-label]=\"'Row: ' + (row['reference'] ?? 'document')\"\r\n [attr.aria-selected]=\"isRowSelected(row)\"\r\n (click)=\"onRowClick(row, $event)\"></tr>\r\n </table>\r\n </div>\r\n </mat-radio-group>\r\n }\r\n }\r\n </div>\r\n </div>\r\n @if (!inputConfig()?.disabled && !inputConfig()?.readonly && !selectedDocument) {\r\n <mat-paginator [pageSizeOptions]=\"[5, 10, 25, 50]\"\r\n [pageSize]=\"pageSizeForDisplay\"\r\n [length]=\"footerConfig ? footerConfig.totalItems : dataSource.filteredData.length\"\r\n [pageIndex]=\"pageIndexForDisplay\"\r\n (page)=\"onPageChange($event)\"\r\n showFirstLastButtons\r\n aria-label=\"Transaction list pagination\" class=\"doc-picker-paginator\"></mat-paginator>\r\n }\r\n }\r\n</mat-card>\r\n\r\n", styles: [":host{--doc-picker-radius-lg: 12px;--doc-picker-radius-sm: 8px;--doc-picker-radius-pill: 6px;--doc-picker-shadow: 0 2px 8px rgba(0, 0, 0, .08);--doc-picker-primary: var(--mat-sys-primary, #6750a4);--doc-picker-surface: var(--mat-sys-surface, #fef7ff);--doc-picker-surface-container: var(--mat-sys-surface-container, #f3edf7);--doc-picker-on-surface: var(--mat-sys-on-surface, #1c1b1f);--doc-picker-on-surface-variant: var(--mat-sys-on-surface-variant, #49454f);--doc-picker-outline: var(--mat-sys-outline, #79747e)}@media(prefers-color-scheme:dark){:host{--doc-picker-shadow: 0 1px 3px rgba(0, 0, 0, .3)}}.doc-picker-card{border-radius:var(--doc-picker-radius-lg);box-shadow:var(--doc-picker-shadow);border:1px solid color-mix(in srgb,var(--doc-picker-outline) 15%,transparent);overflow:hidden;background:var(--doc-picker-surface)}.doc-picker-header{display:flex;align-items:center;gap:.75rem;padding:0rem;background:color-mix(in srgb,var(--doc-picker-primary) 4%,transparent);border-bottom:1px solid color-mix(in srgb,var(--doc-picker-outline) 10%,transparent)}.doc-picker-header-icon{width:2.25rem;height:2.25rem;min-width:2.25rem;border-radius:var(--doc-picker-radius-sm);background:color-mix(in srgb,var(--doc-picker-primary) 12%,transparent);display:flex;align-items:center;justify-content:center;flex-shrink:0}.doc-picker-header-icon mat-icon{font-size:1.25rem;width:1.25rem;height:1.25rem;color:var(--doc-picker-primary)}.doc-picker-header-content{flex:1;min-width:0}.doc-picker-title{font-size:.9375rem;font-weight:600;letter-spacing:-.01em;color:var(--doc-picker-on-surface);margin:0;line-height:1.3}.doc-picker-subtitle{font-size:.8125rem;color:var(--doc-picker-on-surface-variant);line-height:1.35;margin:.25rem 0 0}.doc-picker-toolbar{display:flex;align-items:center;gap:.5rem;flex-shrink:0;width:100%}.doc-picker-selection-badge{flex-shrink:0;font-size:.75rem;font-weight:500;padding:.25rem .5rem;border-radius:var(--doc-picker-radius-pill);background:color-mix(in srgb,var(--doc-picker-primary) 14%,transparent);color:var(--doc-picker-primary);white-space:nowrap}.doc-picker-search{width:100%;min-width:8rem}.doc-picker-search .mat-mdc-form-field{--mdc-filled-text-field-container-color: transparent;--mdc-filled-text-field-container-shape: var(--doc-picker-radius-sm)}.doc-picker-search .mat-mdc-form-field-subscript-wrapper{display:none}.doc-picker-search input{font-size:.8125rem}.doc-picker-refresh{flex-shrink:0;min-width:fit-content;min-height:fit-content;transition:transform .15s}.doc-picker-refresh mat-icon{height:1.5rem;width:1.5rem;font-size:1.5rem;color:var(--doc-picker-primary);margin:0;padding:0;vertical-align:middle;display:inline-block;line-height:1}.doc-picker-refresh:hover{transform:rotate(90deg)}.doc-picker-loading{display:flex;justify-content:center;align-items:center;padding:1.5rem;min-height:6rem}.doc-picker-content-area{position:relative;min-height:6rem}.doc-picker-loading-overlay{position:absolute;inset:0;z-index:2;background:color-mix(in srgb,var(--doc-picker-surface) 95%,transparent);border-radius:var(--doc-picker-radius-sm)}.doc-picker-error{display:flex;flex-wrap:wrap;align-items:center;gap:.5rem;padding:.75rem 1rem;margin:.75rem 1rem;background:color-mix(in srgb,var(--mat-sys-error, #b3261e) 8%,transparent);border-radius:var(--doc-picker-radius-sm)}.doc-picker-error mat-icon{flex-shrink:0;font-size:1.25rem;width:1.25rem;height:1.25rem}.doc-picker-error-text{flex:1;font-size:.8125rem;color:var(--doc-picker-on-surface)}.doc-picker-retry{min-height:2.25rem;font-size:.8125rem;transition:all .15s}.doc-picker-retry mat-icon{margin-right:.25rem;vertical-align:middle;font-size:1rem;width:1rem;height:1rem}.doc-picker-body{padding:.75rem 1rem;display:flex;flex-direction:column;gap:.75rem}.doc-picker-helper{display:flex;align-items:flex-start;gap:.5rem;padding:.5rem .75rem;background:color-mix(in srgb,var(--doc-picker-primary) 6%,transparent);border-radius:var(--doc-picker-radius-sm);font-size:.8125rem;color:var(--doc-picker-on-surface-variant);line-height:1.4}.doc-picker-helper-icon{font-size:1.125rem;width:1.125rem;height:1.125rem;flex-shrink:0;margin-top:.125rem}.doc-picker-helper strong{color:var(--doc-picker-on-surface)}.doc-picker-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.75rem;font-size:.8125rem;color:var(--doc-picker-on-surface-variant);padding:1rem;background:var(--doc-picker-surface-container);border-radius:var(--doc-picker-radius-sm);text-align:center;margin:0}.doc-picker-empty mat-icon{font-size:1.25rem;width:1.25rem;height:1.25rem;opacity:.7}.doc-picker-table-wrapper{overflow:auto;max-height:50vh;border-radius:var(--doc-picker-radius-sm);border:1px solid color-mix(in srgb,var(--doc-picker-outline) 15%,transparent)}.doc-picker-table{width:100%;min-width:fit-content;table-layout:auto;border-collapse:collapse}.doc-picker-table .mat-mdc-header-row{background:color-mix(in srgb,var(--doc-picker-primary) 4%,transparent)}.doc-picker-table .mat-mdc-header-row{position:sticky;top:0;z-index:3;box-shadow:0 2px 4px #0000000f}.doc-picker-table .mat-mdc-header-cell{font-size:.75rem;font-weight:500;text-transform:uppercase;letter-spacing:.04em;color:var(--doc-picker-on-surface-variant);background:var(--mat-table-background-color, var(--mat-sys-surface));padding:.35rem .5rem}.doc-picker-table .mat-mdc-cell{font-size:.75rem;padding:.35rem .5rem}.doc-picker-col-icons,.doc-picker-col-actions{width:2.5rem;min-width:2.5rem;max-width:2.5rem;background:var(--mat-table-background-color, var(--mat-sys-surface))}.doc-picker-col-text{width:fit-content;min-width:4rem;max-width:18rem}.doc-picker-col-numeric{width:min-content;min-width:4rem}.doc-picker-col-icons,.doc-picker-col-actions{text-align:center}.doc-picker-table th.doc-picker-col-actions,.doc-picker-table td.doc-picker-col-actions{background:var(--mat-table-background-color, var(--mat-sys-surface))!important;box-shadow:-4px 0 8px #0000000f}.doc-picker-col-actions .mat-mdc-checkbox,.doc-picker-col-actions .mat-mdc-radio-button{--mdc-checkbox-state-layer-size: 2rem}.doc-picker-radio-group{display:block}.doc-picker-row-icon{font-size:1.125rem!important;width:1.125rem!important;height:1.125rem!important;color:var(--doc-picker-primary)}.doc-picker-cell-value{transition:color .15s}.doc-picker-cell-text{display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}.doc-picker-cell-selected{color:var(--doc-picker-primary);font-weight:500}.doc-picker-row{cursor:pointer;transition:background-color .15s}.doc-picker-row:hover{background:color-mix(in srgb,var(--doc-picker-primary) 6%,transparent)}.doc-picker-row-selected{background:color-mix(in srgb,var(--doc-picker-primary) 12%,transparent)}.doc-picker-row-selected:hover{background:color-mix(in srgb,var(--doc-picker-primary) 14%,transparent)}.doc-picker-paginator{background:var(--doc-picker-surface);border-top:1px solid color-mix(in srgb,var(--doc-picker-outline) 10%,transparent)}.doc-picker-paginator .mat-mdc-paginator-container{padding:.5rem 1rem;font-size:.8125rem}.text-right-align{text-align:right}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { 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.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatCardModule }, { kind: "component", type: i3.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatProgressSpinnerModule }, { kind: "component", type: i3$2.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { 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.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { 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: 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: "component", type: i1$1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i5.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatTableModule }, { kind: "component", type: i5$1.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i5$1.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i5$1.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i5$1.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i5$1.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i5$1.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i5$1.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i5$1.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i5$1.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i5$1.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "ngmodule", type: MatSortModule }, { kind: "directive", type: i10.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i10.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "ngmodule", type: MatPaginatorModule }, { kind: "component", type: i11.MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }, { kind: "ngmodule", type: MatDividerModule }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i3$3.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatRadioModule }, { kind: "directive", type: i13.MatRadioGroup, selector: "mat-radio-group", inputs: ["color", "name", "labelPosition", "value", "selected", "disabled", "required", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioGroup"] }, { kind: "component", type: i13.MatRadioButton, selector: "mat-radio-button", inputs: ["id", "name", "aria-label", "aria-labelledby", "aria-describedby", "disableRipple", "tabIndex", "checked", "value", "labelPosition", "disabled", "required", "color", "disabledInteractive"], outputs: ["change"], exportAs: ["matRadioButton"] }, { kind: "pipe", type: FormatDataPipe, name: "formatData" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
652
+ }
653
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: DocumentPickerReactiveInputComponent, decorators: [{
654
+ type: Component,
655
+ args: [{ selector: 'lib-document-picker-reactive-input', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
656
+ ReactiveFormsModule,
657
+ MatCardModule,
658
+ MatIconModule,
659
+ MatProgressSpinnerModule,
660
+ MatFormFieldModule,
661
+ MatInputModule,
662
+ MatButtonModule,
663
+ MatTooltipModule,
664
+ MatTableModule,
665
+ MatSortModule,
666
+ MatPaginatorModule,
667
+ MatDividerModule,
668
+ MatCheckboxModule,
669
+ MatRadioModule,
670
+ FormatDataPipe,
671
+ ], host: {
672
+ '[class.floating]': 'shouldLabelFloat',
673
+ '[id]': 'id',
674
+ }, providers: [{ provide: MatFormFieldControl, useExisting: DocumentPickerReactiveInputComponent }], template: "<mat-card class=\"doc-picker-card\">\r\n <header class=\"doc-picker-header\">\r\n @if (!inputConfig()?.disabled && !inputConfig()?.readonly && !selectedDocument && !dataLoadingError) {\r\n <div class=\"doc-picker-toolbar\">\r\n <mat-form-field subscriptSizing=\"dynamic\" class=\"doc-picker-search\">\r\n <input matInput [placeholder]=\"searchPlaceholder()\" [formControl]=\"searchFormControl\"\r\n [attr.aria-label]=\"searchPlaceholder()\">\r\n @if (searchFormControl.value) {\r\n <button mat-icon-button matSuffix (click)=\"clearSearch()\" type=\"button\"\r\n aria-label=\"Clear search\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n } @else {\r\n <mat-icon matSuffix>search</mat-icon>\r\n }\r\n </mat-form-field>\r\n @if (isMultiSelect && getSelectedIds().length > 0) {\r\n <span class=\"doc-picker-selection-badge\" role=\"status\" aria-live=\"polite\">\r\n {{ getSelectedIds().length }} selected\r\n </span>\r\n }\r\n </div>\r\n }\r\n </header>\r\n\r\n @if (dataLoadingError) {\r\n <div class=\"doc-picker-error\">\r\n <mat-icon color=\"warn\">error</mat-icon>\r\n <span class=\"doc-picker-error-text\">{{ dataLoadingError }}</span>\r\n @if (!inputConfig()?.disabled && !inputConfig()?.readonly) {\r\n <button mat-stroked-button color=\"warn\" (click)=\"refreshDocuments()\" class=\"doc-picker-retry\"\r\n aria-label=\"Retry loading documents\">\r\n <mat-icon>refresh</mat-icon>\r\n Retry\r\n </button>\r\n }\r\n </div>\r\n } @else {\r\n <div class=\"doc-picker-body\">\r\n @if (!inputConfig()?.disabled && !inputConfig()?.readonly && !selectedDocument) {\r\n <div class=\"doc-picker-helper\">\r\n <mat-icon class=\"doc-picker-helper-icon\" color=\"primary\">info</mat-icon>\r\n <span><strong>{{ isMultiSelect ? 'Link transactions' : 'Link a transaction' }}</strong> \u2014 Search or sort to find {{ isMultiSelect ? 'them' : 'one' }}, then {{ isMultiSelect ? 'check the box' : 'select the radio' }} to select {{ isMultiSelect ? 'them' : 'it' }}.</span>\r\n </div>\r\n }\r\n <div class=\"doc-picker-content-area\">\r\n @if (_loadingCols || loadingData) {\r\n <div class=\"doc-picker-loading doc-picker-loading-overlay\">\r\n <mat-spinner [diameter]=\"40\" aria-label=\"Loading documents\"></mat-spinner>\r\n </div>\r\n }\r\n @if (dataSource.filteredData.length === 0 && !loadingData && !_loadingCols) {\r\n <div class=\"doc-picker-empty\">\r\n <mat-icon>folder_open</mat-icon>\r\n <span>{{ emptyMessage() }}</span>\r\n <button mat-stroked-button color=\"warn\" (click)=\"refreshDocuments()\" class=\"doc-picker-retry\"\r\n aria-label=\"Retry loading documents\">\r\n <mat-icon>refresh</mat-icon>\r\n Retry\r\n </button>\r\n </div>\r\n }\r\n @if (dataSource.filteredData.length > 0 && _cols.length > 0) {\r\n @if (isMultiSelect) {\r\n <div class=\"doc-picker-table-wrapper\">\r\n <table mat-table [dataSource]=\"dataSource\" class=\"doc-picker-table\" matSort matSortActive=\"updatedAt\"\r\n matSortDisableClear matSortDirection=\"desc\" role=\"grid\" aria-label=\"Transaction list\">\r\n @for (col of _cols; track col.formControlName) {\r\n <ng-container [matColumnDef]=\"col.formControlName\" [stickyEnd]=\"$last\">\r\n <th mat-header-cell *matHeaderCellDef mat-sort-header\r\n [disabled]=\"col.formControlName === 'icons' || col.formControlName === 'actions'\"\r\n [class.text-right-align]=\"col.type === 'currency' || col.type === 'number'\"\r\n [class.doc-picker-col-icons]=\"col.formControlName === 'icons'\"\r\n [class.doc-picker-col-actions]=\"col.formControlName === 'actions'\"\r\n [class.doc-picker-col-text]=\"col.formControlName !== 'icons' && col.formControlName !== 'actions' && col.type !== 'currency' && col.type !== 'number'\"\r\n [class.doc-picker-col-numeric]=\"col.type === 'currency' || col.type === 'number'\">\r\n @if (col.formControlName === 'actions') {\r\n <button mat-icon-button (click)=\"refreshDocuments()\" class=\"doc-picker-refresh\"\r\n matTooltip=\"Refresh list\" matTooltipPosition=\"below\" aria-label=\"Refresh document list\">\r\n <mat-icon>sync</mat-icon>\r\n </button>\r\n }@else {\r\n {{ col.label }}\r\n }\r\n </th>\r\n <td mat-cell *matCellDef=\"let row\"\r\n [class.text-right-align]=\"col.type === 'currency' || col.type === 'number'\"\r\n [class.doc-picker-col-icons]=\"col.formControlName === 'icons'\"\r\n [class.doc-picker-col-actions]=\"col.formControlName === 'actions'\"\r\n [class.doc-picker-col-text]=\"col.formControlName !== 'icons' && col.formControlName !== 'actions' && col.type !== 'currency' && col.type !== 'number'\"\r\n [class.doc-picker-col-numeric]=\"col.type === 'currency' || col.type === 'number'\">\r\n @if (col.formControlName === 'icons') {\r\n <mat-icon class=\"doc-picker-row-icon\">description</mat-icon>\r\n } @else if (col.formControlName === 'actions') {\r\n <mat-checkbox\r\n [checked]=\"isRowSelected(row)\"\r\n [disabled]=\"!!inputConfig()?.disabled || !!inputConfig()?.readonly\"\r\n (change)=\"selectRow(row)\"\r\n [matTooltip]=\"isRowSelected(row) ? 'Clear selection' : 'Select ' + (row['reference'] ?? 'document')\"\r\n matTooltipPosition=\"below\"\r\n [attr.aria-label]=\"isRowSelected(row) ? 'Clear selection' : 'Select ' + (row['reference'] ?? 'document')\">\r\n </mat-checkbox>\r\n } @else {\r\n <span class=\"doc-picker-cell-value doc-picker-cell-text\"\r\n [class.doc-picker-cell-selected]=\"isRowSelected(row)\"\r\n [matTooltip]=\"row[col.formControlName] | formatData:col.type\"\r\n matTooltipPosition=\"above\">\r\n {{ row[col.formControlName] | formatData:col.type }}\r\n </span>\r\n }\r\n </td>\r\n </ng-container>\r\n }\r\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns; sticky: true\"></tr>\r\n <tr mat-row class=\"doc-picker-row\" *matRowDef=\"let row; columns: displayedColumns;\"\r\n [class.doc-picker-row-selected]=\"isRowSelected(row)\"\r\n [attr.aria-label]=\"'Row: ' + (row['reference'] ?? 'document')\"\r\n [attr.aria-selected]=\"isRowSelected(row)\"></tr>\r\n </table>\r\n </div>\r\n } @else {\r\n <mat-radio-group [value]=\"value\" (change)=\"onRadioChange($event)\" class=\"doc-picker-radio-group\">\r\n <div class=\"doc-picker-table-wrapper\">\r\n <table mat-table [dataSource]=\"dataSource\" class=\"doc-picker-table\" matSort matSortActive=\"updatedAt\"\r\n matSortDisableClear matSortDirection=\"desc\" role=\"grid\" aria-label=\"Transaction list\">\r\n @for (col of _cols; track col.formControlName) {\r\n <ng-container [matColumnDef]=\"col.formControlName\" [stickyEnd]=\"$last\">\r\n <th mat-header-cell *matHeaderCellDef mat-sort-header\r\n [disabled]=\"col.formControlName === 'icons' || col.formControlName === 'actions'\"\r\n [class.text-right-align]=\"col.type === 'currency' || col.type === 'number'\"\r\n [class.doc-picker-col-icons]=\"col.formControlName === 'icons'\"\r\n [class.doc-picker-col-actions]=\"col.formControlName === 'actions'\"\r\n [class.doc-picker-col-text]=\"col.formControlName !== 'icons' && col.formControlName !== 'actions' && col.type !== 'currency' && col.type !== 'number'\"\r\n [class.doc-picker-col-numeric]=\"col.type === 'currency' || col.type === 'number'\">\r\n \r\n\r\n @if (col.formControlName === 'actions') {\r\n <button mat-icon-button (click)=\"refreshDocuments()\" class=\"doc-picker-refresh\"\r\n matTooltip=\"Refresh list\" matTooltipPosition=\"below\" aria-label=\"Refresh document list\">\r\n <mat-icon>sync</mat-icon>\r\n </button>\r\n }@else {\r\n {{ col.label }}\r\n }\r\n \r\n </th>\r\n <td mat-cell *matCellDef=\"let row\"\r\n [class.text-right-align]=\"col.type === 'currency' || col.type === 'number'\"\r\n [class.doc-picker-col-icons]=\"col.formControlName === 'icons'\"\r\n [class.doc-picker-col-actions]=\"col.formControlName === 'actions'\"\r\n [class.doc-picker-col-text]=\"col.formControlName !== 'icons' && col.formControlName !== 'actions' && col.type !== 'currency' && col.type !== 'number'\"\r\n [class.doc-picker-col-numeric]=\"col.type === 'currency' || col.type === 'number'\">\r\n @if (col.formControlName === 'icons') {\r\n <mat-icon class=\"doc-picker-row-icon\">description</mat-icon>\r\n } @else if (col.formControlName === 'actions') {\r\n <mat-radio-button\r\n [value]=\"getRowId(row)\"\r\n [disabled]=\"!!inputConfig()?.disabled || !!inputConfig()?.readonly\"\r\n (click)=\"onRadioClick(row, $event)\"\r\n [matTooltip]=\"isRowSelected(row) ? 'Clear selection' : 'Select ' + (row['reference'] ?? 'document')\"\r\n matTooltipPosition=\"below\"\r\n [attr.aria-label]=\"isRowSelected(row) ? 'Clear selection' : 'Select ' + (row['reference'] ?? 'document')\">\r\n </mat-radio-button>\r\n } @else {\r\n <span class=\"doc-picker-cell-value doc-picker-cell-text\"\r\n [class.doc-picker-cell-selected]=\"isRowSelected(row)\"\r\n [matTooltip]=\"row[col.formControlName] | formatData:col.type\"\r\n matTooltipPosition=\"above\">\r\n {{ row[col.formControlName] | formatData:col.type }}\r\n </span>\r\n }\r\n </td>\r\n </ng-container>\r\n }\r\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns; sticky: true\"></tr>\r\n <tr mat-row class=\"doc-picker-row\" *matRowDef=\"let row; columns: displayedColumns;\"\r\n [class.doc-picker-row-selected]=\"isRowSelected(row)\"\r\n [attr.aria-label]=\"'Row: ' + (row['reference'] ?? 'document')\"\r\n [attr.aria-selected]=\"isRowSelected(row)\"\r\n (click)=\"onRowClick(row, $event)\"></tr>\r\n </table>\r\n </div>\r\n </mat-radio-group>\r\n }\r\n }\r\n </div>\r\n </div>\r\n @if (!inputConfig()?.disabled && !inputConfig()?.readonly && !selectedDocument) {\r\n <mat-paginator [pageSizeOptions]=\"[5, 10, 25, 50]\"\r\n [pageSize]=\"pageSizeForDisplay\"\r\n [length]=\"footerConfig ? footerConfig.totalItems : dataSource.filteredData.length\"\r\n [pageIndex]=\"pageIndexForDisplay\"\r\n (page)=\"onPageChange($event)\"\r\n showFirstLastButtons\r\n aria-label=\"Transaction list pagination\" class=\"doc-picker-paginator\"></mat-paginator>\r\n }\r\n }\r\n</mat-card>\r\n\r\n", styles: [":host{--doc-picker-radius-lg: 12px;--doc-picker-radius-sm: 8px;--doc-picker-radius-pill: 6px;--doc-picker-shadow: 0 2px 8px rgba(0, 0, 0, .08);--doc-picker-primary: var(--mat-sys-primary, #6750a4);--doc-picker-surface: var(--mat-sys-surface, #fef7ff);--doc-picker-surface-container: var(--mat-sys-surface-container, #f3edf7);--doc-picker-on-surface: var(--mat-sys-on-surface, #1c1b1f);--doc-picker-on-surface-variant: var(--mat-sys-on-surface-variant, #49454f);--doc-picker-outline: var(--mat-sys-outline, #79747e)}@media(prefers-color-scheme:dark){:host{--doc-picker-shadow: 0 1px 3px rgba(0, 0, 0, .3)}}.doc-picker-card{border-radius:var(--doc-picker-radius-lg);box-shadow:var(--doc-picker-shadow);border:1px solid color-mix(in srgb,var(--doc-picker-outline) 15%,transparent);overflow:hidden;background:var(--doc-picker-surface)}.doc-picker-header{display:flex;align-items:center;gap:.75rem;padding:0rem;background:color-mix(in srgb,var(--doc-picker-primary) 4%,transparent);border-bottom:1px solid color-mix(in srgb,var(--doc-picker-outline) 10%,transparent)}.doc-picker-header-icon{width:2.25rem;height:2.25rem;min-width:2.25rem;border-radius:var(--doc-picker-radius-sm);background:color-mix(in srgb,var(--doc-picker-primary) 12%,transparent);display:flex;align-items:center;justify-content:center;flex-shrink:0}.doc-picker-header-icon mat-icon{font-size:1.25rem;width:1.25rem;height:1.25rem;color:var(--doc-picker-primary)}.doc-picker-header-content{flex:1;min-width:0}.doc-picker-title{font-size:.9375rem;font-weight:600;letter-spacing:-.01em;color:var(--doc-picker-on-surface);margin:0;line-height:1.3}.doc-picker-subtitle{font-size:.8125rem;color:var(--doc-picker-on-surface-variant);line-height:1.35;margin:.25rem 0 0}.doc-picker-toolbar{display:flex;align-items:center;gap:.5rem;flex-shrink:0;width:100%}.doc-picker-selection-badge{flex-shrink:0;font-size:.75rem;font-weight:500;padding:.25rem .5rem;border-radius:var(--doc-picker-radius-pill);background:color-mix(in srgb,var(--doc-picker-primary) 14%,transparent);color:var(--doc-picker-primary);white-space:nowrap}.doc-picker-search{width:100%;min-width:8rem}.doc-picker-search .mat-mdc-form-field{--mdc-filled-text-field-container-color: transparent;--mdc-filled-text-field-container-shape: var(--doc-picker-radius-sm)}.doc-picker-search .mat-mdc-form-field-subscript-wrapper{display:none}.doc-picker-search input{font-size:.8125rem}.doc-picker-refresh{flex-shrink:0;min-width:fit-content;min-height:fit-content;transition:transform .15s}.doc-picker-refresh mat-icon{height:1.5rem;width:1.5rem;font-size:1.5rem;color:var(--doc-picker-primary);margin:0;padding:0;vertical-align:middle;display:inline-block;line-height:1}.doc-picker-refresh:hover{transform:rotate(90deg)}.doc-picker-loading{display:flex;justify-content:center;align-items:center;padding:1.5rem;min-height:6rem}.doc-picker-content-area{position:relative;min-height:6rem}.doc-picker-loading-overlay{position:absolute;inset:0;z-index:2;background:color-mix(in srgb,var(--doc-picker-surface) 95%,transparent);border-radius:var(--doc-picker-radius-sm)}.doc-picker-error{display:flex;flex-wrap:wrap;align-items:center;gap:.5rem;padding:.75rem 1rem;margin:.75rem 1rem;background:color-mix(in srgb,var(--mat-sys-error, #b3261e) 8%,transparent);border-radius:var(--doc-picker-radius-sm)}.doc-picker-error mat-icon{flex-shrink:0;font-size:1.25rem;width:1.25rem;height:1.25rem}.doc-picker-error-text{flex:1;font-size:.8125rem;color:var(--doc-picker-on-surface)}.doc-picker-retry{min-height:2.25rem;font-size:.8125rem;transition:all .15s}.doc-picker-retry mat-icon{margin-right:.25rem;vertical-align:middle;font-size:1rem;width:1rem;height:1rem}.doc-picker-body{padding:.75rem 1rem;display:flex;flex-direction:column;gap:.75rem}.doc-picker-helper{display:flex;align-items:flex-start;gap:.5rem;padding:.5rem .75rem;background:color-mix(in srgb,var(--doc-picker-primary) 6%,transparent);border-radius:var(--doc-picker-radius-sm);font-size:.8125rem;color:var(--doc-picker-on-surface-variant);line-height:1.4}.doc-picker-helper-icon{font-size:1.125rem;width:1.125rem;height:1.125rem;flex-shrink:0;margin-top:.125rem}.doc-picker-helper strong{color:var(--doc-picker-on-surface)}.doc-picker-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.75rem;font-size:.8125rem;color:var(--doc-picker-on-surface-variant);padding:1rem;background:var(--doc-picker-surface-container);border-radius:var(--doc-picker-radius-sm);text-align:center;margin:0}.doc-picker-empty mat-icon{font-size:1.25rem;width:1.25rem;height:1.25rem;opacity:.7}.doc-picker-table-wrapper{overflow:auto;max-height:50vh;border-radius:var(--doc-picker-radius-sm);border:1px solid color-mix(in srgb,var(--doc-picker-outline) 15%,transparent)}.doc-picker-table{width:100%;min-width:fit-content;table-layout:auto;border-collapse:collapse}.doc-picker-table .mat-mdc-header-row{background:color-mix(in srgb,var(--doc-picker-primary) 4%,transparent)}.doc-picker-table .mat-mdc-header-row{position:sticky;top:0;z-index:3;box-shadow:0 2px 4px #0000000f}.doc-picker-table .mat-mdc-header-cell{font-size:.75rem;font-weight:500;text-transform:uppercase;letter-spacing:.04em;color:var(--doc-picker-on-surface-variant);background:var(--mat-table-background-color, var(--mat-sys-surface));padding:.35rem .5rem}.doc-picker-table .mat-mdc-cell{font-size:.75rem;padding:.35rem .5rem}.doc-picker-col-icons,.doc-picker-col-actions{width:2.5rem;min-width:2.5rem;max-width:2.5rem;background:var(--mat-table-background-color, var(--mat-sys-surface))}.doc-picker-col-text{width:fit-content;min-width:4rem;max-width:18rem}.doc-picker-col-numeric{width:min-content;min-width:4rem}.doc-picker-col-icons,.doc-picker-col-actions{text-align:center}.doc-picker-table th.doc-picker-col-actions,.doc-picker-table td.doc-picker-col-actions{background:var(--mat-table-background-color, var(--mat-sys-surface))!important;box-shadow:-4px 0 8px #0000000f}.doc-picker-col-actions .mat-mdc-checkbox,.doc-picker-col-actions .mat-mdc-radio-button{--mdc-checkbox-state-layer-size: 2rem}.doc-picker-radio-group{display:block}.doc-picker-row-icon{font-size:1.125rem!important;width:1.125rem!important;height:1.125rem!important;color:var(--doc-picker-primary)}.doc-picker-cell-value{transition:color .15s}.doc-picker-cell-text{display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}.doc-picker-cell-selected{color:var(--doc-picker-primary);font-weight:500}.doc-picker-row{cursor:pointer;transition:background-color .15s}.doc-picker-row:hover{background:color-mix(in srgb,var(--doc-picker-primary) 6%,transparent)}.doc-picker-row-selected{background:color-mix(in srgb,var(--doc-picker-primary) 12%,transparent)}.doc-picker-row-selected:hover{background:color-mix(in srgb,var(--doc-picker-primary) 14%,transparent)}.doc-picker-paginator{background:var(--doc-picker-surface);border-top:1px solid color-mix(in srgb,var(--doc-picker-outline) 10%,transparent)}.doc-picker-paginator .mat-mdc-paginator-container{padding:.5rem 1rem;font-size:.8125rem}.text-right-align{text-align:right}\n"] }]
675
+ }], ctorParameters: () => [], propDecorators: { formBuilderFunctions: [{ type: i0.Input, args: [{ isSignal: true, alias: "formBuilderFunctions", required: false }] }], searchPlaceholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchPlaceholder", required: false }] }], emptyMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyMessage", required: false }] }], inputConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputConfig", required: false }] }], sort: [{ type: i0.ViewChild, args: [i0.forwardRef(() => MatSort), { isSignal: true }] }], paginator: [{ type: i0.ViewChild, args: [i0.forwardRef(() => MatPaginator), { isSignal: true }] }] } });
676
+
677
+ /** Wraps a reactive document-picker control inside a `mat-form-field`. */
678
+ class DocumentPickerComponent {
679
+ constructor() {
680
+ this.inputConfig = input.required(...(ngDevMode ? [{ debugName: "inputConfig" }] : /* istanbul ignore next */ []));
681
+ this.formGroup = input.required(...(ngDevMode ? [{ debugName: "formGroup" }] : /* istanbul ignore next */ []));
682
+ this.editorMode = input(false, ...(ngDevMode ? [{ debugName: "editorMode" }] : /* istanbul ignore next */ []));
683
+ this.formBuilderFunctions = input(undefined, ...(ngDevMode ? [{ debugName: "formBuilderFunctions" }] : /* istanbul ignore next */ []));
684
+ this.reload = output();
685
+ this.errorMessage = computed(() => getInputErrorMessage(this.inputConfig(), this.formGroup()), ...(ngDevMode ? [{ debugName: "errorMessage" }] : /* istanbul ignore next */ []));
686
+ }
687
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: DocumentPickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
688
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: DocumentPickerComponent, isStandalone: true, selector: "lib-document-picker", inputs: { inputConfig: { classPropertyName: "inputConfig", publicName: "inputConfig", isSignal: true, isRequired: true, transformFunction: null }, formGroup: { classPropertyName: "formGroup", publicName: "formGroup", isSignal: true, isRequired: true, transformFunction: null }, editorMode: { classPropertyName: "editorMode", publicName: "editorMode", isSignal: true, isRequired: false, transformFunction: null }, formBuilderFunctions: { classPropertyName: "formBuilderFunctions", publicName: "formBuilderFunctions", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { reload: "reload" }, ngImport: i0, template: "<form [formGroup]=\"formGroup()\">\r\n @if (inputConfig(); as inputConfig) {\r\n <mat-form-field [appearance]=\"inputConfig.appearance || 'fill'\" subscriptSizing=\"dynamic\">\r\n <mat-label>\r\n {{ inputConfig.label }}\r\n <lib-t-form-input-status [inputConfig]=\"inputConfig\"></lib-t-form-input-status>\r\n </mat-label>\r\n\r\n <lib-document-picker-reactive-input\r\n [disabled]=\"!!inputConfig.disabled\"\r\n [inputConfig]=\"inputConfig\"\r\n [formBuilderFunctions]=\"formBuilderFunctions()\"\r\n [required]=\"inputConfig.required\"\r\n [formControlName]=\"inputConfig.id\"\r\n ></lib-document-picker-reactive-input>\r\n\r\n @if (inputConfig.hintLabel || inputConfig.temporaryHint) {\r\n <mat-hint class=\"inputHint\">\r\n {{ inputConfig.temporaryHint || inputConfig.hintLabel }}\r\n </mat-hint>\r\n }\r\n\r\n @if (!!errorMessage()) {\r\n <mat-error class=\"oneLineTextEllipsis\" matTooltipClass=\"errorToolTip\">{{ errorMessage() }}</mat-error>\r\n }\r\n\r\n @if (inputConfig.prefixIcon) {\r\n <mat-icon matPrefix>{{ inputConfig.prefixIcon }}</mat-icon>\r\n }\r\n\r\n @if (inputConfig.canReload?.canReload) {\r\n <button\r\n mat-icon-button\r\n style=\"margin-right: 4px;\"\r\n matTooltip=\"Click to refresh this field.\"\r\n class=\"input-sync-button\"\r\n (click)=\"inputConfig.canReload.emit()\"\r\n matSuffix\r\n >\r\n <mat-icon style=\"color: var(--mat-sys-primary)\">sync</mat-icon>\r\n </button>\r\n }\r\n\r\n @if (inputConfig.suffixIcon && inputConfig.id !== 'password') {\r\n <mat-icon matSuffix>{{ inputConfig.suffixIcon }}</mat-icon>\r\n }\r\n\r\n @if (inputConfig.prefixText) {\r\n <span matPrefix style=\"top: 0\">{{ inputConfig.prefixText }}</span>\r\n }\r\n @if (inputConfig.suffixText) {\r\n <span matSuffix style=\"padding-left: 5px\">{{ inputConfig.suffixText }}</span>\r\n }\r\n\r\n @if (inputConfig.maxLength && formGroup()) {\r\n <mat-hint align=\"end\">\r\n {{ (formGroup().controls[inputConfig.id]?.value?.length || 0) + '/' + inputConfig.maxLength }}\r\n </mat-hint>\r\n }\r\n </mat-form-field>\r\n }\r\n</form>\r\n", styles: ["mat-form-field{width:100%}mat-form-field .input-sync-button{display:none}mat-form-field:hover .input-sync-button{display:inline-block}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { 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.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { 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: 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: "directive", type: i2.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i2.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i2.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i5.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: DocumentPickerReactiveInputComponent, selector: "lib-document-picker-reactive-input", inputs: ["formBuilderFunctions", "searchPlaceholder", "emptyMessage", "inputConfig"] }, { kind: "component", type: TFormInputStatusComponent, selector: "lib-t-form-input-status", inputs: ["inputConfig"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
689
+ }
690
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: DocumentPickerComponent, decorators: [{
691
+ type: Component,
692
+ args: [{ selector: 'lib-document-picker', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
693
+ ReactiveFormsModule,
694
+ MatFormFieldModule,
695
+ MatIconModule,
696
+ MatButtonModule,
697
+ MatTooltipModule,
698
+ DocumentPickerReactiveInputComponent,
699
+ TFormInputStatusComponent,
700
+ ], template: "<form [formGroup]=\"formGroup()\">\r\n @if (inputConfig(); as inputConfig) {\r\n <mat-form-field [appearance]=\"inputConfig.appearance || 'fill'\" subscriptSizing=\"dynamic\">\r\n <mat-label>\r\n {{ inputConfig.label }}\r\n <lib-t-form-input-status [inputConfig]=\"inputConfig\"></lib-t-form-input-status>\r\n </mat-label>\r\n\r\n <lib-document-picker-reactive-input\r\n [disabled]=\"!!inputConfig.disabled\"\r\n [inputConfig]=\"inputConfig\"\r\n [formBuilderFunctions]=\"formBuilderFunctions()\"\r\n [required]=\"inputConfig.required\"\r\n [formControlName]=\"inputConfig.id\"\r\n ></lib-document-picker-reactive-input>\r\n\r\n @if (inputConfig.hintLabel || inputConfig.temporaryHint) {\r\n <mat-hint class=\"inputHint\">\r\n {{ inputConfig.temporaryHint || inputConfig.hintLabel }}\r\n </mat-hint>\r\n }\r\n\r\n @if (!!errorMessage()) {\r\n <mat-error class=\"oneLineTextEllipsis\" matTooltipClass=\"errorToolTip\">{{ errorMessage() }}</mat-error>\r\n }\r\n\r\n @if (inputConfig.prefixIcon) {\r\n <mat-icon matPrefix>{{ inputConfig.prefixIcon }}</mat-icon>\r\n }\r\n\r\n @if (inputConfig.canReload?.canReload) {\r\n <button\r\n mat-icon-button\r\n style=\"margin-right: 4px;\"\r\n matTooltip=\"Click to refresh this field.\"\r\n class=\"input-sync-button\"\r\n (click)=\"inputConfig.canReload.emit()\"\r\n matSuffix\r\n >\r\n <mat-icon style=\"color: var(--mat-sys-primary)\">sync</mat-icon>\r\n </button>\r\n }\r\n\r\n @if (inputConfig.suffixIcon && inputConfig.id !== 'password') {\r\n <mat-icon matSuffix>{{ inputConfig.suffixIcon }}</mat-icon>\r\n }\r\n\r\n @if (inputConfig.prefixText) {\r\n <span matPrefix style=\"top: 0\">{{ inputConfig.prefixText }}</span>\r\n }\r\n @if (inputConfig.suffixText) {\r\n <span matSuffix style=\"padding-left: 5px\">{{ inputConfig.suffixText }}</span>\r\n }\r\n\r\n @if (inputConfig.maxLength && formGroup()) {\r\n <mat-hint align=\"end\">\r\n {{ (formGroup().controls[inputConfig.id]?.value?.length || 0) + '/' + inputConfig.maxLength }}\r\n </mat-hint>\r\n }\r\n </mat-form-field>\r\n }\r\n</form>\r\n", styles: ["mat-form-field{width:100%}mat-form-field .input-sync-button{display:none}mat-form-field:hover .input-sync-button{display:inline-block}\n"] }]
701
+ }], propDecorators: { inputConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputConfig", required: true }] }], formGroup: [{ type: i0.Input, args: [{ isSignal: true, alias: "formGroup", required: true }] }], editorMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "editorMode", required: false }] }], formBuilderFunctions: [{ type: i0.Input, args: [{ isSignal: true, alias: "formBuilderFunctions", required: false }] }], reload: [{ type: i0.Output, args: ["reload"] }] } });
702
+
703
+ export { DocumentPickerComponent };
704
+ //# sourceMappingURL=ngx-t-forms-document-picker.component-qObjcqhE.mjs.map