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 @@
1
+ {"version":3,"file":"ngx-t-forms-forms-builder-menu.component-qrhM0jGL.mjs","sources":["../../../projects/ngx-t-forms/src/lib/components/form-builder/elements/select-form-template/select-form-template.component.ts","../../../projects/ngx-t-forms/src/lib/components/form-builder/elements/select-form-template/select-form-template.component.html","../../../projects/ngx-t-forms/src/lib/components/form-builder/elements/form-submissions-config/config.ts","../../../projects/ngx-t-forms/src/lib/components/form-builder/elements/form-submissions-config/form-submissions-config.component.ts","../../../projects/ngx-t-forms/src/lib/components/form-builder/elements/form-submissions-config/form-submissions-config.component.html","../../../projects/ngx-t-forms/src/lib/components/form-builder/elements/forms-builder-menu/forms-builder-menu.component.ts","../../../projects/ngx-t-forms/src/lib/components/form-builder/elements/forms-builder-menu/forms-builder-menu.component.html"],"sourcesContent":["import { AsyncPipe, TitleCasePipe } from '@angular/common';\r\nimport { ChangeDetectionStrategy, Component, OnInit, inject } from '@angular/core';\r\nimport { MatButtonModule } from '@angular/material/button';\r\nimport { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';\r\nimport { MatIconModule } from '@angular/material/icon';\r\nimport { MatProgressSpinnerModule } from '@angular/material/progress-spinner';\r\nimport { MatTooltipModule } from '@angular/material/tooltip';\r\n\r\nimport { FormsStoreService } from '../../../forms/store/forms-store.service';\r\nimport { getAvatar } from '../../../../shared/functions/getAvatar';\r\n\r\nimport { DaysAgoPipe } from '../../../../../lib/shared/pipes/date/days-ago.pipe';\r\nimport type { FormInterface } from 'ngx-t-forms-types';\r\n\r\n@Component({\r\n selector: 'lib-select-form-template',\r\n imports: [\r\n AsyncPipe,\r\n TitleCasePipe,\r\n MatButtonModule,\r\n MatIconModule,\r\n MatProgressSpinnerModule,\r\n MatTooltipModule,\r\n DaysAgoPipe,\r\n ],\r\n templateUrl: './select-form-template.component.html',\r\n styleUrl: './select-form-template.component.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n})\r\nexport class SelectFormTemplateComponent implements OnInit {\r\n readonly #store = inject(FormsStoreService);\r\n readonly #dialogRef = inject(MatDialogRef<SelectFormTemplateComponent>);\r\n // TODO(phase-3): MAT_DIALOG_DATA payload shape is not typed by callers; keep `unknown` here.\r\n protected readonly data = inject<unknown>(MAT_DIALOG_DATA);\r\n\r\n protected readonly selectForms$ = this.#store.selectors.selectForms$;\r\n protected readonly selectLoadingForms$ = this.#store.selectors.selectLoadingForms$;\r\n\r\n ngOnInit(): void {\r\n this.#store.effects.loadForms$();\r\n }\r\n\r\n protected close(): void {\r\n this.#dialogRef.close();\r\n }\r\n\r\n protected selectForm(form: FormInterface): void {\r\n this.#store.actionsFormBuilder.applyFormTemplate(form);\r\n this.#dialogRef.close(form);\r\n }\r\n\r\n protected getFormAvatar(formTitle: string): string {\r\n return getAvatar(formTitle);\r\n }\r\n}\r\n","<div class=\"template-select-dialog\">\r\n <!-- Header: icon + title + subtitle per design rule §4 -->\r\n <header class=\"dialog-header\">\r\n <div class=\"header-icon\" aria-hidden=\"true\">\r\n <mat-icon>description</mat-icon>\r\n </div>\r\n <div class=\"header-text\">\r\n <h1 class=\"header-title\">Choose a Form Template</h1>\r\n <p class=\"header-subtitle\">\r\n Select a pre-built form template to start with. You can customize and save it as your own form after copying it to the editor.\r\n </p>\r\n </div>\r\n </header>\r\n\r\n <section class=\"dialog-content\">\r\n @if (selectLoadingForms$ | async) {\r\n <div class=\"loading-state\">\r\n <mat-spinner diameter=\"40\" aria-label=\"Loading form templates\"></mat-spinner>\r\n <span class=\"loading-text\">Loading form templates...</span>\r\n </div>\r\n } @else {\r\n <ul class=\"form-template-list\" aria-label=\"Available form templates\">\r\n @for (form of selectForms$ | async; track form._id) {\r\n <li>\r\n <button\r\n type=\"button\"\r\n class=\"form-list-item\"\r\n (click)=\"selectForm(form)\"\r\n [matTooltip]=\"'Click to select this template'\"\r\n [attr.aria-label]=\"'Select template: ' + form.formTitle\">\r\n <img\r\n class=\"form-avatar\"\r\n [class.form-avatar--error]=\"form.errors.length > 0\"\r\n [src]=\"getFormAvatar(form.formTitle)\"\r\n [alt]=\"''\"\r\n aria-hidden=\"true\">\r\n <div class=\"form-item-content\">\r\n <span class=\"form-title\">{{ form.formTitle | titlecase }}</span>\r\n <div class=\"form-metadata\">\r\n @if (form.errors.length > 0) {\r\n <span class=\"metadata-item\">\r\n <mat-icon color=\"warn\" aria-hidden=\"true\">error</mat-icon>\r\n <small>{{ form.errors.length }}</small>\r\n </span>\r\n <span class=\"metadata-divider\" aria-hidden=\"true\">•</span>\r\n }\r\n <span class=\"metadata-item\">\r\n <mat-icon aria-hidden=\"true\">add_circle_outline</mat-icon>\r\n <small>{{ form.createdAt | daysAgo }}</small>\r\n </span>\r\n <span class=\"metadata-divider\" aria-hidden=\"true\">•</span>\r\n <span class=\"metadata-item\">\r\n <mat-icon aria-hidden=\"true\">update</mat-icon>\r\n <small>{{ form.updatedAt | daysAgo }}</small>\r\n </span>\r\n </div>\r\n </div>\r\n </button>\r\n </li>\r\n }\r\n </ul>\r\n\r\n @if ((selectForms$ | async)?.length === 0) {\r\n <div class=\"empty-state\">\r\n <mat-icon class=\"empty-state-icon\" aria-hidden=\"true\">folder_off</mat-icon>\r\n <p>No form templates available.</p>\r\n </div>\r\n }\r\n }\r\n </section>\r\n\r\n <footer class=\"dialog-actions\">\r\n <button mat-button (click)=\"close()\" aria-label=\"Close dialog\">\r\n Close\r\n </button>\r\n </footer>\r\n</div>\r\n","\r\n\r\nimport { ConfigurationValidTestInterface, ElementEditorInnerSectionElementInterface, ElementEditorTypes, NgxTFormsConfig, SpecialElementKeys } from \"ngx-t-forms-types\"\r\n\r\n\r\n\r\n\r\nexport function SubmissionAPIListItemConfig (environment: NgxTFormsConfig): ElementEditorInnerSectionElementInterface[]{\r\n return [\r\n\r\n {\r\n id: '16140923-0542-4d5d-9b63-186c1e91b1a7',\r\n name: SpecialElementKeys.MatOptionsApiCall,\r\n editType: ElementEditorTypes.ApiCall,\r\n required: true,\r\n postmanCollectionConfig: {\r\n collectionUrl: environment['POSTMAN_COLLECTION_URL'] as string,\r\n collectionKey: environment['POSTMAN_COLLECTION_KEY'] as string\r\n },\r\n hint: `APIs are loaded from Postman collection. Configure required headers, payload format, and response mapping before use. Ensure API is documented in Postman.`,\r\n deepBind: ['data'],\r\n label: 'Select form submission api',\r\n },\r\n \r\n {\r\n name: SpecialElementKeys.Default,\r\n deepBind: [\r\n\r\n 'data',\r\n 'backEndConfig',\r\n 'minimumInputRequired',\r\n ],\r\n additionalTest: [\r\n {\r\n testType: 'exists',\r\n deepBind: [\r\n\r\n 'data',\r\n 'backEndConfig',\r\n 'minimumInputRequired',\r\n ],\r\n } as ConfigurationValidTestInterface\r\n\r\n ],\r\n hint: `These are payload fields that are required to be filled in order to fetch data from the selected source`,\r\n editType: ElementEditorTypes.RequiredInputs,\r\n label: 'Set up required inputs',\r\n id: \"2d0f1e18-897b-4c28-97bc-3078be09f8ee\"\r\n },\r\n {\r\n name: SpecialElementKeys.Default,\r\n deepBind: ['data','projectFormData'],\r\n editType: ElementEditorTypes.FormPayloadProjection,\r\n label: 'Project form data',\r\n defaultValue: `data:{$formValue}`,\r\n hint: 'Choose how the submitted form is shaped before it is sent — sent flat, or wrapped under one or more keys.',\r\n id: \"$2d0f1e18-897b-4c28-97bc-3078be09f8ee\"\r\n },\r\n ]}\r\nexport const SubmissionAPIOtherConfig : ElementEditorInnerSectionElementInterface[] = [\r\n {\r\n id:\"7acaa5d1-fb37-4dc0-9f1a-53b6f36534e0\",\r\n name:SpecialElementKeys.Default,\r\n deepBind:['submissionHandle','submissionMessage'],\r\n editType:ElementEditorTypes.Input,\r\n label:\"Submission Message\",\r\n hint:\"Message shown to the user after successful form submission.\",\r\n },\r\n {\r\n id:\"5636c16c-be58-48d9-b701-81fe05573a39\",\r\n name:SpecialElementKeys.Default,\r\n deepBind:['submissionHandle','innerComponentShowSubmitButton'],\r\n editType:ElementEditorTypes.Toggle,\r\n label:\"Show submit button in inner component form\",\r\n },\r\n {\r\n id:\"c9103faa-eeba-4cf3-b3d0-f25fd05ccb3c\",\r\n name:SpecialElementKeys.Default,\r\n deepBind:['systemDefault'],\r\n editType:ElementEditorTypes.Toggle,\r\n label:\"Is system default\",\r\n }\r\n] \r\n \r\n export const SubmissionDialogConfig = [\r\n {\r\n titleIcon:'send',\r\n id:'44023662-7343-4c93-999d-fc03c54438c3',\r\n title:'Form Submission Endpoint',\r\n description:`Choose where to send your form data after submission. Connect to your database, data pipeline, or\r\n third-party service.`,\r\n primaryKey:'submissionAPI',\r\n sectionLabel:'Submission Endpoints',\r\n emptyMessage:'No submission endpoints configured. Add one to send form data.',\r\n elements : SubmissionAPIOtherConfig\r\n },\r\n {\r\n titleIcon:'rule',\r\n title:'Data Validation Rules',\r\n description:`Define validation rules to ensure data quality before form submission.\r\n <br>\r\n <strong>Note:</strong> All validation endpoints must return a boolean value -\r\n <code>true</code> indicates valid data that will be submitted.`,\r\n primaryKey:'canSubmitAPI',\r\n sectionLabel:'Validation Endpoints',\r\n emptyMessage:'No validation endpoints configured. Add one to validate data before submission.',\r\n id:'acac6045-5b13-4c8d-a7ee-da194ebbad41',\r\n }\r\n ]","import { ChangeDetectionStrategy, Component, computed, inject, signal } from '@angular/core';\r\n\r\nimport { ClipboardModule } from '@angular/cdk/clipboard';\r\nimport { MatButtonModule } from '@angular/material/button';\r\nimport { MAT_DIALOG_DATA, MatDialog, MatDialogModule } from '@angular/material/dialog';\r\nimport { MatDividerModule } from '@angular/material/divider';\r\nimport { MatExpansionModule } from '@angular/material/expansion';\r\nimport { MatFormFieldModule } from '@angular/material/form-field';\r\nimport { MatIconModule } from '@angular/material/icon';\r\nimport { MatTooltipModule } from '@angular/material/tooltip';\r\n\r\nimport { SubmissionAPIListItemConfig, SubmissionDialogConfig } from './config';\r\nimport { FormsStoreService } from '../../../forms/store/forms-store.service';\r\nimport { testAgainstItem } from '../../../t-dynamic-data-edit/functions/testData';\r\n\r\nimport { TDynamicDataEditComponent } from '../../../t-dynamic-data-edit/t-dynamic-data-edit.component';\r\n\r\nimport { assignDeepPropertyToObject } from '../../../../../lib/shared';\r\nimport { NGX_T_FORMS_CONFIG_TOKEN } from '../../../../../lib/injection-tokens';\r\n\r\nimport {\r\n APIDataFetchingConfigurationInterface,\r\n ElementEditorInnerSectionElementInterface,\r\n validateApiDataFetchingConfiguration,\r\n} from 'ngx-t-forms-types';\r\n\r\ntype SubmissionApiKey = 'submissionAPI' | 'canSubmitAPI';\r\n\r\n@Component({\r\n selector: 'lib-form-submissions-config',\r\n imports: [\r\n ClipboardModule,\r\n MatButtonModule,\r\n MatDialogModule,\r\n MatDividerModule,\r\n MatExpansionModule,\r\n MatFormFieldModule,\r\n MatIconModule,\r\n MatTooltipModule,\r\n TDynamicDataEditComponent,\r\n ],\r\n templateUrl: './form-submissions-config.component.html',\r\n styleUrl: './form-submissions-config.component.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n})\r\nexport class FormSubmissionsConfigComponent {\r\n // TODO: NGX_T_FORMS_CONFIG should be #private; kept accessible due to template/getter usage.\r\n protected readonly NGX_T_FORMS_CONFIG = inject(NGX_T_FORMS_CONFIG_TOKEN);\r\n\r\n readonly #data: { store: FormsStoreService } = inject(MAT_DIALOG_DATA);\r\n readonly store: FormsStoreService = this.#data.store;\r\n readonly #matDialog = inject(MatDialog);\r\n\r\n protected readonly form = computed(\r\n () => this.store.signalSelectors.selectFormInEdit()?.form,\r\n );\r\n\r\n protected readonly formInputs = this.store.formBuilderSignalSelectors.getAllFormInputs;\r\n\r\n protected readonly formValidationError = this.store.formBuilderSignalSelectors.formErrors;\r\n\r\n /** The endpoint currently open in the inline editor (one panel at a time). */\r\n protected readonly keyInEdit = signal<SubmissionApiKey | undefined>(undefined);\r\n\r\n /** Draft endpoint being added or edited; `undefined` when the editor is closed. */\r\n protected readonly dataPlaceholder = signal<\r\n { data: APIDataFetchingConfigurationInterface } | undefined\r\n >(undefined);\r\n\r\n /** True when the inline editor is updating an existing endpoint rather than adding one. */\r\n protected readonly isEditingExisting = computed(\r\n () => this.dataPlaceholder()?.data?._id != null,\r\n );\r\n\r\n /**\r\n * Panels enriched with their live endpoint list and required-state error.\r\n * Driven entirely from {@link SubmissionDialogConfig}, so adding a panel is a\r\n * config-only change — no template branching on `primaryKey`.\r\n */\r\n protected readonly panels = computed(() => {\r\n const form = this.form();\r\n return SubmissionDialogConfig.map((panel) => {\r\n const apis = form?.submissionHandle?.[panel.primaryKey as SubmissionApiKey] ?? [];\r\n const error =\r\n panel.primaryKey === 'submissionAPI' && apis.length === 0\r\n ? 'At least one submission API is required'\r\n : undefined;\r\n return { ...panel, apis, error };\r\n });\r\n });\r\n\r\n /** Editor elements for the inline endpoint form, gated by their `additionalTest`. */\r\n protected readonly submissionApiElements = computed(() => {\r\n const placeholder = this.dataPlaceholder() ?? { data: {} };\r\n return SubmissionAPIListItemConfig(this.NGX_T_FORMS_CONFIG).filter(\r\n (el) =>\r\n !el.additionalTest ||\r\n el.additionalTest.every((test) => testAgainstItem(test, placeholder)),\r\n );\r\n });\r\n\r\n /** Validation errors for the draft endpoint, computed once per change. */\r\n readonly #placeholderErrors = computed(() =>\r\n validateApiDataFetchingConfiguration(this.dataPlaceholder() ?? {}).map((error) => ({\r\n message: error.message,\r\n key: 'data.' + error.key,\r\n })),\r\n );\r\n\r\n /** Store-level validation errors bound to a given panel element. */\r\n errorsFor(\r\n element: ElementEditorInnerSectionElementInterface,\r\n ): { key: string; message: string }[] {\r\n const bind = element.deepBind?.join('.');\r\n return this.formValidationError()?.filter((error) => error.key === bind) ?? [];\r\n }\r\n\r\n /** Draft-endpoint validation errors bound to a given inline-editor element. */\r\n validationErrors(\r\n element: ElementEditorInnerSectionElementInterface,\r\n ): { key: string; message: string }[] {\r\n const bind = element.deepBind?.join('.');\r\n return this.#placeholderErrors().filter((error) => error.key === bind);\r\n }\r\n\r\n /**\r\n * Event payload types from `lib-t-dynamic-data-edit` are heterogeneous (per\r\n * element kind). Until that emission contract is narrowed via a discriminated\r\n * union, accept `unknown` and forward through; element-level handlers narrow.\r\n */\r\n elementBlur(_event: unknown, _element: ElementEditorInnerSectionElementInterface): void {\r\n // intentional no-op\r\n }\r\n\r\n formInputChange(value: unknown, ele: ElementEditorInnerSectionElementInterface): void {\r\n this.store.actionsFormBuilder.formInputChange(ele, value);\r\n }\r\n\r\n elementConfigurationChanged(\r\n value: unknown,\r\n ele: ElementEditorInnerSectionElementInterface,\r\n ): void {\r\n const applyTo = { ...this.dataPlaceholder() };\r\n if (ele.clearOnChange) {\r\n ele.clearOnChange.forEach((clear: string[]) => {\r\n assignDeepPropertyToObject(applyTo, clear, undefined);\r\n });\r\n }\r\n if (ele.deepBind) {\r\n assignDeepPropertyToObject(applyTo, ele.deepBind, value);\r\n }\r\n // Placeholder shape is dynamic — `applyTo` is built from a partial spread plus\r\n // deep-bind assignments. The data field is known to be the API configuration\r\n // type by contract with the element editor.\r\n this.dataPlaceholder.set({ ...applyTo } as { data: APIDataFetchingConfigurationInterface });\r\n }\r\n\r\n addNewSubmitApi(key: string): void {\r\n this.dataPlaceholder.set({ data: {} as APIDataFetchingConfigurationInterface });\r\n this.keyInEdit.set(key as SubmissionApiKey);\r\n }\r\n\r\n editSubmitApi(api: APIDataFetchingConfigurationInterface, key: string): void {\r\n this.dataPlaceholder.set({ data: { ...api } });\r\n this.keyInEdit.set(key as SubmissionApiKey);\r\n }\r\n\r\n saveSubmitApi(): void {\r\n this.store.actionsFormBuilder.saveSubmitApi(this.dataPlaceholder(), this.keyInEdit());\r\n this.#closeEditor();\r\n }\r\n\r\n removeSubmissionApi(api: APIDataFetchingConfigurationInterface, key: string): void {\r\n this.store.actionsFormBuilder.removeSubmissionApi(api, key as SubmissionApiKey);\r\n this.#closeEditor();\r\n }\r\n\r\n cancelSubmitApi(): void {\r\n this.#closeEditor();\r\n }\r\n\r\n close(): void {\r\n this.#matDialog.closeAll();\r\n }\r\n\r\n #closeEditor(): void {\r\n this.dataPlaceholder.set(undefined);\r\n this.keyInEdit.set(undefined);\r\n }\r\n}\r\n","<div class=\"submissions-dialog\">\r\n <!-- Header: icon + title + subtitle per design rule §4 -->\r\n <header class=\"dialog-header\">\r\n <div class=\"header-icon\" aria-hidden=\"true\">\r\n <mat-icon>settings</mat-icon>\r\n </div>\r\n <div class=\"header-text\">\r\n <h1 class=\"header-title\">Form Submission Configuration</h1>\r\n <p class=\"header-subtitle\">Configure how your form is submitted and validated before submission.</p>\r\n </div>\r\n <button mat-icon-button mat-dialog-close [attr.aria-label]=\"'Close dialog'\" class=\"header-close\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </header>\r\n\r\n <section class=\"dialog-content\">\r\n <mat-accordion multi>\r\n @for (panel of panels(); track panel.id) {\r\n <mat-expansion-panel [expanded]=\"true\" class=\"config-panel\">\r\n <mat-expansion-panel-header class=\"panel-header\">\r\n <mat-panel-title class=\"panel-title\">\r\n <mat-icon class=\"panel-icon\" [color]=\"'primary'\">{{ panel.titleIcon }}</mat-icon>\r\n {{ panel.title }}\r\n </mat-panel-title>\r\n </mat-expansion-panel-header>\r\n\r\n <div class=\"panel-content\">\r\n <p class=\"panel-description\" [innerHTML]=\"panel.description\"></p>\r\n\r\n <!-- Dynamic form elements (submission message, toggles, etc.) -->\r\n @if ((panel?.elements || []).length > 0) {\r\n <div class=\"edit-section\">\r\n @for (edit of (panel?.elements || []); track edit.id) {\r\n <div class=\"edit-field\">\r\n <lib-t-dynamic-data-edit\r\n [editorConfig]=\"edit\"\r\n [data]=\"form()\"\r\n [validationErrors]=\"errorsFor(edit)\"\r\n (valueChange)=\"formInputChange($event, edit)\"\r\n [formInputs]=\"(formInputs()) || []\"\r\n (blur)=\"elementBlur($event, edit)\">\r\n </lib-t-dynamic-data-edit>\r\n </div>\r\n }\r\n </div>\r\n }\r\n\r\n <!-- API endpoints list -->\r\n <div class=\"api-section\">\r\n <h3 class=\"api-section-header\" [class.api-section-header--error]=\"panel.error\">\r\n {{ panel.sectionLabel }}\r\n </h3>\r\n\r\n @if (panel.apis.length === 0) {\r\n <div class=\"empty-state\" [class.empty-state--error]=\"panel.error\">\r\n <mat-icon class=\"empty-state-icon\">add_link</mat-icon>\r\n <p>{{ panel.emptyMessage }}</p>\r\n </div>\r\n }\r\n\r\n @for (api of panel.apis; track api._id) {\r\n <div\r\n class=\"api-list-item\"\r\n [class.api-list-item--active]=\"keyInEdit() === panel.primaryKey && dataPlaceholder()?.data?._id === api._id\">\r\n <span class=\"api-method-tag\" [class.api-method-tag--post]=\"api.httpMethod === 'POST'\">\r\n {{ api.httpMethod }}\r\n </span>\r\n <div class=\"api-details\">\r\n <span class=\"api-name\">{{ api.name }}</span>\r\n <span class=\"api-endpoint\" [matTooltip]=\"api.httpEndPoint\" matTooltipPosition=\"above\">\r\n {{ api.httpEndPoint }}\r\n </span>\r\n </div>\r\n <div class=\"api-item-actions\">\r\n <button\r\n (click)=\"editSubmitApi(api, panel.primaryKey)\"\r\n mat-icon-button\r\n matTooltip=\"Edit endpoint\"\r\n [attr.aria-label]=\"'Edit endpoint ' + api.name\"\r\n class=\"api-edit-btn\">\r\n <mat-icon>edit</mat-icon>\r\n </button>\r\n <button\r\n [cdkCopyToClipboard]=\"api.httpEndPoint || ''\"\r\n mat-icon-button\r\n matTooltip=\"Copy URL\"\r\n [attr.aria-label]=\"'Copy endpoint URL'\"\r\n class=\"api-copy-btn\"\r\n (click)=\"$event.stopPropagation()\">\r\n <mat-icon>content_copy</mat-icon>\r\n </button>\r\n <button\r\n (click)=\"removeSubmissionApi(api, panel.primaryKey)\"\r\n mat-icon-button\r\n matTooltip=\"Remove endpoint\"\r\n [attr.aria-label]=\"'Remove endpoint ' + api.name\"\r\n class=\"api-remove-btn\">\r\n <mat-icon>delete</mat-icon>\r\n </button>\r\n </div>\r\n </div>\r\n <mat-divider></mat-divider>\r\n }\r\n\r\n @if (keyInEdit() !== panel.primaryKey) {\r\n <div class=\"api-actions\">\r\n <button\r\n (click)=\"addNewSubmitApi(panel.primaryKey)\"\r\n mat-stroked-button\r\n color=\"primary\"\r\n class=\"add-endpoint-btn\">\r\n <mat-icon>add</mat-icon>\r\n Add new endpoint\r\n </button>\r\n </div>\r\n }\r\n\r\n @if (panel.error) {\r\n <mat-error class=\"panel-error\">{{ panel.error }}</mat-error>\r\n }\r\n </div>\r\n\r\n <!-- Inline edit form for new/editing endpoint -->\r\n @if (keyInEdit() === panel.primaryKey) {\r\n <div class=\"edit-section edit-section--inline\">\r\n <h4 class=\"inline-edit-title\">\r\n {{ isEditingExisting() ? 'Edit endpoint' : 'New endpoint' }}\r\n </h4>\r\n @for (element of submissionApiElements(); track element.id) {\r\n <div class=\"edit-field\">\r\n <lib-t-dynamic-data-edit\r\n [editorConfig]=\"element\"\r\n [data]=\"dataPlaceholder()\"\r\n [validationErrors]=\"validationErrors(element)\"\r\n (valueChange)=\"elementConfigurationChanged($event, element)\"\r\n [formInputs]=\"(formInputs()) || []\"\r\n (blur)=\"elementBlur($event, element)\">\r\n </lib-t-dynamic-data-edit>\r\n </div>\r\n }\r\n <mat-divider></mat-divider>\r\n <div class=\"inline-edit-actions\">\r\n <button mat-flat-button (click)=\"saveSubmitApi()\" color=\"primary\">\r\n {{ isEditingExisting() ? 'Update' : 'Save' }}\r\n </button>\r\n <button mat-button (click)=\"cancelSubmitApi()\" color=\"warn\">Cancel</button>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </mat-expansion-panel>\r\n }\r\n </mat-accordion>\r\n </section>\r\n</div>\r\n","import { ChangeDetectionStrategy, Component, DestroyRef, Signal, computed, inject } from '@angular/core';\r\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\r\nimport { MatBadgeModule } from '@angular/material/badge';\r\nimport { MatButtonModule } from '@angular/material/button';\r\nimport { MatIconModule } from '@angular/material/icon';\r\nimport { MatMenuModule } from '@angular/material/menu';\r\nimport { MatTooltipModule } from '@angular/material/tooltip';\r\nimport { MatCardModule } from '@angular/material/card';\r\nimport { MatToolbarModule } from '@angular/material/toolbar';\r\nimport { MatDividerModule } from '@angular/material/divider';\r\nimport { MatProgressSpinnerModule } from '@angular/material/progress-spinner';\r\nimport { MatFormFieldModule } from '@angular/material/form-field';\r\nimport { MatSnackBar } from '@angular/material/snack-bar';\r\nimport { MatDialog } from '@angular/material/dialog';\r\nimport { CdkDrag } from '@angular/cdk/drag-drop';\r\nimport { ClipboardModule } from '@angular/cdk/clipboard';\r\n\r\nimport { FormJsonViewComponent } from '../form-json-view/form-json-view.component';\r\nimport { SelectFormTemplateComponent } from '../select-form-template/select-form-template.component';\r\nimport { FormSubmissionsConfigComponent } from '../form-submissions-config/form-submissions-config.component';\r\nimport { FormsStoreService } from '../../../forms/store/forms-store.service';\r\n\r\nimport { take } from 'rxjs';\r\nimport type { FormInterface, ValidationError } from 'ngx-t-forms-types';\r\n\r\ninterface FormsBuilderMenuItem {\r\n label: string;\r\n icon: string;\r\n hint: string;\r\n errors?: boolean;\r\n action: () => void;\r\n}\r\n\r\n@Component({\r\n selector: 'lib-forms-builder-menu',\r\n imports: [\r\n MatBadgeModule,\r\n MatButtonModule,\r\n MatIconModule,\r\n MatMenuModule,\r\n MatTooltipModule,\r\n MatCardModule,\r\n MatToolbarModule,\r\n MatDividerModule,\r\n MatProgressSpinnerModule,\r\n MatFormFieldModule,\r\n CdkDrag,\r\n ClipboardModule,\r\n FormJsonViewComponent,\r\n ],\r\n templateUrl: './forms-builder-menu.component.html',\r\n styleUrl: './forms-builder-menu.component.scss',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n})\r\nexport class FormsBuilderMenuComponent {\r\n readonly #store = inject(FormsStoreService);\r\n readonly #destroyRef = inject(DestroyRef);\r\n protected readonly snackBar = inject(MatSnackBar);\r\n protected readonly dialog = inject(MatDialog);\r\n\r\n protected showJson = false;\r\n\r\n protected readonly form: Signal<FormInterface | undefined> = computed(\r\n () => this.#store.signalSelectors.selectFormInEdit()?.form,\r\n );\r\n\r\n protected readonly formCopy: Signal<string> = computed(() => JSON.stringify(this.form() || {}));\r\n\r\n protected readonly errors: Signal<ReadonlyArray<ValidationError>> =\r\n this.#store.formBuilderSignalSelectors.formErrors;\r\n\r\n protected readonly configHasErrors: Signal<boolean> = computed(() =>\r\n this.errors().some((error) => error.key.split('.')?.[0] === 'submissionHandle'),\r\n );\r\n\r\n protected readonly items: Signal<ReadonlyArray<FormsBuilderMenuItem>> = computed(() => [\r\n {\r\n label: 'Templates',\r\n icon: 'content_copy',\r\n hint: 'Select a form to apply as a template',\r\n action: (): void => this.openDialog(),\r\n },\r\n {\r\n label: 'Submission Config',\r\n hint: 'Setup form submission api and other configurations',\r\n icon: 'api',\r\n errors: this.configHasErrors(),\r\n action: (): void => this.openFormSubmissionDialog(),\r\n },\r\n ]);\r\n\r\n protected openDialog(): void {\r\n const dialogRef = this.dialog.open(SelectFormTemplateComponent);\r\n dialogRef\r\n .afterClosed()\r\n .pipe(take(1), takeUntilDestroyed(this.#destroyRef))\r\n .subscribe((form) => {\r\n if (form) {\r\n this.applyFormTemplate(form);\r\n }\r\n });\r\n }\r\n\r\n protected applyFormTemplate = (form: FormInterface): void =>\r\n this.#store.actionsFormBuilder.applyFormTemplate(form);\r\n\r\n protected openFormSubmissionDialog(): void {\r\n const dialogRef = this.dialog.open(FormSubmissionsConfigComponent, {\r\n data: { store: this.#store },\r\n });\r\n\r\n dialogRef\r\n .afterClosed()\r\n .pipe(take(1), takeUntilDestroyed(this.#destroyRef))\r\n .subscribe(() => {\r\n // no-op\r\n });\r\n }\r\n\r\n protected toggleJson(): void {\r\n this.showJson = !this.showJson;\r\n }\r\n}\r\n","<button [matBadge]=\"'!'\" matBadgeColor=\"warn\" [matTooltip]=\"configHasErrors() === false?'\nClick to view form configuration\n':'Click to fix or add missing form configurations'\" [matBadgeHidden]=\"!!(configHasErrors()) === false\"\n [matMenuTriggerFor]=\"configMenu\" mat-flat-button>\n Config\n <mat-icon>\n settings_suggest\n </mat-icon>\n</button>\n\n<mat-menu #configMenu=\"matMenu\">\n\n\n <div mat-subheader style=\"padding-left: 16px;\">Form edit options</div>\n @for (item of items(); track item.label) {\n <button [matTooltip]=\"item.hint\" matTooltipPosition=\"right\" style=\"padding-top:4px;padding-bottom:4px\"\n (click)=\"item?.action()\" mat-menu-item>\n <mat-icon>{{item.icon}}</mat-icon>\n\n <span>\n @if (item.errors) {\n <div style=\"line-height: normal;\">\n {{item.label}}\n </div>\n <div style=\"line-height: normal;\">\n\n <mat-error>\n <small>\n Invalid configurations\n </small>\n\n </mat-error>\n </div>\n }@else {\n\n {{item.label}}\n\n }\n\n\n </span>\n\n </button>\n <mat-divider></mat-divider>\n }\n <button [matTooltip]=\"showJson?'Hide json':'Show json'\" (click)=\"toggleJson()\" mat-menu-item>\n <mat-icon>data_object</mat-icon>\n\n <span>\n <div>\n Show json\n </div>\n\n\n\n </span>\n </button>\n\n</mat-menu>\n\n@if (showJson) {\n<div class=\"DragBoundary\">\n @defer (on viewport) {\n <mat-card cdkDragBoundary=\"DragBoundary\" cdkDrag class=\"menuCard\">\n <mat-toolbar\n style=\"background: var(--mat-sidenav-content-background-color);color:var(--mdc-filled-button-label-text-color, var(--mat-app-on-primary))\">\n <span>\n Json Form Value\n </span>\n <span class=\"spacer\"></span>\n\n <mat-icon cdkDragHandle style=\"\n margin:8px;\n color:var(--mat-divider-color, var(--mat-app-outline))\">\n drag_indicator\n </mat-icon>\n </mat-toolbar>\n <mat-divider style=\"margin-bottom: 12px;\"></mat-divider>\n\n\n <mat-card-content style=\" overflow-y: auto;\n max-height: calc(100vh - 150px);\">\n <lib-form-json-view></lib-form-json-view>\n </mat-card-content>\n <mat-card-actions>\n <span class=\"spacer\"></span>\n <button (click)=\"toggleJson()\" mat-flat-button>\n Close\n </button>\n <button color=\"primary\" [cdkCopyToClipboard]=\"(formCopy())||''\" matTooltip=\"Copy json to clipboard\"\n mat-flat-button>\n Copy\n </button>\n\n </mat-card-actions>\n\n\n </mat-card>\n }@placeholder {\n <div style=\"padding: 50px;display:flex;justify-content:center;align-items:center; text-align: center;\">\n <mat-spinner diameter=\"20\" />\n </div>\n\n }\n</div>\n}\n"],"names":["i2","i3","i4","i1","i6","i7","i8","i9","i10","i11"],"mappings":"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"}
@@ -0,0 +1,124 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, ElementRef, input, signal, PLATFORM_ID, ChangeDetectionStrategy, Component, output, computed } from '@angular/core';
3
+ import * as i1$1 from '@angular/forms';
4
+ import { NgControl, ReactiveFormsModule } from '@angular/forms';
5
+ import * as i2 from '@angular/material/form-field';
6
+ import { MatFormFieldControl, MatFormFieldModule } from '@angular/material/form-field';
7
+ import * as i3 from '@angular/material/icon';
8
+ import { MatIconModule } from '@angular/material/icon';
9
+ import * as i1 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 { B as BaseCustomInput, m as getInputErrorMessage, n as TFormInputStatusComponent } from './ngx-t-forms-ngx-t-forms-u_kigDid.mjs';
14
+ import * as i3$1 from '@angular/common';
15
+ import { isPlatformBrowser, CommonModule } from '@angular/common';
16
+
17
+ const DEFAULT_OPTIONS = {
18
+ enableHighAccuracy: true,
19
+ timeout: 5000,
20
+ maximumAge: 0
21
+ };
22
+ const getGeoLocation = (options = DEFAULT_OPTIONS) => {
23
+ return new Promise((resolve, reject) => {
24
+ if (!navigator.geolocation) {
25
+ const error = {
26
+ code: 0,
27
+ message: 'Geolocation is not supported by this browser',
28
+ PERMISSION_DENIED: 1,
29
+ POSITION_UNAVAILABLE: 2,
30
+ TIMEOUT: 3
31
+ };
32
+ reject(error);
33
+ return;
34
+ }
35
+ navigator.geolocation.getCurrentPosition((position) => resolve(position), (error) => reject(error), options);
36
+ });
37
+ };
38
+
39
+ const customInputConfig = {
40
+ controlType: 'lib-geo-location-form-input',
41
+ nextId: 0
42
+ };
43
+ class GeoLocationFormInputComponent extends BaseCustomInput {
44
+ #platformId;
45
+ constructor() {
46
+ super(inject(NgControl, { optional: true, self: true }), inject(ElementRef), customInputConfig);
47
+ this.formBuilderFunctions = input(undefined, ...(ngDevMode ? [{ debugName: "formBuilderFunctions" }] : /* istanbul ignore next */ []));
48
+ this.inputConfig = input.required(...(ngDevMode ? [{ debugName: "inputConfig" }] : /* istanbul ignore next */ []));
49
+ this.isLoading = signal(false, ...(ngDevMode ? [{ debugName: "isLoading" }] : /* istanbul ignore next */ []));
50
+ this.error = signal(false, ...(ngDevMode ? [{ debugName: "error" }] : /* istanbul ignore next */ []));
51
+ this.#platformId = inject(PLATFORM_ID);
52
+ }
53
+ get empty() {
54
+ const n = this.value;
55
+ // Check for null, undefined, or empty string, but allow 0
56
+ return n === null || n === undefined || n === '';
57
+ }
58
+ get shouldLabelFloat() {
59
+ return true;
60
+ }
61
+ async getLocation() {
62
+ if (!isPlatformBrowser(this.#platformId))
63
+ return;
64
+ try {
65
+ this.error.set(false);
66
+ this.isLoading.set(true);
67
+ const currentLocation = await getGeoLocation();
68
+ this.isLoading.set(false);
69
+ this.value = currentLocation;
70
+ this.onChange(this.value);
71
+ this.stateChanges.next();
72
+ }
73
+ catch {
74
+ this.isLoading.set(false);
75
+ this.error.set(true);
76
+ this.errors = { externalError: true };
77
+ }
78
+ }
79
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: GeoLocationFormInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
80
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: GeoLocationFormInputComponent, isStandalone: true, selector: "lib-geo-location-form-input", inputs: { formBuilderFunctions: { classPropertyName: "formBuilderFunctions", publicName: "formBuilderFunctions", isSignal: true, isRequired: false, transformFunction: null }, inputConfig: { classPropertyName: "inputConfig", publicName: "inputConfig", isSignal: true, isRequired: true, transformFunction: null } }, providers: [
81
+ {
82
+ provide: MatFormFieldControl,
83
+ useExisting: GeoLocationFormInputComponent
84
+ }
85
+ ], usesInheritance: true, ngImport: i0, template: "@if (!!empty) {\r\n <p class=\"empty-state\">\r\n Click icon to get your location\r\n </p>\r\n}\r\n<div class=\"coordinates-section\">\r\n @if (!empty) {\r\n <div class=\"coordinate-item\">\r\n <mat-icon color=\"primary\">map</mat-icon>\r\n <span class=\"value\">\r\n <div class=\"inner-value\">\r\n {{ value?.coords?.latitude || 'N/A' }} <span class=\"unit\">\u00B0N</span>\r\n </div>\r\n <div class=\"inner-value label\">\r\n latitude\r\n </div>\r\n </span>\r\n </div>\r\n <div class=\"coordinate-item\">\r\n <mat-icon color=\"primary\">map</mat-icon>\r\n <span class=\"value\">\r\n <div class=\"inner-value\">\r\n {{ value?.coords?.longitude || 'N/A' }}\r\n <span class=\"unit\">\u00B0E</span>\r\n </div>\r\n <div class=\"inner-value label\">\r\n longitude\r\n </div>\r\n </span>\r\n </div>\r\n <div class=\"coordinate-item\">\r\n <mat-icon color=\"primary\">zoom_in_map</mat-icon>\r\n <span class=\"value\">\r\n <div class=\"inner-value\">\r\n {{ value?.coords?.accuracy | number:'1.0-0' }}\r\n <span class=\"unit\">m</span>\r\n </div>\r\n <div class=\"inner-value label\">\r\n accuracy\r\n </div>\r\n </span>\r\n </div>\r\n }\r\n <button mat-flat-button (click)=\"getLocation()\">\r\n {{ empty ? 'Get Location' : 'Update Location' }}\r\n <mat-icon>my_location</mat-icon>\r\n </button>\r\n</div>\r\n", styles: [".coordinates-section{display:flex;padding:0;flex-direction:row;flex-wrap:wrap;gap:8px;justify-content:flex-start;align-items:center}.coordinate-item{flex:0 1 auto;width:fit-content;min-width:100px;display:flex;flex-direction:row;align-items:center;gap:8px;padding:4px;background:#f0f8ff;border-radius:8px;white-space:nowrap;font-size:small;border:solid 1px #daedfd}.empty-state{padding-left:16px;padding-right:16px;font-size:small;font-weight:500;line-height:normal;white-space:normal}mat-toolbar{max-width:100%;padding:0}.inner-value{line-height:normal;font-weight:500}.label{opacity:.6}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.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: "pipe", type: i3$1.DecimalPipe, name: "number" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
86
+ }
87
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: GeoLocationFormInputComponent, decorators: [{
88
+ type: Component,
89
+ args: [{ selector: 'lib-geo-location-form-input', imports: [CommonModule, MatButtonModule, MatIconModule], providers: [
90
+ {
91
+ provide: MatFormFieldControl,
92
+ useExisting: GeoLocationFormInputComponent
93
+ }
94
+ ], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (!!empty) {\r\n <p class=\"empty-state\">\r\n Click icon to get your location\r\n </p>\r\n}\r\n<div class=\"coordinates-section\">\r\n @if (!empty) {\r\n <div class=\"coordinate-item\">\r\n <mat-icon color=\"primary\">map</mat-icon>\r\n <span class=\"value\">\r\n <div class=\"inner-value\">\r\n {{ value?.coords?.latitude || 'N/A' }} <span class=\"unit\">\u00B0N</span>\r\n </div>\r\n <div class=\"inner-value label\">\r\n latitude\r\n </div>\r\n </span>\r\n </div>\r\n <div class=\"coordinate-item\">\r\n <mat-icon color=\"primary\">map</mat-icon>\r\n <span class=\"value\">\r\n <div class=\"inner-value\">\r\n {{ value?.coords?.longitude || 'N/A' }}\r\n <span class=\"unit\">\u00B0E</span>\r\n </div>\r\n <div class=\"inner-value label\">\r\n longitude\r\n </div>\r\n </span>\r\n </div>\r\n <div class=\"coordinate-item\">\r\n <mat-icon color=\"primary\">zoom_in_map</mat-icon>\r\n <span class=\"value\">\r\n <div class=\"inner-value\">\r\n {{ value?.coords?.accuracy | number:'1.0-0' }}\r\n <span class=\"unit\">m</span>\r\n </div>\r\n <div class=\"inner-value label\">\r\n accuracy\r\n </div>\r\n </span>\r\n </div>\r\n }\r\n <button mat-flat-button (click)=\"getLocation()\">\r\n {{ empty ? 'Get Location' : 'Update Location' }}\r\n <mat-icon>my_location</mat-icon>\r\n </button>\r\n</div>\r\n", styles: [".coordinates-section{display:flex;padding:0;flex-direction:row;flex-wrap:wrap;gap:8px;justify-content:flex-start;align-items:center}.coordinate-item{flex:0 1 auto;width:fit-content;min-width:100px;display:flex;flex-direction:row;align-items:center;gap:8px;padding:4px;background:#f0f8ff;border-radius:8px;white-space:nowrap;font-size:small;border:solid 1px #daedfd}.empty-state{padding-left:16px;padding-right:16px;font-size:small;font-weight:500;line-height:normal;white-space:normal}mat-toolbar{max-width:100%;padding:0}.inner-value{line-height:normal;font-weight:500}.label{opacity:.6}\n"] }]
95
+ }], ctorParameters: () => [], propDecorators: { formBuilderFunctions: [{ type: i0.Input, args: [{ isSignal: true, alias: "formBuilderFunctions", required: false }] }], inputConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputConfig", required: true }] }] } });
96
+
97
+ /** Wraps the inner geo-location control inside a `mat-form-field`. */
98
+ class GeoLocationComponent {
99
+ constructor() {
100
+ this.inputConfig = input.required(...(ngDevMode ? [{ debugName: "inputConfig" }] : /* istanbul ignore next */ []));
101
+ this.formGroup = input.required(...(ngDevMode ? [{ debugName: "formGroup" }] : /* istanbul ignore next */ []));
102
+ this.editorMode = input(false, ...(ngDevMode ? [{ debugName: "editorMode" }] : /* istanbul ignore next */ []));
103
+ this.formBuilderFunctions = input(undefined, ...(ngDevMode ? [{ debugName: "formBuilderFunctions" }] : /* istanbul ignore next */ []));
104
+ this.reload = output();
105
+ this.errorMessage = computed(() => getInputErrorMessage(this.inputConfig(), this.formGroup()), ...(ngDevMode ? [{ debugName: "errorMessage" }] : /* istanbul ignore next */ []));
106
+ }
107
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: GeoLocationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
108
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: GeoLocationComponent, isStandalone: true, selector: "lib-geo-location", 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-geo-location-form-input\r\n [inputConfig]=\"inputConfig\"\r\n [formControlName]=\"inputConfig.id\"\r\n [required]=\"inputConfig.required\"\r\n ></lib-geo-location-form-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.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.prefixIcon) {\r\n <mat-icon matPrefix>{{ inputConfig.prefixIcon }}</mat-icon>\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$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.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.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i5.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: TFormInputStatusComponent, selector: "lib-t-form-input-status", inputs: ["inputConfig"] }, { kind: "component", type: GeoLocationFormInputComponent, selector: "lib-geo-location-form-input", inputs: ["formBuilderFunctions", "inputConfig"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
109
+ }
110
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: GeoLocationComponent, decorators: [{
111
+ type: Component,
112
+ args: [{ selector: 'lib-geo-location', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
113
+ ReactiveFormsModule,
114
+ MatFormFieldModule,
115
+ MatIconModule,
116
+ MatButtonModule,
117
+ MatTooltipModule,
118
+ TFormInputStatusComponent,
119
+ GeoLocationFormInputComponent,
120
+ ], 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-geo-location-form-input\r\n [inputConfig]=\"inputConfig\"\r\n [formControlName]=\"inputConfig.id\"\r\n [required]=\"inputConfig.required\"\r\n ></lib-geo-location-form-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.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.prefixIcon) {\r\n <mat-icon matPrefix>{{ inputConfig.prefixIcon }}</mat-icon>\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"] }]
121
+ }], 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"] }] } });
122
+
123
+ export { GeoLocationComponent };
124
+ //# sourceMappingURL=ngx-t-forms-geo-location.component-Bosp1UzR.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ngx-t-forms-geo-location.component-Bosp1UzR.mjs","sources":["../../../projects/ngx-t-forms/src/lib/components/t-form-input/elements/Geo-location-form-input/functions/getGeoLocation.ts","../../../projects/ngx-t-forms/src/lib/components/t-form-input/elements/Geo-location-form-input/elements/geo-location-form-input/geo-location-form-input.component.ts","../../../projects/ngx-t-forms/src/lib/components/t-form-input/elements/Geo-location-form-input/elements/geo-location-form-input/geo-location-form-input.component.html","../../../projects/ngx-t-forms/src/lib/components/t-form-input/elements/Geo-location-form-input/geo-location.component.ts","../../../projects/ngx-t-forms/src/lib/components/t-form-input/elements/Geo-location-form-input/geo-location.component.html"],"sourcesContent":["\r\n\r\nconst DEFAULT_OPTIONS: PositionOptions = {\r\n enableHighAccuracy: true,\r\n timeout: 5000,\r\n maximumAge: 0\r\n};\r\n\r\nconst getGeoLocation = (options: PositionOptions = DEFAULT_OPTIONS): Promise<GeolocationPosition> => {\r\n return new Promise((resolve, reject) => {\r\n if (!navigator.geolocation) {\r\n const error= {\r\n code: 0,\r\n message: 'Geolocation is not supported by this browser',\r\n PERMISSION_DENIED: 1,\r\n POSITION_UNAVAILABLE: 2,\r\n TIMEOUT: 3\r\n };\r\n reject(error);\r\n return;\r\n }\r\n\r\n navigator.geolocation.getCurrentPosition(\r\n (position: GeolocationPosition) => resolve(position),\r\n (error: GeolocationPositionError) => reject(error),\r\n options\r\n );\r\n });\r\n};\r\n\r\nexport default getGeoLocation;","import { ChangeDetectionStrategy, Component, ElementRef, PLATFORM_ID, inject, input, signal } from '@angular/core';\r\nimport { isPlatformBrowser } from '@angular/common';\r\n\r\nimport { MatFormFieldControl } from '@angular/material/form-field';\r\nimport { MatButtonModule } from '@angular/material/button';\r\nimport { MatIconModule } from '@angular/material/icon';\r\nimport { CommonModule } from '@angular/common';\r\nimport { NgControl } from '@angular/forms';\r\nimport type { FormBuilderFunctions, ITowerStepColumn } from 'ngx-t-forms-types';\r\nimport getGeoLocation from '../../functions/getGeoLocation';\r\nimport { BaseCustomInput, BaseCustomInputConfig } from '../../../../../../services/core/t-input-controller/functions/baseCustomInput';\r\n\r\nconst customInputConfig: BaseCustomInputConfig = {\r\n controlType: 'lib-geo-location-form-input',\r\n nextId: 0\r\n};\r\n\r\n@Component({\r\n selector: 'lib-geo-location-form-input',\r\n imports: [CommonModule, MatButtonModule, MatIconModule],\r\n templateUrl: './geo-location-form-input.component.html',\r\n styleUrl: './geo-location-form-input.component.css',\r\n providers: [\r\n {\r\n provide: MatFormFieldControl,\r\n useExisting: GeoLocationFormInputComponent\r\n }\r\n ],\r\n changeDetection: ChangeDetectionStrategy.OnPush\r\n})\r\nexport class GeoLocationFormInputComponent extends BaseCustomInput<GeolocationPosition | null> {\r\n readonly formBuilderFunctions = input<FormBuilderFunctions | undefined>(undefined);\r\n readonly inputConfig = input.required<ITowerStepColumn>();\r\n\r\n protected readonly isLoading = signal(false);\r\n protected readonly error = signal(false);\r\n\r\n readonly #platformId = inject(PLATFORM_ID);\r\n\r\n constructor() {\r\n super(\r\n inject(NgControl, { optional: true, self: true }) as NgControl,\r\n inject<ElementRef<HTMLElement>>(ElementRef),\r\n customInputConfig\r\n );\r\n }\r\n\r\n override get empty(): boolean {\r\n const n = this.value;\r\n // Check for null, undefined, or empty string, but allow 0\r\n return n === null || n === undefined || (n as unknown) === '';\r\n }\r\n\r\n override get shouldLabelFloat(): boolean {\r\n return true;\r\n }\r\n\r\n protected async getLocation(): Promise<void> {\r\n if (!isPlatformBrowser(this.#platformId)) return;\r\n try {\r\n this.error.set(false);\r\n this.isLoading.set(true);\r\n const currentLocation = await getGeoLocation();\r\n this.isLoading.set(false);\r\n this.value = currentLocation;\r\n this.onChange(this.value);\r\n this.stateChanges.next();\r\n } catch {\r\n this.isLoading.set(false);\r\n this.error.set(true);\r\n this.errors = { externalError: true };\r\n }\r\n }\r\n}\r\n","@if (!!empty) {\r\n <p class=\"empty-state\">\r\n Click icon to get your location\r\n </p>\r\n}\r\n<div class=\"coordinates-section\">\r\n @if (!empty) {\r\n <div class=\"coordinate-item\">\r\n <mat-icon color=\"primary\">map</mat-icon>\r\n <span class=\"value\">\r\n <div class=\"inner-value\">\r\n {{ value?.coords?.latitude || 'N/A' }} <span class=\"unit\">°N</span>\r\n </div>\r\n <div class=\"inner-value label\">\r\n latitude\r\n </div>\r\n </span>\r\n </div>\r\n <div class=\"coordinate-item\">\r\n <mat-icon color=\"primary\">map</mat-icon>\r\n <span class=\"value\">\r\n <div class=\"inner-value\">\r\n {{ value?.coords?.longitude || 'N/A' }}\r\n <span class=\"unit\">°E</span>\r\n </div>\r\n <div class=\"inner-value label\">\r\n longitude\r\n </div>\r\n </span>\r\n </div>\r\n <div class=\"coordinate-item\">\r\n <mat-icon color=\"primary\">zoom_in_map</mat-icon>\r\n <span class=\"value\">\r\n <div class=\"inner-value\">\r\n {{ value?.coords?.accuracy | number:'1.0-0' }}\r\n <span class=\"unit\">m</span>\r\n </div>\r\n <div class=\"inner-value label\">\r\n accuracy\r\n </div>\r\n </span>\r\n </div>\r\n }\r\n <button mat-flat-button (click)=\"getLocation()\">\r\n {{ empty ? 'Get Location' : 'Update Location' }}\r\n <mat-icon>my_location</mat-icon>\r\n </button>\r\n</div>\r\n","import { ChangeDetectionStrategy, Component, computed, input, output } from '@angular/core';\r\nimport { FormGroup, ReactiveFormsModule } from '@angular/forms';\r\nimport { MatFormFieldModule } from '@angular/material/form-field';\r\nimport { MatIconModule } from '@angular/material/icon';\r\nimport { MatButtonModule } from '@angular/material/button';\r\nimport { MatTooltipModule } from '@angular/material/tooltip';\r\nimport type { FormBuilderFunctions, ITowerStepColumn } from 'ngx-t-forms-types';\r\nimport { TFormInputStatusComponent } from '../../../t-form-input-status/t-form-input-status.component';\r\nimport { GeoLocationFormInputComponent } from './elements/geo-location-form-input/geo-location-form-input.component';\r\nimport { getInputErrorMessage } from '../../../../services/core/t-input-controller/functions/inputErrorMessage';\r\n\r\n/** Wraps the inner geo-location control inside a `mat-form-field`. */\r\n@Component({\r\n selector: 'lib-geo-location',\r\n templateUrl: './geo-location.component.html',\r\n styleUrl: './geo-location.component.css',\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n imports: [\r\n ReactiveFormsModule,\r\n MatFormFieldModule,\r\n MatIconModule,\r\n MatButtonModule,\r\n MatTooltipModule,\r\n TFormInputStatusComponent,\r\n GeoLocationFormInputComponent,\r\n ],\r\n})\r\nexport class GeoLocationComponent {\r\n readonly inputConfig = input.required<ITowerStepColumn>();\r\n readonly formGroup = input.required<FormGroup>();\r\n readonly editorMode = input<boolean>(false);\r\n readonly formBuilderFunctions = input<FormBuilderFunctions | undefined>(undefined);\r\n readonly reload = output<void>();\r\n\r\n protected readonly errorMessage = computed(() =>\r\n getInputErrorMessage(this.inputConfig(), this.formGroup()),\r\n );\r\n}\r\n","<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-geo-location-form-input\r\n [inputConfig]=\"inputConfig\"\r\n [formControlName]=\"inputConfig.id\"\r\n [required]=\"inputConfig.required\"\r\n ></lib-geo-location-form-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.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.prefixIcon) {\r\n <mat-icon matPrefix>{{ inputConfig.prefixIcon }}</mat-icon>\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"],"names":["i2","i3","i4"],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import { ElementTypes } from 'ngx-t-forms-types';
2
+
3
+ const InputElementIconMap = {
4
+ [ElementTypes.Input]: 'text_fields',
5
+ [ElementTypes.Location]: 'location_on',
6
+ [ElementTypes.AutoCompleteInput]: 'manage_search',
7
+ [ElementTypes.Toggle]: 'toggle_on',
8
+ [ElementTypes.Select]: 'arrow_drop_down_circle',
9
+ [ElementTypes.PaginatedSelectionTable]: 'table_chart',
10
+ [ElementTypes.IconSelect]: 'emoji_emotions',
11
+ [ElementTypes.Textarea]: 'notes',
12
+ [ElementTypes.DatePicker]: 'calendar_today',
13
+ [ElementTypes.DateRangePicker]: 'date_range',
14
+ [ElementTypes.FileUpload]: 'upload_file',
15
+ [ElementTypes.Signature]: 'draw',
16
+ [ElementTypes.ImageCapture]: 'photo_camera',
17
+ [ElementTypes.SectionTitle]: 'title',
18
+ [ElementTypes.MultipleInput]: 'list_alt',
19
+ [ElementTypes.Editor]: 'edit_note',
20
+ [ElementTypes.MscoaSelection]: 'account_tree',
21
+ [ElementTypes.WorkflowDocumentPicker]: 'description',
22
+ [ElementTypes.WorkflowAdjudication]: 'gavel',
23
+ };
24
+ function getInputIcon(element) {
25
+ if (!element)
26
+ return 'help_outline';
27
+ return InputElementIconMap[element] ?? 'help_outline';
28
+ }
29
+
30
+ export { getInputIcon as g };
31
+ //# sourceMappingURL=ngx-t-forms-getInputIcon-B4ADgevZ.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ngx-t-forms-getInputIcon-B4ADgevZ.mjs","sources":["../../../projects/ngx-t-forms/src/lib/shared/functions/getInputIcon.ts"],"sourcesContent":["import { ElementTypes } from 'ngx-t-forms-types';\r\n\r\nexport const InputElementIconMap: Record<ElementTypes, string> = {\r\n [ElementTypes.Input]: 'text_fields',\r\n [ElementTypes.Location]: 'location_on',\r\n [ElementTypes.AutoCompleteInput]: 'manage_search',\r\n [ElementTypes.Toggle]: 'toggle_on',\r\n [ElementTypes.Select]: 'arrow_drop_down_circle',\r\n [ElementTypes.PaginatedSelectionTable]: 'table_chart',\r\n [ElementTypes.IconSelect]: 'emoji_emotions',\r\n [ElementTypes.Textarea]: 'notes',\r\n [ElementTypes.DatePicker]: 'calendar_today',\r\n [ElementTypes.DateRangePicker]: 'date_range',\r\n [ElementTypes.FileUpload]: 'upload_file',\r\n [ElementTypes.Signature]: 'draw',\r\n [ElementTypes.ImageCapture]: 'photo_camera',\r\n [ElementTypes.SectionTitle]: 'title',\r\n [ElementTypes.MultipleInput]: 'list_alt',\r\n [ElementTypes.Editor]: 'edit_note',\r\n [ElementTypes.MscoaSelection]: 'account_tree',\r\n [ElementTypes.WorkflowDocumentPicker]: 'description',\r\n [ElementTypes.WorkflowAdjudication]: 'gavel',\r\n};\r\n\r\nexport function getInputIcon(element: ElementTypes | undefined | null): string {\r\n if (!element) return 'help_outline';\r\n return InputElementIconMap[element] ?? 'help_outline';\r\n}\r\n"],"names":[],"mappings":";;AAEO,MAAM,mBAAmB,GAAiC;AAC/D,IAAA,CAAC,YAAY,CAAC,KAAK,GAAG,aAAa;AACnC,IAAA,CAAC,YAAY,CAAC,QAAQ,GAAG,aAAa;AACtC,IAAA,CAAC,YAAY,CAAC,iBAAiB,GAAG,eAAe;AACjD,IAAA,CAAC,YAAY,CAAC,MAAM,GAAG,WAAW;AAClC,IAAA,CAAC,YAAY,CAAC,MAAM,GAAG,wBAAwB;AAC/C,IAAA,CAAC,YAAY,CAAC,uBAAuB,GAAG,aAAa;AACrD,IAAA,CAAC,YAAY,CAAC,UAAU,GAAG,gBAAgB;AAC3C,IAAA,CAAC,YAAY,CAAC,QAAQ,GAAG,OAAO;AAChC,IAAA,CAAC,YAAY,CAAC,UAAU,GAAG,gBAAgB;AAC3C,IAAA,CAAC,YAAY,CAAC,eAAe,GAAG,YAAY;AAC5C,IAAA,CAAC,YAAY,CAAC,UAAU,GAAG,aAAa;AACxC,IAAA,CAAC,YAAY,CAAC,SAAS,GAAG,MAAM;AAChC,IAAA,CAAC,YAAY,CAAC,YAAY,GAAG,cAAc;AAC3C,IAAA,CAAC,YAAY,CAAC,YAAY,GAAG,OAAO;AACpC,IAAA,CAAC,YAAY,CAAC,aAAa,GAAG,UAAU;AACxC,IAAA,CAAC,YAAY,CAAC,MAAM,GAAG,WAAW;AAClC,IAAA,CAAC,YAAY,CAAC,cAAc,GAAG,cAAc;AAC7C,IAAA,CAAC,YAAY,CAAC,sBAAsB,GAAG,aAAa;AACpD,IAAA,CAAC,YAAY,CAAC,oBAAoB,GAAG,OAAO;CAC7C;AAEK,SAAU,YAAY,CAAC,OAAwC,EAAA;AACnE,IAAA,IAAI,CAAC,OAAO;AAAE,QAAA,OAAO,cAAc;AACnC,IAAA,OAAO,mBAAmB,CAAC,OAAO,CAAC,IAAI,cAAc;AACvD;;;;"}
@@ -0,0 +1,180 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, ElementRef, input, viewChild, PLATFORM_ID, ChangeDetectionStrategy, Component, output, computed } from '@angular/core';
3
+ import * as i1$1 from '@angular/forms';
4
+ import { NgControl, ReactiveFormsModule } from '@angular/forms';
5
+ import * as i2 from '@angular/material/form-field';
6
+ import { MatFormFieldControl, MatFormFieldModule } from '@angular/material/form-field';
7
+ import * as i3 from '@angular/material/icon';
8
+ import { MatIconModule } from '@angular/material/icon';
9
+ import * as i1 from '@angular/material/button';
10
+ import { MatButtonModule } from '@angular/material/button';
11
+ import * as i5$1 from '@angular/material/tooltip';
12
+ import { MatTooltipModule } from '@angular/material/tooltip';
13
+ import { B as BaseCustomInput, m as getInputErrorMessage, n as TFormInputStatusComponent } from './ngx-t-forms-ngx-t-forms-u_kigDid.mjs';
14
+ import { isPlatformBrowser } from '@angular/common';
15
+ import * as i5 from '@angular/material/toolbar';
16
+ import { MatToolbarModule } from '@angular/material/toolbar';
17
+
18
+ // Image capture
19
+ async function setupDevices(cameraCallback) {
20
+ // SSR guard (Trap 14): free helper has no DI context. Returning `undefined`
21
+ // matches the existing "no media device" branch — caller contract preserved.
22
+ if (typeof navigator === 'undefined')
23
+ return undefined;
24
+ if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
25
+ try {
26
+ const stream = await navigator.mediaDevices.getUserMedia({
27
+ video: true,
28
+ });
29
+ if (stream) {
30
+ cameraCallback(stream);
31
+ return stream;
32
+ }
33
+ else {
34
+ return 'You have no output video device';
35
+ }
36
+ }
37
+ catch (e) {
38
+ return e;
39
+ }
40
+ }
41
+ return undefined;
42
+ }
43
+ function fileUploaderValidator(control) {
44
+ // Implement your validation logic here
45
+ const file = control.value;
46
+ // Example validation: Check if file is provided
47
+ if (!file || !file.base64) {
48
+ return { requiredFile: 'You must upload a file.' };
49
+ }
50
+ // Add more validation logic as needed
51
+ // ...
52
+ return null; // Return null if no validation errors
53
+ }
54
+
55
+ const customInputConfig = {
56
+ controlType: 'app-camera-capture',
57
+ nextId: 0,
58
+ };
59
+ class CameraCaptureComponent extends BaseCustomInput {
60
+ #platformId;
61
+ constructor() {
62
+ super(inject(NgControl, { optional: true, self: true }), inject(ElementRef), customInputConfig);
63
+ this.inputConfig = input.required(...(ngDevMode ? [{ debugName: "inputConfig" }] : /* istanbul ignore next */ []));
64
+ this.video = viewChild.required('video');
65
+ this.canvas = viewChild.required('canvas');
66
+ this.WIDTH = 640;
67
+ this.HEIGHT = 480;
68
+ this.captures = [];
69
+ this.isCaptured = false;
70
+ this.videoMode = false;
71
+ this.#platformId = inject(PLATFORM_ID);
72
+ this.setup = (stream) => {
73
+ if (!isPlatformBrowser(this.#platformId))
74
+ return;
75
+ const videoEl = this.video()?.nativeElement;
76
+ if (!videoEl)
77
+ return;
78
+ try {
79
+ videoEl.srcObject = stream;
80
+ void videoEl.play();
81
+ }
82
+ catch {
83
+ // Ignored: play() may reject if the element is detached or autoplay is blocked.
84
+ }
85
+ };
86
+ }
87
+ get empty() {
88
+ return !this.value;
89
+ }
90
+ get shouldLabelFloat() {
91
+ return this.focused || !this.empty;
92
+ }
93
+ recapture() {
94
+ if (!isPlatformBrowser(this.#platformId))
95
+ return;
96
+ const videoEl = this.video()?.nativeElement;
97
+ if (!videoEl)
98
+ return;
99
+ videoEl.srcObject = null;
100
+ this.isCaptured = false;
101
+ setupDevices(this.setup);
102
+ this.value = null;
103
+ this.stateChanges.next();
104
+ }
105
+ touch() {
106
+ this.markAsTouched();
107
+ }
108
+ capture() {
109
+ if (!isPlatformBrowser(this.#platformId))
110
+ return;
111
+ const videoEl = this.video()?.nativeElement;
112
+ const canvasEl = this.canvas()?.nativeElement;
113
+ if (!videoEl || !canvasEl)
114
+ return;
115
+ this.touch();
116
+ this.drawImageToCanvas(videoEl);
117
+ const fileType = this.inputConfig()?.fileType;
118
+ this.value = {
119
+ fileName: new Date(),
120
+ type: fileType,
121
+ base64: canvasEl.toDataURL('image/png'),
122
+ };
123
+ this.captures.push(canvasEl.toDataURL('image/png'));
124
+ this.isCaptured = true;
125
+ this.stopVideo();
126
+ this.onChange(this.value);
127
+ this.stateChanges.next();
128
+ }
129
+ stopVideo() {
130
+ if (!isPlatformBrowser(this.#platformId))
131
+ return;
132
+ const videoEl = this.video()?.nativeElement;
133
+ const src = videoEl?.srcObject;
134
+ if (src && src instanceof MediaStream) {
135
+ src.getTracks().forEach(track => track.stop());
136
+ }
137
+ }
138
+ drawImageToCanvas(image) {
139
+ if (!isPlatformBrowser(this.#platformId))
140
+ return;
141
+ const canvasEl = this.canvas()?.nativeElement;
142
+ const ctx = canvasEl?.getContext('2d');
143
+ if (!ctx)
144
+ return;
145
+ ctx.drawImage(image, 0, 0, this.WIDTH, this.HEIGHT);
146
+ }
147
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: CameraCaptureComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
148
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: CameraCaptureComponent, isStandalone: true, selector: "lib-camera-capture", inputs: { inputConfig: { classPropertyName: "inputConfig", publicName: "inputConfig", isSignal: true, isRequired: true, transformFunction: null } }, providers: [{ provide: MatFormFieldControl, useExisting: CameraCaptureComponent }], viewQueries: [{ propertyName: "video", first: true, predicate: ["video"], descendants: true, isSignal: true }, { propertyName: "canvas", first: true, predicate: ["canvas"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<br>\r\n<div class=\"video-container\">\r\n <video\r\n style=\"margin: auto;\"\r\n [style.display]=\"!isCaptured ? 'block' : 'none'\"\r\n #video\r\n id=\"video\"\r\n [width]=\"WIDTH\"\r\n [height]=\"HEIGHT\"\r\n autoplay\r\n ></video>\r\n <canvas\r\n [style.display]=\"isCaptured ? 'block' : 'none'\"\r\n #canvas\r\n id=\"canvas\"\r\n [width]=\"WIDTH\"\r\n [height]=\"HEIGHT\"\r\n ></canvas>\r\n</div>\r\n<mat-toolbar style=\"background: none;\">\r\n <span class=\"spacer\"></span>\r\n <button (click)=\"isCaptured ? recapture() : capture()\" [color]=\"isCaptured?'primary':'warn'\" mat-icon-button>\r\n <mat-icon>\r\n photo_camera\r\n </mat-icon>\r\n\r\n </button>\r\n @if (!isCaptured) {\r\n <button (click)=\"stopVideo()\" mat-icon-button>\r\n <mat-icon>\r\n stop\r\n </mat-icon>\r\n\r\n </button>\r\n }\r\n <span class=\"spacer\"></span>\r\n</mat-toolbar>\r\n", styles: [""], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatToolbarModule }, { kind: "component", type: i5.MatToolbar, selector: "mat-toolbar", inputs: ["color"], exportAs: ["matToolbar"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
149
+ }
150
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: CameraCaptureComponent, decorators: [{
151
+ type: Component,
152
+ args: [{ selector: 'lib-camera-capture', imports: [MatIconModule, MatToolbarModule, MatButtonModule], providers: [{ provide: MatFormFieldControl, useExisting: CameraCaptureComponent }], changeDetection: ChangeDetectionStrategy.OnPush, template: "<br>\r\n<div class=\"video-container\">\r\n <video\r\n style=\"margin: auto;\"\r\n [style.display]=\"!isCaptured ? 'block' : 'none'\"\r\n #video\r\n id=\"video\"\r\n [width]=\"WIDTH\"\r\n [height]=\"HEIGHT\"\r\n autoplay\r\n ></video>\r\n <canvas\r\n [style.display]=\"isCaptured ? 'block' : 'none'\"\r\n #canvas\r\n id=\"canvas\"\r\n [width]=\"WIDTH\"\r\n [height]=\"HEIGHT\"\r\n ></canvas>\r\n</div>\r\n<mat-toolbar style=\"background: none;\">\r\n <span class=\"spacer\"></span>\r\n <button (click)=\"isCaptured ? recapture() : capture()\" [color]=\"isCaptured?'primary':'warn'\" mat-icon-button>\r\n <mat-icon>\r\n photo_camera\r\n </mat-icon>\r\n\r\n </button>\r\n @if (!isCaptured) {\r\n <button (click)=\"stopVideo()\" mat-icon-button>\r\n <mat-icon>\r\n stop\r\n </mat-icon>\r\n\r\n </button>\r\n }\r\n <span class=\"spacer\"></span>\r\n</mat-toolbar>\r\n" }]
153
+ }], ctorParameters: () => [], propDecorators: { inputConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputConfig", required: true }] }], video: [{ type: i0.ViewChild, args: ['video', { isSignal: true }] }], canvas: [{ type: i0.ViewChild, args: ['canvas', { isSignal: true }] }] } });
154
+
155
+ /** Wraps the camera-capture control inside a `mat-form-field`. */
156
+ class ImageCaptureInputElementComponent {
157
+ constructor() {
158
+ this.inputConfig = input.required(...(ngDevMode ? [{ debugName: "inputConfig" }] : /* istanbul ignore next */ []));
159
+ this.formGroup = input.required(...(ngDevMode ? [{ debugName: "formGroup" }] : /* istanbul ignore next */ []));
160
+ this.reload = output();
161
+ this.errorMessage = computed(() => getInputErrorMessage(this.inputConfig(), this.formGroup()), ...(ngDevMode ? [{ debugName: "errorMessage" }] : /* istanbul ignore next */ []));
162
+ }
163
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: ImageCaptureInputElementComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
164
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: ImageCaptureInputElementComponent, isStandalone: true, selector: "lib-image-capture-input-element", inputs: { inputConfig: { classPropertyName: "inputConfig", publicName: "inputConfig", isSignal: true, isRequired: true, transformFunction: null }, formGroup: { classPropertyName: "formGroup", publicName: "formGroup", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { reload: "reload" }, ngImport: i0, template: "<ng-container [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-camera-capture\r\n [required]=\"inputConfig.required\"\r\n [inputConfig]=\"inputConfig\"\r\n [formControlName]=\"inputConfig.id\"\r\n ></lib-camera-capture>\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.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.prefixIcon) {\r\n <mat-icon matPrefix>{{ inputConfig.prefixIcon }}</mat-icon>\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</ng-container>\r\n", styles: ["mat-form-field{width:100%!important}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$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.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.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i5$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: TFormInputStatusComponent, selector: "lib-t-form-input-status", inputs: ["inputConfig"] }, { kind: "component", type: CameraCaptureComponent, selector: "lib-camera-capture", inputs: ["inputConfig"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
165
+ }
166
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: ImageCaptureInputElementComponent, decorators: [{
167
+ type: Component,
168
+ args: [{ selector: 'lib-image-capture-input-element', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
169
+ ReactiveFormsModule,
170
+ MatFormFieldModule,
171
+ MatIconModule,
172
+ MatButtonModule,
173
+ MatTooltipModule,
174
+ TFormInputStatusComponent,
175
+ CameraCaptureComponent,
176
+ ], template: "<ng-container [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-camera-capture\r\n [required]=\"inputConfig.required\"\r\n [inputConfig]=\"inputConfig\"\r\n [formControlName]=\"inputConfig.id\"\r\n ></lib-camera-capture>\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.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.prefixIcon) {\r\n <mat-icon matPrefix>{{ inputConfig.prefixIcon }}</mat-icon>\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</ng-container>\r\n", styles: ["mat-form-field{width:100%!important}mat-form-field .input-sync-button{display:none}mat-form-field:hover .input-sync-button{display:inline-block}\n"] }]
177
+ }], propDecorators: { inputConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputConfig", required: true }] }], formGroup: [{ type: i0.Input, args: [{ isSignal: true, alias: "formGroup", required: true }] }], reload: [{ type: i0.Output, args: ["reload"] }] } });
178
+
179
+ export { ImageCaptureInputElementComponent };
180
+ //# sourceMappingURL=ngx-t-forms-image-capture-input-element.component-C1g7Z0cK.mjs.map