ngx-t-forms 2.0.29 → 2.0.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (161) hide show
  1. package/fesm2022/ngx-t-forms-auto-complete-input-element.component-DCKuXHAW.mjs +104 -0
  2. package/fesm2022/ngx-t-forms-auto-complete-input-element.component-DCKuXHAW.mjs.map +1 -0
  3. package/fesm2022/ngx-t-forms-basic-input-input-element.component-Ce4ipSUc.mjs +85 -0
  4. package/fesm2022/ngx-t-forms-basic-input-input-element.component-Ce4ipSUc.mjs.map +1 -0
  5. package/fesm2022/ngx-t-forms-calculated-field-rules.component-C5TPddVe.mjs +643 -0
  6. package/fesm2022/ngx-t-forms-calculated-field-rules.component-C5TPddVe.mjs.map +1 -0
  7. package/fesm2022/ngx-t-forms-chip-options-creator-editor.component-CICQaqz6.mjs +97 -0
  8. package/fesm2022/ngx-t-forms-chip-options-creator-editor.component-CICQaqz6.mjs.map +1 -0
  9. package/fesm2022/ngx-t-forms-config-mscoa-additional-inputs.component-CzisLSIP.mjs +195 -0
  10. package/fesm2022/ngx-t-forms-config-mscoa-additional-inputs.component-CzisLSIP.mjs.map +1 -0
  11. package/fesm2022/ngx-t-forms-data-source-picker.component-Dzz_o6fJ.mjs +261 -0
  12. package/fesm2022/ngx-t-forms-data-source-picker.component-Dzz_o6fJ.mjs.map +1 -0
  13. package/fesm2022/ngx-t-forms-date-picker-input-element.component-CYUbVyzP.mjs +85 -0
  14. package/fesm2022/ngx-t-forms-date-picker-input-element.component-CYUbVyzP.mjs.map +1 -0
  15. package/fesm2022/ngx-t-forms-date-range-picker-input-element.component-CmoquQGV.mjs +156 -0
  16. package/fesm2022/ngx-t-forms-date-range-picker-input-element.component-CmoquQGV.mjs.map +1 -0
  17. package/fesm2022/ngx-t-forms-document-list-label-config-editor.component-CLUOXreG.mjs +368 -0
  18. package/fesm2022/ngx-t-forms-document-list-label-config-editor.component-CLUOXreG.mjs.map +1 -0
  19. package/fesm2022/ngx-t-forms-document-picker.component-qObjcqhE.mjs +704 -0
  20. package/fesm2022/ngx-t-forms-document-picker.component-qObjcqhE.mjs.map +1 -0
  21. package/fesm2022/ngx-t-forms-editor-input-element.component-BLXlfb6F.mjs +294 -0
  22. package/fesm2022/ngx-t-forms-editor-input-element.component-BLXlfb6F.mjs.map +1 -0
  23. package/fesm2022/ngx-t-forms-editor-js-input.component-BQL0AH7H.mjs +240 -0
  24. package/fesm2022/ngx-t-forms-editor-js-input.component-BQL0AH7H.mjs.map +1 -0
  25. package/fesm2022/ngx-t-forms-file-upload-input-element.component-C7mMeEjF.mjs +205 -0
  26. package/fesm2022/ngx-t-forms-file-upload-input-element.component-C7mMeEjF.mjs.map +1 -0
  27. package/fesm2022/ngx-t-forms-form-input-selector.component-C9u8zq9B.mjs +86 -0
  28. package/fesm2022/ngx-t-forms-form-input-selector.component-C9u8zq9B.mjs.map +1 -0
  29. package/fesm2022/ngx-t-forms-form-json-view.component-856Hx1Bg.mjs +22 -0
  30. package/fesm2022/ngx-t-forms-form-json-view.component-856Hx1Bg.mjs.map +1 -0
  31. package/fesm2022/ngx-t-forms-form-payload-projection.component-CDkTuX9S.mjs +179 -0
  32. package/fesm2022/ngx-t-forms-form-payload-projection.component-CDkTuX9S.mjs.map +1 -0
  33. package/fesm2022/ngx-t-forms-form-section-stepper.component-Bs50-nEB.mjs +319 -0
  34. package/fesm2022/ngx-t-forms-form-section-stepper.component-Bs50-nEB.mjs.map +1 -0
  35. package/fesm2022/ngx-t-forms-forms-builder-menu.component-qrhM0jGL.mjs +379 -0
  36. package/fesm2022/ngx-t-forms-forms-builder-menu.component-qrhM0jGL.mjs.map +1 -0
  37. package/fesm2022/ngx-t-forms-geo-location.component-Bosp1UzR.mjs +124 -0
  38. package/fesm2022/ngx-t-forms-geo-location.component-Bosp1UzR.mjs.map +1 -0
  39. package/fesm2022/ngx-t-forms-getInputIcon-B4ADgevZ.mjs +31 -0
  40. package/fesm2022/ngx-t-forms-getInputIcon-B4ADgevZ.mjs.map +1 -0
  41. package/fesm2022/ngx-t-forms-image-capture-input-element.component-C1g7Z0cK.mjs +180 -0
  42. package/fesm2022/ngx-t-forms-image-capture-input-element.component-C1g7Z0cK.mjs.map +1 -0
  43. package/fesm2022/ngx-t-forms-index-dDSobs6A.mjs +2 -0
  44. package/fesm2022/ngx-t-forms-index-dDSobs6A.mjs.map +1 -0
  45. package/fesm2022/ngx-t-forms-input-custom.component-BkbHFAyR.mjs +105 -0
  46. package/fesm2022/ngx-t-forms-input-custom.component-BkbHFAyR.mjs.map +1 -0
  47. package/fesm2022/ngx-t-forms-input-editor.component-BPUOM9kQ.mjs +181 -0
  48. package/fesm2022/ngx-t-forms-input-editor.component-BPUOM9kQ.mjs.map +1 -0
  49. package/fesm2022/{ngx-t-forms-map-mat-options-keys-CbdW82su.mjs → ngx-t-forms-map-mat-options-keys-B6hJ7Io5.mjs} +12 -14
  50. package/fesm2022/ngx-t-forms-map-mat-options-keys-B6hJ7Io5.mjs.map +1 -0
  51. package/fesm2022/ngx-t-forms-mat-chip-list-editor.component-c7uZT1sr.mjs +66 -0
  52. package/fesm2022/ngx-t-forms-mat-chip-list-editor.component-c7uZT1sr.mjs.map +1 -0
  53. package/fesm2022/ngx-t-forms-mat-slider-editor.component-CTSBrM-j.mjs +211 -0
  54. package/fesm2022/ngx-t-forms-mat-slider-editor.component-CTSBrM-j.mjs.map +1 -0
  55. package/fesm2022/ngx-t-forms-mat-slider-toggle-editor.component-CcYiwx-8.mjs +165 -0
  56. package/fesm2022/ngx-t-forms-mat-slider-toggle-editor.component-CcYiwx-8.mjs.map +1 -0
  57. package/fesm2022/ngx-t-forms-missing-form-configs.component-DrnH8qdG.mjs +38 -0
  58. package/fesm2022/ngx-t-forms-missing-form-configs.component-DrnH8qdG.mjs.map +1 -0
  59. package/fesm2022/ngx-t-forms-mscoa-chart-toolbar.component-C_abEBQ5.mjs +38 -0
  60. package/fesm2022/ngx-t-forms-mscoa-chart-toolbar.component-C_abEBQ5.mjs.map +1 -0
  61. package/fesm2022/ngx-t-forms-mscoa-error-display.component-99DpVSy7.mjs +126 -0
  62. package/fesm2022/ngx-t-forms-mscoa-error-display.component-99DpVSy7.mjs.map +1 -0
  63. package/fesm2022/ngx-t-forms-mscoa-segment-config.component-C0qsMfsq.mjs +336 -0
  64. package/fesm2022/ngx-t-forms-mscoa-segment-config.component-C0qsMfsq.mjs.map +1 -0
  65. package/fesm2022/ngx-t-forms-mscoa-temporary-hint.component-B1Z-IXSL.mjs +74 -0
  66. package/fesm2022/ngx-t-forms-mscoa-temporary-hint.component-B1Z-IXSL.mjs.map +1 -0
  67. package/fesm2022/ngx-t-forms-multiple-input-input-element.component-C7y1OGPx.mjs +905 -0
  68. package/fesm2022/ngx-t-forms-multiple-input-input-element.component-C7y1OGPx.mjs.map +1 -0
  69. package/fesm2022/ngx-t-forms-ngx-t-forms-u_kigDid.mjs +19461 -0
  70. package/fesm2022/ngx-t-forms-ngx-t-forms-u_kigDid.mjs.map +1 -0
  71. package/fesm2022/ngx-t-forms-paginated-selection-table-AQZSMmhr.mjs +555 -0
  72. package/fesm2022/ngx-t-forms-paginated-selection-table-AQZSMmhr.mjs.map +1 -0
  73. package/fesm2022/ngx-t-forms-pipeline-generator.component-DmNSc5aw.mjs +748 -0
  74. package/fesm2022/ngx-t-forms-pipeline-generator.component-DmNSc5aw.mjs.map +1 -0
  75. package/fesm2022/ngx-t-forms-record-list-manager.component-CUMMvMch.mjs +358 -0
  76. package/fesm2022/ngx-t-forms-record-list-manager.component-CUMMvMch.mjs.map +1 -0
  77. package/fesm2022/ngx-t-forms-required-inputs.component-Ch2yNcIS.mjs +272 -0
  78. package/fesm2022/ngx-t-forms-required-inputs.component-Ch2yNcIS.mjs.map +1 -0
  79. package/fesm2022/ngx-t-forms-rest-api-call-setup.component-C_aFtdvW.mjs +398 -0
  80. package/fesm2022/ngx-t-forms-rest-api-call-setup.component-C_aFtdvW.mjs.map +1 -0
  81. package/fesm2022/ngx-t-forms-search-field.component-B2ZO7lqO.mjs +38 -0
  82. package/fesm2022/ngx-t-forms-search-field.component-B2ZO7lqO.mjs.map +1 -0
  83. package/fesm2022/ngx-t-forms-section-report.component-BxOhR6C0.mjs +98 -0
  84. package/fesm2022/ngx-t-forms-section-report.component-BxOhR6C0.mjs.map +1 -0
  85. package/fesm2022/ngx-t-forms-select-input-element.component-DbgZdNoe.mjs +150 -0
  86. package/fesm2022/ngx-t-forms-select-input-element.component-DbgZdNoe.mjs.map +1 -0
  87. package/fesm2022/ngx-t-forms-selection-options-editor.component-Dhln81DL.mjs +169 -0
  88. package/fesm2022/ngx-t-forms-selection-options-editor.component-Dhln81DL.mjs.map +1 -0
  89. package/fesm2022/ngx-t-forms-t-workflow-picker.component-leBokXvM.mjs +204 -0
  90. package/fesm2022/ngx-t-forms-t-workflow-picker.component-leBokXvM.mjs.map +1 -0
  91. package/fesm2022/ngx-t-forms-textarea-input-element.component-BEbXJjFA.mjs +95 -0
  92. package/fesm2022/ngx-t-forms-textarea-input-element.component-BEbXJjFA.mjs.map +1 -0
  93. package/fesm2022/ngx-t-forms-toggle-input-element.component-DDErRUJd.mjs +82 -0
  94. package/fesm2022/ngx-t-forms-toggle-input-element.component-DDErRUJd.mjs.map +1 -0
  95. package/fesm2022/ngx-t-forms-validators-config.component-oGjQVGE2.mjs +733 -0
  96. package/fesm2022/ngx-t-forms-validators-config.component-oGjQVGE2.mjs.map +1 -0
  97. package/fesm2022/ngx-t-forms-workflow-adjudication.component-CtU8dECN.mjs +1303 -0
  98. package/fesm2022/ngx-t-forms-workflow-adjudication.component-CtU8dECN.mjs.map +1 -0
  99. package/fesm2022/ngx-t-forms.mjs +2 -1
  100. package/fesm2022/ngx-t-forms.mjs.map +1 -1
  101. package/package.json +20 -18
  102. package/styles/_editor-mixins.scss +62 -0
  103. package/styles/_json-editor-syntax.scss +26 -0
  104. package/styles/_signature-pad.scss +26 -0
  105. package/styles/_tokens.scss +148 -0
  106. package/types/ngx-t-forms.d.ts +1767 -621
  107. package/fesm2022/ngx-t-forms-calculated-field-rules.component-D-SBMdYg.mjs +0 -313
  108. package/fesm2022/ngx-t-forms-calculated-field-rules.component-D-SBMdYg.mjs.map +0 -1
  109. package/fesm2022/ngx-t-forms-chip-options-creator-editor.component-1cpszpPN.mjs +0 -191
  110. package/fesm2022/ngx-t-forms-chip-options-creator-editor.component-1cpszpPN.mjs.map +0 -1
  111. package/fesm2022/ngx-t-forms-config-mscoa-additional-inputs.component-DFdAVWTg.mjs +0 -207
  112. package/fesm2022/ngx-t-forms-config-mscoa-additional-inputs.component-DFdAVWTg.mjs.map +0 -1
  113. package/fesm2022/ngx-t-forms-data-source-picker.component-DxORinAD.mjs +0 -204
  114. package/fesm2022/ngx-t-forms-data-source-picker.component-DxORinAD.mjs.map +0 -1
  115. package/fesm2022/ngx-t-forms-document-list-label-config-editor.component-DcWS1txl.mjs +0 -289
  116. package/fesm2022/ngx-t-forms-document-list-label-config-editor.component-DcWS1txl.mjs.map +0 -1
  117. package/fesm2022/ngx-t-forms-form-input-selector.component-B2QEnvkq.mjs +0 -134
  118. package/fesm2022/ngx-t-forms-form-input-selector.component-B2QEnvkq.mjs.map +0 -1
  119. package/fesm2022/ngx-t-forms-form-json-view.component-DePf44w6.mjs +0 -22
  120. package/fesm2022/ngx-t-forms-form-json-view.component-DePf44w6.mjs.map +0 -1
  121. package/fesm2022/ngx-t-forms-form-section-stepper.component-BTkcSjg7.mjs +0 -270
  122. package/fesm2022/ngx-t-forms-form-section-stepper.component-BTkcSjg7.mjs.map +0 -1
  123. package/fesm2022/ngx-t-forms-forms-builder-menu.component-Wamzf_sq.mjs +0 -345
  124. package/fesm2022/ngx-t-forms-forms-builder-menu.component-Wamzf_sq.mjs.map +0 -1
  125. package/fesm2022/ngx-t-forms-input-editor.component-D4xHO76K.mjs +0 -147
  126. package/fesm2022/ngx-t-forms-input-editor.component-D4xHO76K.mjs.map +0 -1
  127. package/fesm2022/ngx-t-forms-map-mat-options-keys-CbdW82su.mjs.map +0 -1
  128. package/fesm2022/ngx-t-forms-mat-chip-list-editor.component-DmTyO9Wi.mjs +0 -105
  129. package/fesm2022/ngx-t-forms-mat-chip-list-editor.component-DmTyO9Wi.mjs.map +0 -1
  130. package/fesm2022/ngx-t-forms-mat-slider-editor.component-DZ4TenrI.mjs +0 -109
  131. package/fesm2022/ngx-t-forms-mat-slider-editor.component-DZ4TenrI.mjs.map +0 -1
  132. package/fesm2022/ngx-t-forms-mat-slider-toggle-editor.component-DPyBYE4p.mjs +0 -155
  133. package/fesm2022/ngx-t-forms-mat-slider-toggle-editor.component-DPyBYE4p.mjs.map +0 -1
  134. package/fesm2022/ngx-t-forms-missing-form-configs.component-BRmnwAK6.mjs +0 -28
  135. package/fesm2022/ngx-t-forms-missing-form-configs.component-BRmnwAK6.mjs.map +0 -1
  136. package/fesm2022/ngx-t-forms-mscoa-chart-toolbar.component-D_umeAPL.mjs +0 -43
  137. package/fesm2022/ngx-t-forms-mscoa-chart-toolbar.component-D_umeAPL.mjs.map +0 -1
  138. package/fesm2022/ngx-t-forms-mscoa-error-display.component-CSX2NCNU.mjs +0 -116
  139. package/fesm2022/ngx-t-forms-mscoa-error-display.component-CSX2NCNU.mjs.map +0 -1
  140. package/fesm2022/ngx-t-forms-mscoa-segment-config.component-B6IF8kGg.mjs +0 -296
  141. package/fesm2022/ngx-t-forms-mscoa-segment-config.component-B6IF8kGg.mjs.map +0 -1
  142. package/fesm2022/ngx-t-forms-mscoa-temporary-hint.component-BPkjsRmH.mjs +0 -83
  143. package/fesm2022/ngx-t-forms-mscoa-temporary-hint.component-BPkjsRmH.mjs.map +0 -1
  144. package/fesm2022/ngx-t-forms-ngx-t-forms-D9qmig6g.mjs +0 -16844
  145. package/fesm2022/ngx-t-forms-ngx-t-forms-D9qmig6g.mjs.map +0 -1
  146. package/fesm2022/ngx-t-forms-pipeline-generator.component-DBJEyCbd.mjs +0 -613
  147. package/fesm2022/ngx-t-forms-pipeline-generator.component-DBJEyCbd.mjs.map +0 -1
  148. package/fesm2022/ngx-t-forms-record-list-manager.component-Dgs9lNSr.mjs +0 -269
  149. package/fesm2022/ngx-t-forms-record-list-manager.component-Dgs9lNSr.mjs.map +0 -1
  150. package/fesm2022/ngx-t-forms-required-inputs.component-CSIJvSHq.mjs +0 -190
  151. package/fesm2022/ngx-t-forms-required-inputs.component-CSIJvSHq.mjs.map +0 -1
  152. package/fesm2022/ngx-t-forms-rest-api-call-setup.component-CY-JSkGs.mjs +0 -291
  153. package/fesm2022/ngx-t-forms-rest-api-call-setup.component-CY-JSkGs.mjs.map +0 -1
  154. package/fesm2022/ngx-t-forms-section-report.component-12-KdKT6.mjs +0 -156
  155. package/fesm2022/ngx-t-forms-section-report.component-12-KdKT6.mjs.map +0 -1
  156. package/fesm2022/ngx-t-forms-selection-options-editor.component-Be3QAG_L.mjs +0 -186
  157. package/fesm2022/ngx-t-forms-selection-options-editor.component-Be3QAG_L.mjs.map +0 -1
  158. package/fesm2022/ngx-t-forms-t-workflow-picker.component-a4f1r8gH.mjs +0 -187
  159. package/fesm2022/ngx-t-forms-t-workflow-picker.component-a4f1r8gH.mjs.map +0 -1
  160. package/fesm2022/ngx-t-forms-validators-config.component-B3j9Dmgu.mjs +0 -215
  161. package/fesm2022/ngx-t-forms-validators-config.component-B3j9Dmgu.mjs.map +0 -1
@@ -0,0 +1,398 @@
1
+ import * as i0 from '@angular/core';
2
+ import { input, output, inject, DestroyRef, signal, computed, effect, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
3
+ import { JsDataTypes, DataSources } from 'ngx-t-forms-types';
4
+ import { h as TreeComponent, i as convertPostmanFolderItemsToTree, _ as _isEqual, E as EmptyStateComponent, j as ErrorListComponent } from './ngx-t-forms-ngx-t-forms-u_kigDid.mjs';
5
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
6
+ import { HttpClient, HttpErrorResponse } from '@angular/common/http';
7
+ import { take, tap, catchError, throwError } from 'rxjs';
8
+ import * as i1 from '@angular/material/tree';
9
+ import { MatTreeModule } from '@angular/material/tree';
10
+ import * as i3 from '@angular/material/icon';
11
+ import { MatIconModule } from '@angular/material/icon';
12
+ import * as i1$1 from '@angular/material/button';
13
+ import { MatButtonModule } from '@angular/material/button';
14
+ import * as i3$1 from '@angular/material/progress-spinner';
15
+ import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
16
+ import * as i5 from '@angular/material/tooltip';
17
+ import { MatTooltipModule } from '@angular/material/tooltip';
18
+ import { S as SearchFieldComponent } from './ngx-t-forms-search-field.component-B2ZO7lqO.mjs';
19
+
20
+ /** True when an item's own name or description contains the (already-lowercased) search text. */
21
+ function itemMatches(item, searchText) {
22
+ return ((item.name?.toLowerCase().includes(searchText) ?? false) ||
23
+ (item.description?.toLowerCase().includes(searchText) ?? false));
24
+ }
25
+ /**
26
+ * Recursively prunes a folder tree to the items relevant to `searchText`.
27
+ *
28
+ * An item is kept when it matches directly (its whole subtree is then
29
+ * preserved) OR when one of its descendants matches — in which case the
30
+ * ancestor folder is preserved but its children are pruned to only the
31
+ * matching branches. This fixes the legacy defect where ancestor folders of a
32
+ * deep match were dropped (or whole sibling subtrees were retained).
33
+ */
34
+ function pruneItems(items, searchText) {
35
+ if (!items) {
36
+ return [];
37
+ }
38
+ return items.reduce((kept, item) => {
39
+ if (itemMatches(item, searchText)) {
40
+ // Direct hit: keep the item and its full subtree intact.
41
+ kept.push(item);
42
+ return kept;
43
+ }
44
+ const matchingChildren = pruneItems(item.item, searchText);
45
+ if (matchingChildren.length > 0) {
46
+ // Ancestor of a match: keep the folder but only the matching branches.
47
+ kept.push({ ...item, item: matchingChildren });
48
+ }
49
+ return kept;
50
+ }, []);
51
+ }
52
+ /**
53
+ * Filters a fetched Postman collection by a free-text search key, preserving
54
+ * the ancestor folders of every match. An empty/whitespace key returns the
55
+ * full set of top-level items unchanged.
56
+ */
57
+ function filterCollectionItems(collections, searchKey) {
58
+ const items = collections.collection.item;
59
+ const searchText = searchKey.trim().toLowerCase();
60
+ if (!searchText) {
61
+ return items;
62
+ }
63
+ return pruneItems(items, searchText);
64
+ }
65
+
66
+ /**
67
+ * Maps an HTTP method to its design-token CSS colour value.
68
+ *
69
+ * Returns a `var(--lib-forms-method-*)` reference (dark-mode safe, no hex /
70
+ * named colours) so the tree can colour-code endpoints. Unknown methods fall
71
+ * back to `currentColor`. Matching is case-insensitive.
72
+ */
73
+ function methodColor(method) {
74
+ switch (method.toUpperCase()) {
75
+ case 'GET':
76
+ return 'var(--lib-forms-method-get)';
77
+ case 'POST':
78
+ return 'var(--lib-forms-method-post)';
79
+ case 'PUT':
80
+ return 'var(--lib-forms-method-put)';
81
+ case 'PATCH':
82
+ return 'var(--lib-forms-method-patch)';
83
+ case 'DELETE':
84
+ return 'var(--lib-forms-method-delete)';
85
+ default:
86
+ return 'currentColor';
87
+ }
88
+ }
89
+
90
+ /**
91
+ * Internal Postman-collection picker used by `rest-api-call-setup`.
92
+ *
93
+ * Fetches a Postman collection over HTTP and renders it as a searchable tree of
94
+ * endpoints, emitting the selected folder item to the parent. Embedded
95
+ * component — owns only its tree content; the parent renders any field
96
+ * label / hint / errors.
97
+ */
98
+ class PostmanCollectionsComponent {
99
+ constructor() {
100
+ /** Postman API config (collection URL + key). When invalid the component shows an error. */
101
+ this.postmanCollectionConfig = input(undefined, ...(ngDevMode ? [{ debugName: "postmanCollectionConfig" }] : /* istanbul ignore next */ []));
102
+ /** Endpoint IDs currently in a loading state (rendered with a spinner in the tree). */
103
+ this.loadingEndPoints = input([], ...(ngDevMode ? [{ debugName: "loadingEndPoints" }] : /* istanbul ignore next */ []));
104
+ /** Emits when the user picks an endpoint node from the tree. */
105
+ this.nodeSelectionChanged = output();
106
+ this.#httpClient = inject(HttpClient);
107
+ this.#destroyRef = inject(DestroyRef);
108
+ /** Imperative mat-tree backing store reused from the access-rules tree. */
109
+ this.treeComponent = new TreeComponent();
110
+ /** Raw fetched collection; `undefined` until the request resolves. */
111
+ this.#collection = signal(undefined, ...(ngDevMode ? [{ debugName: "#collection" }] : /* istanbul ignore next */ []));
112
+ /** Current search text, two-way bound to the search field. */
113
+ this.searchKey = signal('', ...(ngDevMode ? [{ debugName: "searchKey" }] : /* istanbul ignore next */ []));
114
+ /** Request-in-flight flag. */
115
+ this.loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
116
+ /** Last error (invalid config or HTTP failure); `undefined` when healthy. */
117
+ this.error = signal(undefined, ...(ngDevMode ? [{ debugName: "error" }] : /* istanbul ignore next */ []));
118
+ /** Folder items after applying the current search, ancestor-folders preserved. */
119
+ this.filteredItems = computed(() => {
120
+ const collection = this.#collection();
121
+ if (!collection) {
122
+ return [];
123
+ }
124
+ return filterCollectionItems(collection, this.searchKey());
125
+ }, ...(ngDevMode ? [{ debugName: "filteredItems" }] : /* istanbul ignore next */ []));
126
+ /** Tree nodes derived from {@link filteredItems}. */
127
+ this.#treeData = computed(() => convertPostmanFolderItemsToTree(this.filteredItems()), ...(ngDevMode ? [{ debugName: "#treeData" }] : /* istanbul ignore next */ []));
128
+ /** True once a collection is loaded but the current search yields nothing. */
129
+ this.isEmpty = computed(() => Boolean(this.#collection()) && this.#treeData().length === 0, ...(ngDevMode ? [{ debugName: "isEmpty" }] : /* istanbul ignore next */ []));
130
+ /** Cache for {@link getNodeLines} so identical levels reuse one array. */
131
+ this.#nodeLinesCache = new Map();
132
+ /** Push derived tree data into the imperative mat-tree data source. */
133
+ this.syncTree = effect(() => {
134
+ this.treeComponent.assignDataSourceData(this.#treeData());
135
+ }, ...(ngDevMode ? [{ debugName: "syncTree" }] : /* istanbul ignore next */ []));
136
+ this.#hasLoadedOnce = false;
137
+ /** Fetch (or re-fetch) the collection only when the config input's content actually changes. */
138
+ this.loadOnConfigChange = effect(() => {
139
+ const config = this.postmanCollectionConfig();
140
+ if (this.#hasLoadedOnce && _isEqual(this.#loadedConfig, config)) {
141
+ return;
142
+ }
143
+ this.#hasLoadedOnce = true;
144
+ this.#loadedConfig = config;
145
+ this.#loadCollection(config);
146
+ }, ...(ngDevMode ? [{ debugName: "loadOnConfigChange" }] : /* istanbul ignore next */ []));
147
+ this.hasChild = (_, node) => this.treeComponent.hasChild(_, node);
148
+ }
149
+ #httpClient;
150
+ #destroyRef;
151
+ /** Raw fetched collection; `undefined` until the request resolves. */
152
+ #collection;
153
+ /** Tree nodes derived from {@link filteredItems}. */
154
+ #treeData;
155
+ /** Cache for {@link getNodeLines} so identical levels reuse one array. */
156
+ #nodeLinesCache;
157
+ /** Last config the effect acted on; guards against re-fetching when an unstable parent binding hands us a new-but-equal reference. */
158
+ #loadedConfig;
159
+ #hasLoadedOnce;
160
+ #isValidConfig(config) {
161
+ return Boolean(config?.collectionUrl) && Boolean(config?.collectionKey);
162
+ }
163
+ #loadCollection(config) {
164
+ if (!this.#isValidConfig(config)) {
165
+ this.#collection.set(undefined);
166
+ this.loading.set(false);
167
+ this.error.set(new HttpErrorResponse({ error: 'Invalid Postman Collection Config' }));
168
+ return;
169
+ }
170
+ const requestOptions = {
171
+ params: { apikey: config.collectionKey, clearSystemHeaders: true },
172
+ headers: { 'Content-Type': 'application/json' },
173
+ };
174
+ this.loading.set(true);
175
+ this.#httpClient
176
+ .get(config.collectionUrl, requestOptions)
177
+ .pipe(take(1), tap(data => {
178
+ this.#collection.set(data);
179
+ this.error.set(undefined);
180
+ this.loading.set(false);
181
+ }), catchError((err) => {
182
+ this.loading.set(false);
183
+ this.error.set(err);
184
+ return throwError(() => err);
185
+ }), takeUntilDestroyed(this.#destroyRef))
186
+ .subscribe();
187
+ }
188
+ selectNode(node) {
189
+ this.nodeSelectionChanged.emit(node);
190
+ }
191
+ methodColor(method) {
192
+ return methodColor(method);
193
+ }
194
+ isEndpointLoading(id) {
195
+ return this.loadingEndPoints().includes(id);
196
+ }
197
+ /** Memoised 1..level vertical guide-line indices for tree indentation. */
198
+ getNodeLines(level) {
199
+ const cached = this.#nodeLinesCache.get(level);
200
+ if (cached) {
201
+ return cached;
202
+ }
203
+ const lines = Array.from({ length: level }, (_, i) => i + 1);
204
+ this.#nodeLinesCache.set(level, lines);
205
+ return lines;
206
+ }
207
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: PostmanCollectionsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
208
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: PostmanCollectionsComponent, isStandalone: true, selector: "lib-postman-collections", inputs: { postmanCollectionConfig: { classPropertyName: "postmanCollectionConfig", publicName: "postmanCollectionConfig", isSignal: true, isRequired: false, transformFunction: null }, loadingEndPoints: { classPropertyName: "loadingEndPoints", publicName: "loadingEndPoints", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { nodeSelectionChanged: "nodeSelectionChanged" }, host: { classAttribute: "lib-postman-collections" }, ngImport: i0, template: "@if (loading()) {\n <div class=\"loading-container\">\n <mat-spinner diameter=\"36\"></mat-spinner>\n </div>\n} @else {\n <lib-search-field\n class=\"search\"\n placeholder=\"Search api\"\n [(value)]=\"searchKey\" />\n\n @if (error(); as err) {\n <lib-empty-state icon=\"error_outline\" [message]=\"err.message\" />\n } @else if (isEmpty()) {\n <lib-empty-state\n icon=\"search_off\"\n [message]=\"searchKey() ? 'No endpoints match your search' : 'No endpoints in this collection'\" />\n } @else {\n <mat-tree\n [dataSource]=\"treeComponent.dataSource\"\n [treeControl]=\"treeComponent.treeControl\">\n <mat-tree-node *matTreeNodeDef=\"let node\" matTreeNodePadding>\n @if (isEndpointLoading(node.value.id)) {\n <mat-spinner diameter=\"22\" class=\"loading-spinner\"></mat-spinner>\n }\n @for (line of getNodeLines(node.level); track line) {\n <div class=\"line\" [style.left.px]=\"line * 40 + 8\"></div>\n }\n @if (node.value?.request; as request) {\n <button\n mat-button\n class=\"item\"\n [disabled]=\"(!request.body?.raw && request.method === 'POST') || !request.url?.raw\"\n [matTooltip]=\"request.url?.raw || 'Invalid Postman config, missing Endpoint URL'\"\n (click)=\"selectNode(node.value)\">\n <span class=\"node-key method\" [style.color]=\"methodColor(request.method)\">\n {{ request.method }}\n </span>\n <span>{{ node.key }}</span>\n </button>\n }\n </mat-tree-node>\n\n <mat-tree-node *matTreeNodeDef=\"let node; when: hasChild\" matTreeNodePadding>\n <button\n mat-icon-button\n matTreeNodeToggle\n class=\"toggle\"\n [attr.aria-label]=\"'Toggle ' + node.key\">\n <mat-icon>\n {{ treeComponent.treeControl.isExpanded(node) ? 'expand_more' : 'chevron_right' }}\n </mat-icon>\n </button>\n <mat-icon class=\"folder-icon\">\n {{ treeComponent.treeControl.isExpanded(node) ? 'folder_open' : 'folder' }}\n </mat-icon>\n <span class=\"folder-label\">{{ node.key }}</span>\n </mat-tree-node>\n </mat-tree>\n }\n}\n", styles: [":host{display:block}.search{margin-bottom:1rem}mat-tree{background:none}:host mat-tree-node{min-height:28px;height:32px}.toggle{padding:0}.folder-icon{color:var(--lib-forms-on-surface-variant)}.folder-label{margin-left:.5rem;font-weight:500}.item{display:flex;width:100%;justify-content:left;text-align:left;font-size:small;font-weight:400;white-space:nowrap;overflow:hidden}.method{display:inline-block;width:38px;text-align:right}.line{position:absolute;height:32px;left:48px;width:1px;background:color-mix(in srgb,var(--lib-forms-outline) 40%,transparent)}.loading-container{display:flex;align-items:center;justify-content:center;height:100%;padding:2rem}\n"], dependencies: [{ kind: "ngmodule", type: MatTreeModule }, { kind: "directive", type: i1.MatTreeNodeDef, selector: "[matTreeNodeDef]", inputs: ["matTreeNodeDefWhen", "matTreeNode"] }, { kind: "directive", type: i1.MatTreeNodePadding, selector: "[matTreeNodePadding]", inputs: ["matTreeNodePadding", "matTreeNodePaddingIndent"] }, { kind: "directive", type: i1.MatTreeNodeToggle, selector: "[matTreeNodeToggle]", inputs: ["matTreeNodeToggleRecursive"] }, { kind: "component", type: i1.MatTree, selector: "mat-tree", exportAs: ["matTree"] }, { kind: "directive", type: i1.MatTreeNode, selector: "mat-tree-node", inputs: ["tabIndex", "disabled"], outputs: ["activation", "expandedChange"], exportAs: ["matTreeNode"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { 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: MatProgressSpinnerModule }, { kind: "component", type: i3$1.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { 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: SearchFieldComponent, selector: "lib-search-field", inputs: ["value", "placeholder", "resultCount"], outputs: ["valueChange"] }, { kind: "component", type: EmptyStateComponent, selector: "lib-empty-state", inputs: ["icon", "message"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
209
+ }
210
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: PostmanCollectionsComponent, decorators: [{
211
+ type: Component,
212
+ args: [{ selector: 'lib-postman-collections', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.Emulated, host: { 'class': 'lib-postman-collections' }, imports: [
213
+ MatTreeModule,
214
+ MatIconModule,
215
+ MatButtonModule,
216
+ MatProgressSpinnerModule,
217
+ MatTooltipModule,
218
+ SearchFieldComponent,
219
+ EmptyStateComponent,
220
+ ], template: "@if (loading()) {\n <div class=\"loading-container\">\n <mat-spinner diameter=\"36\"></mat-spinner>\n </div>\n} @else {\n <lib-search-field\n class=\"search\"\n placeholder=\"Search api\"\n [(value)]=\"searchKey\" />\n\n @if (error(); as err) {\n <lib-empty-state icon=\"error_outline\" [message]=\"err.message\" />\n } @else if (isEmpty()) {\n <lib-empty-state\n icon=\"search_off\"\n [message]=\"searchKey() ? 'No endpoints match your search' : 'No endpoints in this collection'\" />\n } @else {\n <mat-tree\n [dataSource]=\"treeComponent.dataSource\"\n [treeControl]=\"treeComponent.treeControl\">\n <mat-tree-node *matTreeNodeDef=\"let node\" matTreeNodePadding>\n @if (isEndpointLoading(node.value.id)) {\n <mat-spinner diameter=\"22\" class=\"loading-spinner\"></mat-spinner>\n }\n @for (line of getNodeLines(node.level); track line) {\n <div class=\"line\" [style.left.px]=\"line * 40 + 8\"></div>\n }\n @if (node.value?.request; as request) {\n <button\n mat-button\n class=\"item\"\n [disabled]=\"(!request.body?.raw && request.method === 'POST') || !request.url?.raw\"\n [matTooltip]=\"request.url?.raw || 'Invalid Postman config, missing Endpoint URL'\"\n (click)=\"selectNode(node.value)\">\n <span class=\"node-key method\" [style.color]=\"methodColor(request.method)\">\n {{ request.method }}\n </span>\n <span>{{ node.key }}</span>\n </button>\n }\n </mat-tree-node>\n\n <mat-tree-node *matTreeNodeDef=\"let node; when: hasChild\" matTreeNodePadding>\n <button\n mat-icon-button\n matTreeNodeToggle\n class=\"toggle\"\n [attr.aria-label]=\"'Toggle ' + node.key\">\n <mat-icon>\n {{ treeComponent.treeControl.isExpanded(node) ? 'expand_more' : 'chevron_right' }}\n </mat-icon>\n </button>\n <mat-icon class=\"folder-icon\">\n {{ treeComponent.treeControl.isExpanded(node) ? 'folder_open' : 'folder' }}\n </mat-icon>\n <span class=\"folder-label\">{{ node.key }}</span>\n </mat-tree-node>\n </mat-tree>\n }\n}\n", styles: [":host{display:block}.search{margin-bottom:1rem}mat-tree{background:none}:host mat-tree-node{min-height:28px;height:32px}.toggle{padding:0}.folder-icon{color:var(--lib-forms-on-surface-variant)}.folder-label{margin-left:.5rem;font-weight:500}.item{display:flex;width:100%;justify-content:left;text-align:left;font-size:small;font-weight:400;white-space:nowrap;overflow:hidden}.method{display:inline-block;width:38px;text-align:right}.line{position:absolute;height:32px;left:48px;width:1px;background:color-mix(in srgb,var(--lib-forms-outline) 40%,transparent)}.loading-container{display:flex;align-items:center;justify-content:center;height:100%;padding:2rem}\n"] }]
221
+ }], propDecorators: { postmanCollectionConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "postmanCollectionConfig", required: false }] }], loadingEndPoints: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadingEndPoints", required: false }] }], nodeSelectionChanged: [{ type: i0.Output, args: ["nodeSelectionChanged"] }] } });
222
+
223
+ let nextId = 0;
224
+ /** CSS-variable colour per HTTP method (dark-mode-safe; never a hex literal). */
225
+ const METHOD_COLOR = {
226
+ GET: 'var(--lib-forms-method-get)',
227
+ POST: 'var(--lib-forms-method-post)',
228
+ PUT: 'var(--lib-forms-method-put)',
229
+ DELETE: 'var(--lib-forms-method-delete)',
230
+ };
231
+ /** Maps a JS `typeof` string to the shared {@link JsDataTypes} enum member. */
232
+ function toJsDataType(value) {
233
+ switch (typeof value) {
234
+ case 'string':
235
+ return JsDataTypes.String;
236
+ case 'number':
237
+ return JsDataTypes.Number;
238
+ case 'bigint':
239
+ return JsDataTypes.BigInt;
240
+ case 'boolean':
241
+ return JsDataTypes.Boolean;
242
+ case 'symbol':
243
+ return JsDataTypes.Symbol;
244
+ case 'function':
245
+ return JsDataTypes.Function;
246
+ case 'object':
247
+ return JsDataTypes.Object;
248
+ default:
249
+ return JsDataTypes.Undefined;
250
+ }
251
+ }
252
+ /**
253
+ * Lets the user pick an API endpoint from a Postman collection and exposes the
254
+ * resulting {@link APIDataFetchingConfigurationInterface}. Renders one of three
255
+ * states — no collection configured, the endpoint picker, or the selected
256
+ * endpoint card — and embeds {@link PostmanCollectionsComponent} for the tree.
257
+ *
258
+ * Internal editor consumed by `t-dynamic-data-edit` and `data-source-picker`;
259
+ * the parent owns the field label, hint and validation chrome.
260
+ *
261
+ * @example
262
+ * <lib-rest-api-call-setup
263
+ * [postmanCollectionConfig]="config()"
264
+ * [value]="value()"
265
+ * [disabled]="disabled()"
266
+ * (valueChanged)="onApiConfig($event)" />
267
+ */
268
+ class RestApiCallSetupComponent {
269
+ constructor() {
270
+ this.#fallbackId = `lib-rest-api-call-setup-${nextId++}`;
271
+ /** Optional consumer-provided host id. */
272
+ this.id = input(undefined, ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
273
+ /** Postman collection that backs the picker. */
274
+ this.postmanCollectionConfig = input(undefined, ...(ngDevMode ? [{ debugName: "postmanCollectionConfig" }] : /* istanbul ignore next */ []));
275
+ /**
276
+ * Optional HTTP GET function for fetching sample responses. Retained on the
277
+ * contract for parity; this editor does not invoke it (selection is resolved
278
+ * from the Postman collection the parent already loads).
279
+ */
280
+ this.httpGetDataFunction = input(undefined, ...(ngDevMode ? [{ debugName: "httpGetDataFunction" }] : /* istanbul ignore next */ []));
281
+ /** Disables the picker and shows a lock affordance. */
282
+ this.disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
283
+ /** Current configuration value. */
284
+ this.value = input(undefined, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
285
+ /** Validation errors surfaced from the parent editor. */
286
+ this.errors = input([], ...(ngDevMode ? [{ debugName: "errors" }] : /* istanbul ignore next */ []));
287
+ /** Emits whenever the user selects a new endpoint or clears the value. */
288
+ this.valueChanged = output();
289
+ /** Endpoint IDs currently loading sample data (forwarded to the picker). */
290
+ this.loadingEndPoints = signal([], ...(ngDevMode ? [{ debugName: "loadingEndPoints" }] : /* istanbul ignore next */ []));
291
+ /** Local snapshot of the value, bridged from the `value` input. */
292
+ this.#localValue = signal(undefined, ...(ngDevMode ? [{ debugName: "#localValue" }] : /* istanbul ignore next */ []));
293
+ /** Read-only view of the active configuration for the template. */
294
+ this.currentValue = this.#localValue.asReadonly();
295
+ /** Host id: consumer-provided or a stable per-instance fallback. */
296
+ this.hostId = computed(() => this.id() ?? this.#fallbackId, ...(ngDevMode ? [{ debugName: "hostId" }] : /* istanbul ignore next */ []));
297
+ /** True once the snapshot carries a usable endpoint + method. */
298
+ this.hasValidValue = computed(() => {
299
+ const v = this.#localValue();
300
+ return Boolean(v?.httpEndPoint) && Boolean(v?.httpMethod);
301
+ }, ...(ngDevMode ? [{ debugName: "hasValidValue" }] : /* istanbul ignore next */ []));
302
+ /** Discrete UI mode driving the template's `@switch`. */
303
+ this.mode = computed(() => {
304
+ if (!this.postmanCollectionConfig())
305
+ return 'no-collection';
306
+ return this.hasValidValue() ? 'selected' : 'picker';
307
+ }, ...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []));
308
+ /** Token-based colour for the selected endpoint's HTTP method badge. */
309
+ this.methodColor = computed(() => {
310
+ const method = this.#localValue()?.httpMethod;
311
+ return method && method in METHOD_COLOR ? METHOD_COLOR[method] : 'currentColor';
312
+ }, ...(ngDevMode ? [{ debugName: "methodColor" }] : /* istanbul ignore next */ []));
313
+ /**
314
+ * Bridge the `value` input into the local mutable snapshot, de-duping with a
315
+ * deep structural compare (replaces the legacy `JSON.stringify` equality so
316
+ * key order and `undefined` no longer cause spurious resets).
317
+ */
318
+ this.valueBridge = effect(() => {
319
+ const next = this.value();
320
+ if (!_isEqual(next, this.#localValue())) {
321
+ this.#localValue.set(next);
322
+ }
323
+ }, ...(ngDevMode ? [{ debugName: "valueBridge" }] : /* istanbul ignore next */ []));
324
+ }
325
+ #fallbackId;
326
+ /** Local snapshot of the value, bridged from the `value` input. */
327
+ #localValue;
328
+ /** Maps the selected tree node into the API config and emits it. */
329
+ nodeSelectionChanged(node) {
330
+ const { id, name, request, response } = node;
331
+ if (!request || !response)
332
+ return;
333
+ let requestBody;
334
+ try {
335
+ requestBody = JSON.parse(request.body?.raw || '{}');
336
+ }
337
+ catch {
338
+ requestBody = {};
339
+ }
340
+ const isPost = request.method === 'POST';
341
+ const minimumInputRequired = isPost
342
+ ? this.#extractRequiredInputs(requestBody)
343
+ : [];
344
+ const config = {
345
+ _id: id,
346
+ name,
347
+ httpEndPoint: request.url.raw,
348
+ httpMethod: request.method,
349
+ source: DataSources.Api,
350
+ postFormData: isPost,
351
+ backEndConfig: { minimumInputRequired },
352
+ };
353
+ this.#localValue.set(config);
354
+ this.valueChanged.emit(config);
355
+ }
356
+ /**
357
+ * Clears the selection and emits a single `undefined` (the legacy double-emit
358
+ * — `undefined` then a stub `{ source }` — was removed; see FLAG).
359
+ */
360
+ clearValue() {
361
+ this.#localValue.set(undefined);
362
+ this.valueChanged.emit(undefined);
363
+ }
364
+ /**
365
+ * Derives the POST endpoint's required inputs from the request body. Top-level
366
+ * keys are primary; entries under `data` are secondary (non-primary).
367
+ */
368
+ #extractRequiredInputs(requestBody) {
369
+ const { data, ...rest } = requestBody;
370
+ const dataEntries = data && typeof data === 'object' ? { ...data } : {};
371
+ const primaryKeys = Object.entries(rest).map(([key, val]) => this.#toRequiredInput(key, val, true));
372
+ const secondaryKeys = Object.entries(dataEntries).map(([key, val]) => this.#toRequiredInput(key, val, false));
373
+ return [...primaryKeys, ...secondaryKeys];
374
+ }
375
+ #toRequiredInput(name, value, primaryKey) {
376
+ return { name, type: toJsDataType(value), primaryKey };
377
+ }
378
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: RestApiCallSetupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
379
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: RestApiCallSetupComponent, isStandalone: true, selector: "lib-rest-api-call-setup", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, postmanCollectionConfig: { classPropertyName: "postmanCollectionConfig", publicName: "postmanCollectionConfig", isSignal: true, isRequired: false, transformFunction: null }, httpGetDataFunction: { classPropertyName: "httpGetDataFunction", publicName: "httpGetDataFunction", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChanged: "valueChanged" }, host: { properties: { "id": "hostId()", "attr.data-mode": "mode()" }, classAttribute: "lib-rest-api-call-setup" }, ngImport: i0, template: "@switch (mode()) {\n @case ('no-collection') {\n <lib-empty-state\n icon=\"link_off\"\n message=\"No Postman collection configured. Add a collection id and API key to pick an endpoint.\" />\n }\n\n @case ('selected') {\n <div class=\"lib-rest-api-call-setup__card\">\n <button\n type=\"button\"\n class=\"lib-rest-api-call-setup__endpoint\"\n mat-button\n [disabled]=\"disabled()\"\n [matTooltip]=\"currentValue()?.httpEndPoint ?? ''\"\n (click)=\"clearValue()\">\n <span class=\"lib-rest-api-call-setup__method\" [style.color]=\"methodColor()\">\n {{ currentValue()?.httpMethod }}\n </span>\n <span class=\"lib-rest-api-call-setup__name\">\n {{ currentValue()?.name }}\n </span>\n <mat-icon class=\"lib-rest-api-call-setup__clear\" aria-hidden=\"true\">close</mat-icon>\n </button>\n </div>\n }\n\n @case ('picker') {\n <lib-postman-collections\n class=\"lib-rest-api-call-setup__picker\"\n [class.lib-rest-api-call-setup__picker--disabled]=\"disabled()\"\n [postmanCollectionConfig]=\"postmanCollectionConfig()!\"\n [loadingEndPoints]=\"loadingEndPoints()\"\n (nodeSelectionChanged)=\"nodeSelectionChanged($event)\" />\n }\n}\n\n@if (disabled()) {\n <p class=\"lib-rest-api-call-setup__lock\">\n <mat-icon aria-hidden=\"true\">lock</mat-icon>\n <span>This endpoint is locked and cannot be changed.</span>\n </p>\n}\n\n<lib-error-list [errors]=\"errors()\" />\n", styles: [":host{display:flex;flex-direction:column;gap:1.5rem}.lib-rest-api-call-setup__card{background:var(--lib-forms-surface);border:1px solid color-mix(in srgb,var(--lib-forms-outline) 15%,transparent);border-radius:var(--lib-forms-radius-lg, 12px);box-shadow:var(--lib-forms-shadow-resting);padding:.5rem}.lib-rest-api-call-setup__endpoint{display:flex;align-items:center;gap:.75rem;width:100%;justify-content:flex-start;padding:.5rem .75rem;font-weight:400;text-align:left;color:var(--lib-forms-on-surface);overflow:hidden}.lib-rest-api-call-setup__method{flex:0 0 auto;font-size:.625rem;font-weight:600;letter-spacing:.08em;text-transform:uppercase}.lib-rest-api-call-setup__name{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--lib-forms-on-surface)}.lib-rest-api-call-setup__clear{flex:0 0 auto;color:var(--lib-forms-on-surface-variant)}.lib-rest-api-call-setup__picker--disabled{opacity:.55;pointer-events:none}.lib-rest-api-call-setup__lock{display:flex;align-items:center;gap:.5rem;margin:0;font-size:.8125rem;line-height:1.4;color:var(--lib-forms-on-surface-variant)}\n"], dependencies: [{ kind: "component", type: PostmanCollectionsComponent, selector: "lib-postman-collections", inputs: ["postmanCollectionConfig", "loadingEndPoints"], outputs: ["nodeSelectionChanged"] }, { kind: "component", type: EmptyStateComponent, selector: "lib-empty-state", inputs: ["icon", "message"] }, { kind: "component", type: ErrorListComponent, selector: "lib-error-list", inputs: ["errors"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1$1.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i5.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
380
+ }
381
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: RestApiCallSetupComponent, decorators: [{
382
+ type: Component,
383
+ args: [{ selector: 'lib-rest-api-call-setup', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.Emulated, imports: [
384
+ PostmanCollectionsComponent,
385
+ EmptyStateComponent,
386
+ ErrorListComponent,
387
+ MatButtonModule,
388
+ MatIconModule,
389
+ MatTooltipModule,
390
+ ], host: {
391
+ 'class': 'lib-rest-api-call-setup',
392
+ '[id]': 'hostId()',
393
+ '[attr.data-mode]': 'mode()',
394
+ }, template: "@switch (mode()) {\n @case ('no-collection') {\n <lib-empty-state\n icon=\"link_off\"\n message=\"No Postman collection configured. Add a collection id and API key to pick an endpoint.\" />\n }\n\n @case ('selected') {\n <div class=\"lib-rest-api-call-setup__card\">\n <button\n type=\"button\"\n class=\"lib-rest-api-call-setup__endpoint\"\n mat-button\n [disabled]=\"disabled()\"\n [matTooltip]=\"currentValue()?.httpEndPoint ?? ''\"\n (click)=\"clearValue()\">\n <span class=\"lib-rest-api-call-setup__method\" [style.color]=\"methodColor()\">\n {{ currentValue()?.httpMethod }}\n </span>\n <span class=\"lib-rest-api-call-setup__name\">\n {{ currentValue()?.name }}\n </span>\n <mat-icon class=\"lib-rest-api-call-setup__clear\" aria-hidden=\"true\">close</mat-icon>\n </button>\n </div>\n }\n\n @case ('picker') {\n <lib-postman-collections\n class=\"lib-rest-api-call-setup__picker\"\n [class.lib-rest-api-call-setup__picker--disabled]=\"disabled()\"\n [postmanCollectionConfig]=\"postmanCollectionConfig()!\"\n [loadingEndPoints]=\"loadingEndPoints()\"\n (nodeSelectionChanged)=\"nodeSelectionChanged($event)\" />\n }\n}\n\n@if (disabled()) {\n <p class=\"lib-rest-api-call-setup__lock\">\n <mat-icon aria-hidden=\"true\">lock</mat-icon>\n <span>This endpoint is locked and cannot be changed.</span>\n </p>\n}\n\n<lib-error-list [errors]=\"errors()\" />\n", styles: [":host{display:flex;flex-direction:column;gap:1.5rem}.lib-rest-api-call-setup__card{background:var(--lib-forms-surface);border:1px solid color-mix(in srgb,var(--lib-forms-outline) 15%,transparent);border-radius:var(--lib-forms-radius-lg, 12px);box-shadow:var(--lib-forms-shadow-resting);padding:.5rem}.lib-rest-api-call-setup__endpoint{display:flex;align-items:center;gap:.75rem;width:100%;justify-content:flex-start;padding:.5rem .75rem;font-weight:400;text-align:left;color:var(--lib-forms-on-surface);overflow:hidden}.lib-rest-api-call-setup__method{flex:0 0 auto;font-size:.625rem;font-weight:600;letter-spacing:.08em;text-transform:uppercase}.lib-rest-api-call-setup__name{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--lib-forms-on-surface)}.lib-rest-api-call-setup__clear{flex:0 0 auto;color:var(--lib-forms-on-surface-variant)}.lib-rest-api-call-setup__picker--disabled{opacity:.55;pointer-events:none}.lib-rest-api-call-setup__lock{display:flex;align-items:center;gap:.5rem;margin:0;font-size:.8125rem;line-height:1.4;color:var(--lib-forms-on-surface-variant)}\n"] }]
395
+ }], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], postmanCollectionConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "postmanCollectionConfig", required: false }] }], httpGetDataFunction: [{ type: i0.Input, args: [{ isSignal: true, alias: "httpGetDataFunction", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], errors: [{ type: i0.Input, args: [{ isSignal: true, alias: "errors", required: false }] }], valueChanged: [{ type: i0.Output, args: ["valueChanged"] }] } });
396
+
397
+ export { RestApiCallSetupComponent };
398
+ //# sourceMappingURL=ngx-t-forms-rest-api-call-setup.component-C_aFtdvW.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ngx-t-forms-rest-api-call-setup.component-C_aFtdvW.mjs","sources":["../../../projects/ngx-t-forms/src/lib/components/t-dynamic-data-edit/elements/postman-collections/functions/filterCollectionItems.ts","../../../projects/ngx-t-forms/src/lib/components/t-dynamic-data-edit/elements/postman-collections/functions/methodColors.ts","../../../projects/ngx-t-forms/src/lib/components/t-dynamic-data-edit/elements/postman-collections/postman-collections.component.ts","../../../projects/ngx-t-forms/src/lib/components/t-dynamic-data-edit/elements/postman-collections/postman-collections.component.html","../../../projects/ngx-t-forms/src/lib/components/t-dynamic-data-edit/elements/rest-api-call-setup/rest-api-call-setup.component.ts","../../../projects/ngx-t-forms/src/lib/components/t-dynamic-data-edit/elements/rest-api-call-setup/rest-api-call-setup.component.html"],"sourcesContent":["import type { IFolderItem, IGetPostmanCollections } from 'ngx-t-forms-types';\n\n/** True when an item's own name or description contains the (already-lowercased) search text. */\nfunction itemMatches(item: IFolderItem, searchText: string): boolean {\n return (\n (item.name?.toLowerCase().includes(searchText) ?? false) ||\n (item.description?.toLowerCase().includes(searchText) ?? false)\n );\n}\n\n/**\n * Recursively prunes a folder tree to the items relevant to `searchText`.\n *\n * An item is kept when it matches directly (its whole subtree is then\n * preserved) OR when one of its descendants matches — in which case the\n * ancestor folder is preserved but its children are pruned to only the\n * matching branches. This fixes the legacy defect where ancestor folders of a\n * deep match were dropped (or whole sibling subtrees were retained).\n */\nfunction pruneItems(items: IFolderItem[] | undefined, searchText: string): IFolderItem[] {\n if (!items) {\n return [];\n }\n return items.reduce<IFolderItem[]>((kept, item) => {\n if (itemMatches(item, searchText)) {\n // Direct hit: keep the item and its full subtree intact.\n kept.push(item);\n return kept;\n }\n const matchingChildren = pruneItems(item.item, searchText);\n if (matchingChildren.length > 0) {\n // Ancestor of a match: keep the folder but only the matching branches.\n kept.push({ ...item, item: matchingChildren });\n }\n return kept;\n }, []);\n}\n\n/**\n * Filters a fetched Postman collection by a free-text search key, preserving\n * the ancestor folders of every match. An empty/whitespace key returns the\n * full set of top-level items unchanged.\n */\nexport function filterCollectionItems(\n collections: IGetPostmanCollections,\n searchKey: string,\n): IFolderItem[] {\n const items = collections.collection.item;\n const searchText = searchKey.trim().toLowerCase();\n if (!searchText) {\n return items;\n }\n return pruneItems(items, searchText);\n}\n","/**\n * Maps an HTTP method to its design-token CSS colour value.\n *\n * Returns a `var(--lib-forms-method-*)` reference (dark-mode safe, no hex /\n * named colours) so the tree can colour-code endpoints. Unknown methods fall\n * back to `currentColor`. Matching is case-insensitive.\n */\nexport function methodColor(method: string): string {\n switch (method.toUpperCase()) {\n case 'GET':\n return 'var(--lib-forms-method-get)';\n case 'POST':\n return 'var(--lib-forms-method-post)';\n case 'PUT':\n return 'var(--lib-forms-method-put)';\n case 'PATCH':\n return 'var(--lib-forms-method-patch)';\n case 'DELETE':\n return 'var(--lib-forms-method-delete)';\n default:\n return 'currentColor';\n }\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n DestroyRef,\n ViewEncapsulation,\n computed,\n effect,\n inject,\n input,\n output,\n signal,\n} from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { HttpClient, HttpErrorResponse } from '@angular/common/http';\nimport { catchError, take, tap, throwError } from 'rxjs';\n\nimport { MatTreeModule } from '@angular/material/tree';\nimport { MatIconModule } from '@angular/material/icon';\nimport { MatButtonModule } from '@angular/material/button';\nimport { MatProgressSpinnerModule } from '@angular/material/progress-spinner';\nimport { MatTooltipModule } from '@angular/material/tooltip';\n\nimport type {\n FlatNode,\n IFolderItem,\n IGetPostmanCollections,\n IPostmanCollectionConfig,\n TreeNode,\n} from 'ngx-t-forms-types';\n\nimport { TreeComponent } from '../api-value-access-rules/functions/convertDataToTree';\nimport { convertPostmanFolderItemsToTree } from './functions/convertPostmanCollectionToTree';\nimport { filterCollectionItems } from './functions/filterCollectionItems';\nimport { methodColor } from './functions/methodColors';\nimport { SearchFieldComponent } from '../_shared/search-field/search-field.component';\nimport { EmptyStateComponent } from '../_shared/empty-state/empty-state.component';\nimport { _isEqual } from '../../../../shared/functions/isEqual';\n\n/**\n * Internal Postman-collection picker used by `rest-api-call-setup`.\n *\n * Fetches a Postman collection over HTTP and renders it as a searchable tree of\n * endpoints, emitting the selected folder item to the parent. Embedded\n * component — owns only its tree content; the parent renders any field\n * label / hint / errors.\n */\n@Component({\n selector: 'lib-postman-collections',\n templateUrl: './postman-collections.component.html',\n styleUrls: ['./postman-collections.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.Emulated,\n host: { 'class': 'lib-postman-collections' },\n imports: [\n MatTreeModule,\n MatIconModule,\n MatButtonModule,\n MatProgressSpinnerModule,\n MatTooltipModule,\n SearchFieldComponent,\n EmptyStateComponent,\n ],\n})\nexport class PostmanCollectionsComponent {\n /** Postman API config (collection URL + key). When invalid the component shows an error. */\n readonly postmanCollectionConfig = input<IPostmanCollectionConfig | undefined>(undefined);\n\n /** Endpoint IDs currently in a loading state (rendered with a spinner in the tree). */\n readonly loadingEndPoints = input<string[]>([]);\n\n /** Emits when the user picks an endpoint node from the tree. */\n readonly nodeSelectionChanged = output<IFolderItem>();\n\n readonly #httpClient = inject(HttpClient);\n readonly #destroyRef = inject(DestroyRef);\n\n /** Imperative mat-tree backing store reused from the access-rules tree. */\n protected readonly treeComponent = new TreeComponent();\n\n /** Raw fetched collection; `undefined` until the request resolves. */\n readonly #collection = signal<IGetPostmanCollections | undefined>(undefined);\n\n /** Current search text, two-way bound to the search field. */\n protected readonly searchKey = signal<string>('');\n\n /** Request-in-flight flag. */\n protected readonly loading = signal<boolean>(false);\n\n /** Last error (invalid config or HTTP failure); `undefined` when healthy. */\n protected readonly error = signal<HttpErrorResponse | undefined>(undefined);\n\n /** Folder items after applying the current search, ancestor-folders preserved. */\n protected readonly filteredItems = computed<IFolderItem[]>(() => {\n const collection = this.#collection();\n if (!collection) {\n return [];\n }\n return filterCollectionItems(collection, this.searchKey());\n });\n\n /** Tree nodes derived from {@link filteredItems}. */\n readonly #treeData = computed<TreeNode[]>(() =>\n convertPostmanFolderItemsToTree(this.filteredItems()),\n );\n\n /** True once a collection is loaded but the current search yields nothing. */\n protected readonly isEmpty = computed<boolean>(\n () => Boolean(this.#collection()) && this.#treeData().length === 0,\n );\n\n /** Cache for {@link getNodeLines} so identical levels reuse one array. */\n readonly #nodeLinesCache = new Map<number, readonly number[]>();\n\n /** Push derived tree data into the imperative mat-tree data source. */\n protected readonly syncTree = effect(() => {\n this.treeComponent.assignDataSourceData(this.#treeData());\n });\n\n /** Last config the effect acted on; guards against re-fetching when an unstable parent binding hands us a new-but-equal reference. */\n #loadedConfig: IPostmanCollectionConfig | undefined;\n #hasLoadedOnce = false;\n\n /** Fetch (or re-fetch) the collection only when the config input's content actually changes. */\n protected readonly loadOnConfigChange = effect(() => {\n const config = this.postmanCollectionConfig();\n if (this.#hasLoadedOnce && _isEqual(this.#loadedConfig, config)) {\n return;\n }\n this.#hasLoadedOnce = true;\n this.#loadedConfig = config;\n this.#loadCollection(config);\n });\n\n #isValidConfig(config: IPostmanCollectionConfig | undefined): config is IPostmanCollectionConfig {\n return Boolean(config?.collectionUrl) && Boolean(config?.collectionKey);\n }\n\n #loadCollection(config: IPostmanCollectionConfig | undefined): void {\n if (!this.#isValidConfig(config)) {\n this.#collection.set(undefined);\n this.loading.set(false);\n this.error.set(new HttpErrorResponse({ error: 'Invalid Postman Collection Config' }));\n return;\n }\n\n const requestOptions = {\n params: { apikey: config.collectionKey, clearSystemHeaders: true },\n headers: { 'Content-Type': 'application/json' },\n };\n\n this.loading.set(true);\n this.#httpClient\n .get<IGetPostmanCollections>(config.collectionUrl, requestOptions)\n .pipe(\n take(1),\n tap(data => {\n this.#collection.set(data);\n this.error.set(undefined);\n this.loading.set(false);\n }),\n catchError((err: HttpErrorResponse) => {\n this.loading.set(false);\n this.error.set(err);\n return throwError(() => err);\n }),\n takeUntilDestroyed(this.#destroyRef),\n )\n .subscribe();\n }\n\n protected selectNode(node: IFolderItem): void {\n this.nodeSelectionChanged.emit(node);\n }\n\n protected methodColor(method: string): string {\n return methodColor(method);\n }\n\n protected isEndpointLoading(id: string): boolean {\n return this.loadingEndPoints().includes(id);\n }\n\n protected hasChild = (_: number, node: FlatNode): boolean =>\n this.treeComponent.hasChild(_, node);\n\n /** Memoised 1..level vertical guide-line indices for tree indentation. */\n protected getNodeLines(level: number): readonly number[] {\n const cached = this.#nodeLinesCache.get(level);\n if (cached) {\n return cached;\n }\n const lines = Array.from({ length: level }, (_, i) => i + 1);\n this.#nodeLinesCache.set(level, lines);\n return lines;\n }\n}\n","@if (loading()) {\n <div class=\"loading-container\">\n <mat-spinner diameter=\"36\"></mat-spinner>\n </div>\n} @else {\n <lib-search-field\n class=\"search\"\n placeholder=\"Search api\"\n [(value)]=\"searchKey\" />\n\n @if (error(); as err) {\n <lib-empty-state icon=\"error_outline\" [message]=\"err.message\" />\n } @else if (isEmpty()) {\n <lib-empty-state\n icon=\"search_off\"\n [message]=\"searchKey() ? 'No endpoints match your search' : 'No endpoints in this collection'\" />\n } @else {\n <mat-tree\n [dataSource]=\"treeComponent.dataSource\"\n [treeControl]=\"treeComponent.treeControl\">\n <mat-tree-node *matTreeNodeDef=\"let node\" matTreeNodePadding>\n @if (isEndpointLoading(node.value.id)) {\n <mat-spinner diameter=\"22\" class=\"loading-spinner\"></mat-spinner>\n }\n @for (line of getNodeLines(node.level); track line) {\n <div class=\"line\" [style.left.px]=\"line * 40 + 8\"></div>\n }\n @if (node.value?.request; as request) {\n <button\n mat-button\n class=\"item\"\n [disabled]=\"(!request.body?.raw && request.method === 'POST') || !request.url?.raw\"\n [matTooltip]=\"request.url?.raw || 'Invalid Postman config, missing Endpoint URL'\"\n (click)=\"selectNode(node.value)\">\n <span class=\"node-key method\" [style.color]=\"methodColor(request.method)\">\n {{ request.method }}\n </span>\n <span>{{ node.key }}</span>\n </button>\n }\n </mat-tree-node>\n\n <mat-tree-node *matTreeNodeDef=\"let node; when: hasChild\" matTreeNodePadding>\n <button\n mat-icon-button\n matTreeNodeToggle\n class=\"toggle\"\n [attr.aria-label]=\"'Toggle ' + node.key\">\n <mat-icon>\n {{ treeComponent.treeControl.isExpanded(node) ? 'expand_more' : 'chevron_right' }}\n </mat-icon>\n </button>\n <mat-icon class=\"folder-icon\">\n {{ treeComponent.treeControl.isExpanded(node) ? 'folder_open' : 'folder' }}\n </mat-icon>\n <span class=\"folder-label\">{{ node.key }}</span>\n </mat-tree-node>\n </mat-tree>\n }\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n ViewEncapsulation,\n computed,\n effect,\n input,\n output,\n signal,\n} from '@angular/core';\nimport type { Observable } from 'rxjs';\n\nimport {\n APIDataFetchingConfigurationInterface,\n DataSources,\n IFolderItem,\n IPostmanCollectionConfig,\n JsDataTypes,\n MinimumInputRequiredInterface,\n} from 'ngx-t-forms-types';\n\nimport type { IConfigElementError } from '../../t-dynamic-data-edit.component';\nimport { _isEqual } from '../../../../shared/functions/isEqual';\nimport { EmptyStateComponent } from '../_shared/empty-state/empty-state.component';\nimport { ErrorListComponent } from '../_shared/error-list/error-list.component';\nimport { PostmanCollectionsComponent } from '../postman-collections/postman-collections.component';\n\nimport { MatButtonModule } from '@angular/material/button';\nimport { MatIconModule } from '@angular/material/icon';\nimport { MatTooltipModule } from '@angular/material/tooltip';\n\nlet nextId = 0;\n\n/** Discrete UI mode this editor is in, derived from its inputs and value. */\ntype SetupMode = 'no-collection' | 'picker' | 'selected';\n\n/** HTTP method understood by the method-colour map; falls back to neutral. */\ntype HttpMethod = APIDataFetchingConfigurationInterface['httpMethod'];\n\n/** CSS-variable colour per HTTP method (dark-mode-safe; never a hex literal). */\nconst METHOD_COLOR: Readonly<Record<HttpMethod, string>> = {\n GET: 'var(--lib-forms-method-get)',\n POST: 'var(--lib-forms-method-post)',\n PUT: 'var(--lib-forms-method-put)',\n DELETE: 'var(--lib-forms-method-delete)',\n};\n\n/** Maps a JS `typeof` string to the shared {@link JsDataTypes} enum member. */\nfunction toJsDataType(value: unknown): JsDataTypes {\n switch (typeof value) {\n case 'string':\n return JsDataTypes.String;\n case 'number':\n return JsDataTypes.Number;\n case 'bigint':\n return JsDataTypes.BigInt;\n case 'boolean':\n return JsDataTypes.Boolean;\n case 'symbol':\n return JsDataTypes.Symbol;\n case 'function':\n return JsDataTypes.Function;\n case 'object':\n return JsDataTypes.Object;\n default:\n return JsDataTypes.Undefined;\n }\n}\n\n/**\n * Lets the user pick an API endpoint from a Postman collection and exposes the\n * resulting {@link APIDataFetchingConfigurationInterface}. Renders one of three\n * states — no collection configured, the endpoint picker, or the selected\n * endpoint card — and embeds {@link PostmanCollectionsComponent} for the tree.\n *\n * Internal editor consumed by `t-dynamic-data-edit` and `data-source-picker`;\n * the parent owns the field label, hint and validation chrome.\n *\n * @example\n * <lib-rest-api-call-setup\n * [postmanCollectionConfig]=\"config()\"\n * [value]=\"value()\"\n * [disabled]=\"disabled()\"\n * (valueChanged)=\"onApiConfig($event)\" />\n */\n@Component({\n selector: 'lib-rest-api-call-setup',\n templateUrl: './rest-api-call-setup.component.html',\n styleUrl: './rest-api-call-setup.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.Emulated,\n imports: [\n PostmanCollectionsComponent,\n EmptyStateComponent,\n ErrorListComponent,\n MatButtonModule,\n MatIconModule,\n MatTooltipModule,\n ],\n host: {\n 'class': 'lib-rest-api-call-setup',\n '[id]': 'hostId()',\n '[attr.data-mode]': 'mode()',\n },\n})\nexport class RestApiCallSetupComponent {\n readonly #fallbackId = `lib-rest-api-call-setup-${nextId++}`;\n\n /** Optional consumer-provided host id. */\n readonly id = input<string | undefined>(undefined);\n\n /** Postman collection that backs the picker. */\n readonly postmanCollectionConfig = input<IPostmanCollectionConfig | undefined>(undefined);\n\n /**\n * Optional HTTP GET function for fetching sample responses. Retained on the\n * contract for parity; this editor does not invoke it (selection is resolved\n * from the Postman collection the parent already loads).\n */\n readonly httpGetDataFunction = input<\n ((url: string, options: Record<string, unknown>) => Observable<unknown>) | undefined\n >(undefined);\n\n /** Disables the picker and shows a lock affordance. */\n readonly disabled = input<boolean>(false);\n\n /** Current configuration value. */\n readonly value = input<APIDataFetchingConfigurationInterface | undefined>(undefined);\n\n /** Validation errors surfaced from the parent editor. */\n readonly errors = input<IConfigElementError[] | undefined>([]);\n\n /** Emits whenever the user selects a new endpoint or clears the value. */\n readonly valueChanged = output<APIDataFetchingConfigurationInterface | undefined>();\n\n /** Endpoint IDs currently loading sample data (forwarded to the picker). */\n protected readonly loadingEndPoints = signal<string[]>([]);\n\n /** Local snapshot of the value, bridged from the `value` input. */\n readonly #localValue = signal<APIDataFetchingConfigurationInterface | undefined>(undefined);\n\n /** Read-only view of the active configuration for the template. */\n protected readonly currentValue = this.#localValue.asReadonly();\n\n /** Host id: consumer-provided or a stable per-instance fallback. */\n protected readonly hostId = computed<string>(() => this.id() ?? this.#fallbackId);\n\n /** True once the snapshot carries a usable endpoint + method. */\n protected readonly hasValidValue = computed<boolean>(() => {\n const v = this.#localValue();\n return Boolean(v?.httpEndPoint) && Boolean(v?.httpMethod);\n });\n\n /** Discrete UI mode driving the template's `@switch`. */\n protected readonly mode = computed<SetupMode>(() => {\n if (!this.postmanCollectionConfig()) return 'no-collection';\n return this.hasValidValue() ? 'selected' : 'picker';\n });\n\n /** Token-based colour for the selected endpoint's HTTP method badge. */\n protected readonly methodColor = computed<string>(() => {\n const method = this.#localValue()?.httpMethod;\n return method && method in METHOD_COLOR ? METHOD_COLOR[method] : 'currentColor';\n });\n\n /**\n * Bridge the `value` input into the local mutable snapshot, de-duping with a\n * deep structural compare (replaces the legacy `JSON.stringify` equality so\n * key order and `undefined` no longer cause spurious resets).\n */\n protected readonly valueBridge = effect(() => {\n const next = this.value();\n if (!_isEqual(next, this.#localValue())) {\n this.#localValue.set(next);\n }\n });\n\n /** Maps the selected tree node into the API config and emits it. */\n protected nodeSelectionChanged(node: IFolderItem): void {\n const { id, name, request, response } = node;\n if (!request || !response) return;\n\n let requestBody: Record<string, unknown>;\n try {\n requestBody = JSON.parse(request.body?.raw || '{}') as Record<string, unknown>;\n } catch {\n requestBody = {};\n }\n\n const isPost = request.method === 'POST';\n const minimumInputRequired: MinimumInputRequiredInterface[] = isPost\n ? this.#extractRequiredInputs(requestBody)\n : [];\n\n const config: APIDataFetchingConfigurationInterface = {\n _id: id,\n name,\n httpEndPoint: request.url.raw,\n httpMethod: request.method,\n source: DataSources.Api,\n postFormData: isPost,\n backEndConfig: { minimumInputRequired },\n };\n\n this.#localValue.set(config);\n this.valueChanged.emit(config);\n }\n\n /**\n * Clears the selection and emits a single `undefined` (the legacy double-emit\n * — `undefined` then a stub `{ source }` — was removed; see FLAG).\n */\n protected clearValue(): void {\n this.#localValue.set(undefined);\n this.valueChanged.emit(undefined);\n }\n\n /**\n * Derives the POST endpoint's required inputs from the request body. Top-level\n * keys are primary; entries under `data` are secondary (non-primary).\n */\n #extractRequiredInputs(requestBody: Record<string, unknown>): MinimumInputRequiredInterface[] {\n const { data, ...rest } = requestBody;\n const dataEntries: Record<string, unknown> =\n data && typeof data === 'object' ? { ...data } : {};\n\n const primaryKeys = Object.entries(rest).map(([key, val]) =>\n this.#toRequiredInput(key, val, true),\n );\n const secondaryKeys = Object.entries(dataEntries).map(([key, val]) =>\n this.#toRequiredInput(key, val, false),\n );\n\n return [...primaryKeys, ...secondaryKeys];\n }\n\n #toRequiredInput(\n name: string,\n value: unknown,\n primaryKey: boolean,\n ): MinimumInputRequiredInterface {\n return { name, type: toJsDataType(value), primaryKey };\n }\n}\n","@switch (mode()) {\n @case ('no-collection') {\n <lib-empty-state\n icon=\"link_off\"\n message=\"No Postman collection configured. Add a collection id and API key to pick an endpoint.\" />\n }\n\n @case ('selected') {\n <div class=\"lib-rest-api-call-setup__card\">\n <button\n type=\"button\"\n class=\"lib-rest-api-call-setup__endpoint\"\n mat-button\n [disabled]=\"disabled()\"\n [matTooltip]=\"currentValue()?.httpEndPoint ?? ''\"\n (click)=\"clearValue()\">\n <span class=\"lib-rest-api-call-setup__method\" [style.color]=\"methodColor()\">\n {{ currentValue()?.httpMethod }}\n </span>\n <span class=\"lib-rest-api-call-setup__name\">\n {{ currentValue()?.name }}\n </span>\n <mat-icon class=\"lib-rest-api-call-setup__clear\" aria-hidden=\"true\">close</mat-icon>\n </button>\n </div>\n }\n\n @case ('picker') {\n <lib-postman-collections\n class=\"lib-rest-api-call-setup__picker\"\n [class.lib-rest-api-call-setup__picker--disabled]=\"disabled()\"\n [postmanCollectionConfig]=\"postmanCollectionConfig()!\"\n [loadingEndPoints]=\"loadingEndPoints()\"\n (nodeSelectionChanged)=\"nodeSelectionChanged($event)\" />\n }\n}\n\n@if (disabled()) {\n <p class=\"lib-rest-api-call-setup__lock\">\n <mat-icon aria-hidden=\"true\">lock</mat-icon>\n <span>This endpoint is locked and cannot be changed.</span>\n </p>\n}\n\n<lib-error-list [errors]=\"errors()\" />\n"],"names":["i2","i3","i4","i1"],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import * as i0 from '@angular/core';
2
+ import { model, input, ViewEncapsulation, ChangeDetectionStrategy, Component } from '@angular/core';
3
+ import * as i3 from '@angular/material/icon';
4
+ import { MatIconModule } from '@angular/material/icon';
5
+
6
+ /**
7
+ * Internal search field: a tokenised input with a leading icon, an optional
8
+ * result-count badge, and a clear button. Two-way bound via `value`.
9
+ *
10
+ * @example
11
+ * <lib-search-field [(value)]="query" [resultCount]="matches().length"
12
+ * placeholder="Search options" />
13
+ */
14
+ class SearchFieldComponent {
15
+ constructor() {
16
+ /** Two-way search text. */
17
+ this.value = model('', ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
18
+ /** Placeholder shown when empty. */
19
+ this.placeholder = input('Search', ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
20
+ /** Optional result-count badge; `undefined` hides it. */
21
+ this.resultCount = input(undefined, ...(ngDevMode ? [{ debugName: "resultCount" }] : /* istanbul ignore next */ []));
22
+ }
23
+ onInput(event) {
24
+ this.value.set(event.target.value);
25
+ }
26
+ clear() {
27
+ this.value.set('');
28
+ }
29
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: SearchFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
30
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: SearchFieldComponent, isStandalone: true, selector: "lib-search-field", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, resultCount: { classPropertyName: "resultCount", publicName: "resultCount", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, host: { classAttribute: "lib-search-field" }, ngImport: i0, template: "<mat-icon class=\"lib-search-field__icon\">search</mat-icon>\n<input\n class=\"lib-search-field__input\"\n type=\"text\"\n [placeholder]=\"placeholder()\"\n [value]=\"value()\"\n (input)=\"onInput($event)\"\n aria-label=\"Search\" />\n@if (resultCount() !== undefined) {\n<span class=\"lib-search-field__count\">{{ resultCount() }}</span>\n}\n@if (value()) {\n<button type=\"button\" class=\"lib-search-field__clear\" (click)=\"clear()\" aria-label=\"Clear search\">\n <mat-icon>close</mat-icon>\n</button>\n}\n", styles: [":host{display:flex;align-items:center;gap:.5rem;min-height:2.25rem;padding:.5rem .75rem;border:1px solid var(--lib-forms-outline);border-radius:var(--lib-forms-radius-sm, 8px);background:var(--lib-forms-surface);transition:border-color var(--lib-forms-duration-hover, .3s) var(--lib-forms-easing),box-shadow var(--lib-forms-duration-hover, .3s) var(--lib-forms-easing)}:host:focus-within{outline:none;border-color:var(--lib-forms-primary);box-shadow:0 0 0 2px color-mix(in srgb,var(--lib-forms-primary) 25%,transparent)}.lib-search-field__icon{flex:none;width:1.125rem;height:1.125rem;font-size:1.125rem;color:var(--lib-forms-on-surface-variant)}.lib-search-field__input{flex:1 1 auto;min-width:0;border:none;outline:none;background:transparent;font-size:.875rem;color:var(--lib-forms-on-surface)}.lib-search-field__input::placeholder{color:color-mix(in srgb,var(--lib-forms-on-surface-variant) 60%,transparent)}.lib-search-field__count{flex:none;font-size:.75rem;color:var(--lib-forms-on-surface-variant)}.lib-search-field__clear{display:inline-flex;align-items:center;justify-content:center;flex:none;width:1.25rem;height:1.25rem;padding:0;border:none;border-radius:var(--lib-forms-radius-sm, 8px);background:transparent;color:var(--lib-forms-on-surface-variant);cursor:pointer;transition:color var(--lib-forms-duration-hover, .3s) var(--lib-forms-easing),background var(--lib-forms-duration-hover, .3s) var(--lib-forms-easing)}.lib-search-field__clear:hover{color:var(--lib-forms-error);background:var(--sem-error-surface)}.lib-search-field__clear mat-icon{width:1rem;height:1rem;font-size:1rem}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
31
+ }
32
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: SearchFieldComponent, decorators: [{
33
+ type: Component,
34
+ args: [{ selector: 'lib-search-field', imports: [MatIconModule], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.Emulated, host: { 'class': 'lib-search-field' }, template: "<mat-icon class=\"lib-search-field__icon\">search</mat-icon>\n<input\n class=\"lib-search-field__input\"\n type=\"text\"\n [placeholder]=\"placeholder()\"\n [value]=\"value()\"\n (input)=\"onInput($event)\"\n aria-label=\"Search\" />\n@if (resultCount() !== undefined) {\n<span class=\"lib-search-field__count\">{{ resultCount() }}</span>\n}\n@if (value()) {\n<button type=\"button\" class=\"lib-search-field__clear\" (click)=\"clear()\" aria-label=\"Clear search\">\n <mat-icon>close</mat-icon>\n</button>\n}\n", styles: [":host{display:flex;align-items:center;gap:.5rem;min-height:2.25rem;padding:.5rem .75rem;border:1px solid var(--lib-forms-outline);border-radius:var(--lib-forms-radius-sm, 8px);background:var(--lib-forms-surface);transition:border-color var(--lib-forms-duration-hover, .3s) var(--lib-forms-easing),box-shadow var(--lib-forms-duration-hover, .3s) var(--lib-forms-easing)}:host:focus-within{outline:none;border-color:var(--lib-forms-primary);box-shadow:0 0 0 2px color-mix(in srgb,var(--lib-forms-primary) 25%,transparent)}.lib-search-field__icon{flex:none;width:1.125rem;height:1.125rem;font-size:1.125rem;color:var(--lib-forms-on-surface-variant)}.lib-search-field__input{flex:1 1 auto;min-width:0;border:none;outline:none;background:transparent;font-size:.875rem;color:var(--lib-forms-on-surface)}.lib-search-field__input::placeholder{color:color-mix(in srgb,var(--lib-forms-on-surface-variant) 60%,transparent)}.lib-search-field__count{flex:none;font-size:.75rem;color:var(--lib-forms-on-surface-variant)}.lib-search-field__clear{display:inline-flex;align-items:center;justify-content:center;flex:none;width:1.25rem;height:1.25rem;padding:0;border:none;border-radius:var(--lib-forms-radius-sm, 8px);background:transparent;color:var(--lib-forms-on-surface-variant);cursor:pointer;transition:color var(--lib-forms-duration-hover, .3s) var(--lib-forms-easing),background var(--lib-forms-duration-hover, .3s) var(--lib-forms-easing)}.lib-search-field__clear:hover{color:var(--lib-forms-error);background:var(--sem-error-surface)}.lib-search-field__clear mat-icon{width:1rem;height:1rem;font-size:1rem}\n"] }]
35
+ }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], resultCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "resultCount", required: false }] }] } });
36
+
37
+ export { SearchFieldComponent as S };
38
+ //# sourceMappingURL=ngx-t-forms-search-field.component-B2ZO7lqO.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ngx-t-forms-search-field.component-B2ZO7lqO.mjs","sources":["../../../projects/ngx-t-forms/src/lib/components/t-dynamic-data-edit/elements/_shared/search-field/search-field.component.ts","../../../projects/ngx-t-forms/src/lib/components/t-dynamic-data-edit/elements/_shared/search-field/search-field.component.html"],"sourcesContent":["import { ChangeDetectionStrategy, Component, ViewEncapsulation, input, model } from '@angular/core';\nimport { MatIconModule } from '@angular/material/icon';\n\n/**\n * Internal search field: a tokenised input with a leading icon, an optional\n * result-count badge, and a clear button. Two-way bound via `value`.\n *\n * @example\n * <lib-search-field [(value)]=\"query\" [resultCount]=\"matches().length\"\n * placeholder=\"Search options\" />\n */\n@Component({\n selector: 'lib-search-field',\n imports: [MatIconModule],\n templateUrl: './search-field.component.html',\n styleUrl: './search-field.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.Emulated,\n host: { 'class': 'lib-search-field' },\n})\nexport class SearchFieldComponent {\n /** Two-way search text. */\n readonly value = model<string>('');\n /** Placeholder shown when empty. */\n readonly placeholder = input<string>('Search');\n /** Optional result-count badge; `undefined` hides it. */\n readonly resultCount = input<number | undefined>(undefined);\n\n protected onInput(event: Event): void {\n this.value.set((event.target as HTMLInputElement).value);\n }\n\n protected clear(): void {\n this.value.set('');\n }\n}\n","<mat-icon class=\"lib-search-field__icon\">search</mat-icon>\n<input\n class=\"lib-search-field__input\"\n type=\"text\"\n [placeholder]=\"placeholder()\"\n [value]=\"value()\"\n (input)=\"onInput($event)\"\n aria-label=\"Search\" />\n@if (resultCount() !== undefined) {\n<span class=\"lib-search-field__count\">{{ resultCount() }}</span>\n}\n@if (value()) {\n<button type=\"button\" class=\"lib-search-field__clear\" (click)=\"clear()\" aria-label=\"Clear search\">\n <mat-icon>close</mat-icon>\n</button>\n}\n"],"names":["i1"],"mappings":";;;;;AAGA;;;;;;;AAOG;MAUU,oBAAoB,CAAA;AATjC,IAAA,WAAA,GAAA;;AAWW,QAAA,IAAA,CAAA,KAAK,GAAG,KAAK,CAAS,EAAE,4EAAC;;AAEzB,QAAA,IAAA,CAAA,WAAW,GAAG,KAAK,CAAS,QAAQ,kFAAC;;AAErC,QAAA,IAAA,CAAA,WAAW,GAAG,KAAK,CAAqB,SAAS,kFAAC;AAS5D,IAAA;AAPW,IAAA,OAAO,CAAC,KAAY,EAAA;QAC5B,IAAI,CAAC,KAAK,CAAC,GAAG,CAAE,KAAK,CAAC,MAA2B,CAAC,KAAK,CAAC;IAC1D;IAEU,KAAK,GAAA;AACb,QAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;IACpB;+GAdW,oBAAoB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;mGAApB,oBAAoB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,kBAAA,EAAA,MAAA,EAAA,EAAA,KAAA,EAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,UAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,KAAA,EAAA,aAAA,EAAA,EAAA,IAAA,EAAA,EAAA,cAAA,EAAA,kBAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,ECpBjC,wgBAgBA,EAAA,MAAA,EAAA,CAAA,kkDAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EDHY,aAAa,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAAA,EAAA,CAAA,OAAA,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,QAAA,EAAA,SAAA,EAAA,SAAA,EAAA,UAAA,CAAA,EAAA,QAAA,EAAA,CAAA,SAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA,CAAA;;4FAOZ,oBAAoB,EAAA,UAAA,EAAA,CAAA;kBAThC,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,kBAAkB,WACnB,CAAC,aAAa,CAAC,EAAA,eAAA,EAGP,uBAAuB,CAAC,MAAM,EAAA,aAAA,EAChC,iBAAiB,CAAC,QAAQ,EAAA,IAAA,EACnC,EAAE,OAAO,EAAE,kBAAkB,EAAE,EAAA,QAAA,EAAA,wgBAAA,EAAA,MAAA,EAAA,CAAA,kkDAAA,CAAA,EAAA;;;;;"}