ngx-t-forms 2.0.30 → 2.0.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (161) hide show
  1. package/fesm2022/ngx-t-forms-auto-complete-input-element.component-CaXs4561.mjs +104 -0
  2. package/fesm2022/ngx-t-forms-auto-complete-input-element.component-CaXs4561.mjs.map +1 -0
  3. package/fesm2022/ngx-t-forms-basic-input-input-element.component-Dotyd-Qs.mjs +85 -0
  4. package/fesm2022/ngx-t-forms-basic-input-input-element.component-Dotyd-Qs.mjs.map +1 -0
  5. package/fesm2022/ngx-t-forms-calculated-field-rules.component-BhxT6tRq.mjs +643 -0
  6. package/fesm2022/ngx-t-forms-calculated-field-rules.component-BhxT6tRq.mjs.map +1 -0
  7. package/fesm2022/ngx-t-forms-chip-options-creator-editor.component-d4QeVhsp.mjs +97 -0
  8. package/fesm2022/ngx-t-forms-chip-options-creator-editor.component-d4QeVhsp.mjs.map +1 -0
  9. package/fesm2022/ngx-t-forms-config-mscoa-additional-inputs.component-Gn8exJ9a.mjs +195 -0
  10. package/fesm2022/ngx-t-forms-config-mscoa-additional-inputs.component-Gn8exJ9a.mjs.map +1 -0
  11. package/fesm2022/ngx-t-forms-data-source-picker.component-Ebf_if9j.mjs +261 -0
  12. package/fesm2022/ngx-t-forms-data-source-picker.component-Ebf_if9j.mjs.map +1 -0
  13. package/fesm2022/ngx-t-forms-date-picker-input-element.component-kdinBGRA.mjs +85 -0
  14. package/fesm2022/ngx-t-forms-date-picker-input-element.component-kdinBGRA.mjs.map +1 -0
  15. package/fesm2022/ngx-t-forms-date-range-picker-input-element.component-4W6uvrDU.mjs +156 -0
  16. package/fesm2022/ngx-t-forms-date-range-picker-input-element.component-4W6uvrDU.mjs.map +1 -0
  17. package/fesm2022/ngx-t-forms-document-list-label-config-editor.component-CR6EvgJO.mjs +368 -0
  18. package/fesm2022/ngx-t-forms-document-list-label-config-editor.component-CR6EvgJO.mjs.map +1 -0
  19. package/fesm2022/ngx-t-forms-document-picker.component-BThdRFec.mjs +704 -0
  20. package/fesm2022/ngx-t-forms-document-picker.component-BThdRFec.mjs.map +1 -0
  21. package/fesm2022/ngx-t-forms-editor-input-element.component-1X6uAPeZ.mjs +294 -0
  22. package/fesm2022/ngx-t-forms-editor-input-element.component-1X6uAPeZ.mjs.map +1 -0
  23. package/fesm2022/ngx-t-forms-editor-js-input.component-5MD8wRj0.mjs +240 -0
  24. package/fesm2022/ngx-t-forms-editor-js-input.component-5MD8wRj0.mjs.map +1 -0
  25. package/fesm2022/ngx-t-forms-file-upload-input-element.component-BAtuymMY.mjs +205 -0
  26. package/fesm2022/ngx-t-forms-file-upload-input-element.component-BAtuymMY.mjs.map +1 -0
  27. package/fesm2022/ngx-t-forms-form-input-selector.component-B42xP3jh.mjs +86 -0
  28. package/fesm2022/ngx-t-forms-form-input-selector.component-B42xP3jh.mjs.map +1 -0
  29. package/fesm2022/ngx-t-forms-form-json-view.component-DnnLXqR0.mjs +22 -0
  30. package/fesm2022/ngx-t-forms-form-json-view.component-DnnLXqR0.mjs.map +1 -0
  31. package/fesm2022/ngx-t-forms-form-payload-projection.component-Ip9ewB18.mjs +179 -0
  32. package/fesm2022/ngx-t-forms-form-payload-projection.component-Ip9ewB18.mjs.map +1 -0
  33. package/fesm2022/ngx-t-forms-form-section-stepper.component-BPgPfZSy.mjs +319 -0
  34. package/fesm2022/ngx-t-forms-form-section-stepper.component-BPgPfZSy.mjs.map +1 -0
  35. package/fesm2022/ngx-t-forms-forms-builder-menu.component-Dv0Dfw79.mjs +379 -0
  36. package/fesm2022/ngx-t-forms-forms-builder-menu.component-Dv0Dfw79.mjs.map +1 -0
  37. package/fesm2022/ngx-t-forms-geo-location.component-Bmd84Gcb.mjs +124 -0
  38. package/fesm2022/ngx-t-forms-geo-location.component-Bmd84Gcb.mjs.map +1 -0
  39. package/fesm2022/ngx-t-forms-getInputIcon-B4ADgevZ.mjs +31 -0
  40. package/fesm2022/ngx-t-forms-getInputIcon-B4ADgevZ.mjs.map +1 -0
  41. package/fesm2022/ngx-t-forms-image-capture-input-element.component-CUd04Ghl.mjs +180 -0
  42. package/fesm2022/ngx-t-forms-image-capture-input-element.component-CUd04Ghl.mjs.map +1 -0
  43. package/fesm2022/ngx-t-forms-index-BcrQ01DQ.mjs +2 -0
  44. package/fesm2022/ngx-t-forms-index-BcrQ01DQ.mjs.map +1 -0
  45. package/fesm2022/ngx-t-forms-input-custom.component-Cn-KH0Lb.mjs +105 -0
  46. package/fesm2022/ngx-t-forms-input-custom.component-Cn-KH0Lb.mjs.map +1 -0
  47. package/fesm2022/ngx-t-forms-input-editor.component-DLru1Ezu.mjs +193 -0
  48. package/fesm2022/ngx-t-forms-input-editor.component-DLru1Ezu.mjs.map +1 -0
  49. package/fesm2022/{ngx-t-forms-map-mat-options-keys-SM5XM9uy.mjs → ngx-t-forms-map-mat-options-keys-CVlPdrCO.mjs} +12 -14
  50. package/fesm2022/ngx-t-forms-map-mat-options-keys-CVlPdrCO.mjs.map +1 -0
  51. package/fesm2022/ngx-t-forms-mat-chip-list-editor.component-BWisS3Em.mjs +66 -0
  52. package/fesm2022/ngx-t-forms-mat-chip-list-editor.component-BWisS3Em.mjs.map +1 -0
  53. package/fesm2022/ngx-t-forms-mat-slider-editor.component-CTSBrM-j.mjs +211 -0
  54. package/fesm2022/ngx-t-forms-mat-slider-editor.component-CTSBrM-j.mjs.map +1 -0
  55. package/fesm2022/ngx-t-forms-mat-slider-toggle-editor.component-CcYiwx-8.mjs +165 -0
  56. package/fesm2022/ngx-t-forms-mat-slider-toggle-editor.component-CcYiwx-8.mjs.map +1 -0
  57. package/fesm2022/ngx-t-forms-missing-form-configs.component-DxdynZY6.mjs +38 -0
  58. package/fesm2022/ngx-t-forms-missing-form-configs.component-DxdynZY6.mjs.map +1 -0
  59. package/fesm2022/ngx-t-forms-mscoa-chart-toolbar.component-D4Xa_Yi0.mjs +38 -0
  60. package/fesm2022/ngx-t-forms-mscoa-chart-toolbar.component-D4Xa_Yi0.mjs.map +1 -0
  61. package/fesm2022/ngx-t-forms-mscoa-error-display.component-99DpVSy7.mjs +126 -0
  62. package/fesm2022/ngx-t-forms-mscoa-error-display.component-99DpVSy7.mjs.map +1 -0
  63. package/fesm2022/ngx-t-forms-mscoa-segment-config.component-Bo0aDEMy.mjs +447 -0
  64. package/fesm2022/ngx-t-forms-mscoa-segment-config.component-Bo0aDEMy.mjs.map +1 -0
  65. package/fesm2022/ngx-t-forms-mscoa-temporary-hint.component-B1Z-IXSL.mjs +74 -0
  66. package/fesm2022/ngx-t-forms-mscoa-temporary-hint.component-B1Z-IXSL.mjs.map +1 -0
  67. package/fesm2022/ngx-t-forms-multiple-input-input-element.component-C8JP3D6r.mjs +905 -0
  68. package/fesm2022/ngx-t-forms-multiple-input-input-element.component-C8JP3D6r.mjs.map +1 -0
  69. package/fesm2022/ngx-t-forms-ngx-t-forms-C2G8_WQk.mjs +20310 -0
  70. package/fesm2022/ngx-t-forms-ngx-t-forms-C2G8_WQk.mjs.map +1 -0
  71. package/fesm2022/ngx-t-forms-paginated-selection-table-0OI1ikWW.mjs +555 -0
  72. package/fesm2022/ngx-t-forms-paginated-selection-table-0OI1ikWW.mjs.map +1 -0
  73. package/fesm2022/ngx-t-forms-pipeline-generator.component-CZ21sd77.mjs +748 -0
  74. package/fesm2022/ngx-t-forms-pipeline-generator.component-CZ21sd77.mjs.map +1 -0
  75. package/fesm2022/ngx-t-forms-record-list-manager.component-CykBq_nW.mjs +358 -0
  76. package/fesm2022/ngx-t-forms-record-list-manager.component-CykBq_nW.mjs.map +1 -0
  77. package/fesm2022/ngx-t-forms-required-inputs.component-ONbhxVSH.mjs +272 -0
  78. package/fesm2022/ngx-t-forms-required-inputs.component-ONbhxVSH.mjs.map +1 -0
  79. package/fesm2022/ngx-t-forms-rest-api-call-setup.component-WPUxtY7Q.mjs +398 -0
  80. package/fesm2022/ngx-t-forms-rest-api-call-setup.component-WPUxtY7Q.mjs.map +1 -0
  81. package/fesm2022/ngx-t-forms-search-field.component-B2ZO7lqO.mjs +38 -0
  82. package/fesm2022/ngx-t-forms-search-field.component-B2ZO7lqO.mjs.map +1 -0
  83. package/fesm2022/ngx-t-forms-section-report.component-C1w16LYm.mjs +98 -0
  84. package/fesm2022/ngx-t-forms-section-report.component-C1w16LYm.mjs.map +1 -0
  85. package/fesm2022/ngx-t-forms-select-input-element.component-CWcywuS6.mjs +150 -0
  86. package/fesm2022/ngx-t-forms-select-input-element.component-CWcywuS6.mjs.map +1 -0
  87. package/fesm2022/ngx-t-forms-selection-options-editor.component-KjbZhc2u.mjs +169 -0
  88. package/fesm2022/ngx-t-forms-selection-options-editor.component-KjbZhc2u.mjs.map +1 -0
  89. package/fesm2022/ngx-t-forms-t-workflow-picker.component-CtavFAUq.mjs +204 -0
  90. package/fesm2022/ngx-t-forms-t-workflow-picker.component-CtavFAUq.mjs.map +1 -0
  91. package/fesm2022/ngx-t-forms-textarea-input-element.component-DkJkBQif.mjs +95 -0
  92. package/fesm2022/ngx-t-forms-textarea-input-element.component-DkJkBQif.mjs.map +1 -0
  93. package/fesm2022/ngx-t-forms-toggle-input-element.component-Dr7MNli8.mjs +82 -0
  94. package/fesm2022/ngx-t-forms-toggle-input-element.component-Dr7MNli8.mjs.map +1 -0
  95. package/fesm2022/ngx-t-forms-validators-config.component-BknyAmV_.mjs +574 -0
  96. package/fesm2022/ngx-t-forms-validators-config.component-BknyAmV_.mjs.map +1 -0
  97. package/fesm2022/ngx-t-forms-workflow-adjudication.component-CPvwm7f4.mjs +1303 -0
  98. package/fesm2022/ngx-t-forms-workflow-adjudication.component-CPvwm7f4.mjs.map +1 -0
  99. package/fesm2022/ngx-t-forms.mjs +2 -1
  100. package/fesm2022/ngx-t-forms.mjs.map +1 -1
  101. package/package.json +20 -18
  102. package/styles/_editor-mixins.scss +62 -0
  103. package/styles/_json-editor-syntax.scss +26 -0
  104. package/styles/_signature-pad.scss +26 -0
  105. package/styles/_tokens.scss +148 -0
  106. package/types/ngx-t-forms.d.ts +1921 -733
  107. package/fesm2022/ngx-t-forms-calculated-field-rules.component-Ct6_c_Lj.mjs +0 -313
  108. package/fesm2022/ngx-t-forms-calculated-field-rules.component-Ct6_c_Lj.mjs.map +0 -1
  109. package/fesm2022/ngx-t-forms-chip-options-creator-editor.component-yuM1KHho.mjs +0 -191
  110. package/fesm2022/ngx-t-forms-chip-options-creator-editor.component-yuM1KHho.mjs.map +0 -1
  111. package/fesm2022/ngx-t-forms-config-mscoa-additional-inputs.component-BptpYSe-.mjs +0 -207
  112. package/fesm2022/ngx-t-forms-config-mscoa-additional-inputs.component-BptpYSe-.mjs.map +0 -1
  113. package/fesm2022/ngx-t-forms-data-source-picker.component-Badna1Rl.mjs +0 -204
  114. package/fesm2022/ngx-t-forms-data-source-picker.component-Badna1Rl.mjs.map +0 -1
  115. package/fesm2022/ngx-t-forms-document-list-label-config-editor.component-2_8XzUgD.mjs +0 -289
  116. package/fesm2022/ngx-t-forms-document-list-label-config-editor.component-2_8XzUgD.mjs.map +0 -1
  117. package/fesm2022/ngx-t-forms-form-input-selector.component-DV4Sts9F.mjs +0 -134
  118. package/fesm2022/ngx-t-forms-form-input-selector.component-DV4Sts9F.mjs.map +0 -1
  119. package/fesm2022/ngx-t-forms-form-json-view.component-B8seYzMQ.mjs +0 -22
  120. package/fesm2022/ngx-t-forms-form-json-view.component-B8seYzMQ.mjs.map +0 -1
  121. package/fesm2022/ngx-t-forms-form-section-stepper.component-x_83iAWA.mjs +0 -281
  122. package/fesm2022/ngx-t-forms-form-section-stepper.component-x_83iAWA.mjs.map +0 -1
  123. package/fesm2022/ngx-t-forms-forms-builder-menu.component-UWo_dyVt.mjs +0 -345
  124. package/fesm2022/ngx-t-forms-forms-builder-menu.component-UWo_dyVt.mjs.map +0 -1
  125. package/fesm2022/ngx-t-forms-input-editor.component-B_kkOoEO.mjs +0 -147
  126. package/fesm2022/ngx-t-forms-input-editor.component-B_kkOoEO.mjs.map +0 -1
  127. package/fesm2022/ngx-t-forms-map-mat-options-keys-SM5XM9uy.mjs.map +0 -1
  128. package/fesm2022/ngx-t-forms-mat-chip-list-editor.component-C41AL9Et.mjs +0 -105
  129. package/fesm2022/ngx-t-forms-mat-chip-list-editor.component-C41AL9Et.mjs.map +0 -1
  130. package/fesm2022/ngx-t-forms-mat-slider-editor.component-BWe8U-sI.mjs +0 -109
  131. package/fesm2022/ngx-t-forms-mat-slider-editor.component-BWe8U-sI.mjs.map +0 -1
  132. package/fesm2022/ngx-t-forms-mat-slider-toggle-editor.component-B_XlkHuK.mjs +0 -155
  133. package/fesm2022/ngx-t-forms-mat-slider-toggle-editor.component-B_XlkHuK.mjs.map +0 -1
  134. package/fesm2022/ngx-t-forms-missing-form-configs.component-DPNNyKkt.mjs +0 -28
  135. package/fesm2022/ngx-t-forms-missing-form-configs.component-DPNNyKkt.mjs.map +0 -1
  136. package/fesm2022/ngx-t-forms-mscoa-chart-toolbar.component-DY1QnG08.mjs +0 -43
  137. package/fesm2022/ngx-t-forms-mscoa-chart-toolbar.component-DY1QnG08.mjs.map +0 -1
  138. package/fesm2022/ngx-t-forms-mscoa-error-display.component-CRc_4l3l.mjs +0 -116
  139. package/fesm2022/ngx-t-forms-mscoa-error-display.component-CRc_4l3l.mjs.map +0 -1
  140. package/fesm2022/ngx-t-forms-mscoa-segment-config.component-Ckr_nuZF.mjs +0 -296
  141. package/fesm2022/ngx-t-forms-mscoa-segment-config.component-Ckr_nuZF.mjs.map +0 -1
  142. package/fesm2022/ngx-t-forms-mscoa-temporary-hint.component-GYxT-56Y.mjs +0 -83
  143. package/fesm2022/ngx-t-forms-mscoa-temporary-hint.component-GYxT-56Y.mjs.map +0 -1
  144. package/fesm2022/ngx-t-forms-ngx-t-forms-DP2koSL5.mjs +0 -17401
  145. package/fesm2022/ngx-t-forms-ngx-t-forms-DP2koSL5.mjs.map +0 -1
  146. package/fesm2022/ngx-t-forms-pipeline-generator.component-BxHetD_Q.mjs +0 -613
  147. package/fesm2022/ngx-t-forms-pipeline-generator.component-BxHetD_Q.mjs.map +0 -1
  148. package/fesm2022/ngx-t-forms-record-list-manager.component-BQuMkoXo.mjs +0 -269
  149. package/fesm2022/ngx-t-forms-record-list-manager.component-BQuMkoXo.mjs.map +0 -1
  150. package/fesm2022/ngx-t-forms-required-inputs.component-CLyq9dIR.mjs +0 -190
  151. package/fesm2022/ngx-t-forms-required-inputs.component-CLyq9dIR.mjs.map +0 -1
  152. package/fesm2022/ngx-t-forms-rest-api-call-setup.component-CWeIUKLz.mjs +0 -291
  153. package/fesm2022/ngx-t-forms-rest-api-call-setup.component-CWeIUKLz.mjs.map +0 -1
  154. package/fesm2022/ngx-t-forms-section-report.component-BtaF39WD.mjs +0 -156
  155. package/fesm2022/ngx-t-forms-section-report.component-BtaF39WD.mjs.map +0 -1
  156. package/fesm2022/ngx-t-forms-selection-options-editor.component-B4cEGWrK.mjs +0 -186
  157. package/fesm2022/ngx-t-forms-selection-options-editor.component-B4cEGWrK.mjs.map +0 -1
  158. package/fesm2022/ngx-t-forms-t-workflow-picker.component-BkVN4Wdk.mjs +0 -187
  159. package/fesm2022/ngx-t-forms-t-workflow-picker.component-BkVN4Wdk.mjs.map +0 -1
  160. package/fesm2022/ngx-t-forms-validators-config.component-Cq07Er-G.mjs +0 -215
  161. package/fesm2022/ngx-t-forms-validators-config.component-Cq07Er-G.mjs.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ngx-t-forms-editor-input-element.component-1X6uAPeZ.mjs","sources":["../../../projects/ngx-t-forms/src/lib/components/t-form-input/elements/editor-input-element/core/quill-input/quill.config.ts","../../../projects/ngx-t-forms/src/lib/components/t-form-input/elements/editor-input-element/core/quill-input/quill-input.component.ts","../../../projects/ngx-t-forms/src/lib/components/t-form-input/elements/editor-input-element/core/quill-input/quill-input.component.html","../../../projects/ngx-t-forms/src/lib/components/t-form-input/elements/editor-input-element/editor-input-element.component.ts","../../../projects/ngx-t-forms/src/lib/components/t-form-input/elements/editor-input-element/editor-input-element.component.html"],"sourcesContent":["import type Quill from 'quill';\nimport type { Op, QuillOptions } from 'quill';\n\n/**\n * Serialized Quill document — the Delta op-list persisted as the control value.\n *\n * Stored as a plain object (NOT a live `Delta` instance) so it round-trips through\n * reactive-form state and the library's structural `_isEqual` check cleanly. `_isEqual`\n * rejects values whose constructors differ, so a `Delta` instance would never compare\n * equal to the plain object rehydrated from saved form data.\n */\nexport interface QuillContent {\n ops: Op[];\n}\n\n/** Inputs the host component feeds into the Quill setup. */\nexport interface QuillEditorPayload {\n /** Render the editor in non-editable mode. */\n readOnly: boolean;\n /** Placeholder shown while the document is empty. */\n placeholder?: string;\n}\n\n/**\n * Narrow surface of Quill's built-in table module (`getModule('table')`), typed so the\n * host component can drive table operations without leaking `any`.\n */\nexport interface QuillTableModule {\n insertTable(rows: number, columns: number): void;\n insertRowBelow(): void;\n insertColumnRight(): void;\n deleteRow(): void;\n deleteColumn(): void;\n deleteTable(): void;\n}\n\n/** A custom toolbar control wired to a native Quill table operation. */\nexport interface QuillTableControl {\n /** Toolbar format key — Quill renders it as a `button.ql-<format>`. */\n format: string;\n /** Tooltip surfaced via the button's `title` attribute. */\n title: string;\n /** Inline SVG markup. Paths use `ql-stroke` so they inherit the themed icon colour. */\n icon: string;\n /** Operation run against the native table module when the button is pressed. */\n run: (table: QuillTableModule) => void;\n}\n\nconst svg = (body: string): string => `<svg viewBox=\"0 0 18 18\">${body}</svg>`;\n\n/**\n * Word-like table toolkit backed by Quill's native table module. Each control degrades to a\n * no-op when the caret is outside a table, so the buttons are always safe to press.\n */\nexport const QUILL_TABLE_CONTROLS: readonly QuillTableControl[] = [\n {\n format: 'table-insert',\n title: 'Insert table (3×3)',\n icon: svg('<rect class=\"ql-stroke\" fill=\"none\" x=\"3\" y=\"4\" width=\"12\" height=\"10\" rx=\"1\"></rect><line class=\"ql-stroke\" x1=\"3\" y1=\"7.3\" x2=\"15\" y2=\"7.3\"></line><line class=\"ql-stroke\" x1=\"3\" y1=\"10.6\" x2=\"15\" y2=\"10.6\"></line><line class=\"ql-stroke\" x1=\"7\" y1=\"4\" x2=\"7\" y2=\"14\"></line><line class=\"ql-stroke\" x1=\"11\" y1=\"4\" x2=\"11\" y2=\"14\"></line>'),\n run: table => table.insertTable(3, 3),\n },\n {\n format: 'table-row',\n title: 'Insert row below',\n icon: svg('<rect class=\"ql-stroke\" fill=\"none\" x=\"3\" y=\"3\" width=\"12\" height=\"6\" rx=\"1\"></rect><line class=\"ql-stroke\" x1=\"9\" y1=\"11\" x2=\"9\" y2=\"15\"></line><line class=\"ql-stroke\" x1=\"7\" y1=\"13\" x2=\"11\" y2=\"13\"></line>'),\n run: table => table.insertRowBelow(),\n },\n {\n format: 'table-column',\n title: 'Insert column right',\n icon: svg('<rect class=\"ql-stroke\" fill=\"none\" x=\"3\" y=\"3\" width=\"6\" height=\"12\" rx=\"1\"></rect><line class=\"ql-stroke\" x1=\"13\" y1=\"6\" x2=\"13\" y2=\"12\"></line><line class=\"ql-stroke\" x1=\"11\" y1=\"9\" x2=\"15\" y2=\"9\"></line>'),\n run: table => table.insertColumnRight(),\n },\n {\n format: 'table-delete-row',\n title: 'Delete row',\n icon: svg('<rect class=\"ql-stroke\" fill=\"none\" x=\"3\" y=\"3\" width=\"12\" height=\"6\" rx=\"1\"></rect><line class=\"ql-stroke\" x1=\"7\" y1=\"13\" x2=\"11\" y2=\"13\"></line>'),\n run: table => table.deleteRow(),\n },\n {\n format: 'table-delete-column',\n title: 'Delete column',\n icon: svg('<rect class=\"ql-stroke\" fill=\"none\" x=\"3\" y=\"3\" width=\"6\" height=\"12\" rx=\"1\"></rect><line class=\"ql-stroke\" x1=\"11\" y1=\"9\" x2=\"15\" y2=\"9\"></line>'),\n run: table => table.deleteColumn(),\n },\n {\n format: 'table-delete',\n title: 'Delete table',\n icon: svg('<rect class=\"ql-stroke\" fill=\"none\" x=\"3\" y=\"3\" width=\"12\" height=\"12\" rx=\"1\"></rect><line class=\"ql-stroke\" x1=\"5.5\" y1=\"5.5\" x2=\"12.5\" y2=\"12.5\"></line><line class=\"ql-stroke\" x1=\"12.5\" y1=\"5.5\" x2=\"5.5\" y2=\"12.5\"></line>'),\n run: table => table.deleteTable(),\n },\n];\n\n/**\n * Human-readable tooltips for the built-in controls, keyed by the button's CSS selector.\n * Quill ships no titles of its own, so these make the toolbar self-explanatory.\n */\nexport const QUILL_BUILTIN_TITLES: Readonly<Record<string, string>> = {\n '.ql-bold': 'Bold',\n '.ql-italic': 'Italic',\n '.ql-underline': 'Underline',\n '.ql-strike': 'Strikethrough',\n '.ql-blockquote': 'Quote',\n '.ql-code-block': 'Code block',\n '.ql-link': 'Insert link',\n '.ql-image': 'Insert image',\n '.ql-video': 'Embed video',\n '.ql-clean': 'Clear formatting',\n '.ql-list[value=\"ordered\"]': 'Numbered list',\n '.ql-list[value=\"bullet\"]': 'Bulleted list',\n '.ql-list[value=\"check\"]': 'Checklist',\n '.ql-script[value=\"sub\"]': 'Subscript',\n '.ql-script[value=\"super\"]': 'Superscript',\n '.ql-indent[value=\"-1\"]': 'Decrease indent',\n '.ql-indent[value=\"+1\"]': 'Increase indent',\n '.ql-direction[value=\"rtl\"]': 'Right-to-left',\n '.ql-color': 'Text colour',\n '.ql-background': 'Highlight colour',\n '.ql-align': 'Alignment',\n '.ql-header': 'Heading',\n '.ql-font': 'Font',\n '.ql-size': 'Font size',\n};\n\n/**\n * Comprehensive, logically grouped \"snow\" toolbar — headings/fonts, inline styling, colour,\n * scripts, lists, indentation/alignment, blocks, media and a native table toolkit.\n */\nconst TOOLBAR_CONTAINER: readonly unknown[] = [\n [{ header: [1, 2, 3, 4, 5, 6, false] }, { font: [] }, { size: ['small', false, 'large', 'huge'] }],\n ['bold', 'italic', 'underline', 'strike'],\n [{ color: [] }, { background: [] }],\n [{ script: 'sub' }, { script: 'super' }],\n [{ list: 'ordered' }, { list: 'bullet' }, { list: 'check' }],\n [{ indent: '-1' }, { indent: '+1' }, { align: [] }, { direction: 'rtl' }],\n ['blockquote', 'code-block'],\n ['link', 'image', 'video'],\n QUILL_TABLE_CONTROLS.map(control => control.format),\n ['clean']\n];\n\n/** The `this` context Quill binds when it invokes a toolbar handler. */\ninterface ToolbarHandlerContext {\n quill: Quill;\n}\n\n/**\n * Builds the toolbar handler map for the custom table buttons.\n *\n * These MUST be supplied in the toolbar config (not added later via `addHandler`): Quill's\n * toolbar skips attaching a click listener to any button whose format is neither a registered\n * blot nor already present in `handlers` at construction time. A late `addHandler` sets the\n * handler but never re-attaches the listener, so the button stays inert.\n */\nconst buildTableHandlers = (): Record<string, (this: ToolbarHandlerContext) => void> => {\n const handlers: Record<string, (this: ToolbarHandlerContext) => void> = {};\n for (const control of QUILL_TABLE_CONTROLS) {\n handlers[control.format] = function tableHandler(this: ToolbarHandlerContext): void {\n const table = this.quill.getModule('table') as QuillTableModule;\n // Native table ops bail when there is no selection; force focus + a range first.\n this.quill.getSelection(true);\n control.run(table);\n };\n }\n return handlers;\n};\n\n/**\n * Builds a ready-to-use `QuillOptions` for a \"snow\" editor with the native table module\n * enabled and the custom table-button handlers wired into the toolbar config.\n *\n * Browser-only by construction: callers MUST instantiate Quill behind an\n * `isPlatformBrowser(...)` guard because Quill touches `document` at construction time.\n */\nexport const buildQuillOptions = (payload: QuillEditorPayload): QuillOptions => ({\n theme: 'snow',\n readOnly: payload.readOnly,\n placeholder: payload.placeholder ?? \"Let's write something amazing...\",\n modules: {\n toolbar: {\n container: TOOLBAR_CONTAINER,\n handlers: buildTableHandlers()\n },\n table: true,\n history: { delay: 1000, maxStack: 100, userOnly: true },\n clipboard: { matchVisual: false }\n }\n});\n\n/**\n * Quill's empty document is a single trailing newline op. Treat that — and a literally\n * empty op-list — as \"no value\" so `required` validation behaves intuitively.\n */\nexport const isEmptyQuillDocument = (ops: Op[]): boolean =>\n ops.length === 0 || (ops.length === 1 && ops[0]?.insert === '\\n');\n","/// <reference path=\"../../../../../../../types/quill.d.ts\" />\nimport {\n AfterViewInit,\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n Input,\n OnDestroy,\n PLATFORM_ID,\n inject,\n input,\n output,\n viewChild\n} from '@angular/core';\nimport { isPlatformBrowser } from '@angular/common';\nimport { NgControl } from '@angular/forms';\n\nimport { ITowerStepColumn } from 'ngx-t-forms-types';\n// Mirrors the EditorJS sibling (Trap 16): `quill` is a browser-only bundle that touches\n// `document` at construction time and crashes under bare-Node SSR. The top-level import is\n// type-only (zero runtime emission); the real load happens inside the SSR-gated\n// `ngAfterViewInit` via dynamic `import()`.\nimport type QuillType from 'quill';\nimport { MatFormFieldControl } from '@angular/material/form-field';\n\nimport { BaseCustomInput, BaseCustomInputConfig } from '../../../../../../services/core/t-input-controller/functions/baseCustomInput';\nimport {\n buildQuillOptions,\n isEmptyQuillDocument,\n QUILL_BUILTIN_TITLES,\n QUILL_TABLE_CONTROLS,\n QuillContent\n} from './quill.config';\nimport { _isEqual } from '../../../../../../shared/functions/isEqual';\n\nconst customInputConfig: BaseCustomInputConfig = {\n controlType: 'lib-quill-input',\n nextId: 0\n};\n\n/**\n * Quill (\"snow\" theme) rich-text editor wired into Angular Material's form-field as a\n * custom `MatFormFieldControl`. The full Quill setup — toolbar, formats, history — lives in\n * `quill.config.ts`; this component owns lifecycle, SSR gating and value round-tripping.\n */\n@Component({\n selector: 'lib-quill-input',\n templateUrl: './quill-input.component.html',\n styleUrl: './quill-input.component.css',\n imports: [],\n host: {\n '[class.floating]': 'shouldLabelFloat',\n '[id]': 'id'\n },\n providers: [{ provide: MatFormFieldControl, useExisting: QuillInputComponent }],\n changeDetection: ChangeDetectionStrategy.OnPush\n})\nexport class QuillInputComponent\n extends BaseCustomInput<QuillContent | undefined>\n implements AfterViewInit, OnDestroy {\n\n readonly inputConfig = input.required<ITowerStepColumn>();\n\n readonly valueChanged = output<QuillContent | undefined>();\n\n protected editor: QuillType | undefined;\n\n private readonly editorHost = viewChild.required<ElementRef<HTMLElement>>('editorHost');\n\n readonly #platformId = inject(PLATFORM_ID);\n\n #changeHandler: (() => void) | undefined;\n\n constructor() {\n super(\n inject(NgControl, { optional: true, self: true }) as NgControl,\n inject<ElementRef<HTMLElement>>(ElementRef),\n customInputConfig\n );\n }\n\n override get empty(): boolean {\n const n = this.value;\n return n === null || n === undefined;\n }\n\n override get shouldLabelFloat(): boolean {\n return true;\n }\n\n override _value: QuillContent | undefined = undefined;\n\n @Input() override set value(value: QuillContent | undefined) {\n if (!_isEqual(this._value, value)) {\n this._value = value;\n this.onChange(value);\n this.stateChanges.next();\n }\n }\n\n override get value(): QuillContent | undefined {\n return this._value;\n }\n\n async ngAfterViewInit(): Promise<void> {\n if (!isPlatformBrowser(this.#platformId)) return;\n\n // Browser-only dynamic load — see the Trap 16 comment at the top of this file. The\n // CSS import injects Quill's global theme styles (Quill's runtime DOM is not view-scoped).\n const [{ default: Quill, Delta }] = await Promise.all([\n import('quill'),\n import('quill/dist/quill.snow.css')\n ]);\n\n const config = this.inputConfig();\n this.editor = new Quill(this.editorHost().nativeElement, buildQuillOptions({\n readOnly: config.readonly || false,\n placeholder: config.placeholder\n }));\n\n const initial = this.value;\n if (initial?.ops?.length) {\n this.editor.setContents(new Delta(initial.ops), 'silent');\n }\n\n this.#decorateToolbar();\n\n this.#changeHandler = () => this.contentChangedSaveValue();\n this.editor.on('text-change', this.#changeHandler);\n }\n\n /**\n * Quill ships no icons for custom buttons and no tooltips for any button. Inject themeable\n * SVG icons (their `ql-stroke` paths inherit the toolbar colour) and `title` tooltips so the\n * toolbar reads clearly in both light and dark mode.\n */\n #decorateToolbar(): void {\n const root = this._elementRef.nativeElement;\n for (const control of QUILL_TABLE_CONTROLS) {\n const button = root.querySelector<HTMLElement>(`.ql-${control.format}`);\n if (!button) continue;\n button.innerHTML = control.icon;\n button.setAttribute('title', control.title);\n }\n for (const [selector, title] of Object.entries(QUILL_BUILTIN_TITLES)) {\n root.querySelectorAll<HTMLElement>(selector).forEach(el => el.setAttribute('title', title));\n }\n }\n\n contentChangedSaveValue(): void {\n if (!this.editor) return;\n const ops = this.editor.getContents().ops;\n const value: QuillContent | undefined = isEmptyQuillDocument(ops) ? undefined : { ops };\n this.value = value;\n this.onChange(value);\n console.error('Quill content changed, new value:', value);\n this.valueChanged.emit(value);\n }\n\n override ngOnDestroy(): void {\n this.stateChanges.complete();\n if (this.editor && this.#changeHandler) {\n this.editor.off('text-change', this.#changeHandler);\n }\n this.editor = undefined;\n }\n}\n","\n<div class=\"quill-host\">\n <div #editorHost></div>\n</div>\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 { ITowerStepColumn } from 'ngx-t-forms-types';\r\nimport { RichTextEditorType } from 'ngx-t-forms-types';\r\nimport { TFormInputStatusComponent } from '../../../t-form-input-status/t-form-input-status.component';\r\nimport { EditorJsInputComponent } from './core/editor-js-input/editor-js-input.component';\r\nimport { QuillInputComponent } from './core/quill-input/quill-input.component';\r\nimport { getInputErrorMessage } from '../../../../services/core/t-input-controller/functions/inputErrorMessage';\r\n\r\n/**\r\n * Wraps a configurable rich-text editor inside a `mat-form-field`, selecting the concrete\r\n * editor (EditorJS or Quill) from the column's `richTextEditorLibrary`, with shared\r\n * label / hint / error / suffix / prefix metadata from the column.\r\n */\r\n@Component({\r\n selector: 'lib-editor-input-element',\r\n templateUrl: './editor-input-element.component.html',\r\n styleUrl: './editor-input-element.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 EditorJsInputComponent,\r\n QuillInputComponent,\r\n ],\r\n})\r\nexport class EditorInputElementComponent {\r\n readonly inputConfig = input.required<ITowerStepColumn>();\r\n readonly formGroup = input.required<FormGroup>();\r\n readonly reload = output<void>();\r\n\r\n /** Editor-library enum exposed for `@switch` in the template. */\r\n protected readonly editorType = RichTextEditorType;\r\n\r\n protected readonly errorMessage = computed(() =>\r\n getInputErrorMessage(this.inputConfig(), this.formGroup()),\r\n );\r\n}\r\n","<form [formGroup]=\"formGroup()\">\n @if (inputConfig(); as inputConfig) {\n <mat-form-field [appearance]=\"inputConfig.appearance || 'fill'\" subscriptSizing=\"dynamic\">\n <mat-label>\n {{ inputConfig.label }}\n <lib-t-form-input-status [inputConfig]=\"inputConfig\"></lib-t-form-input-status>\n </mat-label>\n\n @switch (inputConfig.richTextEditorLibrary) {\n @case (editorType.Quill) {\n <lib-quill-input\n [inputConfig]=\"inputConfig\"\n [formControlName]=\"inputConfig.id\"\n [required]=\"inputConfig.required\"\n ></lib-quill-input>\n }\n @case (editorType.EditorJS) {\n <lib-editor-js-input\n [inputConfig]=\"inputConfig\"\n [formControlName]=\"inputConfig.id\"\n [required]=\"inputConfig.required\"\n ></lib-editor-js-input>\n }\n }\n\n @if (inputConfig.hintLabel || inputConfig.temporaryHint) {\n <mat-hint class=\"inputHint\">\n {{ inputConfig.temporaryHint || inputConfig.hintLabel }}\n </mat-hint>\n }\n\n @if (!!errorMessage()) {\n <mat-error class=\"oneLineTextEllipsis\" matTooltipClass=\"errorToolTip\">{{ errorMessage() }}</mat-error>\n }\n\n @if (inputConfig.prefixIcon) {\n <mat-icon matPrefix>{{ inputConfig.prefixIcon }}</mat-icon>\n }\n\n @if (inputConfig.canReload?.canReload) {\n <button\n mat-icon-button\n style=\"margin-right: 4px;\"\n matTooltip=\"Click to refresh this field.\"\n class=\"input-sync-button\"\n (click)=\"inputConfig.canReload.emit()\"\n matSuffix\n >\n <mat-icon style=\"color: var(--mat-sys-primary)\">sync</mat-icon>\n </button>\n }\n\n @if (inputConfig.suffixIcon && inputConfig.id !== 'password') {\n <mat-icon matSuffix>{{ inputConfig.suffixIcon }}</mat-icon>\n }\n\n @if (inputConfig.prefixText) {\n <span matPrefix style=\"top: 0\">{{ inputConfig.prefixText }}</span>\n }\n @if (inputConfig.suffixText) {\n <span matSuffix style=\"padding-left: 5px\">{{ inputConfig.suffixText }}</span>\n }\n\n @if (inputConfig.maxLength && formGroup()) {\n <mat-hint align=\"end\">\n {{ (formGroup().controls[inputConfig.id]?.value?.length || 0) + '/' + inputConfig.maxLength }}\n </mat-hint>\n }\n </mat-form-field>\n }\n</form>\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAgDA,MAAM,GAAG,GAAG,CAAC,IAAY,KAAa,CAAA,yBAAA,EAA4B,IAAI,CAAA,MAAA,CAAQ;AAE9E;;;AAGG;AACI,MAAM,oBAAoB,GAAiC;AAChE,IAAA;AACE,QAAA,MAAM,EAAE,cAAc;AACtB,QAAA,KAAK,EAAE,oBAAoB;AAC3B,QAAA,IAAI,EAAE,GAAG,CAAC,mVAAmV,CAAC;AAC9V,QAAA,GAAG,EAAE,KAAK,IAAI,KAAK,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC;AACtC,KAAA;AACD,IAAA;AACE,QAAA,MAAM,EAAE,WAAW;AACnB,QAAA,KAAK,EAAE,kBAAkB;AACzB,QAAA,IAAI,EAAE,GAAG,CAAC,iNAAiN,CAAC;QAC5N,GAAG,EAAE,KAAK,IAAI,KAAK,CAAC,cAAc,EAAE;AACrC,KAAA;AACD,IAAA;AACE,QAAA,MAAM,EAAE,cAAc;AACtB,QAAA,KAAK,EAAE,qBAAqB;AAC5B,QAAA,IAAI,EAAE,GAAG,CAAC,iNAAiN,CAAC;QAC5N,GAAG,EAAE,KAAK,IAAI,KAAK,CAAC,iBAAiB,EAAE;AACxC,KAAA;AACD,IAAA;AACE,QAAA,MAAM,EAAE,kBAAkB;AAC1B,QAAA,KAAK,EAAE,YAAY;AACnB,QAAA,IAAI,EAAE,GAAG,CAAC,oJAAoJ,CAAC;QAC/J,GAAG,EAAE,KAAK,IAAI,KAAK,CAAC,SAAS,EAAE;AAChC,KAAA;AACD,IAAA;AACE,QAAA,MAAM,EAAE,qBAAqB;AAC7B,QAAA,KAAK,EAAE,eAAe;AACtB,QAAA,IAAI,EAAE,GAAG,CAAC,mJAAmJ,CAAC;QAC9J,GAAG,EAAE,KAAK,IAAI,KAAK,CAAC,YAAY,EAAE;AACnC,KAAA;AACD,IAAA;AACE,QAAA,MAAM,EAAE,cAAc;AACtB,QAAA,KAAK,EAAE,cAAc;AACrB,QAAA,IAAI,EAAE,GAAG,CAAC,iOAAiO,CAAC;QAC5O,GAAG,EAAE,KAAK,IAAI,KAAK,CAAC,WAAW,EAAE;AAClC,KAAA;CACF;AAED;;;AAGG;AACI,MAAM,oBAAoB,GAAqC;AACpE,IAAA,UAAU,EAAE,MAAM;AAClB,IAAA,YAAY,EAAE,QAAQ;AACtB,IAAA,eAAe,EAAE,WAAW;AAC5B,IAAA,YAAY,EAAE,eAAe;AAC7B,IAAA,gBAAgB,EAAE,OAAO;AACzB,IAAA,gBAAgB,EAAE,YAAY;AAC9B,IAAA,UAAU,EAAE,aAAa;AACzB,IAAA,WAAW,EAAE,cAAc;AAC3B,IAAA,WAAW,EAAE,aAAa;AAC1B,IAAA,WAAW,EAAE,kBAAkB;AAC/B,IAAA,2BAA2B,EAAE,eAAe;AAC5C,IAAA,0BAA0B,EAAE,eAAe;AAC3C,IAAA,yBAAyB,EAAE,WAAW;AACtC,IAAA,yBAAyB,EAAE,WAAW;AACtC,IAAA,2BAA2B,EAAE,aAAa;AAC1C,IAAA,wBAAwB,EAAE,iBAAiB;AAC3C,IAAA,wBAAwB,EAAE,iBAAiB;AAC3C,IAAA,4BAA4B,EAAE,eAAe;AAC7C,IAAA,WAAW,EAAE,aAAa;AAC1B,IAAA,gBAAgB,EAAE,kBAAkB;AACpC,IAAA,WAAW,EAAE,WAAW;AACxB,IAAA,YAAY,EAAE,SAAS;AACvB,IAAA,UAAU,EAAE,MAAM;AAClB,IAAA,UAAU,EAAE,WAAW;CACxB;AAED;;;AAGG;AACH,MAAM,iBAAiB,GAAuB;AAC5C,IAAA,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,CAAC;AAClG,IAAA,CAAC,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,CAAC;IACzC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC;IACnC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;AACxC,IAAA,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;IAC5D,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;IACzE,CAAC,YAAY,EAAE,YAAY,CAAC;AAC5B,IAAA,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC;IAC1B,oBAAoB,CAAC,GAAG,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC;AACnD,IAAA,CAAC,OAAO;CACT;AAOD;;;;;;;AAOG;AACH,MAAM,kBAAkB,GAAG,MAA4D;IACrF,MAAM,QAAQ,GAA0D,EAAE;AAC1E,IAAA,KAAK,MAAM,OAAO,IAAI,oBAAoB,EAAE;AAC1C,QAAA,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,SAAS,YAAY,GAAA;YAC9C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,CAAqB;;AAE/D,YAAA,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC;AAC7B,YAAA,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;AACpB,QAAA,CAAC;IACH;AACA,IAAA,OAAO,QAAQ;AACjB,CAAC;AAED;;;;;;AAMG;AACI,MAAM,iBAAiB,GAAG,CAAC,OAA2B,MAAoB;AAC/E,IAAA,KAAK,EAAE,MAAM;IACb,QAAQ,EAAE,OAAO,CAAC,QAAQ;AAC1B,IAAA,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,kCAAkC;AACtE,IAAA,OAAO,EAAE;AACP,QAAA,OAAO,EAAE;AACP,YAAA,SAAS,EAAE,iBAAiB;YAC5B,QAAQ,EAAE,kBAAkB;AAC7B,SAAA;AACD,QAAA,KAAK,EAAE,IAAI;AACX,QAAA,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE;AACvD,QAAA,SAAS,EAAE,EAAE,WAAW,EAAE,KAAK;AAChC;AACF,CAAA,CAAC;AAEF;;;AAGG;AACI,MAAM,oBAAoB,GAAG,CAAC,GAAS,KAC5C,GAAG,CAAC,MAAM,KAAK,CAAC,KAAK,GAAG,CAAC,MAAM,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;;AClMnE;AAmCA,MAAM,iBAAiB,GAA0B;AAC/C,IAAA,WAAW,EAAE,iBAAiB;AAC9B,IAAA,MAAM,EAAE;CACT;AAED;;;;AAIG;AAaG,MAAO,mBACX,SAAQ,eAAyC,CAAA;AAWxC,IAAA,WAAW;AAEpB,IAAA,cAAc;AAEd,IAAA,WAAA,GAAA;QACE,KAAK,CACH,MAAM,CAAC,SAAS,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAc,EAC9D,MAAM,CAA0B,UAAU,CAAC,EAC3C,iBAAiB,CAClB;AAjBM,QAAA,IAAA,CAAA,WAAW,GAAG,KAAK,CAAC,QAAQ,iFAAoB;QAEhD,IAAA,CAAA,YAAY,GAAG,MAAM,EAA4B;AAIzC,QAAA,IAAA,CAAA,UAAU,GAAG,SAAS,CAAC,QAAQ,CAA0B,YAAY,CAAC;AAE9E,QAAA,IAAA,CAAA,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC;QAqBjC,IAAA,CAAA,MAAM,GAA6B,SAAS;IAXrD;AAEA,IAAA,IAAa,KAAK,GAAA;AAChB,QAAA,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK;AACpB,QAAA,OAAO,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,SAAS;IACtC;AAEA,IAAA,IAAa,gBAAgB,GAAA;AAC3B,QAAA,OAAO,IAAI;IACb;IAIA,IAAsB,KAAK,CAAC,KAA+B,EAAA;QACzD,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE;AACjC,YAAA,IAAI,CAAC,MAAM,GAAG,KAAK;AACnB,YAAA,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;AACpB,YAAA,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE;QAC1B;IACF;AAEA,IAAA,IAAa,KAAK,GAAA;QAChB,OAAO,IAAI,CAAC,MAAM;IACpB;AAEA,IAAA,MAAM,eAAe,GAAA;AACnB,QAAA,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,WAAW,CAAC;YAAE;;;AAI1C,QAAA,MAAM,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YACpD,OAAO,OAAO,CAAC;YACf,OAAO,2BAA2B;AACnC,SAAA,CAAC;AAEF,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,EAAE;AACjC,QAAA,IAAI,CAAC,MAAM,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,aAAa,EAAE,iBAAiB,CAAC;AACzE,YAAA,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,KAAK;YAClC,WAAW,EAAE,MAAM,CAAC;AACrB,SAAA,CAAC,CAAC;AAEH,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK;AAC1B,QAAA,IAAI,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE;AACxB,YAAA,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC;QAC3D;QAEA,IAAI,CAAC,gBAAgB,EAAE;QAEvB,IAAI,CAAC,cAAc,GAAG,MAAM,IAAI,CAAC,uBAAuB,EAAE;QAC1D,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,aAAa,EAAE,IAAI,CAAC,cAAc,CAAC;IACpD;AAEA;;;;AAIG;IACH,gBAAgB,GAAA;AACd,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,aAAa;AAC3C,QAAA,KAAK,MAAM,OAAO,IAAI,oBAAoB,EAAE;AAC1C,YAAA,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAc,CAAA,IAAA,EAAO,OAAO,CAAC,MAAM,CAAA,CAAE,CAAC;AACvE,YAAA,IAAI,CAAC,MAAM;gBAAE;AACb,YAAA,MAAM,CAAC,SAAS,GAAG,OAAO,CAAC,IAAI;YAC/B,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC;QAC7C;AACA,QAAA,KAAK,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,oBAAoB,CAAC,EAAE;YACpE,IAAI,CAAC,gBAAgB,CAAc,QAAQ,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAC7F;IACF;IAEA,uBAAuB,GAAA;QACrB,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE;QAClB,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,GAAG;AACzC,QAAA,MAAM,KAAK,GAA6B,oBAAoB,CAAC,GAAG,CAAC,GAAG,SAAS,GAAG,EAAE,GAAG,EAAE;AACvF,QAAA,IAAI,CAAC,KAAK,GAAG,KAAK;AAClB,QAAA,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;AACpB,QAAA,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,KAAK,CAAC;AACzD,QAAA,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC;IAC/B;IAES,WAAW,GAAA;AAClB,QAAA,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE;QAC5B,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,cAAc,EAAE;YACtC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,aAAa,EAAE,IAAI,CAAC,cAAc,CAAC;QACrD;AACA,QAAA,IAAI,CAAC,MAAM,GAAG,SAAS;IACzB;+GA5GW,mBAAmB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;AAAnB,IAAA,SAAA,IAAA,CAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,mBAAmB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,KAAA,EAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,UAAA,EAAA,OAAA,EAAA,QAAA,EAAA,KAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,YAAA,EAAA,cAAA,EAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,gBAAA,EAAA,kBAAA,EAAA,IAAA,EAAA,IAAA,EAAA,EAAA,EAAA,SAAA,EAHnB,CAAC,EAAE,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,mBAAmB,EAAE,CAAC,2KCtDjF,mEAIA,EAAA,MAAA,EAAA,CAAA,2pKAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA,CAAA;;4FDqDa,mBAAmB,EAAA,UAAA,EAAA,CAAA;kBAZ/B,SAAS;+BACE,iBAAiB,EAAA,OAAA,EAGlB,EAAE,EAAA,IAAA,EACL;AACJ,wBAAA,kBAAkB,EAAE,kBAAkB;AACtC,wBAAA,MAAM,EAAE;AACT,qBAAA,EAAA,SAAA,EACU,CAAC,EAAE,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAA,mBAAqB,EAAE,CAAC,EAAA,eAAA,EAC9D,uBAAuB,CAAC,MAAM,EAAA,QAAA,EAAA,mEAAA,EAAA,MAAA,EAAA,CAAA,2pKAAA,CAAA,EAAA;oQAY2B,YAAY,EAAA,EAAA,QAAA,EAAA,IAAA,EAAA,CAAA,EAAA,CAAA,EAAA,KAAA,EAAA,CAAA;sBAyBrF;;;AE/EH;;;;AAIG;MAiBU,2BAA2B,CAAA;AAhBxC,IAAA,WAAA,GAAA;AAiBW,QAAA,IAAA,CAAA,WAAW,GAAG,KAAK,CAAC,QAAQ,iFAAoB;AAChD,QAAA,IAAA,CAAA,SAAS,GAAG,KAAK,CAAC,QAAQ,+EAAa;QACvC,IAAA,CAAA,MAAM,GAAG,MAAM,EAAQ;;QAGb,IAAA,CAAA,UAAU,GAAG,kBAAkB;AAE/B,QAAA,IAAA,CAAA,YAAY,GAAG,QAAQ,CAAC,MACzC,oBAAoB,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,mFAC3D;AACF,IAAA;+GAXY,2BAA2B,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;AAA3B,IAAA,SAAA,IAAA,CAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,2BAA2B,2YClCxC,w7EAuEA,EAAA,MAAA,EAAA,CAAA,oJAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,ED/CI,mBAAmB,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,aAAA,EAAA,QAAA,EAAA,8CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,eAAA,EAAA,QAAA,EAAA,2CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,oBAAA,EAAA,QAAA,EAAA,sGAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,iBAAA,EAAA,QAAA,EAAA,wIAAA,EAAA,MAAA,EAAA,CAAA,UAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,kBAAA,EAAA,QAAA,EAAA,aAAA,EAAA,MAAA,EAAA,CAAA,WAAA,CAAA,EAAA,OAAA,EAAA,CAAA,UAAA,CAAA,EAAA,QAAA,EAAA,CAAA,QAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,eAAA,EAAA,QAAA,EAAA,mBAAA,EAAA,MAAA,EAAA,CAAA,iBAAA,EAAA,UAAA,EAAA,SAAA,CAAA,EAAA,OAAA,EAAA,CAAA,eAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EACnB,kBAAkB,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,YAAA,EAAA,QAAA,EAAA,gBAAA,EAAA,MAAA,EAAA,CAAA,oBAAA,EAAA,OAAA,EAAA,YAAA,EAAA,YAAA,EAAA,iBAAA,EAAA,WAAA,CAAA,EAAA,QAAA,EAAA,CAAA,cAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,QAAA,EAAA,QAAA,EAAA,WAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,OAAA,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,IAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,QAAA,EAAA,QAAA,EAAA,uBAAA,EAAA,MAAA,EAAA,CAAA,IAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,SAAA,EAAA,QAAA,EAAA,+CAAA,EAAA,MAAA,EAAA,CAAA,eAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,SAAA,EAAA,QAAA,EAAA,+CAAA,EAAA,MAAA,EAAA,CAAA,eAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAClB,aAAa,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,OAAA,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,QAAA,EAAA,SAAA,EAAA,SAAA,EAAA,UAAA,CAAA,EAAA,QAAA,EAAA,CAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EACb,eAAe,uNACf,gBAAgB,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,UAAA,EAAA,QAAA,EAAA,cAAA,EAAA,MAAA,EAAA,CAAA,oBAAA,EAAA,4BAAA,EAAA,oBAAA,EAAA,qBAAA,EAAA,qBAAA,EAAA,yBAAA,EAAA,YAAA,EAAA,iBAAA,CAAA,EAAA,QAAA,EAAA,CAAA,YAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAChB,yBAAyB,EAAA,QAAA,EAAA,yBAAA,EAAA,MAAA,EAAA,CAAA,aAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACzB,sBAAsB,6HACtB,mBAAmB,EAAA,QAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,CAAA,aAAA,EAAA,OAAA,CAAA,EAAA,OAAA,EAAA,CAAA,cAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA,CAAA;;4FAGV,2BAA2B,EAAA,UAAA,EAAA,CAAA;kBAhBvC,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,0BAA0B,EAAA,eAAA,EAGnB,uBAAuB,CAAC,MAAM,EAAA,OAAA,EACtC;wBACP,mBAAmB;wBACnB,kBAAkB;wBAClB,aAAa;wBACb,eAAe;wBACf,gBAAgB;wBAChB,yBAAyB;wBACzB,sBAAsB;wBACtB,mBAAmB;AACpB,qBAAA,EAAA,QAAA,EAAA,w7EAAA,EAAA,MAAA,EAAA,CAAA,oJAAA,CAAA,EAAA;;;;;"}
@@ -0,0 +1,240 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, ElementRef, input, output, PLATFORM_ID, Input, ChangeDetectionStrategy, Component } from '@angular/core';
3
+ import { isPlatformBrowser } from '@angular/common';
4
+ import { NgControl } from '@angular/forms';
5
+ import { MatFormFieldControl } from '@angular/material/form-field';
6
+ import { B as BaseCustomInput, _ as _isEqual } from './ngx-t-forms-ngx-t-forms-C2G8_WQk.mjs';
7
+
8
+ // Third-party Editor.js tool packages ship without typings that line up with
9
+ // the host editor's `ToolConstructable`. We narrow at the registration boundary
10
+ // via `unknown` rather than leaking `any` through this module.
11
+ const asToolConstructable = (tool) => tool;
12
+ /**
13
+ * Dynamically loads every Editor.js plugin bundle and returns a ready-to-use `EditorConfig`.
14
+ *
15
+ * Browser-only: callers MUST gate this behind `isPlatformBrowser(...)` because each plugin
16
+ * package touches `self` / `document` at module-eval time and crashes under bare-Node SSR.
17
+ */
18
+ const loadEditorConfig = async (payload) => {
19
+ const [{ default: Header }, { default: List }, { default: Paragraph }, { default: Quote }, { default: Table }, { default: ImageTool }, { default: Delimiter }, { default: CodeTool }, { default: Embed },] = await Promise.all([
20
+ import('@editorjs/header'),
21
+ import('@editorjs/list'),
22
+ import('@editorjs/paragraph'),
23
+ import('@editorjs/quote'),
24
+ import('@editorjs/table'),
25
+ import('@editorjs/image'),
26
+ import('@editorjs/delimiter'),
27
+ import('@editorjs/code'),
28
+ import('@editorjs/embed'),
29
+ ]);
30
+ return ({
31
+ holder: payload.holderId,
32
+ autofocus: true,
33
+ placeholder: 'Let\'s write something amazing...',
34
+ inlineToolbar: true,
35
+ tools: {
36
+ header: {
37
+ class: asToolConstructable(Header),
38
+ config: {
39
+ levels: [1, 2, 3, 4, 5, 6],
40
+ defaultLevel: 1,
41
+ placeholder: 'Type your heading here...'
42
+ },
43
+ inlineToolbar: ['link', 'bold', 'italic', 'marker']
44
+ },
45
+ list: {
46
+ class: asToolConstructable(List),
47
+ inlineToolbar: true,
48
+ config: {
49
+ defaultStyle: 'unordered',
50
+ placeholder: 'Enter a list item here...'
51
+ }
52
+ },
53
+ paragraph: {
54
+ class: asToolConstructable(Paragraph),
55
+ inlineToolbar: true,
56
+ config: {
57
+ preserveBlank: true,
58
+ placeholder: 'Type your paragraph here...'
59
+ }
60
+ },
61
+ quote: {
62
+ class: asToolConstructable(Quote),
63
+ inlineToolbar: true,
64
+ shortcut: 'CMD+SHIFT+Q',
65
+ config: {
66
+ quotePlaceholder: 'Enter a quote',
67
+ captionPlaceholder: 'Quote\'s author',
68
+ alignmentEnabled: true
69
+ }
70
+ },
71
+ delimiter: {
72
+ class: asToolConstructable(Delimiter)
73
+ },
74
+ image: {
75
+ class: asToolConstructable(ImageTool),
76
+ config: {
77
+ endpoints: {
78
+ byFile: payload.imageUploadEndpoint,
79
+ byUrl: payload.imageFetchEndpoint
80
+ },
81
+ uploader: {
82
+ uploadByFile(file) {
83
+ // Custom upload logic
84
+ }
85
+ }
86
+ }
87
+ },
88
+ table: {
89
+ class: asToolConstructable(Table),
90
+ inlineToolbar: true,
91
+ config: {
92
+ rows: 2,
93
+ cols: 3
94
+ }
95
+ },
96
+ code: {
97
+ class: asToolConstructable(CodeTool),
98
+ config: {
99
+ placeholder: 'Enter code here...'
100
+ }
101
+ },
102
+ embed: {
103
+ class: asToolConstructable(Embed),
104
+ config: {
105
+ services: {
106
+ youtube: true,
107
+ codesandbox: true,
108
+ codepen: true
109
+ }
110
+ }
111
+ },
112
+ },
113
+ defaultBlock: 'paragraph',
114
+ hideToolbar: false,
115
+ data: payload.data,
116
+ readOnly: payload.readOnly,
117
+ logLevel: 'ERROR',
118
+ minHeight: 300,
119
+ onChange: (api, event) => {
120
+ payload.onChangeFn();
121
+ },
122
+ onReady: () => { },
123
+ sanitizer: {
124
+ p: true,
125
+ b: true,
126
+ a: {
127
+ href: true,
128
+ target: '_blank',
129
+ rel: 'nofollow'
130
+ }
131
+ },
132
+ i18n: {
133
+ messages: {
134
+ ui: {
135
+ blockTunes: {
136
+ toggler: {
137
+ 'Click to tune': 'Click to tune',
138
+ 'or drag to move': 'or drag to move'
139
+ }
140
+ }
141
+ }
142
+ }
143
+ }
144
+ });
145
+ };
146
+
147
+ const customInputConfig = {
148
+ controlType: 'lib-editor-js-input',
149
+ nextId: 0
150
+ };
151
+ /**
152
+ * Rich-text input backed by the Editor.js block editor, wired into Angular
153
+ * Material's form-field via {@link MatFormFieldControl}.
154
+ *
155
+ * The Editor.js bundle is browser-only, so it is dynamically imported and
156
+ * instantiated inside `ngAfterViewInit` behind an `isPlatformBrowser` guard
157
+ * to stay SSR-safe. The editor instance is destroyed on `ngOnDestroy`.
158
+ *
159
+ * @deprecated Scheduled for removal. Do not use in new code; migrate existing
160
+ * usages to the supported rich-text input element. Retained only for backward
161
+ * compatibility with forms that still reference `lib-editor-js-input`.
162
+ *
163
+ * @example
164
+ * <lib-editor-js-input [inputConfig]="column()" (valueChanged)="onChange($event)" />
165
+ */
166
+ class EditorJsInputComponent extends BaseCustomInput {
167
+ #platformId;
168
+ constructor() {
169
+ super(inject(NgControl, { optional: true, self: true }), inject(ElementRef), customInputConfig);
170
+ /** Column definition describing the field's id, read-only state and metadata. */
171
+ this.inputConfig = input.required(...(ngDevMode ? [{ debugName: "inputConfig" }] : /* istanbul ignore next */ []));
172
+ /** Emits the editor's saved {@link OutputData} whenever its content changes. */
173
+ this.valueChanged = output();
174
+ this.#platformId = inject(PLATFORM_ID);
175
+ this._value = undefined;
176
+ }
177
+ get empty() {
178
+ const n = this.value;
179
+ // Check for null, undefined, or empty string, but allow 0
180
+ return n === null || n === undefined || n === '';
181
+ }
182
+ get shouldLabelFloat() {
183
+ return true;
184
+ }
185
+ set value(value) {
186
+ if (!_isEqual(this._value, value)) {
187
+ this._value = value;
188
+ this.onChange(value);
189
+ this.stateChanges.next();
190
+ }
191
+ }
192
+ get value() {
193
+ return this._value;
194
+ }
195
+ async ngAfterViewInit() {
196
+ if (!isPlatformBrowser(this.#platformId))
197
+ return;
198
+ if (this.editor) {
199
+ this.editor.destroy();
200
+ }
201
+ const payload = {
202
+ holderId: this.inputConfig().id,
203
+ imageFetchEndpoint: '',
204
+ imageUploadEndpoint: '',
205
+ readOnly: this.inputConfig().readonly || false,
206
+ data: this.value || undefined,
207
+ onChangeFn: this.contentChangedSaveValue.bind(this)
208
+ };
209
+ // Browser-only dynamic load — see Trap 16 comment at the top of this file and in config.ts.
210
+ const [{ default: EditorJS }, config] = await Promise.all([
211
+ import('@editorjs/editorjs'),
212
+ loadEditorConfig(payload),
213
+ ]);
214
+ this.editor = new EditorJS(config);
215
+ }
216
+ async contentChangedSaveValue() {
217
+ const value = await this.editor?.save();
218
+ this.value = value;
219
+ this.onChange(value);
220
+ this.valueChanged.emit(value);
221
+ }
222
+ ngOnDestroy() {
223
+ this.stateChanges.complete();
224
+ this.editor?.destroy();
225
+ }
226
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: EditorJsInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
227
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.12", type: EditorJsInputComponent, isStandalone: true, selector: "lib-editor-js-input", inputs: { inputConfig: { classPropertyName: "inputConfig", publicName: "inputConfig", isSignal: true, isRequired: true, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { valueChanged: "valueChanged" }, host: { properties: { "class.floating": "shouldLabelFloat", "id": "id" } }, providers: [{ provide: MatFormFieldControl, useExisting: EditorJsInputComponent }], usesInheritance: true, ngImport: i0, template: "\r\n<div class=\" editor-container\" style=\"padding: 16px;\">\r\n <div #editorJs [id]=\"inputConfig().id\"></div>\r\n</div>\r\n", styles: [".editor-container{border:solid 1px var(--mat-divider-color, var(--mat-app-outline));padding:16px;background:var(--mdc-elevated-card-container-color, var(--mat-app-surface-container-low))}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
228
+ }
229
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: EditorJsInputComponent, decorators: [{
230
+ type: Component,
231
+ args: [{ selector: 'lib-editor-js-input', imports: [], host: {
232
+ '[class.floating]': 'shouldLabelFloat',
233
+ '[id]': 'id'
234
+ }, providers: [{ provide: MatFormFieldControl, useExisting: EditorJsInputComponent }], changeDetection: ChangeDetectionStrategy.OnPush, template: "\r\n<div class=\" editor-container\" style=\"padding: 16px;\">\r\n <div #editorJs [id]=\"inputConfig().id\"></div>\r\n</div>\r\n", styles: [".editor-container{border:solid 1px var(--mat-divider-color, var(--mat-app-outline));padding:16px;background:var(--mdc-elevated-card-container-color, var(--mat-app-surface-container-low))}\n"] }]
235
+ }], ctorParameters: () => [], propDecorators: { inputConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputConfig", required: true }] }], valueChanged: [{ type: i0.Output, args: ["valueChanged"] }], value: [{
236
+ type: Input
237
+ }] } });
238
+
239
+ export { EditorJsInputComponent };
240
+ //# sourceMappingURL=ngx-t-forms-editor-js-input.component-5MD8wRj0.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ngx-t-forms-editor-js-input.component-5MD8wRj0.mjs","sources":["../../../projects/ngx-t-forms/src/lib/components/t-form-input/elements/editor-input-element/core/form-input-rich-text-editor/config.ts","../../../projects/ngx-t-forms/src/lib/components/t-form-input/elements/editor-input-element/core/editor-js-input/editor-js-input.component.ts","../../../projects/ngx-t-forms/src/lib/components/t-form-input/elements/editor-input-element/core/editor-js-input/editor-js-input.component.html"],"sourcesContent":["/// <reference path=\"../../../../../../../types/editorjs.d.ts\" />\r\nimport type { EditorConfig, LogLevels, OutputData, ToolConstructable } from \"@editorjs/editorjs\";\r\n// `@editorjs/editorjs` is CJS — runtime named imports fail under Node ESM (SSR / smoke harness).\r\n// `LogLevels` is a runtime enum with string values; use the string literal cast at the single use site below.\r\n//\r\n// Wave 2 / Trap 16: every Editor.js plugin package below is a browser-only UMD bundle that crashes\r\n// under bare Node SSR (`self`/`document` not defined at module-eval). They are now loaded via\r\n// dynamic `import()` inside `loadEditorConfig()`, which is only invoked from an SSR-gated\r\n// `ngAfterViewInit` (see `editor-js-input.component.ts`). Static top-level imports here are\r\n// type-only and emit zero runtime code.\r\n\r\nexport interface EditorJsPayload {\r\n holderId: string,\r\n imageFetchEndpoint:string,\r\n imageUploadEndpoint: string,\r\n readOnly:boolean,\r\n onChangeFn: () => void,\r\n data:OutputData|undefined\r\n}\r\n\r\n// Third-party Editor.js tool packages ship without typings that line up with\r\n// the host editor's `ToolConstructable`. We narrow at the registration boundary\r\n// via `unknown` rather than leaking `any` through this module.\r\nconst asToolConstructable = (tool: unknown): ToolConstructable =>\r\n tool as ToolConstructable;\r\n\r\n/**\r\n * Dynamically loads every Editor.js plugin bundle and returns a ready-to-use `EditorConfig`.\r\n *\r\n * Browser-only: callers MUST gate this behind `isPlatformBrowser(...)` because each plugin\r\n * package touches `self` / `document` at module-eval time and crashes under bare-Node SSR.\r\n */\r\nexport const loadEditorConfig = async (\r\n payload: EditorJsPayload\r\n): Promise<EditorConfig> => {\r\n const [\r\n { default: Header },\r\n { default: List },\r\n { default: Paragraph },\r\n { default: Quote },\r\n { default: Table },\r\n { default: ImageTool },\r\n { default: Delimiter },\r\n { default: CodeTool },\r\n { default: Embed },\r\n ] = await Promise.all([\r\n import('@editorjs/header'),\r\n import('@editorjs/list'),\r\n import('@editorjs/paragraph'),\r\n import('@editorjs/quote'),\r\n import('@editorjs/table'),\r\n import('@editorjs/image'),\r\n import('@editorjs/delimiter'),\r\n import('@editorjs/code'),\r\n import('@editorjs/embed'),\r\n ]);\r\n\r\n return ({\r\n holder: payload.holderId,\r\n autofocus: true,\r\n placeholder: 'Let\\'s write something amazing...',\r\n inlineToolbar: true,\r\n tools: {\r\n header: {\r\n class: asToolConstructable(Header),\r\n config: {\r\n levels: [1, 2, 3, 4, 5, 6],\r\n defaultLevel: 1,\r\n placeholder: 'Type your heading here...'\r\n },\r\n inlineToolbar: ['link', 'bold', 'italic', 'marker']\r\n },\r\n list: {\r\n class: asToolConstructable(List),\r\n inlineToolbar: true,\r\n config: {\r\n defaultStyle: 'unordered',\r\n placeholder: 'Enter a list item here...'\r\n }\r\n },\r\n paragraph: {\r\n class: asToolConstructable(Paragraph),\r\n inlineToolbar: true,\r\n config: {\r\n preserveBlank: true,\r\n placeholder: 'Type your paragraph here...'\r\n }\r\n },\r\n quote: {\r\n class: asToolConstructable(Quote),\r\n inlineToolbar: true,\r\n shortcut: 'CMD+SHIFT+Q',\r\n config: {\r\n quotePlaceholder: 'Enter a quote',\r\n captionPlaceholder: 'Quote\\'s author',\r\n alignmentEnabled: true\r\n }\r\n },\r\n delimiter: {\r\n class: asToolConstructable(Delimiter)\r\n },\r\n image: {\r\n class: asToolConstructable(ImageTool),\r\n config: {\r\n endpoints: {\r\n byFile: payload.imageUploadEndpoint,\r\n byUrl: payload.imageFetchEndpoint\r\n },\r\n uploader: {\r\n uploadByFile(file: File) {\r\n // Custom upload logic\r\n }\r\n }\r\n }\r\n },\r\n table: {\r\n class: asToolConstructable(Table),\r\n inlineToolbar: true,\r\n config: {\r\n rows: 2,\r\n cols: 3\r\n }\r\n },\r\n code: {\r\n class: asToolConstructable(CodeTool),\r\n config: {\r\n placeholder: 'Enter code here...'\r\n }\r\n },\r\n\r\n embed: {\r\n class: asToolConstructable(Embed),\r\n config: {\r\n services: {\r\n youtube: true,\r\n codesandbox: true,\r\n codepen: true\r\n }\r\n }\r\n },\r\n\r\n },\r\n defaultBlock: 'paragraph',\r\n hideToolbar: false,\r\n data: payload.data,\r\n readOnly:payload.readOnly,\r\n logLevel: 'ERROR' as LogLevels,\r\n minHeight: 300,\r\n onChange: (api, event) => {\r\n payload.onChangeFn()\r\n },\r\n onReady: () => {},\r\n sanitizer: {\r\n p: true,\r\n b: true,\r\n a: {\r\n href: true,\r\n target: '_blank',\r\n rel: 'nofollow'\r\n }\r\n },\r\n i18n: {\r\n messages: {\r\n ui: {\r\n blockTunes: {\r\n toggler: {\r\n 'Click to tune': 'Click to tune',\r\n 'or drag to move': 'or drag to move'\r\n }\r\n }\r\n }\r\n }\r\n }\r\n });\r\n}\r\n\r\n\r\n","import {\r\n AfterViewInit,\r\n ChangeDetectionStrategy,\r\n Component,\r\n ElementRef,\r\n Input,\r\n OnDestroy,\r\n PLATFORM_ID,\r\n inject,\r\n input,\r\n output\r\n} from '@angular/core';\r\nimport { isPlatformBrowser } from '@angular/common';\r\nimport { NgControl } from '@angular/forms';\r\n\r\nimport { ITowerStepColumn } from 'ngx-t-forms-types';\r\n// Wave 2 / Trap 16: `@editorjs/editorjs` is a browser-only UMD bundle that crashes under\r\n// bare-Node SSR at module-eval time. Type-only import at the top keeps the surface intact\r\n// with zero runtime emission; the runtime load happens inside the SSR-gated `ngAfterViewInit`.\r\nimport type EditorJSType from '@editorjs/editorjs';\r\nimport type { OutputData } from '@editorjs/editorjs';\r\nimport { MatFormFieldControl } from '@angular/material/form-field';\r\n\r\nimport { BaseCustomInput, BaseCustomInputConfig } from '../../../../../../services/core/t-input-controller/functions/baseCustomInput';\r\nimport { loadEditorConfig, EditorJsPayload } from '../form-input-rich-text-editor/config';\r\nimport { _isEqual } from '../../../../../../shared/functions/isEqual';\r\n\r\nconst customInputConfig: BaseCustomInputConfig = {\r\n controlType: 'lib-editor-js-input',\r\n nextId: 0\r\n};\r\n\r\n/**\r\n * Rich-text input backed by the Editor.js block editor, wired into Angular\r\n * Material's form-field via {@link MatFormFieldControl}.\r\n *\r\n * The Editor.js bundle is browser-only, so it is dynamically imported and\r\n * instantiated inside `ngAfterViewInit` behind an `isPlatformBrowser` guard\r\n * to stay SSR-safe. The editor instance is destroyed on `ngOnDestroy`.\r\n *\r\n * @deprecated Scheduled for removal. Do not use in new code; migrate existing\r\n * usages to the supported rich-text input element. Retained only for backward\r\n * compatibility with forms that still reference `lib-editor-js-input`.\r\n *\r\n * @example\r\n * <lib-editor-js-input [inputConfig]=\"column()\" (valueChanged)=\"onChange($event)\" />\r\n */\r\n@Component({\r\n selector: 'lib-editor-js-input',\r\n templateUrl: './editor-js-input.component.html',\r\n styleUrl: './editor-js-input.component.css',\r\n imports: [],\r\n host: {\r\n '[class.floating]': 'shouldLabelFloat',\r\n '[id]': 'id'\r\n },\r\n providers: [{ provide: MatFormFieldControl, useExisting: EditorJsInputComponent }],\r\n changeDetection: ChangeDetectionStrategy.OnPush\r\n})\r\nexport class EditorJsInputComponent\r\n extends BaseCustomInput<OutputData | undefined>\r\n implements AfterViewInit, OnDestroy {\r\n\r\n /** Column definition describing the field's id, read-only state and metadata. */\r\n readonly inputConfig = input.required<ITowerStepColumn>();\r\n\r\n /** Emits the editor's saved {@link OutputData} whenever its content changes. */\r\n readonly valueChanged = output<OutputData | undefined>();\r\n\r\n /** Live Editor.js instance; `undefined` until initialised (or on the server). */\r\n protected editor: EditorJSType | undefined;\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 override _value: OutputData | undefined = undefined;\r\n\r\n @Input() override set value(value: OutputData | undefined) {\r\n if (!_isEqual(this._value, value)) {\r\n this._value = value;\r\n this.onChange(value);\r\n this.stateChanges.next();\r\n }\r\n }\r\n\r\n override get value(): OutputData | undefined {\r\n return this._value;\r\n }\r\n\r\n async ngAfterViewInit(): Promise<void> {\r\n if (!isPlatformBrowser(this.#platformId)) return;\r\n\r\n if (this.editor) {\r\n this.editor.destroy();\r\n }\r\n\r\n const payload: EditorJsPayload = {\r\n holderId: this.inputConfig().id,\r\n imageFetchEndpoint: '',\r\n imageUploadEndpoint: '',\r\n readOnly: this.inputConfig().readonly || false,\r\n data: this.value || undefined,\r\n onChangeFn: this.contentChangedSaveValue.bind(this)\r\n };\r\n\r\n // Browser-only dynamic load — see Trap 16 comment at the top of this file and in config.ts.\r\n const [{ default: EditorJS }, config] = await Promise.all([\r\n import('@editorjs/editorjs'),\r\n loadEditorConfig(payload),\r\n ]);\r\n this.editor = new EditorJS(config);\r\n }\r\n\r\n async contentChangedSaveValue(): Promise<void> {\r\n const value: OutputData | undefined = await this.editor?.save();\r\n this.value = value;\r\n this.onChange(value);\r\n this.valueChanged.emit(value);\r\n }\r\n\r\n override ngOnDestroy(): void {\r\n this.stateChanges.complete();\r\n this.editor?.destroy();\r\n }\r\n}\r\n","\r\n<div class=\" editor-container\" style=\"padding: 16px;\">\r\n <div #editorJs [id]=\"inputConfig().id\"></div>\r\n</div>\r\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,205 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, ElementRef, input, viewChild, computed, PLATFORM_ID, ChangeDetectionStrategy, Component, output } from '@angular/core';
3
+ import * as i1$2 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$1 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, q as getInputErrorMessage, u as TFormInputStatusComponent } from './ngx-t-forms-ngx-t-forms-C2G8_WQk.mjs';
14
+ import { isPlatformBrowser } from '@angular/common';
15
+ import * as i1 from '@angular/material/progress-bar';
16
+ import { MatProgressBarModule } from '@angular/material/progress-bar';
17
+ import * as i5 from '@angular/material/toolbar';
18
+ import { MatToolbarModule } from '@angular/material/toolbar';
19
+ import { InputFileType, UploadTypes, AllDocumentFileExtensions, AllImageFileExtensions } from 'ngx-t-forms-types';
20
+
21
+ const customInputConfig = {
22
+ controlType: 'app-file-uploader',
23
+ nextId: 0,
24
+ };
25
+ class FileUploaderComponent extends BaseCustomInput {
26
+ #platformId;
27
+ constructor() {
28
+ super(inject(NgControl, { optional: true, self: true }), inject(ElementRef), customInputConfig);
29
+ this.inputConfig = input.required(...(ngDevMode ? [{ debugName: "inputConfig" }] : /* istanbul ignore next */ []));
30
+ this.uploader = viewChild.required('uploader');
31
+ this.uploadAccept = computed(() => {
32
+ const cfg = this.inputConfig();
33
+ const fileType = cfg?.fileType;
34
+ if (!fileType) {
35
+ return InputFileType.file;
36
+ }
37
+ return UploadTypes[String(fileType)] ?? InputFileType.file;
38
+ }, ...(ngDevMode ? [{ debugName: "uploadAccept" }] : /* istanbul ignore next */ []));
39
+ this.previewSrc = computed(() => {
40
+ const cfg = this.inputConfig();
41
+ const fileType = cfg?.fileType;
42
+ switch (fileType) {
43
+ case InputFileType.file:
44
+ return 'https://res.cloudinary.com/afrob/image/upload/v1676973154/Flows/Icons/iPhone_14_-_1_tx1scw.png';
45
+ default:
46
+ return this.value?.base64 ?? undefined;
47
+ }
48
+ }, ...(ngDevMode ? [{ debugName: "previewSrc" }] : /* istanbul ignore next */ []));
49
+ this.fileName = null;
50
+ this.loading = null;
51
+ this.dragOver = false;
52
+ this.#platformId = inject(PLATFORM_ID);
53
+ }
54
+ get value() {
55
+ return this._value;
56
+ }
57
+ set value(file) {
58
+ const fileType = this.inputConfig()?.fileType;
59
+ if (!file || typeof file !== 'object') {
60
+ this._value = file;
61
+ this.stateChanges.next();
62
+ return;
63
+ }
64
+ const { base64, fileExtension } = file;
65
+ if (!base64) {
66
+ this._value = file;
67
+ this.stateChanges.next();
68
+ return;
69
+ }
70
+ const allDocExtensions = Object.values(AllDocumentFileExtensions);
71
+ const allImageExtensions = Object.values(AllImageFileExtensions);
72
+ const isFile = allDocExtensions.includes(fileExtension);
73
+ const isImage = allImageExtensions.includes(fileExtension);
74
+ if ((fileType === InputFileType.file && !isFile) ||
75
+ ((fileType === InputFileType.Image || fileType === InputFileType.CaptureImage) && !isImage)) {
76
+ this._value = null;
77
+ this.temporaryError(`Invalid file type. Expected ${fileType} file`);
78
+ this.stateChanges.next();
79
+ return;
80
+ }
81
+ else {
82
+ this._value = file;
83
+ this.stateChanges.next();
84
+ return;
85
+ }
86
+ }
87
+ get empty() {
88
+ return !this.value;
89
+ }
90
+ get shouldLabelFloat() {
91
+ return this.focused || !this.empty;
92
+ }
93
+ onContainerClick(event) {
94
+ this.uploader().nativeElement.click();
95
+ if (event.target !== this._elementRef.nativeElement) {
96
+ this.markAsTouched();
97
+ this.stateChanges.next();
98
+ }
99
+ }
100
+ triggerUploader() {
101
+ this.uploader().nativeElement.click();
102
+ }
103
+ onFileSelected(event) {
104
+ const files = event.target.files;
105
+ if (files && files.length > 0) {
106
+ const file = files[0];
107
+ if (!file)
108
+ return;
109
+ this.assignFile(file);
110
+ }
111
+ }
112
+ assignFile(file) {
113
+ // FileReader is a browser-only API; gate by isPlatformBrowser to keep SSR-safe.
114
+ if (!isPlatformBrowser(this.#platformId)) {
115
+ return;
116
+ }
117
+ const reader = new FileReader();
118
+ reader.onload = () => {
119
+ this.fileName = file.name;
120
+ const nameSplit = file.name.split('.');
121
+ const fileExtension = nameSplit[nameSplit.length - 1];
122
+ this.value = {
123
+ fileName: file.name,
124
+ base64: reader.result,
125
+ type: this.inputConfig()?.fileType,
126
+ blob: file,
127
+ fileExtension,
128
+ };
129
+ this.onChange(this.value);
130
+ };
131
+ reader.readAsDataURL(file);
132
+ }
133
+ onDragOver(event) {
134
+ this.dragOver = true;
135
+ event.preventDefault();
136
+ event.stopPropagation();
137
+ }
138
+ onDrop(event) {
139
+ this.dragOver = false;
140
+ event.preventDefault();
141
+ event.stopPropagation();
142
+ const files = event.dataTransfer?.files;
143
+ if (files && files.length > 0) {
144
+ const file = files[0];
145
+ if (!file)
146
+ return;
147
+ this.assignFile(file);
148
+ }
149
+ }
150
+ onDragLeave(event) {
151
+ this.dragOver = false;
152
+ event.preventDefault();
153
+ event.stopPropagation();
154
+ }
155
+ clearFile(event) {
156
+ event.preventDefault();
157
+ event.stopPropagation();
158
+ this.value = null;
159
+ this.stateChanges.next();
160
+ }
161
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: FileUploaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
162
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: FileUploaderComponent, isStandalone: true, selector: "lib-file-uploader", inputs: { inputConfig: { classPropertyName: "inputConfig", publicName: "inputConfig", isSignal: true, isRequired: true, transformFunction: null } }, host: { properties: { "class.floating": "shouldLabelFloat", "id": "id" } }, providers: [{ provide: MatFormFieldControl, useExisting: FileUploaderComponent }], viewQueries: [{ propertyName: "uploader", first: true, predicate: ["uploader"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "@if (loading) {\r\n <mat-progress-bar mode=\"indeterminate\"></mat-progress-bar>\r\n}\r\n\r\n@if (!shouldLabelFloat) {\r\n <section>\r\n <br>\r\n <div\r\n [style.border-color]=\"dragOver ? ' var(--mat-stepper-header-selected-state-icon-background-color)' : '#ccc;'\"\r\n (dragover)=\"onDragOver($event)\"\r\n (drop)=\"onDrop($event)\"\r\n (dragleave)=\"onDragLeave($event)\"\r\n class=\"drop-zone\">\r\n <div>\r\n <mat-icon>\r\n cloud_upload\r\n </mat-icon>\r\n </div>\r\n <div>\r\n @if (!!errorMessage) {\r\n <span class=\"mat-mdc-form-field-error\">\r\n {{ errorMessage }}\r\n </span>\r\n } @else {\r\n Drag and drop files or click to upload\r\n }\r\n </div>\r\n </div>\r\n </section>\r\n}\r\n\r\n<input\r\n style=\"display: none\"\r\n hidden\r\n [readonly]=\"!!inputConfig().readonly\"\r\n [type]=\"inputConfig().type || 'file'\"\r\n [accept]=\"uploadAccept()\"\r\n (change)=\"onFileSelected($event)\"\r\n #uploader\r\n/>\r\n\r\n@if (!!shouldLabelFloat) {\r\n <div\r\n [style.border-color]=\"dragOver ? 'var(--mat-stepper-header-selected-state-icon-background-color)' : '#ccc;'\"\r\n class=\"drop-zone\"\r\n (dragover)=\"onDragOver($event)\"\r\n (drop)=\"onDrop($event)\"\r\n (dragleave)=\"onDragLeave($event)\">\r\n <img style=\"width: 100%;\" [src]=\"previewSrc()\" alt=\"\">\r\n <mat-toolbar style=\" height: min-content !important;\">\r\n <mat-icon\r\n [style.color]=\"dragOver ? 'var(--mat-stepper-header-selected-state-icon-background-color)' : ''\">\r\n cloud_upload\r\n </mat-icon>\r\n <span class=\"spacer\"></span>\r\n <div style=\"padding: 8px;\">\r\n @if (!!fileName) {\r\n <div style=\"\r\n line-height: normal;width: 100%;\r\n white-space:normal;overflow: hidden;text-overflow: ellipsis;\r\n font-size: 0.75em;color:var(--mat-stepper-header-selected-state-icon-background-color);\">\r\n {{ fileName }}\r\n </div>\r\n }\r\n <div style=\"font-size: 0.875em;\">\r\n Drag and drop files or click to upload\r\n </div>\r\n </div>\r\n\r\n <span class=\"spacer\"></span>\r\n <button (click)=\"clearFile($event)\" mat-icon-button>\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </mat-toolbar>\r\n </div>\r\n}\r\n", styles: [".fileUploader{opacity:0;display:none;transition:opacity .2s;height:50px}:host.floating .fileUploader{opacity:1}.drop-zone{border:2px dashed #ccc;padding:20px;text-align:center;cursor:pointer}.drop-zone:hover{border-color:var(--mat-stepper-header-selected-state-icon-background-color)}\n"], dependencies: [{ kind: "ngmodule", type: MatProgressBarModule }, { kind: "component", type: i1.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { 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$1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
163
+ }
164
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: FileUploaderComponent, decorators: [{
165
+ type: Component,
166
+ args: [{ selector: 'lib-file-uploader', imports: [
167
+ MatProgressBarModule,
168
+ MatIconModule,
169
+ MatToolbarModule,
170
+ MatButtonModule,
171
+ ], host: {
172
+ '[class.floating]': 'shouldLabelFloat',
173
+ '[id]': 'id',
174
+ }, providers: [{ provide: MatFormFieldControl, useExisting: FileUploaderComponent }], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (loading) {\r\n <mat-progress-bar mode=\"indeterminate\"></mat-progress-bar>\r\n}\r\n\r\n@if (!shouldLabelFloat) {\r\n <section>\r\n <br>\r\n <div\r\n [style.border-color]=\"dragOver ? ' var(--mat-stepper-header-selected-state-icon-background-color)' : '#ccc;'\"\r\n (dragover)=\"onDragOver($event)\"\r\n (drop)=\"onDrop($event)\"\r\n (dragleave)=\"onDragLeave($event)\"\r\n class=\"drop-zone\">\r\n <div>\r\n <mat-icon>\r\n cloud_upload\r\n </mat-icon>\r\n </div>\r\n <div>\r\n @if (!!errorMessage) {\r\n <span class=\"mat-mdc-form-field-error\">\r\n {{ errorMessage }}\r\n </span>\r\n } @else {\r\n Drag and drop files or click to upload\r\n }\r\n </div>\r\n </div>\r\n </section>\r\n}\r\n\r\n<input\r\n style=\"display: none\"\r\n hidden\r\n [readonly]=\"!!inputConfig().readonly\"\r\n [type]=\"inputConfig().type || 'file'\"\r\n [accept]=\"uploadAccept()\"\r\n (change)=\"onFileSelected($event)\"\r\n #uploader\r\n/>\r\n\r\n@if (!!shouldLabelFloat) {\r\n <div\r\n [style.border-color]=\"dragOver ? 'var(--mat-stepper-header-selected-state-icon-background-color)' : '#ccc;'\"\r\n class=\"drop-zone\"\r\n (dragover)=\"onDragOver($event)\"\r\n (drop)=\"onDrop($event)\"\r\n (dragleave)=\"onDragLeave($event)\">\r\n <img style=\"width: 100%;\" [src]=\"previewSrc()\" alt=\"\">\r\n <mat-toolbar style=\" height: min-content !important;\">\r\n <mat-icon\r\n [style.color]=\"dragOver ? 'var(--mat-stepper-header-selected-state-icon-background-color)' : ''\">\r\n cloud_upload\r\n </mat-icon>\r\n <span class=\"spacer\"></span>\r\n <div style=\"padding: 8px;\">\r\n @if (!!fileName) {\r\n <div style=\"\r\n line-height: normal;width: 100%;\r\n white-space:normal;overflow: hidden;text-overflow: ellipsis;\r\n font-size: 0.75em;color:var(--mat-stepper-header-selected-state-icon-background-color);\">\r\n {{ fileName }}\r\n </div>\r\n }\r\n <div style=\"font-size: 0.875em;\">\r\n Drag and drop files or click to upload\r\n </div>\r\n </div>\r\n\r\n <span class=\"spacer\"></span>\r\n <button (click)=\"clearFile($event)\" mat-icon-button>\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </mat-toolbar>\r\n </div>\r\n}\r\n", styles: [".fileUploader{opacity:0;display:none;transition:opacity .2s;height:50px}:host.floating .fileUploader{opacity:1}.drop-zone{border:2px dashed #ccc;padding:20px;text-align:center;cursor:pointer}.drop-zone:hover{border-color:var(--mat-stepper-header-selected-state-icon-background-color)}\n"] }]
175
+ }], ctorParameters: () => [], propDecorators: { inputConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputConfig", required: true }] }], uploader: [{ type: i0.ViewChild, args: ['uploader', { isSignal: true }] }] } });
176
+
177
+ /** Wraps a reactive file-uploader control inside a `mat-form-field`. */
178
+ class FileUploadInputElementComponent {
179
+ constructor() {
180
+ this.inputConfig = input.required(...(ngDevMode ? [{ debugName: "inputConfig" }] : /* istanbul ignore next */ []));
181
+ this.formGroup = input.required(...(ngDevMode ? [{ debugName: "formGroup" }] : /* istanbul ignore next */ []));
182
+ this.reload = output();
183
+ this.errorMessage = computed(() => getInputErrorMessage(this.inputConfig(), this.formGroup()), ...(ngDevMode ? [{ debugName: "errorMessage" }] : /* istanbul ignore next */ []));
184
+ }
185
+ getErrors() {
186
+ return this.formGroup().controls[this.inputConfig().id]?.errors;
187
+ }
188
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: FileUploadInputElementComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
189
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: FileUploadInputElementComponent, isStandalone: true, selector: "lib-file-upload-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: "<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-file-uploader\r\n [inputConfig]=\"inputConfig\"\r\n [formControlName]=\"inputConfig.id\"\r\n [required]=\"inputConfig.required\"\r\n ></lib-file-uploader>\r\n\r\n @if (inputConfig.hintLabel || inputConfig.temporaryHint) {\r\n <mat-hint class=\"inputHint\">\r\n {{ inputConfig.temporaryHint || inputConfig.hintLabel }}\r\n </mat-hint>\r\n }\r\n\r\n @if (!!errorMessage()) {\r\n <mat-error class=\"oneLineTextEllipsis\" matTooltipClass=\"errorToolTip\">{{ errorMessage() }}</mat-error>\r\n }\r\n\r\n @if (inputConfig.prefixIcon) {\r\n <mat-icon matPrefix>{{ inputConfig.prefixIcon }}</mat-icon>\r\n }\r\n\r\n @if (inputConfig.canReload?.canReload) {\r\n <button\r\n mat-icon-button\r\n style=\"margin-right: 4px;\"\r\n matTooltip=\"Click to refresh this field.\"\r\n class=\"input-sync-button\"\r\n (click)=\"inputConfig.canReload.emit()\"\r\n matSuffix\r\n >\r\n <mat-icon style=\"color: var(--mat-sys-primary)\">sync</mat-icon>\r\n </button>\r\n }\r\n\r\n @if (inputConfig.suffixIcon && inputConfig.id !== 'password') {\r\n <mat-icon matSuffix>{{ inputConfig.suffixIcon }}</mat-icon>\r\n }\r\n\r\n @if (inputConfig.prefixText) {\r\n <span matPrefix style=\"top: 0\">{{ inputConfig.prefixText }}</span>\r\n }\r\n @if (inputConfig.suffixText) {\r\n <span matSuffix style=\"padding-left: 5px\">{{ inputConfig.suffixText }}</span>\r\n }\r\n\r\n @if (inputConfig.maxLength && formGroup()) {\r\n <mat-hint align=\"end\">\r\n {{ (formGroup().controls[inputConfig.id]?.value?.length || 0) + '/' + inputConfig.maxLength }}\r\n </mat-hint>\r\n }\r\n </mat-form-field>\r\n }\r\n</form>\r\n", styles: ["mat-form-field{width:100%!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$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.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$1.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i5$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: FileUploaderComponent, selector: "lib-file-uploader", inputs: ["inputConfig"] }, { kind: "component", type: TFormInputStatusComponent, selector: "lib-t-form-input-status", inputs: ["inputConfig"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
190
+ }
191
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: FileUploadInputElementComponent, decorators: [{
192
+ type: Component,
193
+ args: [{ selector: 'lib-file-upload-input-element', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
194
+ ReactiveFormsModule,
195
+ MatFormFieldModule,
196
+ MatIconModule,
197
+ MatButtonModule,
198
+ MatTooltipModule,
199
+ FileUploaderComponent,
200
+ TFormInputStatusComponent,
201
+ ], 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-file-uploader\r\n [inputConfig]=\"inputConfig\"\r\n [formControlName]=\"inputConfig.id\"\r\n [required]=\"inputConfig.required\"\r\n ></lib-file-uploader>\r\n\r\n @if (inputConfig.hintLabel || inputConfig.temporaryHint) {\r\n <mat-hint class=\"inputHint\">\r\n {{ inputConfig.temporaryHint || inputConfig.hintLabel }}\r\n </mat-hint>\r\n }\r\n\r\n @if (!!errorMessage()) {\r\n <mat-error class=\"oneLineTextEllipsis\" matTooltipClass=\"errorToolTip\">{{ errorMessage() }}</mat-error>\r\n }\r\n\r\n @if (inputConfig.prefixIcon) {\r\n <mat-icon matPrefix>{{ inputConfig.prefixIcon }}</mat-icon>\r\n }\r\n\r\n @if (inputConfig.canReload?.canReload) {\r\n <button\r\n mat-icon-button\r\n style=\"margin-right: 4px;\"\r\n matTooltip=\"Click to refresh this field.\"\r\n class=\"input-sync-button\"\r\n (click)=\"inputConfig.canReload.emit()\"\r\n matSuffix\r\n >\r\n <mat-icon style=\"color: var(--mat-sys-primary)\">sync</mat-icon>\r\n </button>\r\n }\r\n\r\n @if (inputConfig.suffixIcon && inputConfig.id !== 'password') {\r\n <mat-icon matSuffix>{{ inputConfig.suffixIcon }}</mat-icon>\r\n }\r\n\r\n @if (inputConfig.prefixText) {\r\n <span matPrefix style=\"top: 0\">{{ inputConfig.prefixText }}</span>\r\n }\r\n @if (inputConfig.suffixText) {\r\n <span matSuffix style=\"padding-left: 5px\">{{ inputConfig.suffixText }}</span>\r\n }\r\n\r\n @if (inputConfig.maxLength && formGroup()) {\r\n <mat-hint align=\"end\">\r\n {{ (formGroup().controls[inputConfig.id]?.value?.length || 0) + '/' + inputConfig.maxLength }}\r\n </mat-hint>\r\n }\r\n </mat-form-field>\r\n }\r\n</form>\r\n", styles: ["mat-form-field{width:100%!important}mat-form-field .input-sync-button{display:none}mat-form-field:hover .input-sync-button{display:inline-block}\n"] }]
202
+ }], 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"] }] } });
203
+
204
+ export { FileUploadInputElementComponent };
205
+ //# sourceMappingURL=ngx-t-forms-file-upload-input-element.component-BAtuymMY.mjs.map