@yuuvis/client-framework 2.0.0-beta.0 → 2.0.0-beta.2

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 (389) hide show
  1. package/actions/lib/actions/delete-action/delete/delete.component.d.ts +3 -3
  2. package/actions/lib/actions/delete-action/delete-action.d.ts +1 -1
  3. package/actions/lib/actions.service.d.ts +7 -3
  4. package/actions/lib/components/contextmenu/contextmenu.component.d.ts +3 -1
  5. package/autocomplete/README.md +3 -0
  6. package/autocomplete/index.d.ts +3 -0
  7. package/autocomplete/lib/autocomplete.component.d.ts +72 -0
  8. package/autocomplete/lib/autocomplete.interface.d.ts +4 -0
  9. package/autocomplete/lib/autocomplete.module.d.ts +7 -0
  10. package/common/index.d.ts +4 -4
  11. package/common/lib/common.module.d.ts +19 -0
  12. package/common/lib/common.utils.d.ts +2 -0
  13. package/common/lib/components/confirm/confirm.component.d.ts +7 -0
  14. package/common/lib/components/confirm/confirm.interface.d.ts +7 -0
  15. package/common/lib/components/confirm/confirm.service.d.ts +9 -0
  16. package/common/lib/components/dialog/dialog.component.d.ts +6 -0
  17. package/common/lib/components/dialog/dialog.options.d.ts +7 -0
  18. package/common/lib/components/index.d.ts +5 -0
  19. package/common/lib/directives/autofocus-child.directive.d.ts +13 -0
  20. package/common/lib/directives/autofocus-delayed.directive.d.ts +18 -0
  21. package/common/lib/directives/drag-scroll.directive.d.ts +20 -0
  22. package/common/lib/directives/index.d.ts +8 -4
  23. package/common/lib/directives/noop-value-accessor.directive.d.ts +2 -2
  24. package/common/lib/mat-form-field.abstract.d.ts +41 -0
  25. package/common/lib/services/index.d.ts +1 -1
  26. package/common/lib/services/layout-settings/layout-settings.service.d.ts +18 -0
  27. package/datepicker/README.md +3 -0
  28. package/datepicker/index.d.ts +5 -0
  29. package/datepicker/lib/calendar/calendar.component.d.ts +72 -0
  30. package/datepicker/lib/date-input/date-input-element/date-input-element.component.d.ts +43 -0
  31. package/datepicker/lib/date-input/date-input-hour-element/date-input-hour-element.component.d.ts +11 -0
  32. package/datepicker/lib/date-input/date-input.component.d.ts +61 -0
  33. package/datepicker/lib/datepicker-calendar/datepicker-calendar-trigger.component.d.ts +7 -0
  34. package/datepicker/lib/datepicker-calendar/datepicker-calendar.component.d.ts +12 -0
  35. package/datepicker/lib/datepicker.component.d.ts +80 -0
  36. package/datepicker/lib/datepicker.interface.d.ts +34 -0
  37. package/datepicker/lib/datepicker.module.d.ts +9 -0
  38. package/datepicker/lib/datepicker.service.d.ts +46 -0
  39. package/datepicker/lib/datepicker.utils.d.ts +23 -0
  40. package/datepicker/lib/time-input/time-input.component.d.ts +36 -0
  41. package/datepicker/lib/time-input/time-input.interface.d.ts +6 -0
  42. package/fesm2022/yuuvis-client-framework-actions.mjs +147 -105
  43. package/fesm2022/yuuvis-client-framework-actions.mjs.map +1 -1
  44. package/fesm2022/yuuvis-client-framework-app-bar.mjs +7 -8
  45. package/fesm2022/yuuvis-client-framework-app-bar.mjs.map +1 -1
  46. package/fesm2022/yuuvis-client-framework-autocomplete.mjs +210 -0
  47. package/fesm2022/yuuvis-client-framework-autocomplete.mjs.map +1 -0
  48. package/fesm2022/yuuvis-client-framework-clipboard.mjs +9 -9
  49. package/fesm2022/yuuvis-client-framework-clipboard.mjs.map +1 -1
  50. package/fesm2022/yuuvis-client-framework-common.mjs +853 -780
  51. package/fesm2022/yuuvis-client-framework-common.mjs.map +1 -1
  52. package/fesm2022/yuuvis-client-framework-datepicker.mjs +1688 -0
  53. package/fesm2022/yuuvis-client-framework-datepicker.mjs.map +1 -0
  54. package/fesm2022/yuuvis-client-framework-forms.mjs +945 -1157
  55. package/fesm2022/yuuvis-client-framework-forms.mjs.map +1 -1
  56. package/fesm2022/yuuvis-client-framework-icons.mjs +85 -12
  57. package/fesm2022/yuuvis-client-framework-icons.mjs.map +1 -1
  58. package/fesm2022/yuuvis-client-framework-list.mjs +81 -45
  59. package/fesm2022/yuuvis-client-framework-list.mjs.map +1 -1
  60. package/fesm2022/yuuvis-client-framework-master-details.mjs +112 -0
  61. package/fesm2022/yuuvis-client-framework-master-details.mjs.map +1 -0
  62. package/fesm2022/yuuvis-client-framework-metadata-form-defaults.mjs +60 -0
  63. package/fesm2022/yuuvis-client-framework-metadata-form-defaults.mjs.map +1 -0
  64. package/fesm2022/yuuvis-client-framework-metadata-form.mjs +125 -100
  65. package/fesm2022/yuuvis-client-framework-metadata-form.mjs.map +1 -1
  66. package/fesm2022/yuuvis-client-framework-object-details.mjs +49 -59
  67. package/fesm2022/yuuvis-client-framework-object-details.mjs.map +1 -1
  68. package/fesm2022/yuuvis-client-framework-object-flavor.mjs +188 -77
  69. package/fesm2022/yuuvis-client-framework-object-flavor.mjs.map +1 -1
  70. package/fesm2022/yuuvis-client-framework-object-form.mjs +99 -184
  71. package/fesm2022/yuuvis-client-framework-object-form.mjs.map +1 -1
  72. package/fesm2022/yuuvis-client-framework-object-preview.mjs +11 -11
  73. package/fesm2022/yuuvis-client-framework-object-preview.mjs.map +1 -1
  74. package/fesm2022/yuuvis-client-framework-object-summary.mjs +46 -42
  75. package/fesm2022/yuuvis-client-framework-object-summary.mjs.map +1 -1
  76. package/fesm2022/yuuvis-client-framework-overflow-menu.mjs +126 -0
  77. package/fesm2022/yuuvis-client-framework-overflow-menu.mjs.map +1 -0
  78. package/fesm2022/yuuvis-client-framework-pagination.mjs +7 -9
  79. package/fesm2022/yuuvis-client-framework-pagination.mjs.map +1 -1
  80. package/fesm2022/yuuvis-client-framework-panel.mjs +8 -7
  81. package/fesm2022/yuuvis-client-framework-panel.mjs.map +1 -1
  82. package/fesm2022/yuuvis-client-framework-popout.mjs +212 -0
  83. package/fesm2022/yuuvis-client-framework-popout.mjs.map +1 -0
  84. package/fesm2022/yuuvis-client-framework-renderer.mjs +99 -72
  85. package/fesm2022/yuuvis-client-framework-renderer.mjs.map +1 -1
  86. package/fesm2022/yuuvis-client-framework-sequence-list.mjs +29 -112
  87. package/fesm2022/yuuvis-client-framework-sequence-list.mjs.map +1 -1
  88. package/fesm2022/yuuvis-client-framework-simple-search.mjs +40 -21
  89. package/fesm2022/yuuvis-client-framework-simple-search.mjs.map +1 -1
  90. package/fesm2022/yuuvis-client-framework-split-view.mjs +188 -0
  91. package/fesm2022/yuuvis-client-framework-split-view.mjs.map +1 -0
  92. package/fesm2022/yuuvis-client-framework-tile-list.mjs +100 -93
  93. package/fesm2022/yuuvis-client-framework-tile-list.mjs.map +1 -1
  94. package/fesm2022/yuuvis-client-framework-tree.mjs +15 -15
  95. package/fesm2022/yuuvis-client-framework-tree.mjs.map +1 -1
  96. package/fesm2022/yuuvis-client-framework-upload-progress.mjs +16 -21
  97. package/fesm2022/yuuvis-client-framework-upload-progress.mjs.map +1 -1
  98. package/fesm2022/yuuvis-client-framework.mjs +4 -4
  99. package/fesm2022/yuuvis-client-framework.mjs.map +1 -1
  100. package/forms/index.d.ts +7 -1
  101. package/forms/lib/elements/catalog/catalog.component.d.ts +17 -56
  102. package/forms/lib/elements/data-grid/edit-table-data/edit-data.component.d.ts +5 -4
  103. package/forms/lib/elements/datetime/datetime.component.d.ts +19 -10
  104. package/forms/lib/elements/datetime-range/datetime-range.component.d.ts +12 -27
  105. package/forms/lib/elements/index.d.ts +0 -1
  106. package/forms/lib/elements/number/number.component.d.ts +21 -30
  107. package/forms/lib/elements/number-range/number-range.component.d.ts +12 -7
  108. package/forms/lib/elements/organization/organization.component.d.ts +23 -51
  109. package/forms/lib/elements/range-select-date/range-select-date.component.d.ts +12 -7
  110. package/forms/lib/elements/range-select-filesize/range-select-filesize.component.d.ts +12 -7
  111. package/forms/lib/elements/string/string.component.d.ts +15 -20
  112. package/forms/lib/forms.module.d.ts +8 -11
  113. package/icons/index.d.ts +1 -0
  114. package/icons/lib/icon.component.d.ts +20 -0
  115. package/lib/assets/i18n/de.json +7 -23
  116. package/lib/assets/i18n/en.json +10 -26
  117. package/list/index.d.ts +1 -0
  118. package/list/lib/list-item.directive.d.ts +5 -4
  119. package/list/lib/list.component.d.ts +6 -3
  120. package/list/lib/list.module.d.ts +8 -0
  121. package/master-details/README.md +3 -0
  122. package/master-details/index.d.ts +2 -0
  123. package/master-details/lib/master-details.component.d.ts +58 -0
  124. package/master-details/lib/master-details.interface.d.ts +7 -0
  125. package/master-details/lib/master-details.module.d.ts +7 -0
  126. package/metadata-form/index.d.ts +4 -1
  127. package/metadata-form/lib/metadata-form-field/metadata-form-field.component.d.ts +4 -17
  128. package/metadata-form/lib/metadata-form-field/metadata-form-field.interface.d.ts +11 -0
  129. package/metadata-form/lib/object-metadata-element-error.directive.d.ts +13 -0
  130. package/metadata-form/lib/object-metadata-element-label.directive.d.ts +10 -0
  131. package/metadata-form/lib/object-metadata-element-template.directive.d.ts +3 -3
  132. package/metadata-form-defaults/README.md +3 -0
  133. package/metadata-form-defaults/index.d.ts +2 -0
  134. package/metadata-form-defaults/lib/metadata-form-defaults.module.d.ts +7 -0
  135. package/object-details/lib/object-audit/object-audit.component.d.ts +3 -9
  136. package/object-details/lib/object-details.component.d.ts +0 -2
  137. package/object-details/lib/object-metadata/object-metadata.component.d.ts +4 -3
  138. package/object-details/lib/retention-badge/retention-badge.component.d.ts +0 -3
  139. package/object-flavor/index.d.ts +1 -0
  140. package/object-flavor/lib/abstract-apply-create-flavor/abstract-apply-create-flavor.component.d.ts +1 -2
  141. package/object-flavor/lib/abstract-apply-object-flavor/abstract-apply-object-flavor.component.d.ts +3 -2
  142. package/object-flavor/lib/default-apply-flavor/default-apply-flavor.component.d.ts +19 -0
  143. package/object-flavor/lib/flavor-chip/flavor-chip.component.d.ts +1 -1
  144. package/object-flavor/lib/object-flavor/object-flavor.component.d.ts +3 -6
  145. package/object-flavor/lib/object-flavor-picker/object-flavor-picker.component.d.ts +0 -1
  146. package/object-form/index.d.ts +1 -1
  147. package/object-form/lib/object-form-element/object-form-element.component.d.ts +2 -2
  148. package/object-form/lib/object-form-group/object-form-group.component.d.ts +1 -3
  149. package/object-form/lib/object-form.component.d.ts +2 -2
  150. package/object-form/lib/object-form.interface.d.ts +0 -44
  151. package/object-form/lib/object-form.module.d.ts +7 -0
  152. package/object-form/lib/object-form.service.d.ts +1 -2
  153. package/object-form/lib/object-form.utils.d.ts +1 -1
  154. package/object-summary/lib/object-summary/object-summary.component.d.ts +13 -15
  155. package/overflow-menu/README.md +3 -0
  156. package/overflow-menu/index.d.ts +3 -0
  157. package/overflow-menu/lib/overflow-menu.component.d.ts +31 -0
  158. package/overflow-menu/lib/overflow-menu.interface.d.ts +9 -0
  159. package/overflow-menu/lib/overflow-menu.module.d.ts +7 -0
  160. package/package.json +43 -69
  161. package/popout/README.md +3 -0
  162. package/popout/index.d.ts +3 -0
  163. package/popout/lib/popout.component.d.ts +58 -0
  164. package/popout/lib/popout.interface.d.ts +17 -0
  165. package/popout/lib/popout.module.d.ts +7 -0
  166. package/renderer/lib/property-renderer/abstract.renderer.d.ts +4 -4
  167. package/renderer/lib/property-renderer/icon.renderer.component.d.ts +2 -0
  168. package/renderer/lib/renderer.directive.d.ts +4 -3
  169. package/sequence-list/index.d.ts +0 -1
  170. package/sequence-list/lib/sequence-list.component.d.ts +0 -4
  171. package/simple-search/index.d.ts +0 -1
  172. package/simple-search/lib/simple-search/simple-search.component.d.ts +6 -10
  173. package/split-view/README.md +3 -0
  174. package/split-view/index.d.ts +4 -0
  175. package/split-view/lib/split-area.directive.d.ts +16 -0
  176. package/split-view/lib/split-view.component.d.ts +76 -0
  177. package/split-view/lib/split-view.interface.d.ts +10 -0
  178. package/split-view/lib/split-view.module.d.ts +8 -0
  179. package/styles/client-framework.scss +21 -67
  180. package/tile-list/lib/tile/tile.component.d.ts +1 -2
  181. package/tile-list/lib/tile-config/property-select/property-select.component.d.ts +0 -1
  182. package/tile-list/lib/tile-config/tile-config-trigger/tile-config-trigger.component.d.ts +1 -2
  183. package/tile-list/lib/tile-config/tile-config.component.d.ts +0 -3
  184. package/tile-list/lib/tile-list/tile-list.component.d.ts +5 -5
  185. package/upload-progress/lib/upload-progress/upload-progress-overlay/upload-progress-overlay.component.d.ts +0 -5
  186. package/upload-progress/lib/upload-progress/upload-progress.component.d.ts +0 -4
  187. package/common/lib/components/focus-indicator/focus-indicator.component.d.ts +0 -7
  188. package/common/lib/components/token-input/token-input.component.d.ts +0 -55
  189. package/common/lib/components/token-input/token-input.interface.d.ts +0 -8
  190. package/common/lib/services/error-messages/error-messages.service.d.ts +0 -7
  191. package/esm2022/actions/index.mjs +0 -7
  192. package/esm2022/actions/lib/actions/copy-action/copy-action.mjs +0 -31
  193. package/esm2022/actions/lib/actions/cut-action/cut-action.mjs +0 -30
  194. package/esm2022/actions/lib/actions/delete-action/delete/delete.component.mjs +0 -67
  195. package/esm2022/actions/lib/actions/delete-action/delete-action.mjs +0 -38
  196. package/esm2022/actions/lib/actions/download-action/download-action.mjs +0 -33
  197. package/esm2022/actions/lib/actions.icon.mjs +0 -8
  198. package/esm2022/actions/lib/actions.interface.mjs +0 -19
  199. package/esm2022/actions/lib/actions.module.mjs +0 -16
  200. package/esm2022/actions/lib/actions.service.mjs +0 -89
  201. package/esm2022/actions/lib/components/contextmenu/contextmenu.component.mjs +0 -27
  202. package/esm2022/actions/yuuvis-client-framework-actions.mjs +0 -5
  203. package/esm2022/app-bar/index.mjs +0 -2
  204. package/esm2022/app-bar/lib/app-bar.component.mjs +0 -89
  205. package/esm2022/app-bar/yuuvis-client-framework-app-bar.mjs +0 -5
  206. package/esm2022/clipboard/index.mjs +0 -2
  207. package/esm2022/clipboard/lib/clipboard.component.mjs +0 -48
  208. package/esm2022/clipboard/yuuvis-client-framework-clipboard.mjs +0 -5
  209. package/esm2022/common/index.mjs +0 -7
  210. package/esm2022/common/lib/components/focus-indicator/focus-indicator.component.mjs +0 -41
  211. package/esm2022/common/lib/components/token-input/token-input.component.mjs +0 -324
  212. package/esm2022/common/lib/components/token-input/token-input.interface.mjs +0 -2
  213. package/esm2022/common/lib/directives/busy-overlay.directive.mjs +0 -88
  214. package/esm2022/common/lib/directives/click-double.directive.mjs +0 -61
  215. package/esm2022/common/lib/directives/container-size.directive.mjs +0 -56
  216. package/esm2022/common/lib/directives/drag-select.directive.mjs +0 -114
  217. package/esm2022/common/lib/directives/file-drop-zone/file-drop-zone.directive.mjs +0 -153
  218. package/esm2022/common/lib/directives/file-drop-zone/file-drop-zone.interface.mjs +0 -2
  219. package/esm2022/common/lib/directives/focus-within.directive.mjs +0 -81
  220. package/esm2022/common/lib/directives/index.mjs +0 -9
  221. package/esm2022/common/lib/directives/light-dismiss.directive.mjs +0 -44
  222. package/esm2022/common/lib/directives/longpress.directive.mjs +0 -36
  223. package/esm2022/common/lib/directives/noop-value-accessor.directive.mjs +0 -42
  224. package/esm2022/common/lib/services/error-messages/error-messages.service.mjs +0 -68
  225. package/esm2022/common/lib/services/index.mjs +0 -2
  226. package/esm2022/common/yuuvis-client-framework-common.mjs +0 -5
  227. package/esm2022/forms/index.mjs +0 -24
  228. package/esm2022/forms/lib/elements/catalog/catalog.component.mjs +0 -118
  229. package/esm2022/forms/lib/elements/data-grid/data-grid/data-grid.component.mjs +0 -172
  230. package/esm2022/forms/lib/elements/data-grid/edit-table-data/edit-data.component.mjs +0 -95
  231. package/esm2022/forms/lib/elements/data-grid/model/data-grid.interface.mjs +0 -9
  232. package/esm2022/forms/lib/elements/datetime/datetime.component.mjs +0 -82
  233. package/esm2022/forms/lib/elements/datetime-range/datetime-range.component.mjs +0 -166
  234. package/esm2022/forms/lib/elements/index.mjs +0 -11
  235. package/esm2022/forms/lib/elements/number/number.component.mjs +0 -195
  236. package/esm2022/forms/lib/elements/number-range/number-range.component.mjs +0 -176
  237. package/esm2022/forms/lib/elements/organization/organization.component.mjs +0 -286
  238. package/esm2022/forms/lib/elements/range-select-date/date-range-picker/date-range-picker.component.mjs +0 -38
  239. package/esm2022/forms/lib/elements/range-select-date/range-select-date.component.mjs +0 -181
  240. package/esm2022/forms/lib/elements/range-select-date/range-select-date.interface.mjs +0 -2
  241. package/esm2022/forms/lib/elements/range-select-filesize/range-select-filesize.component.mjs +0 -98
  242. package/esm2022/forms/lib/elements/range-select-filesize/range-select-filesize.interface.mjs +0 -2
  243. package/esm2022/forms/lib/elements/string/string.component.mjs +0 -261
  244. package/esm2022/forms/lib/form-input/form-input.component.mjs +0 -88
  245. package/esm2022/forms/lib/forms.module.mjs +0 -58
  246. package/esm2022/forms/yuuvis-client-framework-forms.mjs +0 -5
  247. package/esm2022/icons/index.mjs +0 -4
  248. package/esm2022/icons/lib/icon.service.mjs +0 -59
  249. package/esm2022/icons/lib/icons.mjs +0 -32
  250. package/esm2022/icons/lib/object-type-icon/object-type-icon.component.mjs +0 -29
  251. package/esm2022/icons/yuuvis-client-framework-icons.mjs +0 -5
  252. package/esm2022/index.mjs +0 -2
  253. package/esm2022/lib/yuuvis-client-framework.module.mjs +0 -15
  254. package/esm2022/list/index.mjs +0 -3
  255. package/esm2022/list/lib/list-item.directive.mjs +0 -72
  256. package/esm2022/list/lib/list.component.mjs +0 -135
  257. package/esm2022/list/yuuvis-client-framework-list.mjs +0 -5
  258. package/esm2022/metadata-form/index.mjs +0 -4
  259. package/esm2022/metadata-form/lib/metadata-default-templates/metadata-default-templates.component.mjs +0 -32
  260. package/esm2022/metadata-form/lib/metadata-form-element-registry.service.mjs +0 -99
  261. package/esm2022/metadata-form/lib/metadata-form-field/metadata-form-field.component.mjs +0 -83
  262. package/esm2022/metadata-form/lib/object-metadata-element-template.directive.mjs +0 -52
  263. package/esm2022/metadata-form/yuuvis-client-framework-metadata-form.mjs +0 -5
  264. package/esm2022/object-details/index.mjs +0 -8
  265. package/esm2022/object-details/lib/object-audit/object-audit.component.mjs +0 -195
  266. package/esm2022/object-details/lib/object-details-shell/object-details-shell.component.mjs +0 -127
  267. package/esm2022/object-details/lib/object-details.component.mjs +0 -61
  268. package/esm2022/object-details/lib/object-metadata/form-section-group.pipe.mjs +0 -17
  269. package/esm2022/object-details/lib/object-metadata/object-metadata.component.mjs +0 -202
  270. package/esm2022/object-details/lib/object-metadata/object-metadata.interface.mjs +0 -2
  271. package/esm2022/object-details/lib/retention-badge/retention-badge.component.mjs +0 -27
  272. package/esm2022/object-details/yuuvis-client-framework-object-details.mjs +0 -5
  273. package/esm2022/object-flavor/index.mjs +0 -6
  274. package/esm2022/object-flavor/lib/abstract-apply-create-flavor/abstract-apply-create-flavor.component.mjs +0 -25
  275. package/esm2022/object-flavor/lib/abstract-apply-object-flavor/abstract-apply-object-flavor.component.mjs +0 -21
  276. package/esm2022/object-flavor/lib/flavor-chip/flavor-chip.component.mjs +0 -35
  277. package/esm2022/object-flavor/lib/object-flavor/object-flavor.component.mjs +0 -93
  278. package/esm2022/object-flavor/lib/object-flavor-picker/object-flavor-picker.component.mjs +0 -43
  279. package/esm2022/object-flavor/yuuvis-client-framework-object-flavor.mjs +0 -5
  280. package/esm2022/object-form/index.mjs +0 -5
  281. package/esm2022/object-form/lib/form-scripting.api.interface.mjs +0 -2
  282. package/esm2022/object-form/lib/form-scripting.service.mjs +0 -160
  283. package/esm2022/object-form/lib/object-form-element/object-form-element.component.mjs +0 -87
  284. package/esm2022/object-form/lib/object-form-extension.interface.mjs +0 -36
  285. package/esm2022/object-form/lib/object-form-group/object-form-group.component.mjs +0 -85
  286. package/esm2022/object-form/lib/object-form-script/form-scripting-element-extension/form-scripting-element-extension.component.mjs +0 -23
  287. package/esm2022/object-form/lib/object-form-script/object-form-script.service.mjs +0 -115
  288. package/esm2022/object-form/lib/object-form-script/object-form-scripting-scope.mjs +0 -251
  289. package/esm2022/object-form/lib/object-form-translate.service.mjs +0 -73
  290. package/esm2022/object-form/lib/object-form.component.mjs +0 -628
  291. package/esm2022/object-form/lib/object-form.interface.mjs +0 -9
  292. package/esm2022/object-form/lib/object-form.model.mjs +0 -20
  293. package/esm2022/object-form/lib/object-form.service.mjs +0 -130
  294. package/esm2022/object-form/lib/object-form.utils.mjs +0 -55
  295. package/esm2022/object-form/lib/object-form.validation.mjs +0 -48
  296. package/esm2022/object-form/yuuvis-client-framework-object-form.mjs +0 -5
  297. package/esm2022/object-preview/index.mjs +0 -3
  298. package/esm2022/object-preview/lib/components/index.mjs +0 -3
  299. package/esm2022/object-preview/lib/components/object-email-preview/object-email-preview.component.mjs +0 -45
  300. package/esm2022/object-preview/lib/components/object-preview/object-preview.component.mjs +0 -78
  301. package/esm2022/object-preview/lib/services/object-preview.service.mjs +0 -119
  302. package/esm2022/object-preview/yuuvis-client-framework-object-preview.mjs +0 -5
  303. package/esm2022/object-summary/index.mjs +0 -5
  304. package/esm2022/object-summary/lib/multi-object-summary/multi-object-summary.component.mjs +0 -33
  305. package/esm2022/object-summary/lib/object-summary/object-summary.component.mjs +0 -275
  306. package/esm2022/object-summary/lib/object-summary-data/object-summary-data.component.mjs +0 -80
  307. package/esm2022/object-summary/lib/object-summary.module.mjs +0 -15
  308. package/esm2022/object-summary/yuuvis-client-framework-object-summary.mjs +0 -5
  309. package/esm2022/pagination/index.mjs +0 -3
  310. package/esm2022/pagination/lib/pagination.component.mjs +0 -46
  311. package/esm2022/pagination/lib/pagination.interface.mjs +0 -2
  312. package/esm2022/pagination/yuuvis-client-framework-pagination.mjs +0 -5
  313. package/esm2022/panel/index.mjs +0 -2
  314. package/esm2022/panel/lib/panel.component.mjs +0 -20
  315. package/esm2022/panel/yuuvis-client-framework-panel.mjs +0 -5
  316. package/esm2022/renderer/index.mjs +0 -11
  317. package/esm2022/renderer/lib/property-renderer/abstract.renderer.mjs +0 -29
  318. package/esm2022/renderer/lib/property-renderer/datetime.renderer.mjs +0 -13
  319. package/esm2022/renderer/lib/property-renderer/decimal.renderer.component.mjs +0 -12
  320. package/esm2022/renderer/lib/property-renderer/filesize.renderer.component.mjs +0 -28
  321. package/esm2022/renderer/lib/property-renderer/icon.renderer.component.mjs +0 -23
  322. package/esm2022/renderer/lib/property-renderer/integer.renderer.component.mjs +0 -12
  323. package/esm2022/renderer/lib/property-renderer/organization.renderer.mjs +0 -19
  324. package/esm2022/renderer/lib/property-renderer/string.renderer.component.mjs +0 -12
  325. package/esm2022/renderer/lib/property-renderer/unknown.renderer.mjs +0 -12
  326. package/esm2022/renderer/lib/renderer.directive.mjs +0 -51
  327. package/esm2022/renderer/lib/services/renderer/renderer.interface.mjs +0 -2
  328. package/esm2022/renderer/lib/services/renderer/renderer.service.mjs +0 -84
  329. package/esm2022/renderer/yuuvis-client-framework-renderer.mjs +0 -5
  330. package/esm2022/sequence-list/index.mjs +0 -4
  331. package/esm2022/sequence-list/lib/due-date-picker/due-date-picker.component.mjs +0 -99
  332. package/esm2022/sequence-list/lib/sequence-list.component.mjs +0 -141
  333. package/esm2022/sequence-list/lib/sequence-list.interface.mjs +0 -2
  334. package/esm2022/sequence-list/yuuvis-client-framework-sequence-list.mjs +0 -5
  335. package/esm2022/simple-search/index.mjs +0 -3
  336. package/esm2022/simple-search/lib/simple-search/simple-search.component.mjs +0 -111
  337. package/esm2022/simple-search/lib/simple-search/simple-search.interface.mjs +0 -2
  338. package/esm2022/simple-search/yuuvis-client-framework-simple-search.mjs +0 -5
  339. package/esm2022/tile-list/index.mjs +0 -11
  340. package/esm2022/tile-list/lib/tile/tile.component.mjs +0 -53
  341. package/esm2022/tile-list/lib/tile-config/action-select/action-select.component.mjs +0 -25
  342. package/esm2022/tile-list/lib/tile-config/icon-select/icon-select.component.mjs +0 -33
  343. package/esm2022/tile-list/lib/tile-config/property-select/property-select.component.mjs +0 -91
  344. package/esm2022/tile-list/lib/tile-config/tile-config-tile/tile-config-tile.component.mjs +0 -66
  345. package/esm2022/tile-list/lib/tile-config/tile-config-trigger/tile-config-trigger.component.mjs +0 -46
  346. package/esm2022/tile-list/lib/tile-config/tile-config.component.mjs +0 -156
  347. package/esm2022/tile-list/lib/tile-extension/directive/tile-extension.directive.mjs +0 -37
  348. package/esm2022/tile-list/lib/tile-extension/extensions/email.extension.mjs +0 -42
  349. package/esm2022/tile-list/lib/tile-extension/tile-extension.service.mjs +0 -35
  350. package/esm2022/tile-list/lib/tile-list/tile-list.component.mjs +0 -510
  351. package/esm2022/tile-list/lib/tile-list/tile-list.interface.mjs +0 -2
  352. package/esm2022/tile-list/yuuvis-client-framework-tile-list.mjs +0 -5
  353. package/esm2022/token-search/index.mjs +0 -3
  354. package/esm2022/token-search/token-search.component.mjs +0 -78
  355. package/esm2022/token-search/token-search.interface.mjs +0 -2
  356. package/esm2022/token-search/yuuvis-client-framework-token-search.mjs +0 -5
  357. package/esm2022/tree/index.mjs +0 -3
  358. package/esm2022/tree/lib/tree-node/tree-node.component.mjs +0 -65
  359. package/esm2022/tree/lib/tree.component.mjs +0 -148
  360. package/esm2022/tree/lib/tree.interface.mjs +0 -2
  361. package/esm2022/tree/lib/tree.service.mjs +0 -95
  362. package/esm2022/tree/yuuvis-client-framework-tree.mjs +0 -5
  363. package/esm2022/upload-progress/index.mjs +0 -2
  364. package/esm2022/upload-progress/lib/upload-progress/upload-progress-overlay/upload-progress-overlay.component.mjs +0 -49
  365. package/esm2022/upload-progress/lib/upload-progress/upload-progress.component.mjs +0 -37
  366. package/esm2022/upload-progress/yuuvis-client-framework-upload-progress.mjs +0 -5
  367. package/esm2022/user-avatar/index.mjs +0 -3
  368. package/esm2022/user-avatar/lib/user-avatar.component.mjs +0 -69
  369. package/esm2022/user-avatar/lib/user-avatar.module.mjs +0 -24
  370. package/esm2022/user-avatar/yuuvis-client-framework-user-avatar.mjs +0 -5
  371. package/esm2022/yuuvis-client-framework.mjs +0 -5
  372. package/fesm2022/yuuvis-client-framework-token-search.mjs +0 -85
  373. package/fesm2022/yuuvis-client-framework-token-search.mjs.map +0 -1
  374. package/fesm2022/yuuvis-client-framework-user-avatar.mjs +0 -96
  375. package/fesm2022/yuuvis-client-framework-user-avatar.mjs.map +0 -1
  376. package/forms/lib/form-input/form-input.component.d.ts +0 -48
  377. package/object-form/lib/object-form-translate.service.d.ts +0 -15
  378. package/object-form/lib/object-form.model.d.ts +0 -18
  379. package/sequence-list/lib/due-date-picker/due-date-picker.component.d.ts +0 -28
  380. package/simple-search/lib/simple-search/simple-search.interface.d.ts +0 -4
  381. package/token-search/README.md +0 -3
  382. package/token-search/index.d.ts +0 -2
  383. package/token-search/token-search.component.d.ts +0 -22
  384. package/token-search/token-search.interface.d.ts +0 -4
  385. package/user-avatar/README.md +0 -3
  386. package/user-avatar/index.d.ts +0 -2
  387. package/user-avatar/lib/user-avatar.component.d.ts +0 -44
  388. package/user-avatar/lib/user-avatar.module.d.ts +0 -8
  389. /package/{metadata-form → metadata-form-defaults}/lib/metadata-default-templates/metadata-default-templates.component.d.ts +0 -0
@@ -1,691 +1,78 @@
1
- import * as i1$2 from '@angular/common';
2
- import { CommonModule, DecimalPipe, NgClass } from '@angular/common';
3
- import * as i0 from '@angular/core';
4
- import { inject, Renderer2, Component, ViewEncapsulation, ViewChild, Input, HostBinding, forwardRef, ElementRef, signal, input, ChangeDetectionStrategy, computed, effect, untracked, EventEmitter, HostListener, Output, output, NgModule } from '@angular/core';
5
- import { FocusWithinDirective, ErrorMessagesService } from '@yuuvis/client-framework/common';
6
- import * as i2 from '@angular/forms';
7
- import { NG_VALUE_ACCESSOR, FormsModule, NG_VALIDATORS, FormBuilder, Validators, ReactiveFormsModule, UntypedFormGroup, UntypedFormControl } from '@angular/forms';
8
- import * as i1 from '@yuuvis/client-core';
9
- import { Classification, FileSizePipe, LocaleNumberPipe, Utils, ClassificationPrefix, Situation, TranslateModule, ClipboardService, TranslateService, OperatorLabel, Operator, SystemService, UserService, YuvUser, SearchUtils, LocaleDatePipe } from '@yuuvis/client-core';
10
- import * as i1$1 from '@yuuvis/components/dropdown';
11
- import { YvcDropdownModule } from '@yuuvis/components/dropdown';
12
- import { CdkMenu, CdkMenuTrigger, CdkMenuItem } from '@angular/cdk/menu';
13
- import * as i4 from '@angular/cdk/table';
14
- import { CdkTableModule } from '@angular/cdk/table';
15
- import { IconService, YUV_ICONS } from '@yuuvis/client-framework/icons';
16
- import * as i3 from '@yuuvis/components/icon';
17
- import { YvcIconModule } from '@yuuvis/components/icon';
18
- import { YvcOverlayRef, YvcOverlayService } from '@yuuvis/components/overlay';
19
- import { map, of, forkJoin } from 'rxjs';
20
- import * as i2$1 from '@yuuvis/components/chips';
21
- import { YvcChipsModule } from '@yuuvis/components/chips';
22
- import { TranslateService as TranslateService$1, TranslateModule as TranslateModule$1 } from '@ngx-translate/core';
23
- import * as i2$2 from '@yuuvis/components/datepicker';
24
- import { YvcDatepickerModule } from '@yuuvis/components/datepicker';
25
- import * as i3$1 from '@yuuvis/components/autocomplete';
26
- import { YvcAutocompleteModule } from '@yuuvis/components/autocomplete';
27
- import { map as map$1, catchError } from 'rxjs/operators';
28
- import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
29
- import { marker } from '@colsen1991/ngx-translate-extract-marker';
30
- import { YvcCheckboxModule } from '@yuuvis/components/checkbox';
31
- import { YvcFocusWithin } from '@yuuvis/components/common';
32
-
33
- /**
34
- * Component for wrapping a form element. Provides a label and focus behaviour.
35
- *
36
- * @example
37
- * <yuv-form-input [label]="'my form element'">
38
- * <!-- form element to be wrapped -->
39
- * </yuv-form-input>
40
- */
41
- class FormInputComponent {
42
- constructor() {
43
- this.renderer = inject(Renderer2);
44
- this.isDisabled = false;
45
- this.isInvalid = false;
46
- this.isRequired = false;
47
- }
48
- /**
49
- * A label string for the wrapped form element
50
- */
51
- set label(val) {
52
- this._label = val;
53
- }
54
- /**
55
- * Indicator that the wrapped form element is invalid. Will then render appropriate styles.
56
- * You may also provide an array of error messages.
57
- */
58
- set invalid(iv) {
59
- if (iv === null || iv === undefined) {
60
- this.isInvalid = false;
61
- this.renderer.removeAttribute(this.labelEl.nativeElement, 'title');
62
- }
63
- else if (Array.isArray(iv)) {
64
- this.isInvalid = iv.length > 0;
65
- if (this.isInvalid) {
66
- this.renderer.setAttribute(this.labelEl.nativeElement, 'title', iv.join(';'));
67
- }
68
- }
69
- else {
70
- this.isInvalid = iv;
71
- }
72
- }
73
- /**
74
- * Indicator that the wrapped form element is disabled. Will then render appropriate styles.
75
- */
76
- set disabled(d) {
77
- this.isDisabled = d;
78
- }
79
- /**
80
- * Indicator that the wrapped form element is mandatory. Will then render appropriate styles.
81
- */
82
- set required(d) {
83
- this.isRequired = d;
84
- }
85
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FormInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
86
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: FormInputComponent, isStandalone: true, selector: "yuv-form-input", inputs: { label: "label", tag: "tag", description: "description", invalid: "invalid", disabled: "disabled", required: "required" }, host: { properties: { "class.disabled": "this.isDisabled", "class.invalid": "this.isInvalid", "class.required": "this.isRequired" } }, viewQueries: [{ propertyName: "labelEl", first: true, predicate: ["label"], descendants: true, static: true }], ngImport: i0, template: "<div class=\"fe-wrapper\" yuvFocusWithin>\n @if (tag) {\n <div class=\"tag\" title=\"{{ tag.title }}\">{{ tag.label }}</div>\n }\n <label class=\"form-input__label\" #label>{{ _label }}</label>\n <div class=\"control\">\n <ng-content></ng-content>\n </div>\n</div>\n@if (description) {\n <div class=\"description\">{{ description }}</div>\n}\n", styles: ["yuv-form-input .yvc-form-element{--yvc-form-element-border-color: transparent;--yvc-form-element-focus-border-color: transparent;--yvc-form-element-focus-outline-color: transparent}yuv-form-input .fe-wrapper{display:flex;transition:all .2s ease-in-out;flex-flow:row nowrap;align-items:center;padding:calc(var(--app-pane-padding) / 4) 0;border-bottom:1px solid var(--text-color-hint)}yuv-form-input .fe-wrapper.focusWithin{border-color:var(--color-accent)}yuv-form-input .fe-wrapper.focusWithin>.form-input__label{color:var(--color-accent)}yuv-form-input .fe-wrapper>div.control{flex:1 1 auto;padding:0 calc(var(--app-pane-padding) / 4);order:1;min-height:20px}yuv-form-input .fe-wrapper>div.control>span{display:inline-block;border-radius:2px;font-size:var(--font-body);line-height:1.5em;background-color:var(--color-accent);padding:0 calc(var(--app-pane-padding) / 4);color:#fff}yuv-form-input .fe-wrapper>.triggers{order:3;display:none}yuv-form-input .fe-wrapper>.triggers.visible{order:2}yuv-form-input .fe-wrapper>.triggers.visible,yuv-form-input .fe-wrapper>.triggers:hover{display:flex}yuv-form-input .fe-wrapper>.form-input__label{text-align:end;transition:all .2s ease-in-out;-webkit-user-select:none;user-select:none;order:4;flex:0 1 auto;padding:2px calc(var(--app-pane-padding) / 4);margin-right:3px;color:var(--text-color-caption);border-radius:2px;font-size:var(--font-caption)}yuv-form-input .fe-wrapper>.form-input__label:hover+.triggers{display:flex}yuv-form-input .fe-wrapper>.tag{order:5;flex:0 0 auto;border-radius:2px;font-size:var(--font-body);display:inline-block;line-height:1.5em;padding:2px;cursor:default;background-color:rgba(var(--color-accent-rgb),.2);color:var(--color-accent);font-family:monospace}yuv-form-input.checkbox{position:relative}yuv-form-input.checkbox .fe-wrapper>.form-input__label{text-align:start}yuv-form-input .description{font-size:var(--font-hint);font-style:italic;padding:calc(var(--app-pane-padding) / 8) calc(var(--app-pane-padding) / 8) 0 calc(var(--app-pane-padding) / 8);color:var(--text-color-caption)}yuv-form-input.required .fe-wrapper>.form-input__label{font-weight:700}yuv-form-input.required .fe-wrapper>.form-input__label:after{content:\"*\";padding:0 4px}yuv-form-input.invalid .fe-wrapper{background:rgba(var(--color-error),.15);border-color:var(--color-error)}yuv-form-input.invalid .fe-wrapper>.form-input__label{background-color:var(--color-error);color:#fff;margin:0 4px}yuv-form-input.invalid .fe-wrapper>.form-input__label:after{content:\"!\";margin-left:calc(var(--app-pane-padding) / 2)}yuv-form-input.disabled .fe-wrapper{opacity:.7;background-color:var(--item-focus-background-color)}yuv-form-input.checkbox .fe-wrapper{border-color:transparent!important}yuv-form-input.checkbox .fe-wrapper>div.control{flex:0 0 auto}yuv-form-input.checkbox .fe-wrapper>.form-input__label{flex:0 1 auto}yuv-form-input:not(.skipToggle) .form-input__label{cursor:pointer}.yuv-form-input .fe-wrapper .fe-wrapper{background:transparent;padding:0}.yuv-form-input input:not([type=checkbox]),.yuv-form-input .p-inputtext{padding:0;border:0!important;display:flex;flex-wrap:wrap;align-items:center;width:100%}.yuv-form-input input{background-color:transparent}.yuv-form-input button.p-button{background:transparent;border:0;border-radius:2px;color:var(--text-color-caption);cursor:pointer;width:20px;height:20px;padding:0;min-width:20px}.yuv-form-input button.p-button:enabled:active,.yuv-form-input button.p-button:enabled:focus{border:0;box-shadow:none;background:var(--color-accent);color:#fff}.yuv-form-input button.p-button:enabled:active,.yuv-form-input button.p-button:enabled:hover{border:0;background:var(--color-accent);color:#fff}.yuv-form-input button.p-button .fa{color:currentColor!important}.yuv-form-input button.p-button yuv-icon{width:16px;height:16px;margin:auto}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: FocusWithinDirective, selector: "[yuvFocusWithin]", outputs: ["yuvFocusWithin", "yuvFocusWithinBlur"] }], encapsulation: i0.ViewEncapsulation.None }); }
87
- }
88
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FormInputComponent, decorators: [{
89
- type: Component,
90
- args: [{ selector: 'yuv-form-input', standalone: true, imports: [CommonModule, FocusWithinDirective], encapsulation: ViewEncapsulation.None, template: "<div class=\"fe-wrapper\" yuvFocusWithin>\n @if (tag) {\n <div class=\"tag\" title=\"{{ tag.title }}\">{{ tag.label }}</div>\n }\n <label class=\"form-input__label\" #label>{{ _label }}</label>\n <div class=\"control\">\n <ng-content></ng-content>\n </div>\n</div>\n@if (description) {\n <div class=\"description\">{{ description }}</div>\n}\n", styles: ["yuv-form-input .yvc-form-element{--yvc-form-element-border-color: transparent;--yvc-form-element-focus-border-color: transparent;--yvc-form-element-focus-outline-color: transparent}yuv-form-input .fe-wrapper{display:flex;transition:all .2s ease-in-out;flex-flow:row nowrap;align-items:center;padding:calc(var(--app-pane-padding) / 4) 0;border-bottom:1px solid var(--text-color-hint)}yuv-form-input .fe-wrapper.focusWithin{border-color:var(--color-accent)}yuv-form-input .fe-wrapper.focusWithin>.form-input__label{color:var(--color-accent)}yuv-form-input .fe-wrapper>div.control{flex:1 1 auto;padding:0 calc(var(--app-pane-padding) / 4);order:1;min-height:20px}yuv-form-input .fe-wrapper>div.control>span{display:inline-block;border-radius:2px;font-size:var(--font-body);line-height:1.5em;background-color:var(--color-accent);padding:0 calc(var(--app-pane-padding) / 4);color:#fff}yuv-form-input .fe-wrapper>.triggers{order:3;display:none}yuv-form-input .fe-wrapper>.triggers.visible{order:2}yuv-form-input .fe-wrapper>.triggers.visible,yuv-form-input .fe-wrapper>.triggers:hover{display:flex}yuv-form-input .fe-wrapper>.form-input__label{text-align:end;transition:all .2s ease-in-out;-webkit-user-select:none;user-select:none;order:4;flex:0 1 auto;padding:2px calc(var(--app-pane-padding) / 4);margin-right:3px;color:var(--text-color-caption);border-radius:2px;font-size:var(--font-caption)}yuv-form-input .fe-wrapper>.form-input__label:hover+.triggers{display:flex}yuv-form-input .fe-wrapper>.tag{order:5;flex:0 0 auto;border-radius:2px;font-size:var(--font-body);display:inline-block;line-height:1.5em;padding:2px;cursor:default;background-color:rgba(var(--color-accent-rgb),.2);color:var(--color-accent);font-family:monospace}yuv-form-input.checkbox{position:relative}yuv-form-input.checkbox .fe-wrapper>.form-input__label{text-align:start}yuv-form-input .description{font-size:var(--font-hint);font-style:italic;padding:calc(var(--app-pane-padding) / 8) calc(var(--app-pane-padding) / 8) 0 calc(var(--app-pane-padding) / 8);color:var(--text-color-caption)}yuv-form-input.required .fe-wrapper>.form-input__label{font-weight:700}yuv-form-input.required .fe-wrapper>.form-input__label:after{content:\"*\";padding:0 4px}yuv-form-input.invalid .fe-wrapper{background:rgba(var(--color-error),.15);border-color:var(--color-error)}yuv-form-input.invalid .fe-wrapper>.form-input__label{background-color:var(--color-error);color:#fff;margin:0 4px}yuv-form-input.invalid .fe-wrapper>.form-input__label:after{content:\"!\";margin-left:calc(var(--app-pane-padding) / 2)}yuv-form-input.disabled .fe-wrapper{opacity:.7;background-color:var(--item-focus-background-color)}yuv-form-input.checkbox .fe-wrapper{border-color:transparent!important}yuv-form-input.checkbox .fe-wrapper>div.control{flex:0 0 auto}yuv-form-input.checkbox .fe-wrapper>.form-input__label{flex:0 1 auto}yuv-form-input:not(.skipToggle) .form-input__label{cursor:pointer}.yuv-form-input .fe-wrapper .fe-wrapper{background:transparent;padding:0}.yuv-form-input input:not([type=checkbox]),.yuv-form-input .p-inputtext{padding:0;border:0!important;display:flex;flex-wrap:wrap;align-items:center;width:100%}.yuv-form-input input{background-color:transparent}.yuv-form-input button.p-button{background:transparent;border:0;border-radius:2px;color:var(--text-color-caption);cursor:pointer;width:20px;height:20px;padding:0;min-width:20px}.yuv-form-input button.p-button:enabled:active,.yuv-form-input button.p-button:enabled:focus{border:0;box-shadow:none;background:var(--color-accent);color:#fff}.yuv-form-input button.p-button:enabled:active,.yuv-form-input button.p-button:enabled:hover{border:0;background:var(--color-accent);color:#fff}.yuv-form-input button.p-button .fa{color:currentColor!important}.yuv-form-input button.p-button yuv-icon{width:16px;height:16px;margin:auto}\n"] }]
91
- }], propDecorators: { labelEl: [{
92
- type: ViewChild,
93
- args: ['label', { static: true }]
94
- }], label: [{
95
- type: Input
96
- }], tag: [{
97
- type: Input
98
- }], description: [{
99
- type: Input
100
- }], invalid: [{
101
- type: Input
102
- }], disabled: [{
103
- type: Input
104
- }], required: [{
105
- type: Input
106
- }], isDisabled: [{
107
- type: HostBinding,
108
- args: ['class.disabled']
109
- }], isInvalid: [{
110
- type: HostBinding,
111
- args: ['class.invalid']
112
- }], isRequired: [{
113
- type: HostBinding,
114
- args: ['class.required']
115
- }] } });
116
-
117
- /**
118
- * Component rendering a simple catalog as form element.
119
- * There are two ways how to use this component. One is to add options as an array
120
- * of strings on your own, the second one is to apply a special classification.
121
- *
122
- * Classifications are used within form models and rendered as object forms. Elements
123
- * with a classification of `catalog[Item1, Item2, Item3]` will use this component
124
- * as well. So you may also choose to set a classification like this in order to
125
- * apply your options.
126
- *
127
- * @example
128
- * <!-- setting options as string array -->
129
- * <yuv-catalog [options]="cities" [(ngModel)]="hometown"></yuv-catalog>
130
- *
131
- * <!-- setting options using a classification -->
132
- * <yuv-catalog [classification]="'catalog[Berlin, Chicago, Paris]'" [(ngModel)]="hometown"></yuv-catalog>
133
- */
134
- class CatalogComponent {
135
- /**
136
- * Array of selectable entries
137
- */
138
- set options(options) {
139
- this._options = options && typeof options[0] === 'string' ? options.map((o) => ({ label: o, value: o })) : options || [];
140
- this.filter = this.filter || this._options?.length > this.enableFilterWhenOptionsExceed;
141
- }
142
- /**
143
- * Additional semantics for the form element.
144
- */
145
- set classifications(c) {
146
- const ce = this.systemService.getClassifications(c).get(Classification.STRING_CATALOG);
147
- if (ce && ce.options) {
148
- this.options = ce.options;
149
- }
150
- }
151
- constructor(systemService) {
152
- this.systemService = systemService;
153
- this._options = [];
154
- this.getLabel = (value) => (this._options ? this._options.find((o) => o.value === value) || { label: value } : { label: value }).label;
155
- /**
156
- * Enable filtering of options
157
- */
158
- this.filter = false;
159
- /**
160
- * By default a filter panel will shown if the number of options exceeds 10 entries. You could
161
- * change this number.
162
- */
163
- this.enableFilterWhenOptionsExceed = 10;
164
- /**
165
- * Indicator that multiple items could be selected
166
- */
167
- this.multiselect = false;
168
- /**
169
- * Will attch the overlay to this HTMLelement
170
- */
171
- this.appendTo = null;
172
- /**
173
- * Will prevent the input from being changed (default: false)
174
- */
175
- this.readonly = false;
176
- // eslint-disable-next-line @typescript-eslint/no-empty-function
177
- this.propagateChange = (_) => { };
178
- }
179
- writeValue(value) {
180
- this.value = value === undefined ? null : value;
181
- }
182
- registerOnChange(fn) {
183
- this.propagateChange = fn;
184
- }
185
- // eslint-disable-next-line @typescript-eslint/no-empty-function
186
- registerOnTouched(fn) { }
187
- onChange(value) {
188
- this.value = value;
189
- this.propagateChange(this.value);
190
- }
191
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CatalogComponent, deps: [{ token: i1.SystemService }], target: i0.ɵɵFactoryTarget.Component }); }
192
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: CatalogComponent, isStandalone: true, selector: "yuv-catalog", inputs: { filter: "filter", situation: "situation", enableFilterWhenOptionsExceed: "enableFilterWhenOptionsExceed", options: "options", multiselect: "multiselect", classifications: "classifications", appendTo: "appendTo", readonly: "readonly" }, host: { classAttribute: "yuv-catalog" }, providers: [
193
- {
194
- provide: NG_VALUE_ACCESSOR,
195
- useExisting: forwardRef(() => CatalogComponent),
196
- multi: true
197
- }
198
- ], ngImport: i0, template: "<yvc-dropdown [multiple]=\"multiselect\" [options]=\"_options\" [(ngModel)]=\"value\" (ngModelChange)=\"onChange($event)\" [filter]=\"filter\"\n [disabled]=\"readonly\"></yvc-dropdown>\n", styles: [":host{display:block}:host ::ng-deep .p-checkbox{flex-shrink:0}:host ::ng-deep .p-multiselect-item{white-space:normal;min-width:33ch}:host ::ng-deep .p-overlay{max-width:300px}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: YvcDropdownModule }, { kind: "component", type: i1$1.Dropdown, selector: "yvc-dropdown", inputs: ["options", "filter", "disabled", "multiple", "disableClearButton"], outputs: ["onDropdownOptionsClose"] }] }); }
199
- }
200
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: CatalogComponent, decorators: [{
201
- type: Component,
202
- args: [{ selector: 'yuv-catalog', standalone: true, imports: [FormsModule, YvcDropdownModule], providers: [
203
- {
204
- provide: NG_VALUE_ACCESSOR,
205
- useExisting: forwardRef(() => CatalogComponent),
206
- multi: true
207
- }
208
- ], host: { class: 'yuv-catalog' }, template: "<yvc-dropdown [multiple]=\"multiselect\" [options]=\"_options\" [(ngModel)]=\"value\" (ngModelChange)=\"onChange($event)\" [filter]=\"filter\"\n [disabled]=\"readonly\"></yvc-dropdown>\n", styles: [":host{display:block}:host ::ng-deep .p-checkbox{flex-shrink:0}:host ::ng-deep .p-multiselect-item{white-space:normal;min-width:33ch}:host ::ng-deep .p-overlay{max-width:300px}\n"] }]
209
- }], ctorParameters: () => [{ type: i1.SystemService }], propDecorators: { filter: [{
210
- type: Input
211
- }], situation: [{
212
- type: Input
213
- }], enableFilterWhenOptionsExceed: [{
214
- type: Input
215
- }], options: [{
216
- type: Input
217
- }], multiselect: [{
218
- type: Input
219
- }], classifications: [{
220
- type: Input
221
- }], appendTo: [{
222
- type: Input
223
- }], readonly: [{
224
- type: Input
225
- }] } });
226
-
227
- /**
228
- * Creates form input for number values.
229
- *
230
- * Implements `ControlValueAccessor` so it can be used within Angular forms.
231
- *
232
- * @example
233
- * <yuv-number [scale]="2"></yuv-number>
234
- *
235
- */
236
- class NumberComponent {
237
- /**
238
- * Number of decimal places
239
- */
240
- set scale(val) {
241
- this._scale = Math.min(val || 0, 30);
242
- }
243
- get scale() {
244
- return this._scale;
245
- }
246
- /**
247
- * Overall amount of digits allowed (including decimal places)
248
- */
249
- set precision(val) {
250
- this._precision = Math.min(val || 100, 100);
251
- }
252
- get precision() {
253
- return this._precision;
254
- }
255
- /**
256
- * Set to true to group number by pattern
257
- */
258
- set grouping(val) {
259
- this._grouping = val ?? true;
260
- }
261
- get grouping() {
262
- return this._grouping;
263
- }
264
- /**
265
- * The pattern to group number value by
266
- */
267
- set groupPattern(val) {
268
- this._pattern = val;
269
- }
270
- get groupPattern() {
271
- return this._pattern;
272
- }
273
- /**
274
- * classification property adds some semantics to the value of this component.
275
- * If you provide a value of `filesize` numbers typed into the control will be
276
- * handled like file sizes (calculates differnt units)
277
- */
278
- set classifications(classifications) {
279
- this.numberPipe =
280
- classifications && classifications.includes(Classification.NUMBER_FILESIZE) ? new FileSizePipe(this.translate) : new LocaleNumberPipe(this.translate);
281
- }
282
- static betweenTwoNumbers(val, minVal, maxVal) {
283
- const min = !Utils.isEmpty(minVal) ? minVal : -Infinity;
284
- const max = !Utils.isEmpty(maxVal) ? maxVal : Infinity;
285
- return val >= min && val <= max;
286
- }
287
- constructor(translate) {
288
- this.translate = translate;
289
- this.innerValue = null;
290
- this._grouping = false;
291
- this.validationErrors = [];
292
- /**
293
- * Will prevent the input from being changed (default: false)
294
- */
295
- this.readonly = false;
296
- // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function
297
- this.propagateChange = (_) => { };
298
- this.numberPipe = new LocaleNumberPipe(this.translate);
299
- }
300
- writeValue(value) {
301
- this.value = value != null ? value : null;
302
- this.innerValue = value != null ? this.numberPipe.numberToString(value, this.grouping, this.groupPattern, this.scale) : null;
303
- }
304
- registerOnChange(fn) {
305
- this.propagateChange = fn;
306
- }
307
- // eslint-disable-next-line @typescript-eslint/no-empty-function
308
- registerOnTouched() { }
309
- onValueChange(evt) {
310
- this.validationErrors = [];
311
- if (Utils.isEmpty(evt)) {
312
- this.value = undefined;
313
- this.propagateChange(this.value);
314
- return;
315
- }
316
- // validate input
317
- const val = this.numberPipe.stringToNumber(evt);
318
- // general number validation
319
- if (isNaN(val) || typeof val !== 'number') {
320
- this.validationErrors.push({ key: 'number' });
321
- }
322
- else {
323
- const split = evt.replaceAll(this.numberPipe.separator, '').split(this.numberPipe.decimalSeparator);
324
- // check precision
325
- if (this.precision !== undefined) {
326
- const prePointDigits = this.precision - (this.scale || 0);
327
- if (split[0]?.length > prePointDigits) {
328
- this.validationErrors.push({ key: 'precision', params: { prePointDigits } });
329
- }
330
- }
331
- // check scale
332
- if (this.scale && split[1]?.length > this.scale) {
333
- this.validationErrors.push({ key: 'scale', params: { scale: this.scale } });
334
- }
335
- // min max
336
- if (!NumberComponent.betweenTwoNumbers(val, this.minValue, this.maxValue)) {
337
- if (Utils.isEmpty(this.minValue)) {
338
- this.validationErrors.push({ key: 'maxvalue', params: { maxValue: this.maxValue } });
339
- }
340
- else if (Utils.isEmpty(this.maxValue)) {
341
- this.validationErrors.push({ key: 'minvalue', params: { minValue: this.minValue } });
342
- }
343
- else {
344
- this.validationErrors.push({ key: 'minmax', params: { minValue: this.minValue, maxValue: this.maxValue } });
345
- }
346
- }
347
- if (!this.validationErrors.length) {
348
- this.value = val;
349
- }
350
- }
351
- this.propagateChange(this.value);
352
- }
353
- // called when the input looses focus
354
- format() {
355
- if (!this.readonly && typeof this.value === 'number' && this.validationErrors.length === 0) {
356
- this.innerValue = this.numberPipe.numberToString(this.value, this.grouping, this.groupPattern, this.scale);
357
- }
358
- }
359
- // called when the input get focus
360
- unformat() {
361
- if (!this.readonly && typeof this.value === 'number' && this.validationErrors.length === 0) {
362
- this.innerValue = this.numberPipe.transform(this.value, false);
363
- }
364
- }
365
- // returns null when valid else the validation object
366
- validate() {
367
- return this.validationErrors.length ? Utils.arrayToObject(this.validationErrors, 'key', (err) => ({ valid: false, ...err })) : null;
368
- }
369
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NumberComponent, deps: [{ token: i1.TranslateService }], target: i0.ɵɵFactoryTarget.Component }); }
370
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: NumberComponent, isStandalone: true, selector: "yuv-number", inputs: { scale: "scale", precision: "precision", grouping: "grouping", groupPattern: "groupPattern", readonly: "readonly", minValue: "minValue", maxValue: "maxValue", classifications: "classifications" }, providers: [
371
- {
372
- provide: NG_VALUE_ACCESSOR,
373
- useExisting: forwardRef(() => NumberComponent),
374
- multi: true
375
- },
376
- {
377
- provide: NG_VALIDATORS,
378
- useExisting: forwardRef(() => NumberComponent),
379
- multi: true
380
- }
381
- ], ngImport: i0, template: "<input type=\"string\" [(ngModel)]=\"innerValue\" (focus)=\"unformat()\" (blur)=\"format()\" class=\"input-number\"\n [readonly]=\"readonly\" (ngModelChange)=\"onValueChange($event)\" />\n", styles: [":host{display:flex}:host input{width:100%;border:0;background-color:transparent}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] }); }
382
- }
383
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NumberComponent, decorators: [{
384
- type: Component,
385
- args: [{ selector: 'yuv-number', standalone: true, imports: [FormsModule], providers: [
386
- {
387
- provide: NG_VALUE_ACCESSOR,
388
- useExisting: forwardRef(() => NumberComponent),
389
- multi: true
390
- },
391
- {
392
- provide: NG_VALIDATORS,
393
- useExisting: forwardRef(() => NumberComponent),
394
- multi: true
395
- }
396
- ], template: "<input type=\"string\" [(ngModel)]=\"innerValue\" (focus)=\"unformat()\" (blur)=\"format()\" class=\"input-number\"\n [readonly]=\"readonly\" (ngModelChange)=\"onValueChange($event)\" />\n", styles: [":host{display:flex}:host input{width:100%;border:0;background-color:transparent}\n"] }]
397
- }], ctorParameters: () => [{ type: i1.TranslateService }], propDecorators: { scale: [{
398
- type: Input
399
- }], precision: [{
400
- type: Input
401
- }], grouping: [{
402
- type: Input
403
- }], groupPattern: [{
404
- type: Input
405
- }], readonly: [{
406
- type: Input
407
- }], minValue: [{
408
- type: Input
409
- }], maxValue: [{
410
- type: Input
411
- }], classifications: [{
412
- type: Input
413
- }] } });
414
-
415
- /**
416
- * Creates form input for strings. Based on the input values different kinds of inputs will be generated.
417
- *
418
- * Implements `ControlValueAccessor` so it can be used within Angular forms.
419
- *
420
- * @example
421
- * <!-- string input validating input to be between 5 and 10 characters -->
422
- * <yuv-string [minLength]="5" [maxLength]="10"></yuv-string>
423
- *
424
- * <!-- string input that only allow digits -->
425
- * <yuv-string [regex]="[0-9]*"></yuv-string>
426
- *
427
- * <!-- string input rendering a large textarea -->
428
- * <yuv-string [rows]="10"></yuv-string>
429
- *
430
- */
431
- class StringComponent {
432
- constructor() {
433
- this.iconsService = inject(IconService);
434
- this.elementRef = inject(ElementRef);
435
- this.classifiytionIcons = {
436
- email: this.iconsService.getIcon(ClassificationPrefix.EMAIL_ICON) || '',
437
- url: this.iconsService.getIcon(ClassificationPrefix.URL_ICON) || '',
438
- phone: this.iconsService.getIcon(ClassificationPrefix.PHONE_ICON) || ''
439
- };
440
- // provides all css variables defined by |yuuvis/comonents
441
- this.fe = true;
442
- /**
443
- * Indicator that multiple strings could be inserted, they will be rendered as chips (default: false).
444
- */
445
- this.multiselect = false;
446
- /**
447
- * Will prevent the input from being changed (default: false)
448
- */
449
- this.readonly = false;
450
- /**
451
- * Enable autofucus for the input (default: false)
452
- */
453
- this.autofocus = false;
454
- this.valid = false;
455
- this.validationErrors = [];
456
- this._classifications = [];
457
- this.propagateChange = (_) => { };
458
- }
459
- /**
460
- * Additional semantics for the form element. Possible values are
461
- * `email` (validates and creates a link to send an email once there
462
- * is a valid email address) and `url` (validates and creates a link
463
- * to an URL typed into the form element).
464
- */
465
- set classifications(c) {
466
- this._classifications = c;
467
- if (c && c.length) {
468
- if (c.includes(Classification.STRING_EMAIL)) {
469
- this.classify = {
470
- hrefPrefix: ClassificationPrefix.EMAIL,
471
- icon: this.classifiytionIcons.email
472
- };
473
- }
474
- else if (c.includes(Classification.STRING_URL)) {
475
- this.classify = {
476
- hrefPrefix: ClassificationPrefix.URL,
477
- icon: this.classifiytionIcons.url
478
- };
479
- }
480
- else if (c.includes(Classification.STRING_PHONE)) {
481
- this.classify = {
482
- hrefPrefix: ClassificationPrefix.PHONE,
483
- icon: this.classifiytionIcons.phone
484
- };
485
- }
486
- }
487
- }
488
- get classifications() {
489
- return this._classifications;
490
- }
491
- propagate() {
492
- this.propagateChange(this.value);
493
- }
494
- writeValue(value) {
495
- if (Array.isArray(value)) {
496
- value = value.filter((v) => typeof v === 'string' && v.trim().length > 0);
497
- }
498
- this.formatedValue = Utils.formatMailTo(value, this.classify?.hrefPrefix === ClassificationPrefix.EMAIL);
499
- this.value = value || null;
500
- }
501
- registerOnChange(fn) {
502
- this.propagateChange = fn;
503
- }
504
- registerOnTouched() { }
505
- onValueChange(val) {
506
- this.maxEntryCountIfInvalid = undefined;
507
- this.validationErrors = [];
508
- if (Utils.isEmpty(val)) {
509
- this.value = null;
510
- this.propagate();
511
- return;
512
- }
513
- const multiCheck = (check) => !!(this.multiselect ? val : [val]).find((v) => check(v));
514
- // validate regular expression
515
- if (this.regex && multiCheck((v) => !RegExp(this.regex).test(v))) {
516
- this.validationErrors.push({ key: 'regex' });
517
- }
518
- // validate classification settings
519
- if (this.classifications && this.classifications.length) {
520
- this.classifications.forEach((c) => {
521
- if (multiCheck((v) => !this.validateClassification(v, c))) {
522
- this.validationErrors.push({ key: 'classification' + c });
523
- }
524
- });
525
- }
526
- // validate min length
527
- if (!Utils.isEmpty(this.minLength) && multiCheck((v) => v.length < this.minLength)) {
528
- this.validationErrors.push({ key: 'minlength', params: { minLength: this.minLength } });
529
- }
530
- // validate max length
531
- if (!Utils.isEmpty(this.maxLength) && multiCheck((v) => v.length > this.maxLength)) {
532
- this.validationErrors.push({ key: 'maxlength', params: { maxLength: this.maxLength } });
533
- }
534
- // validate invalid if only whitespaces
535
- if (multiCheck((v) => v.length > 0 && !v.trim().length)) {
536
- this.validationErrors.push({ key: 'onlyWhitespaces' });
537
- }
538
- if (this.validationErrors.length && this.multiselect && this.value) {
539
- // Setting maxEntryCountIfInvalid to the actual length of the value array to prevent the user to add more entries.
540
- this.maxEntryCountIfInvalid = this.value.length;
541
- }
542
- this.formatedValue = Utils.formatMailTo(val, this.classify?.hrefPrefix === ClassificationPrefix.EMAIL);
543
- this.propagate();
544
- }
545
- onBlur() {
546
- if (this.multiselect) {
547
- // add on blur
548
- this.value.push('');
549
- }
550
- if (this.trimValue()) {
551
- this.propagate();
552
- }
553
- }
554
- /**
555
- * Trims the current value and returns wether or not it has been trimmed
556
- */
557
- trimValue() {
558
- if (this.value) {
559
- if (this.multiselect) {
560
- const lengthBefore = this.value.join('').length;
561
- this.value = this.value.map((v) => v.trim());
562
- return this.value.join('').length !== lengthBefore;
563
- }
564
- else {
565
- const lengthBefore = this.value.length;
566
- this.value = this.value.trim();
567
- return this.value.length !== lengthBefore;
568
- }
569
- }
570
- return false;
571
- }
572
- validateClassification(string, classification) {
573
- if (this.situation === Situation.SEARCH) {
574
- return true;
575
- }
576
- else {
577
- let pattern;
578
- if (classification === Classification.STRING_EMAIL) {
579
- pattern =
580
- /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
581
- }
582
- else if (classification === Classification.STRING_URL) {
583
- pattern = /(http|ftp|https):\/\/[\w-]+(\.[\w-]+)?([\w.,@?^=%&amp;:\/~+#-]*[\w@?^=%&amp;\/~+#-])?/;
584
- }
585
- else if (classification === Classification.STRING_PHONE) {
586
- pattern = /^[+]*[(]{0,1}[0-9]{1,4}[)]{0,1}[-x\s\./0-9]*$/g;
587
- }
588
- return pattern ? pattern.test(string) : true;
589
- }
590
- }
591
- /**
592
- * returns null when valid else the validation object
593
- */
594
- validate() {
595
- if (this.validationErrors.length) {
596
- this.valid = false;
597
- return Utils.arrayToObject(this.validationErrors, 'key', (err) => ({ valid: false, ...err }));
598
- }
599
- else {
600
- this.valid = true;
601
- return null;
602
- }
603
- }
604
- ngAfterViewInit() {
605
- if (this.autofocus) {
606
- if (!this.multiselect) {
607
- const el = this.elementRef.nativeElement.querySelector(this.rows && this.rows > 1 ? 'textarea' : 'input');
608
- if (el)
609
- el.focus();
610
- }
611
- }
612
- }
613
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StringComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
614
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: StringComponent, isStandalone: true, selector: "yuv-string", inputs: { multiselect: "multiselect", rows: "rows", readonly: "readonly", autofocus: "autofocus", classifications: "classifications", situation: "situation", regex: "regex", minLength: "minLength", maxLength: "maxLength" }, host: { properties: { "class.yvc-form-element": "this.fe" } }, providers: [
615
- {
616
- provide: NG_VALUE_ACCESSOR,
617
- useExisting: forwardRef(() => StringComponent),
618
- multi: true
619
- },
620
- {
621
- provide: NG_VALIDATORS,
622
- useExisting: forwardRef(() => StringComponent),
623
- multi: true
624
- }
625
- ], ngImport: i0, template: "@if ((!rows || rows <= 1) && !multiselect) {\n <input type=\"text\" (blur)=\"onBlur()\" [readonly]=\"readonly\" [(ngModel)]=\"value\" (ngModelChange)=\"onValueChange($event)\" />\n}\n@else if ((!rows || rows <= 1) && multiselect) {\n <!-- single line input with multiselect-->\n <yvc-chips\n [(ngModel)]=\"value\"\n [disabled]=\"readonly\"\n [max]=\"maxEntryCountIfInvalid\"\n [addOnBlur]=\"true\"\n (onBlur)=\"onBlur()\"\n (ngModelChange)=\"onValueChange($event)\"\n [ngClass]=\"{ invalid: validationErrors.length }\"\n >\n <ng-template let-item #chipTemplate>\n <span class=\"p-autocomplete-token-label\">\n @if (classify && !validationErrors.length) {\n <div class=\"classify inchip\">\n <a href=\"{{ classify.hrefPrefix + item }}\">\n <yvc-icon [svg]=\"classify.icon!\"></yvc-icon>\n </a>\n </div>\n }\n <div class=\"label\">\n {{ item }}\n </div>\n </span>\n </ng-template>\n </yvc-chips>\n} @else if (rows && rows > 1) {\n <!-- multi line text inputs -->\n <textarea\n class=\"input-textarea\"\n pInputTextarea\n (blur)=\"onBlur()\"\n [(ngModel)]=\"value\"\n [rows]=\"rows\"\n [readonly]=\"readonly\"\n (ngModelChange)=\"onValueChange($event)\"\n ></textarea>\n}\n\n@if (classify) {\n <div class=\"classify\">\n @if (value && !validationErrors.length && (classify.hrefPrefix !== '' || !multiselect || value.length <= 1)) {\n <a href=\"{{ classify.hrefPrefix + formatedValue }}\">\n <yvc-icon [svg]=\"classify.icon!\"></yvc-icon>\n </a>\n } @else {\n <yvc-icon [svg]=\"classify.icon!\"></yvc-icon>\n }\n </div>\n}\n", styles: [":host{display:flex;flex-flow:row nowrap;align-items:center}:host .yvc-chips-list li.chip{--yvc-form-element-border-color: var(--text-color-hint)}:host .classify{color:var(--text-color-hint)}:host .classify a{color:var(--text-color-hint);display:block;border-radius:2px}:host .classify a:hover,:host .classify a:focus{background-color:var(--color-accent);color:#fff}:host .classify yvc-icon{width:18px;height:18px;padding:calc(var(--app-pane-padding) / 8)}:host textarea.input-textarea{width:100%;resize:vertical;background-color:transparent;color:var(--text-color-body);border:1px solid var(--yvc-form-element-border-color)}:host yvc-chips{width:100%}:host input{color:var(--text-color-body);padding:0;border:1px solid var(--yvc-form-element-border-color);display:flex;flex-wrap:wrap;align-items:center;width:100%;background:transparent}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: YvcChipsModule }, { kind: "component", type: i2$1.Chips, selector: "yvc-chips", inputs: ["field", "placeholder", "max", "disabled", "addOnBlur"] }, { kind: "ngmodule", type: YvcIconModule }, { kind: "component", type: i3.Icon, selector: "yvc-icon", inputs: ["label", "svg", "svgSrc"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }] }); }
626
- }
627
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: StringComponent, decorators: [{
628
- type: Component,
629
- args: [{ selector: 'yuv-string', standalone: true, imports: [CommonModule, YvcChipsModule, YvcIconModule, FormsModule], providers: [
630
- {
631
- provide: NG_VALUE_ACCESSOR,
632
- useExisting: forwardRef(() => StringComponent),
633
- multi: true
634
- },
635
- {
636
- provide: NG_VALIDATORS,
637
- useExisting: forwardRef(() => StringComponent),
638
- multi: true
639
- }
640
- ], template: "@if ((!rows || rows <= 1) && !multiselect) {\n <input type=\"text\" (blur)=\"onBlur()\" [readonly]=\"readonly\" [(ngModel)]=\"value\" (ngModelChange)=\"onValueChange($event)\" />\n}\n@else if ((!rows || rows <= 1) && multiselect) {\n <!-- single line input with multiselect-->\n <yvc-chips\n [(ngModel)]=\"value\"\n [disabled]=\"readonly\"\n [max]=\"maxEntryCountIfInvalid\"\n [addOnBlur]=\"true\"\n (onBlur)=\"onBlur()\"\n (ngModelChange)=\"onValueChange($event)\"\n [ngClass]=\"{ invalid: validationErrors.length }\"\n >\n <ng-template let-item #chipTemplate>\n <span class=\"p-autocomplete-token-label\">\n @if (classify && !validationErrors.length) {\n <div class=\"classify inchip\">\n <a href=\"{{ classify.hrefPrefix + item }}\">\n <yvc-icon [svg]=\"classify.icon!\"></yvc-icon>\n </a>\n </div>\n }\n <div class=\"label\">\n {{ item }}\n </div>\n </span>\n </ng-template>\n </yvc-chips>\n} @else if (rows && rows > 1) {\n <!-- multi line text inputs -->\n <textarea\n class=\"input-textarea\"\n pInputTextarea\n (blur)=\"onBlur()\"\n [(ngModel)]=\"value\"\n [rows]=\"rows\"\n [readonly]=\"readonly\"\n (ngModelChange)=\"onValueChange($event)\"\n ></textarea>\n}\n\n@if (classify) {\n <div class=\"classify\">\n @if (value && !validationErrors.length && (classify.hrefPrefix !== '' || !multiselect || value.length <= 1)) {\n <a href=\"{{ classify.hrefPrefix + formatedValue }}\">\n <yvc-icon [svg]=\"classify.icon!\"></yvc-icon>\n </a>\n } @else {\n <yvc-icon [svg]=\"classify.icon!\"></yvc-icon>\n }\n </div>\n}\n", styles: [":host{display:flex;flex-flow:row nowrap;align-items:center}:host .yvc-chips-list li.chip{--yvc-form-element-border-color: var(--text-color-hint)}:host .classify{color:var(--text-color-hint)}:host .classify a{color:var(--text-color-hint);display:block;border-radius:2px}:host .classify a:hover,:host .classify a:focus{background-color:var(--color-accent);color:#fff}:host .classify yvc-icon{width:18px;height:18px;padding:calc(var(--app-pane-padding) / 8)}:host textarea.input-textarea{width:100%;resize:vertical;background-color:transparent;color:var(--text-color-body);border:1px solid var(--yvc-form-element-border-color)}:host yvc-chips{width:100%}:host input{color:var(--text-color-body);padding:0;border:1px solid var(--yvc-form-element-border-color);display:flex;flex-wrap:wrap;align-items:center;width:100%;background:transparent}\n"] }]
641
- }], propDecorators: { fe: [{
642
- type: HostBinding,
643
- args: ['class.yvc-form-element']
644
- }], multiselect: [{
645
- type: Input
646
- }], rows: [{
647
- type: Input
648
- }], readonly: [{
649
- type: Input
650
- }], autofocus: [{
651
- type: Input
652
- }], classifications: [{
653
- type: Input
654
- }], situation: [{
655
- type: Input
656
- }], regex: [{
657
- type: Input
658
- }], minLength: [{
659
- type: Input
660
- }], maxLength: [{
661
- type: Input
662
- }] } });
1
+ import { CdkMenu, CdkMenuTrigger, CdkMenuItem } from '@angular/cdk/menu';
2
+ import * as i5 from '@angular/cdk/table';
3
+ import { CdkTableModule } from '@angular/cdk/table';
4
+ import * as i1$1 from '@angular/common';
5
+ import { CommonModule, DecimalPipe, NgClass } from '@angular/common';
6
+ import * as i0 from '@angular/core';
7
+ import { inject, signal, input, forwardRef, ChangeDetectionStrategy, Component, computed, effect, untracked, viewChild, DestroyRef, Input, output, ElementRef, NgModule } from '@angular/core';
8
+ import * as i1 from '@angular/forms';
9
+ import { FormBuilder, Validators, ReactiveFormsModule, NG_VALUE_ACCESSOR, FormsModule, FormGroup, FormControl } from '@angular/forms';
10
+ import * as i3 from '@angular/material/button';
11
+ import { MatButtonModule } from '@angular/material/button';
12
+ import * as i2 from '@angular/material/dialog';
13
+ import { MAT_DIALOG_DATA, MatDialogRef, MatDialogModule, MatDialog } from '@angular/material/dialog';
14
+ import * as i2$1 from '@angular/material/icon';
15
+ import { MatIconModule } from '@angular/material/icon';
16
+ import * as i4 from '@yuuvis/client-core';
17
+ import { SystemService, ObjectFormTranslateService, Situation, TranslateModule, ClipboardService, TranslateService, Operator, OperatorLabel, LocaleNumberPipe, FileSizePipe, Classification, Utils, UserService, YuvUser, SearchUtils, LocaleDatePipe, ClassificationPrefix } from '@yuuvis/client-core';
18
+ import { YUV_ICONS } from '@yuuvis/client-framework/icons';
19
+ import { map, of, forkJoin } from 'rxjs';
20
+ import { MatFormFieldModule, MatFormFieldControl } from '@angular/material/form-field';
21
+ import { MetadataFormFieldComponent } from '@yuuvis/client-framework/metadata-form';
22
+ import { MatDatepickerModule } from '@angular/material/datepicker';
23
+ import { MatInputModule } from '@angular/material/input';
24
+ import { TranslateService as TranslateService$1 } from '@ngx-translate/core';
25
+ import { AbstractMatFormField, injectNgControl } from '@yuuvis/client-framework/common';
26
+ import * as i2$2 from '@yuuvis/client-framework/datepicker';
27
+ import { DatepickerComponent, YuvDatepickerModule } from '@yuuvis/client-framework/datepicker';
28
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
29
+ import * as i1$2 from '@angular/material/select';
30
+ import { MatSelectModule } from '@angular/material/select';
31
+ import * as i4$1 from '@angular/material/tooltip';
32
+ import { MatTooltipModule } from '@angular/material/tooltip';
33
+ import * as i3$1 from '@yuuvis/client-framework/autocomplete';
34
+ import { YuvAutocompleteModule } from '@yuuvis/client-framework/autocomplete';
35
+ import { map as map$1, catchError, finalize } from 'rxjs/operators';
36
+ import { marker } from '@colsen1991/ngx-translate-extract-marker';
37
+ import { ENTER, COMMA } from '@angular/cdk/keycodes';
38
+ import * as i1$3 from '@angular/material/chips';
39
+ import { MatChipsModule } from '@angular/material/chips';
663
40
 
664
41
  class EditTableDataComponent {
665
42
  constructor() {
666
- this.#oRef = inject((YvcOverlayRef));
667
43
  this.#fb = inject(FormBuilder);
668
- this.#errorMassge = inject(ErrorMessagesService);
669
- this.errorMassage = signal(null);
44
+ this.#system = inject(SystemService);
45
+ this.#errorMessage = inject(ObjectFormTranslateService);
46
+ this.#dialogData = inject(MAT_DIALOG_DATA);
47
+ this.#dialogRef = inject((MatDialogRef));
48
+ this.errorMessage = signal(null);
670
49
  this.tableForm = this.#fb.group({});
671
50
  this.isInnerTableForm = input(true);
672
- this.formElement = this.#oRef.data?.formElement || {};
673
- this.#elementData = this.#oRef.data?.elementData || {};
674
- this.situation = this.#oRef.data?.situation || Situation.EDIT;
675
- this.header = this.#oRef.data?.label || '';
676
- this.adding = this.#oRef.data?.adding;
51
+ this.formElement = this.#dialogData.formElement || {};
52
+ this.columns = (this.formElement['elements'] || []).map((c) => {
53
+ return {
54
+ ...c,
55
+ propertyType: c.type,
56
+ _internalType: this.#system.getInternalFormElementType(c.type, c.classification)
57
+ };
58
+ });
59
+ this.#elementData = this.#dialogData.elementData || {};
60
+ this.situation = this.#dialogData.situation || Situation.EDIT;
61
+ this.header = this.#dialogData.label || '';
62
+ this.adding = this.#dialogData.adding;
677
63
  }
678
- #oRef;
679
64
  #fb;
680
- #errorMassge;
65
+ #system;
66
+ #errorMessage;
67
+ #dialogData;
68
+ #dialogRef;
681
69
  #elementData;
682
70
  cancel() {
683
- if (this.#oRef)
684
- this.#oRef.close();
71
+ this.#dialogRef.close({});
685
72
  }
686
73
  submit() {
687
- if (this.tableForm.valid && this.#oRef)
688
- this.#oRef.close(this.tableForm.getRawValue());
74
+ if (this.tableForm.valid && this.#dialogRef)
75
+ this.#dialogRef.close(this.tableForm.getRawValue());
689
76
  }
690
77
  ngOnInit() {
691
78
  Object.values(this.formElement['elements']).forEach((element) => {
@@ -694,9 +81,9 @@ class EditTableDataComponent {
694
81
  this.tableForm.setValidators(this.#globalErrorValidator());
695
82
  this.#elementData && this.tableForm.patchValue(this.#elementData);
696
83
  this.tableForm.valueChanges.subscribe((v) => {
697
- this.errorMassage.set(this.tableForm.errors
84
+ this.errorMessage.set(this.tableForm.errors
698
85
  ? Object.keys(this.tableForm.errors).map((key) => this.tableForm.errors && this.tableForm.errors[key]
699
- ? Object.keys(this.tableForm.errors[key]).map((k) => ({ [key]: this.#errorMassge.getErrorLabel(k, key) }))
86
+ ? Object.keys(this.tableForm.errors[key]).map((k) => ({ [key]: this.#errorMessage.getErrorLabel(k, key) }))
700
87
  : null)
701
88
  : null);
702
89
  });
@@ -724,24 +111,24 @@ class EditTableDataComponent {
724
111
  return Object.keys(errors).length ? errors : null;
725
112
  };
726
113
  }
727
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: EditTableDataComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
728
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: EditTableDataComponent, isStandalone: true, selector: "yuv-edit-table-data", inputs: { isInnerTableForm: { classPropertyName: "isInnerTableForm", publicName: "isInnerTableForm", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
114
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: EditTableDataComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
115
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.1", type: EditTableDataComponent, isStandalone: true, selector: "yuv-edit-table-data", inputs: { isInnerTableForm: { classPropertyName: "isInnerTableForm", publicName: "isInnerTableForm", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
729
116
  {
730
117
  provide: NG_VALUE_ACCESSOR,
731
118
  useExisting: forwardRef(() => EditTableDataComponent),
732
119
  multi: true
733
120
  }
734
- ], ngImport: i0, template: "<header>\n <h2>{{ 'yuv.form.element.data.grid.edit.headline' | translate: { headline: header } }}</h2>\n</header>\n\n<div [formGroup]=\"tableForm\">\n @for (element of formElement['elements']; track $index) {\n <div [attr.data-name]=\"element.name\" class=\"form-field\">\n <yuv-form-input\n [label]=\"element.label\"\n [required]=\"element.required\"\n [invalid]=\"false\"\n [disabled]=\"element.readonly\"\n [invalid]=\"!tableForm.get(element.label)?.valid && tableForm.get(element.label)?.dirty\"\n >\n @switch (element.type) {\n @case ('string') {\n <yuv-string\n [situation]=\"situation\"\n [formControlName]=\"element.name\"\n [attr.data-name]=\"element.name\"\n [multiselect]=\"element.cardinality === 'multi' || situation === 'SEARCH'\"\n [rows]=\"element.rows\"\n [classifications]=\"element.classifications\"\n [regex]=\"element.regex\"\n [readonly]=\"element.readonly\"\n [minLength]=\"element.minLength\"\n [maxLength]=\"element.maxLength\"\n >\n </yuv-string>\n }\n @case ('decimal') {\n <yuv-number\n [readonly]=\"element.readonly\"\n [precision]=\"element.precision\"\n [scale]=\"element.scale\"\n [pattern]=\"element.pattern\"\n [grouping]=\"element.grouping\"\n [minValue]=\"element.minValue\"\n [maxValue]=\"element.maxValue\"\n [formControlName]=\"element.name\"\n [attr.data-name]=\"element.name\"\n ></yuv-number>\n }\n @default {\n <input [type]=\"element.type\" [id]=\"element.name\" [name]=\"element.name\" [readonly]=\"element.readonly\" [required]=\"element.required\" />\n }\n }\n <!-- <input [type]=\"element.type\" [id]=\"element.name\" [name]=\"element.name\" [readonly]=\"element.readonly\" [required]=\"element.required\" /> -->\n </yuv-form-input>\n @let errorsGroup = errorMassage();\n @if (errorsGroup && tableForm.errors) {\n <div class=\"err-msg\">\n @for (errors of errorsGroup; track $index) {\n @for (error of errors; track $index) {\n {{ error[element.label] }}\n }\n }\n </div>\n }\n </div>\n }\n <footer>\n <button (click)=\"cancel()\">{{ 'yuv.form.element.data.grid.edit.cancel' | translate }}</button>\n <button class=\"primary\" (click)=\"submit()\" [disabled]=\"!tableForm.dirty && !tableForm.valid\">\n @if (adding) {\n {{ 'yuv.form.element.data.grid.edit.add' | translate }}\n } @else {\n {{ 'yuv.form.element.data.grid.edit' | translate }}\n }\n </button>\n </footer>\n</div>\n", styles: [":host{display:flex;flex-direction:column;padding:var(--app-pane-padding)}:host header h2{padding:0;font-weight:400;font-size:var(--font-headline);margin:0 0 var(--app-pane-padding) 0}:host .err-msg{font-size:var(--font-hint);color:var(--color-error);padding:calc(var(--app-pane-padding) / 4) 0;border:0}:host footer{display:flex;justify-content:end;gap:var(--app-pane-padding);margin-block-start:var(--app-pane-padding)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: FormInputComponent, selector: "yuv-form-input", inputs: ["label", "tag", "description", "invalid", "disabled", "required"] }, { kind: "component", type: StringComponent, selector: "yuv-string", inputs: ["multiselect", "rows", "readonly", "autofocus", "classifications", "situation", "regex", "minLength", "maxLength"] }, { kind: "component", type: NumberComponent, selector: "yuv-number", inputs: ["scale", "precision", "grouping", "groupPattern", "readonly", "minValue", "maxValue", "classifications"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
121
+ ], ngImport: i0, template: "<div [formGroup]=\"tableForm\">\n <h2 mat-dialog-title>{{ 'yuv.form.element.data.grid.edit.headline' | translate: { headline: header } }}</h2>\n\n <mat-dialog-content>\n <div class=\"fields\">\n @for (element of columns; track $index) {\n <div [attr.data-name]=\"element.name\" class=\"form-field\">\n <yuv-metadata-form-field [field]=\"element\" [formControlName]=\"element.name\" [situation]=\"situation\"></yuv-metadata-form-field>\n\n @let errorsGroup = errorMessage();\n @if (errorsGroup && tableForm.errors) {\n <div class=\"err-msg\">\n @for (errors of errorsGroup; track $index) {\n @for (error of errors; track $index) {\n {{ error[element.name] }}\n }\n }\n </div>\n }\n </div>\n }\n </div>\n </mat-dialog-content>\n\n <mat-dialog-actions>\n <button mat-button (click)=\"cancel()\">{{ 'yuv.form.element.data.grid.edit.cancel' | translate }}</button>\n <button mat-flat-button class=\"primary\" (click)=\"submit()\" [disabled]=\"!tableForm.dirty && !tableForm.valid\">\n @if (adding) {\n {{ 'yuv.form.element.data.grid.edit.add' | translate }}\n } @else {\n {{ 'yuv.form.element.data.grid.edit' | translate }}\n }\n </button>\n </mat-dialog-actions>\n</div>\n", styles: [":host .fields{padding:var(--ymt-spacing-m)}:host .err-msg{font:var(--ymt-font-body-subtle);color:var(--ymt-danger);padding:var(--ymt-spacing-2xs) 0;border:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i2.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i2.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i2.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: MetadataFormFieldComponent, selector: "yuv-metadata-form-field", inputs: ["field", "situation"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i4.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
735
122
  }
736
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: EditTableDataComponent, decorators: [{
123
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: EditTableDataComponent, decorators: [{
737
124
  type: Component,
738
- args: [{ selector: 'yuv-edit-table-data', standalone: true, imports: [CommonModule, ReactiveFormsModule, FormInputComponent, StringComponent, NumberComponent, TranslateModule], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
125
+ args: [{ selector: 'yuv-edit-table-data', standalone: true, imports: [CommonModule, ReactiveFormsModule, MatDialogModule, MatButtonModule, MatFormFieldModule, MetadataFormFieldComponent, TranslateModule], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
739
126
  {
740
127
  provide: NG_VALUE_ACCESSOR,
741
128
  useExisting: forwardRef(() => EditTableDataComponent),
742
129
  multi: true
743
130
  }
744
- ], template: "<header>\n <h2>{{ 'yuv.form.element.data.grid.edit.headline' | translate: { headline: header } }}</h2>\n</header>\n\n<div [formGroup]=\"tableForm\">\n @for (element of formElement['elements']; track $index) {\n <div [attr.data-name]=\"element.name\" class=\"form-field\">\n <yuv-form-input\n [label]=\"element.label\"\n [required]=\"element.required\"\n [invalid]=\"false\"\n [disabled]=\"element.readonly\"\n [invalid]=\"!tableForm.get(element.label)?.valid && tableForm.get(element.label)?.dirty\"\n >\n @switch (element.type) {\n @case ('string') {\n <yuv-string\n [situation]=\"situation\"\n [formControlName]=\"element.name\"\n [attr.data-name]=\"element.name\"\n [multiselect]=\"element.cardinality === 'multi' || situation === 'SEARCH'\"\n [rows]=\"element.rows\"\n [classifications]=\"element.classifications\"\n [regex]=\"element.regex\"\n [readonly]=\"element.readonly\"\n [minLength]=\"element.minLength\"\n [maxLength]=\"element.maxLength\"\n >\n </yuv-string>\n }\n @case ('decimal') {\n <yuv-number\n [readonly]=\"element.readonly\"\n [precision]=\"element.precision\"\n [scale]=\"element.scale\"\n [pattern]=\"element.pattern\"\n [grouping]=\"element.grouping\"\n [minValue]=\"element.minValue\"\n [maxValue]=\"element.maxValue\"\n [formControlName]=\"element.name\"\n [attr.data-name]=\"element.name\"\n ></yuv-number>\n }\n @default {\n <input [type]=\"element.type\" [id]=\"element.name\" [name]=\"element.name\" [readonly]=\"element.readonly\" [required]=\"element.required\" />\n }\n }\n <!-- <input [type]=\"element.type\" [id]=\"element.name\" [name]=\"element.name\" [readonly]=\"element.readonly\" [required]=\"element.required\" /> -->\n </yuv-form-input>\n @let errorsGroup = errorMassage();\n @if (errorsGroup && tableForm.errors) {\n <div class=\"err-msg\">\n @for (errors of errorsGroup; track $index) {\n @for (error of errors; track $index) {\n {{ error[element.label] }}\n }\n }\n </div>\n }\n </div>\n }\n <footer>\n <button (click)=\"cancel()\">{{ 'yuv.form.element.data.grid.edit.cancel' | translate }}</button>\n <button class=\"primary\" (click)=\"submit()\" [disabled]=\"!tableForm.dirty && !tableForm.valid\">\n @if (adding) {\n {{ 'yuv.form.element.data.grid.edit.add' | translate }}\n } @else {\n {{ 'yuv.form.element.data.grid.edit' | translate }}\n }\n </button>\n </footer>\n</div>\n", styles: [":host{display:flex;flex-direction:column;padding:var(--app-pane-padding)}:host header h2{padding:0;font-weight:400;font-size:var(--font-headline);margin:0 0 var(--app-pane-padding) 0}:host .err-msg{font-size:var(--font-hint);color:var(--color-error);padding:calc(var(--app-pane-padding) / 4) 0;border:0}:host footer{display:flex;justify-content:end;gap:var(--app-pane-padding);margin-block-start:var(--app-pane-padding)}\n"] }]
131
+ ], template: "<div [formGroup]=\"tableForm\">\n <h2 mat-dialog-title>{{ 'yuv.form.element.data.grid.edit.headline' | translate: { headline: header } }}</h2>\n\n <mat-dialog-content>\n <div class=\"fields\">\n @for (element of columns; track $index) {\n <div [attr.data-name]=\"element.name\" class=\"form-field\">\n <yuv-metadata-form-field [field]=\"element\" [formControlName]=\"element.name\" [situation]=\"situation\"></yuv-metadata-form-field>\n\n @let errorsGroup = errorMessage();\n @if (errorsGroup && tableForm.errors) {\n <div class=\"err-msg\">\n @for (errors of errorsGroup; track $index) {\n @for (error of errors; track $index) {\n {{ error[element.name] }}\n }\n }\n </div>\n }\n </div>\n }\n </div>\n </mat-dialog-content>\n\n <mat-dialog-actions>\n <button mat-button (click)=\"cancel()\">{{ 'yuv.form.element.data.grid.edit.cancel' | translate }}</button>\n <button mat-flat-button class=\"primary\" (click)=\"submit()\" [disabled]=\"!tableForm.dirty && !tableForm.valid\">\n @if (adding) {\n {{ 'yuv.form.element.data.grid.edit.add' | translate }}\n } @else {\n {{ 'yuv.form.element.data.grid.edit' | translate }}\n }\n </button>\n </mat-dialog-actions>\n</div>\n", styles: [":host .fields{padding:var(--ymt-spacing-m)}:host .err-msg{font:var(--ymt-font-body-subtle);color:var(--ymt-danger);padding:var(--ymt-spacing-2xs) 0;border:0}\n"] }]
745
132
  }] });
746
133
 
747
134
  var DataGridSizeType;
@@ -756,7 +143,7 @@ var DataGridSizeType;
756
143
  const CDK_IMPORT = [CdkMenu, CdkTableModule, CdkMenuTrigger, CdkMenuItem];
757
144
  class DataGridComponent {
758
145
  constructor() {
759
- this.#overlay = inject(YvcOverlayService);
146
+ this.#dialog = inject(MatDialog);
760
147
  this.#clipboardService = inject(ClipboardService);
761
148
  this.#decimalPipe = inject(DecimalPipe);
762
149
  this.trnaslate = inject(TranslateService);
@@ -790,23 +177,26 @@ class DataGridComponent {
790
177
  // eslint-disable-next-line @typescript-eslint/no-empty-function
791
178
  this.validationChange = () => { };
792
179
  }
793
- #overlay;
180
+ #dialog;
794
181
  #clipboardService;
795
182
  #decimalPipe;
796
183
  #loadData;
797
184
  #sourceData;
798
185
  #openEditOverlay(elementData, adding = false) {
799
- return this.#overlay
186
+ return this.#dialog
800
187
  .open(EditTableDataComponent, {
801
- formElement: {
802
- ...this.formElement()
803
- },
804
- elementData,
805
- situation: this.situation(),
806
- adding,
807
- label: this.tableLabel()
188
+ data: {
189
+ formElement: {
190
+ ...this.formElement()
191
+ },
192
+ elementData,
193
+ situation: this.situation(),
194
+ adding,
195
+ label: this.tableLabel()
196
+ }
808
197
  })
809
- .afterClosed$.pipe(map((result) => result.data));
198
+ .afterClosed()
199
+ .pipe(map((result) => result));
810
200
  }
811
201
  copyLine(element) {
812
202
  this.#clipboardService.addToNavigatorClipBoard(JSON.stringify(element));
@@ -884,19 +274,19 @@ class DataGridComponent {
884
274
  onValueChange(e) {
885
275
  this.propagateChange(e);
886
276
  }
887
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DataGridComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
888
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: DataGridComponent, isStandalone: true, selector: "yuv-data-grid", inputs: { situation: { classPropertyName: "situation", publicName: "situation", isSignal: true, isRequired: false, transformFunction: null }, formElement: { classPropertyName: "formElement", publicName: "formElement", isSignal: true, isRequired: false, transformFunction: null }, formControl: { classPropertyName: "formControl", publicName: "formControl", isSignal: true, isRequired: false, transformFunction: null }, classifications: { classPropertyName: "classifications", publicName: "classifications", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "yuv-data-grid" }, providers: [
277
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: DataGridComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
278
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.1", type: DataGridComponent, isStandalone: true, selector: "yuv-data-grid", inputs: { situation: { classPropertyName: "situation", publicName: "situation", isSignal: true, isRequired: false, transformFunction: null }, formElement: { classPropertyName: "formElement", publicName: "formElement", isSignal: true, isRequired: false, transformFunction: null }, formControl: { classPropertyName: "formControl", publicName: "formControl", isSignal: true, isRequired: false, transformFunction: null }, classifications: { classPropertyName: "classifications", publicName: "classifications", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "yuv-data-grid" }, providers: [
889
279
  {
890
280
  provide: NG_VALUE_ACCESSOR,
891
281
  useExisting: forwardRef(() => DataGridComponent),
892
282
  multi: true
893
283
  },
894
284
  DecimalPipe
895
- ], ngImport: i0, template: "<header>\n <h3>{{ tableLabel() }}</h3>\n @if (!readonly()) {\n <button (click)=\"addRow()\" aria-label=\"Add Row\" class=\"table-options-add-row\">\n <yvc-icon [svg]=\"icons.add\"></yvc-icon>\n </button>\n }\n</header>\n@let displayedCol = displayedColumns();\n@let displayedColActions = displayedColumnsWithActions();\n<div class=\"table-wrapper\" [ngClass]=\"size()\">\n <table cdk-table [dataSource]=\"dataSource()\">\n <!-- Dynamic Columns -->\n @for (column of displayedCol; track $index) {\n <ng-container [cdkColumnDef]=\"column.columnDef\">\n <th class=\"sticky-column\" cdk-header-cell *cdkHeaderCellDef>{{ column.header }}</th>\n <td cdk-cell *cdkCellDef=\"let element\">{{ column.cell(element) }}</td>\n </ng-container>\n }\n\n <!-- Actions Column (Not in displayedColumns) -->\n <ng-container cdkColumnDef=\"actions\">\n <th class=\"actions-header sticky-column\" cdk-header-cell *cdkHeaderCellDef></th>\n <td class=\"actions-row sticky\" cdk-cell *cdkCellDef=\"let element\">\n <!-- Only show the button in the last (empty) row -->\n @if (!readonly()) {\n <button\n aria-label=\"Edit Row\"\n class=\"table-options-menu-bar-item\"\n cdkMenuItem\n (cdkMenuOpened)=\"onMenuTriggert(element)\"\n (cdkMenuClosed)=\"onMenuTriggert(null)\"\n [cdkMenuTriggerFor]=\"options\"\n [cdkMenuTriggerData]=\"{ element: element }\"\n >\n <yvc-icon [svg]=\"icons.more\"></yvc-icon>\n </button>\n }\n </td>\n </ng-container>\n\n <tr cdk-header-row *cdkHeaderRowDef=\"displayedColActions\"></tr>\n @if (!readonly()) {\n <tr (dblclick)=\"editRow(row)\" [class.selected-row]=\"row === selectedRow()\" cdk-row *cdkRowDef=\"let row; columns: displayedColActions\"></tr>\n } @else {\n <tr cdk-row *cdkRowDef=\"let row; columns: displayedColActions\"></tr>\n }\n </table>\n</div>\n<ng-template #options let-element=\"element\">\n <div class=\"table-options-menu\" cdkMenu>\n <button class=\"table-options-menu-item\" (click)=\"copyLine(element)\" cdkMenuItem>{{ 'yuv.form.element.data.grid.copy' | translate }}</button>\n <button class=\"table-options-menu-item\" cdkMenuItem (click)=\"editRow(element)\">{{ 'yuv.form.element.data.grid.edit' | translate }}</button>\n <button class=\"table-options-menu-item\" cdkMenuItem (click)=\"removeRow(element)\">{{ 'yuv.form.element.data.grid.remove' | translate }}</button>\n </div>\n</ng-template>\n", styles: [":root{--table-size-small: 200px;--table-size-medium: 400px;--table-size-large: 600px;--table-size-extra-large: 800px}:host{border:1px solid var(--panel-divider-color)}:host header{display:flex;justify-content:space-between;background-color:var(--panel-background-grey)}:host header h3{text-align:start;-webkit-user-select:none;user-select:none;flex:0 1 auto;padding:1rem;margin:0;color:var(--text-color-caption);border-radius:2px;font-size:var(--font-caption);font-weight:400}:host.yuv-data-grid{display:block}:host.yuv-data-grid .table-wrapper{overflow:auto;position:relative;white-space:nowrap}:host.yuv-data-grid .table-wrapper.small{height:var(--table-size-small)}:host.yuv-data-grid .table-wrapper.medium{height:var(--table-size-medium)}:host.yuv-data-grid .table-wrapper.large{height:var(--table-size-large)}:host.yuv-data-grid .table-wrapper.extra-large{height:var(--table-size-extra-large)}:host.yuv-data-grid ::ng-deep .cdk-header-cell:not(:last-child){padding:.5rem 1rem}:host.yuv-data-grid ::ng-deep table{border-spacing:0}:host.yuv-data-grid ::ng-deep th{border-bottom:1px solid var(--panel-divider-color);border-right:1px solid var(--panel-divider-color);padding:.5rem 0}:host.yuv-data-grid ::ng-deep thead{background-color:var(--panel-background-grey)}:host.yuv-data-grid ::ng-deep tr.cdk-row{cursor:pointer;-webkit-user-select:none;user-select:none;transition:color .2s ease-in-out}:host.yuv-data-grid ::ng-deep tr.cdk-row:hover td{border-top:1px solid var(--panel-background-grey);border-bottom:1px solid var(--panel-background-grey)}:host.yuv-data-grid ::ng-deep tr.cdk-row:hover:has(.actions-row) td.cdk-cell.actions-row.sticky{opacity:1}:host.yuv-data-grid ::ng-deep tr.cdk-row.selected-row{color:var(--text-color-hint)}:host.yuv-data-grid ::ng-deep tr.cdk-row td{border-bottom:1px solid transparent;border-top:1px solid transparent}:host.yuv-data-grid ::ng-deep tr.cdk-row td:not(:last-child){padding:.5rem 1rem}:host.yuv-data-grid ::ng-deep .cdk-table .cdk-header-row th[role=columnheader]{font-weight:500}:host.yuv-data-grid th.cdk-header-cell.sticky-column{position:sticky;top:0;background-color:var(--panel-background-grey)}:host.yuv-data-grid td.cdk-cell.actions-row.sticky{position:sticky;right:0;opacity:0;background-color:var(--panel-background);transition:opacity .2s ease-in-out}:host .table-options-menu-bar-item,:host .table-options-add-row{cursor:pointer;border:none;-webkit-user-select:none;user-select:none;min-width:34px;line-height:26px;padding:0;display:flex;align-items:center;justify-content:center}.table-options-menu{display:inline-flex;flex-direction:column;max-width:280px;background-color:var(--panel-background);border:1px solid var(--panel-divider-color);padding:calc(var(--app-pane-padding) / 6) 0}.table-options-menu .table-options-menu-item{background-color:transparent;cursor:pointer;border:none;border-radius:0;-webkit-user-select:none;user-select:none;display:flex;align-items:center;flex-direction:row;flex:1}.table-options-menu .table-options-menu-item:not(:last-child){border-block-end:1px solid var(--panel-divider-color)}.table-options-menu .table-options-menu-item>span{display:flex;flex-direction:row;flex:1;justify-content:flex-end}.table-options-menu .table-options-menu-item:active{background-color:var(--item-focus-border-color)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: YvcIconModule }, { kind: "component", type: i3.Icon, selector: "yvc-icon", inputs: ["label", "svg", "svgSrc"] }, { kind: "directive", type: CdkMenu, selector: "[cdkMenu]", outputs: ["closed"], exportAs: ["cdkMenu"] }, { kind: "ngmodule", type: CdkTableModule }, { kind: "component", type: i4.CdkTable, selector: "cdk-table, table[cdk-table]", inputs: ["trackBy", "dataSource", "multiTemplateDataRows", "fixedLayout"], outputs: ["contentChanged"], exportAs: ["cdkTable"] }, { kind: "directive", type: i4.CdkRowDef, selector: "[cdkRowDef]", inputs: ["cdkRowDefColumns", "cdkRowDefWhen"] }, { kind: "directive", type: i4.CdkCellDef, selector: "[cdkCellDef]" }, { kind: "directive", type: i4.CdkHeaderCellDef, selector: "[cdkHeaderCellDef]" }, { kind: "directive", type: i4.CdkColumnDef, selector: "[cdkColumnDef]", inputs: ["cdkColumnDef", "sticky", "stickyEnd"] }, { kind: "directive", type: i4.CdkCell, selector: "cdk-cell, td[cdk-cell]" }, { kind: "component", type: i4.CdkRow, selector: "cdk-row, tr[cdk-row]" }, { kind: "directive", type: i4.CdkHeaderCell, selector: "cdk-header-cell, th[cdk-header-cell]" }, { kind: "component", type: i4.CdkHeaderRow, selector: "cdk-header-row, tr[cdk-header-row]" }, { kind: "directive", type: i4.CdkHeaderRowDef, selector: "[cdkHeaderRowDef]", inputs: ["cdkHeaderRowDef", "cdkHeaderRowDefSticky"] }, { kind: "directive", type: CdkMenuTrigger, selector: "[cdkMenuTriggerFor]", inputs: ["cdkMenuTriggerFor", "cdkMenuPosition", "cdkMenuTriggerData"], outputs: ["cdkMenuOpened", "cdkMenuClosed"], exportAs: ["cdkMenuTriggerFor"] }, { kind: "directive", type: CdkMenuItem, selector: "[cdkMenuItem]", inputs: ["cdkMenuItemDisabled", "cdkMenuitemTypeaheadLabel"], outputs: ["cdkMenuItemTriggered"], exportAs: ["cdkMenuItem"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
285
+ ], ngImport: i0, template: "<header>\n <h3>{{ tableLabel() }}</h3>\n @if (!readonly()) {\n <button mat-icon-button (click)=\"addRow()\" class=\"table-options-add-row\">\n <mat-icon>add</mat-icon>\n </button>\n }\n</header>\n@let displayedCol = displayedColumns();\n@let displayedColActions = displayedColumnsWithActions();\n<div class=\"table-wrapper\" [ngClass]=\"size()\">\n <table cdk-table [dataSource]=\"dataSource()\">\n <!-- Dynamic Columns -->\n @for (column of displayedCol; track $index) {\n <ng-container [cdkColumnDef]=\"column.columnDef\">\n <th class=\"sticky-column\" cdk-header-cell *cdkHeaderCellDef>{{ column.header }}</th>\n <td cdk-cell *cdkCellDef=\"let element\">{{ column.cell(element) }}</td>\n </ng-container>\n }\n\n <!-- Actions Column (Not in displayedColumns) -->\n <ng-container cdkColumnDef=\"actions\">\n <th class=\"actions-header sticky-column\" cdk-header-cell *cdkHeaderCellDef></th>\n <td class=\"actions-row sticky\" cdk-cell *cdkCellDef=\"let element\">\n <!-- Only show the button in the last (empty) row -->\n @if (!readonly()) {\n <button\n mat-icon-button\n class=\"table-options-menu-bar-item\"\n cdkMenuItem\n (cdkMenuOpened)=\"onMenuTriggert(element)\"\n (cdkMenuClosed)=\"onMenuTriggert(null)\"\n [cdkMenuTriggerFor]=\"options\"\n [cdkMenuTriggerData]=\"{ element: element }\"\n >\n <mat-icon>more_vert</mat-icon>\n </button>\n }\n </td>\n </ng-container>\n\n <tr cdk-header-row *cdkHeaderRowDef=\"displayedColActions\"></tr>\n @if (!readonly()) {\n <tr (dblclick)=\"editRow(row)\" [class.selected-row]=\"row === selectedRow()\" cdk-row *cdkRowDef=\"let row; columns: displayedColActions\"></tr>\n } @else {\n <tr cdk-row *cdkRowDef=\"let row; columns: displayedColActions\"></tr>\n }\n </table>\n</div>\n<ng-template #options let-element=\"element\">\n <div class=\"table-options-menu\" cdkMenu>\n <button class=\"table-options-menu-item\" (click)=\"copyLine(element)\" cdkMenuItem>{{ 'yuv.form.element.data.grid.copy' | translate }}</button>\n <button class=\"table-options-menu-item\" cdkMenuItem (click)=\"editRow(element)\">{{ 'yuv.form.element.data.grid.edit' | translate }}</button>\n <button class=\"table-options-menu-item\" cdkMenuItem (click)=\"removeRow(element)\">{{ 'yuv.form.element.data.grid.remove' | translate }}</button>\n </div>\n</ng-template>\n", styles: [":root{--table-size-small: 200px;--table-size-medium: 400px;--table-size-large: 600px;--table-size-extra-large: 800px}:host{border:1px solid var(--ymt-outline-variant)}:host header{display:flex;justify-content:space-between;background-color:var(--ymt-surface-panel-grey)}:host header h3{text-align:start;-webkit-user-select:none;user-select:none;flex:0 1 auto;padding:1rem;margin:0;color:var(--ymt-text-color-subtle);border-radius:2px;font:var(--ymt-font-body-subtle);font-weight:400}:host.yuv-data-grid{display:block}:host.yuv-data-grid .table-wrapper{overflow:auto;position:relative;white-space:nowrap}:host.yuv-data-grid .table-wrapper.small{height:var(--table-size-small)}:host.yuv-data-grid .table-wrapper.medium{height:var(--table-size-medium)}:host.yuv-data-grid .table-wrapper.large{height:var(--table-size-large)}:host.yuv-data-grid .table-wrapper.extra-large{height:var(--table-size-extra-large)}:host.yuv-data-grid ::ng-deep .cdk-header-cell:not(:last-child){padding:.5rem 1rem}:host.yuv-data-grid ::ng-deep table{border-spacing:0}:host.yuv-data-grid ::ng-deep th{border-bottom:1px solid var(--ymt-outline-variant);border-right:1px solid var(--ymt-outline-variant);padding:.5rem 0}:host.yuv-data-grid ::ng-deep thead{background-color:var(--ymt-surface-panel)}:host.yuv-data-grid ::ng-deep tr.cdk-row{cursor:pointer;-webkit-user-select:none;user-select:none;transition:color .2s ease-in-out}:host.yuv-data-grid ::ng-deep tr.cdk-row:hover td{border-top:1px solid var(--ymt-surface-panel);border-bottom:1px solid var(--ymt-surface-panel)}:host.yuv-data-grid ::ng-deep tr.cdk-row:hover:has(.actions-row) td.cdk-cell.actions-row.sticky{opacity:1}:host.yuv-data-grid ::ng-deep tr.cdk-row.selected-row{color:var(--ymt-text-color-subtle)}:host.yuv-data-grid ::ng-deep tr.cdk-row td{border-bottom:1px solid transparent;border-top:1px solid transparent}:host.yuv-data-grid ::ng-deep tr.cdk-row td:not(:last-child){padding:.5rem 1rem}:host.yuv-data-grid ::ng-deep .cdk-table .cdk-header-row th[role=columnheader]{font-weight:500}:host.yuv-data-grid th.cdk-header-cell.sticky-column{position:sticky;top:0;background-color:var(--ymt-surface-panel)}:host.yuv-data-grid td.cdk-cell.actions-row.sticky{position:sticky;right:0;opacity:0;background-color:var(--ymt-surface-panel);transition:opacity .2s ease-in-out}:host .table-options-menu-bar-item,:host .table-options-add-row{cursor:pointer;border:none;-webkit-user-select:none;user-select:none;min-width:34px;line-height:26px;padding:0;display:flex;align-items:center;justify-content:center}.table-options-menu{display:inline-flex;flex-direction:column;max-width:280px;background-color:var(--ymt-surface-panel);border:1px solid var(--ymt-outline-variant);padding:var(--ymt-spacing-3xs) 0}.table-options-menu .table-options-menu-item{background-color:transparent;cursor:pointer;border:none;border-radius:0;-webkit-user-select:none;user-select:none;display:flex;align-items:center;flex-direction:row;flex:1}.table-options-menu .table-options-menu-item:not(:last-child){border-block-end:1px solid var(--ymt-outline-variant)}.table-options-menu .table-options-menu-item>span{display:flex;flex-direction:row;flex:1;justify-content:flex-end}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i4.TranslatePipe, name: "translate" }, { kind: "directive", type: CdkMenu, selector: "[cdkMenu]", outputs: ["closed"], exportAs: ["cdkMenu"] }, { kind: "ngmodule", type: CdkTableModule }, { kind: "component", type: i5.CdkTable, selector: "cdk-table, table[cdk-table]", inputs: ["trackBy", "dataSource", "multiTemplateDataRows", "fixedLayout"], outputs: ["contentChanged"], exportAs: ["cdkTable"] }, { kind: "directive", type: i5.CdkRowDef, selector: "[cdkRowDef]", inputs: ["cdkRowDefColumns", "cdkRowDefWhen"] }, { kind: "directive", type: i5.CdkCellDef, selector: "[cdkCellDef]" }, { kind: "directive", type: i5.CdkHeaderCellDef, selector: "[cdkHeaderCellDef]" }, { kind: "directive", type: i5.CdkColumnDef, selector: "[cdkColumnDef]", inputs: ["cdkColumnDef", "sticky", "stickyEnd"] }, { kind: "directive", type: i5.CdkCell, selector: "cdk-cell, td[cdk-cell]" }, { kind: "component", type: i5.CdkRow, selector: "cdk-row, tr[cdk-row]" }, { kind: "directive", type: i5.CdkHeaderCell, selector: "cdk-header-cell, th[cdk-header-cell]" }, { kind: "component", type: i5.CdkHeaderRow, selector: "cdk-header-row, tr[cdk-header-row]" }, { kind: "directive", type: i5.CdkHeaderRowDef, selector: "[cdkHeaderRowDef]", inputs: ["cdkHeaderRowDef", "cdkHeaderRowDefSticky"] }, { kind: "directive", type: CdkMenuTrigger, selector: "[cdkMenuTriggerFor]", inputs: ["cdkMenuTriggerFor", "cdkMenuPosition", "cdkMenuTriggerData"], outputs: ["cdkMenuOpened", "cdkMenuClosed"], exportAs: ["cdkMenuTriggerFor"] }, { kind: "directive", type: CdkMenuItem, selector: "[cdkMenuItem]", inputs: ["cdkMenuItemDisabled", "cdkMenuitemTypeaheadLabel"], outputs: ["cdkMenuItemTriggered"], exportAs: ["cdkMenuItem"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
896
286
  }
897
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DataGridComponent, decorators: [{
287
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: DataGridComponent, decorators: [{
898
288
  type: Component,
899
- args: [{ selector: 'yuv-data-grid', standalone: true, imports: [CommonModule, NgClass, TranslateModule, YvcIconModule, ...CDK_IMPORT], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
289
+ args: [{ selector: 'yuv-data-grid', standalone: true, imports: [CommonModule, NgClass, MatIconModule, MatButtonModule, TranslateModule, ...CDK_IMPORT], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
900
290
  {
901
291
  provide: NG_VALUE_ACCESSOR,
902
292
  useExisting: forwardRef(() => DataGridComponent),
@@ -905,40 +295,52 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
905
295
  DecimalPipe
906
296
  ], host: {
907
297
  class: 'yuv-data-grid'
908
- }, template: "<header>\n <h3>{{ tableLabel() }}</h3>\n @if (!readonly()) {\n <button (click)=\"addRow()\" aria-label=\"Add Row\" class=\"table-options-add-row\">\n <yvc-icon [svg]=\"icons.add\"></yvc-icon>\n </button>\n }\n</header>\n@let displayedCol = displayedColumns();\n@let displayedColActions = displayedColumnsWithActions();\n<div class=\"table-wrapper\" [ngClass]=\"size()\">\n <table cdk-table [dataSource]=\"dataSource()\">\n <!-- Dynamic Columns -->\n @for (column of displayedCol; track $index) {\n <ng-container [cdkColumnDef]=\"column.columnDef\">\n <th class=\"sticky-column\" cdk-header-cell *cdkHeaderCellDef>{{ column.header }}</th>\n <td cdk-cell *cdkCellDef=\"let element\">{{ column.cell(element) }}</td>\n </ng-container>\n }\n\n <!-- Actions Column (Not in displayedColumns) -->\n <ng-container cdkColumnDef=\"actions\">\n <th class=\"actions-header sticky-column\" cdk-header-cell *cdkHeaderCellDef></th>\n <td class=\"actions-row sticky\" cdk-cell *cdkCellDef=\"let element\">\n <!-- Only show the button in the last (empty) row -->\n @if (!readonly()) {\n <button\n aria-label=\"Edit Row\"\n class=\"table-options-menu-bar-item\"\n cdkMenuItem\n (cdkMenuOpened)=\"onMenuTriggert(element)\"\n (cdkMenuClosed)=\"onMenuTriggert(null)\"\n [cdkMenuTriggerFor]=\"options\"\n [cdkMenuTriggerData]=\"{ element: element }\"\n >\n <yvc-icon [svg]=\"icons.more\"></yvc-icon>\n </button>\n }\n </td>\n </ng-container>\n\n <tr cdk-header-row *cdkHeaderRowDef=\"displayedColActions\"></tr>\n @if (!readonly()) {\n <tr (dblclick)=\"editRow(row)\" [class.selected-row]=\"row === selectedRow()\" cdk-row *cdkRowDef=\"let row; columns: displayedColActions\"></tr>\n } @else {\n <tr cdk-row *cdkRowDef=\"let row; columns: displayedColActions\"></tr>\n }\n </table>\n</div>\n<ng-template #options let-element=\"element\">\n <div class=\"table-options-menu\" cdkMenu>\n <button class=\"table-options-menu-item\" (click)=\"copyLine(element)\" cdkMenuItem>{{ 'yuv.form.element.data.grid.copy' | translate }}</button>\n <button class=\"table-options-menu-item\" cdkMenuItem (click)=\"editRow(element)\">{{ 'yuv.form.element.data.grid.edit' | translate }}</button>\n <button class=\"table-options-menu-item\" cdkMenuItem (click)=\"removeRow(element)\">{{ 'yuv.form.element.data.grid.remove' | translate }}</button>\n </div>\n</ng-template>\n", styles: [":root{--table-size-small: 200px;--table-size-medium: 400px;--table-size-large: 600px;--table-size-extra-large: 800px}:host{border:1px solid var(--panel-divider-color)}:host header{display:flex;justify-content:space-between;background-color:var(--panel-background-grey)}:host header h3{text-align:start;-webkit-user-select:none;user-select:none;flex:0 1 auto;padding:1rem;margin:0;color:var(--text-color-caption);border-radius:2px;font-size:var(--font-caption);font-weight:400}:host.yuv-data-grid{display:block}:host.yuv-data-grid .table-wrapper{overflow:auto;position:relative;white-space:nowrap}:host.yuv-data-grid .table-wrapper.small{height:var(--table-size-small)}:host.yuv-data-grid .table-wrapper.medium{height:var(--table-size-medium)}:host.yuv-data-grid .table-wrapper.large{height:var(--table-size-large)}:host.yuv-data-grid .table-wrapper.extra-large{height:var(--table-size-extra-large)}:host.yuv-data-grid ::ng-deep .cdk-header-cell:not(:last-child){padding:.5rem 1rem}:host.yuv-data-grid ::ng-deep table{border-spacing:0}:host.yuv-data-grid ::ng-deep th{border-bottom:1px solid var(--panel-divider-color);border-right:1px solid var(--panel-divider-color);padding:.5rem 0}:host.yuv-data-grid ::ng-deep thead{background-color:var(--panel-background-grey)}:host.yuv-data-grid ::ng-deep tr.cdk-row{cursor:pointer;-webkit-user-select:none;user-select:none;transition:color .2s ease-in-out}:host.yuv-data-grid ::ng-deep tr.cdk-row:hover td{border-top:1px solid var(--panel-background-grey);border-bottom:1px solid var(--panel-background-grey)}:host.yuv-data-grid ::ng-deep tr.cdk-row:hover:has(.actions-row) td.cdk-cell.actions-row.sticky{opacity:1}:host.yuv-data-grid ::ng-deep tr.cdk-row.selected-row{color:var(--text-color-hint)}:host.yuv-data-grid ::ng-deep tr.cdk-row td{border-bottom:1px solid transparent;border-top:1px solid transparent}:host.yuv-data-grid ::ng-deep tr.cdk-row td:not(:last-child){padding:.5rem 1rem}:host.yuv-data-grid ::ng-deep .cdk-table .cdk-header-row th[role=columnheader]{font-weight:500}:host.yuv-data-grid th.cdk-header-cell.sticky-column{position:sticky;top:0;background-color:var(--panel-background-grey)}:host.yuv-data-grid td.cdk-cell.actions-row.sticky{position:sticky;right:0;opacity:0;background-color:var(--panel-background);transition:opacity .2s ease-in-out}:host .table-options-menu-bar-item,:host .table-options-add-row{cursor:pointer;border:none;-webkit-user-select:none;user-select:none;min-width:34px;line-height:26px;padding:0;display:flex;align-items:center;justify-content:center}.table-options-menu{display:inline-flex;flex-direction:column;max-width:280px;background-color:var(--panel-background);border:1px solid var(--panel-divider-color);padding:calc(var(--app-pane-padding) / 6) 0}.table-options-menu .table-options-menu-item{background-color:transparent;cursor:pointer;border:none;border-radius:0;-webkit-user-select:none;user-select:none;display:flex;align-items:center;flex-direction:row;flex:1}.table-options-menu .table-options-menu-item:not(:last-child){border-block-end:1px solid var(--panel-divider-color)}.table-options-menu .table-options-menu-item>span{display:flex;flex-direction:row;flex:1;justify-content:flex-end}.table-options-menu .table-options-menu-item:active{background-color:var(--item-focus-border-color)}\n"] }]
298
+ }, template: "<header>\n <h3>{{ tableLabel() }}</h3>\n @if (!readonly()) {\n <button mat-icon-button (click)=\"addRow()\" class=\"table-options-add-row\">\n <mat-icon>add</mat-icon>\n </button>\n }\n</header>\n@let displayedCol = displayedColumns();\n@let displayedColActions = displayedColumnsWithActions();\n<div class=\"table-wrapper\" [ngClass]=\"size()\">\n <table cdk-table [dataSource]=\"dataSource()\">\n <!-- Dynamic Columns -->\n @for (column of displayedCol; track $index) {\n <ng-container [cdkColumnDef]=\"column.columnDef\">\n <th class=\"sticky-column\" cdk-header-cell *cdkHeaderCellDef>{{ column.header }}</th>\n <td cdk-cell *cdkCellDef=\"let element\">{{ column.cell(element) }}</td>\n </ng-container>\n }\n\n <!-- Actions Column (Not in displayedColumns) -->\n <ng-container cdkColumnDef=\"actions\">\n <th class=\"actions-header sticky-column\" cdk-header-cell *cdkHeaderCellDef></th>\n <td class=\"actions-row sticky\" cdk-cell *cdkCellDef=\"let element\">\n <!-- Only show the button in the last (empty) row -->\n @if (!readonly()) {\n <button\n mat-icon-button\n class=\"table-options-menu-bar-item\"\n cdkMenuItem\n (cdkMenuOpened)=\"onMenuTriggert(element)\"\n (cdkMenuClosed)=\"onMenuTriggert(null)\"\n [cdkMenuTriggerFor]=\"options\"\n [cdkMenuTriggerData]=\"{ element: element }\"\n >\n <mat-icon>more_vert</mat-icon>\n </button>\n }\n </td>\n </ng-container>\n\n <tr cdk-header-row *cdkHeaderRowDef=\"displayedColActions\"></tr>\n @if (!readonly()) {\n <tr (dblclick)=\"editRow(row)\" [class.selected-row]=\"row === selectedRow()\" cdk-row *cdkRowDef=\"let row; columns: displayedColActions\"></tr>\n } @else {\n <tr cdk-row *cdkRowDef=\"let row; columns: displayedColActions\"></tr>\n }\n </table>\n</div>\n<ng-template #options let-element=\"element\">\n <div class=\"table-options-menu\" cdkMenu>\n <button class=\"table-options-menu-item\" (click)=\"copyLine(element)\" cdkMenuItem>{{ 'yuv.form.element.data.grid.copy' | translate }}</button>\n <button class=\"table-options-menu-item\" cdkMenuItem (click)=\"editRow(element)\">{{ 'yuv.form.element.data.grid.edit' | translate }}</button>\n <button class=\"table-options-menu-item\" cdkMenuItem (click)=\"removeRow(element)\">{{ 'yuv.form.element.data.grid.remove' | translate }}</button>\n </div>\n</ng-template>\n", styles: [":root{--table-size-small: 200px;--table-size-medium: 400px;--table-size-large: 600px;--table-size-extra-large: 800px}:host{border:1px solid var(--ymt-outline-variant)}:host header{display:flex;justify-content:space-between;background-color:var(--ymt-surface-panel-grey)}:host header h3{text-align:start;-webkit-user-select:none;user-select:none;flex:0 1 auto;padding:1rem;margin:0;color:var(--ymt-text-color-subtle);border-radius:2px;font:var(--ymt-font-body-subtle);font-weight:400}:host.yuv-data-grid{display:block}:host.yuv-data-grid .table-wrapper{overflow:auto;position:relative;white-space:nowrap}:host.yuv-data-grid .table-wrapper.small{height:var(--table-size-small)}:host.yuv-data-grid .table-wrapper.medium{height:var(--table-size-medium)}:host.yuv-data-grid .table-wrapper.large{height:var(--table-size-large)}:host.yuv-data-grid .table-wrapper.extra-large{height:var(--table-size-extra-large)}:host.yuv-data-grid ::ng-deep .cdk-header-cell:not(:last-child){padding:.5rem 1rem}:host.yuv-data-grid ::ng-deep table{border-spacing:0}:host.yuv-data-grid ::ng-deep th{border-bottom:1px solid var(--ymt-outline-variant);border-right:1px solid var(--ymt-outline-variant);padding:.5rem 0}:host.yuv-data-grid ::ng-deep thead{background-color:var(--ymt-surface-panel)}:host.yuv-data-grid ::ng-deep tr.cdk-row{cursor:pointer;-webkit-user-select:none;user-select:none;transition:color .2s ease-in-out}:host.yuv-data-grid ::ng-deep tr.cdk-row:hover td{border-top:1px solid var(--ymt-surface-panel);border-bottom:1px solid var(--ymt-surface-panel)}:host.yuv-data-grid ::ng-deep tr.cdk-row:hover:has(.actions-row) td.cdk-cell.actions-row.sticky{opacity:1}:host.yuv-data-grid ::ng-deep tr.cdk-row.selected-row{color:var(--ymt-text-color-subtle)}:host.yuv-data-grid ::ng-deep tr.cdk-row td{border-bottom:1px solid transparent;border-top:1px solid transparent}:host.yuv-data-grid ::ng-deep tr.cdk-row td:not(:last-child){padding:.5rem 1rem}:host.yuv-data-grid ::ng-deep .cdk-table .cdk-header-row th[role=columnheader]{font-weight:500}:host.yuv-data-grid th.cdk-header-cell.sticky-column{position:sticky;top:0;background-color:var(--ymt-surface-panel)}:host.yuv-data-grid td.cdk-cell.actions-row.sticky{position:sticky;right:0;opacity:0;background-color:var(--ymt-surface-panel);transition:opacity .2s ease-in-out}:host .table-options-menu-bar-item,:host .table-options-add-row{cursor:pointer;border:none;-webkit-user-select:none;user-select:none;min-width:34px;line-height:26px;padding:0;display:flex;align-items:center;justify-content:center}.table-options-menu{display:inline-flex;flex-direction:column;max-width:280px;background-color:var(--ymt-surface-panel);border:1px solid var(--ymt-outline-variant);padding:var(--ymt-spacing-3xs) 0}.table-options-menu .table-options-menu-item{background-color:transparent;cursor:pointer;border:none;border-radius:0;-webkit-user-select:none;user-select:none;display:flex;align-items:center;flex-direction:row;flex:1}.table-options-menu .table-options-menu-item:not(:last-child){border-block-end:1px solid var(--ymt-outline-variant)}.table-options-menu .table-options-menu-item>span{display:flex;flex-direction:row;flex:1;justify-content:flex-end}\n"] }]
909
299
  }] });
910
300
 
911
- class DatetimeComponent {
301
+ class DatetimeComponent extends AbstractMatFormField {
912
302
  constructor() {
303
+ super(...arguments);
913
304
  this.translate = inject(TranslateService$1);
914
- this.value = null;
915
- this.locale = this.translate.currentLang;
305
+ this.pickerCmp = viewChild.required(DatepickerComponent);
306
+ this.ngControl = injectNgControl(this);
307
+ this._locale = signal(this.translate.currentLang);
308
+ this.locale = input(this.translate.currentLang);
309
+ this.#localeEffect = effect(() => {
310
+ this._locale.set(this.locale() || this.translate.currentLang);
311
+ });
916
312
  /**
917
313
  * Whether or not to allow only values in the future (default: false)
918
314
  */
919
- this.onlyFutureDates = false;
315
+ this.onlyFutureDates = input(false);
920
316
  /**
921
317
  * Will prevent the input from being changed (default: false)
922
318
  */
923
- this.readonly = false;
319
+ this.readonly = input(false);
320
+ /**
321
+ * Whether to show the calendar icon that opens the date picker calendar (default: true)
322
+ */
323
+ this.calendar = input(true);
924
324
  /**
925
325
  * Enables setting time as well (default: false)
926
326
  */
927
- this.withTime = false;
327
+ this.withTime = input(false);
928
328
  // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function
929
329
  this.propagateChange = (fn) => { };
930
330
  // eslint-disable-next-line @typescript-eslint/no-empty-function
931
331
  this.validationChange = () => { };
932
- this._setLabels();
933
- this.translate.onLangChange.subscribe((e) => (this.locale = e.lang));
934
332
  }
935
- _setLabels() {
333
+ #localeEffect;
334
+ #setLabels() {
936
335
  this.labels = {
937
336
  calendarApply: this.translate.instant('yuv.form.element.datetime.calendar.select'),
938
337
  calendarCancel: this.translate.instant('yuv.form.element.datetime.calendar.cancel'),
939
338
  shortcut: { today: this.translate.instant('yuv.form.element.datetime.calendar.today') }
940
339
  };
941
340
  }
341
+ openCalendar() {
342
+ this.pickerCmp().openCalendar();
343
+ }
942
344
  writeValue(value) {
943
345
  if (typeof value === 'string') {
944
346
  value = new Date(value);
@@ -955,37 +357,25 @@ class DatetimeComponent {
955
357
  // eslint-disable-next-line @typescript-eslint/no-empty-function
956
358
  registerOnTouched() { }
957
359
  onValueChange(e) {
958
- this.propagateChange(this.withTime ? e : e.toISOString().split('T')[0]);
360
+ this.propagateChange(this.withTime() ? e : e.toISOString().split('T')[0]);
959
361
  }
960
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DatetimeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
961
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: DatetimeComponent, isStandalone: true, selector: "yuv-datetime", inputs: { onlyFutureDates: "onlyFutureDates", readonly: "readonly", withTime: "withTime" }, providers: [
962
- {
963
- provide: NG_VALUE_ACCESSOR,
964
- useExisting: forwardRef(() => DatetimeComponent),
965
- multi: true
966
- }
967
- ], ngImport: i0, template: "<yvc-datepicker #picker [calendar]=\"true\" [disabled]=\"readonly\" [locale]=\"locale\" [withTime]=\"withTime\" [labels]=\"labels!\"\n [onlyFutureDates]=\"onlyFutureDates\"\n [ngModelOptions]=\"{standalone: true}\" [(ngModel)]=\"value\"\n (ngModelChange)=\"onValueChange($event)\"></yvc-datepicker>", styles: [":host{display:flex}:host yvc-datepicker{flex:1}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: YvcDatepickerModule }, { kind: "component", type: i2$2.Datepicker, selector: "yvc-datepicker", inputs: ["calendar", "readonly", "hour12", "locale", "labels", "withTime", "onlyFutureDates", "minDate", "maxDate", "disabled"] }] }); }
362
+ ngOnInit() {
363
+ this.focusHandled.set(true);
364
+ this.#setLabels();
365
+ this.translate.onLangChange.subscribe((e) => this._locale.set(e.lang));
366
+ }
367
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: DatetimeComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
368
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "19.2.1", type: DatetimeComponent, isStandalone: true, selector: "yuv-datetime", inputs: { locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, onlyFutureDates: { classPropertyName: "onlyFutureDates", publicName: "onlyFutureDates", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, calendar: { classPropertyName: "calendar", publicName: "calendar", isSignal: true, isRequired: false, transformFunction: null }, withTime: { classPropertyName: "withTime", publicName: "withTime", isSignal: true, isRequired: false, transformFunction: null } }, providers: [{ provide: MatFormFieldControl, useExisting: DatetimeComponent }], viewQueries: [{ propertyName: "pickerCmp", first: true, predicate: DatepickerComponent, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<yuv-datepicker\n [calendar]=\"calendar()\"\n [disabled]=\"readonly()\"\n [withTime]=\"withTime()\"\n [locale]=\"_locale()\"\n [labels]=\"labels!\"\n [onlyFutureDates]=\"onlyFutureDates()\"\n [ngModelOptions]=\"{ standalone: true }\"\n [(ngModel)]=\"value\"\n (ngModelChange)=\"onValueChange($event)\"\n></yuv-datepicker>\n", styles: [":host{display:flex;overflow-x:auto;--ymt-scrollbar-outer-size: 0px;--ymt-scrollbar-inner-size: 0px}:host yuv-datepicker{flex:1}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: YuvDatepickerModule }, { kind: "component", type: i2$2.DatepickerComponent, selector: "yuv-datepicker", inputs: ["calendar", "readonly", "hour12", "locale", "labels", "withTime", "onlyFutureDates", "minDate", "maxDate", "disabled"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "ngmodule", type: MatDatepickerModule }] }); }
968
369
  }
969
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DatetimeComponent, decorators: [{
370
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: DatetimeComponent, decorators: [{
970
371
  type: Component,
971
- args: [{ selector: 'yuv-datetime', standalone: true, imports: [FormsModule, YvcDatepickerModule, DatetimeComponent], providers: [
972
- {
973
- provide: NG_VALUE_ACCESSOR,
974
- useExisting: forwardRef(() => DatetimeComponent),
975
- multi: true
976
- }
977
- ], template: "<yvc-datepicker #picker [calendar]=\"true\" [disabled]=\"readonly\" [locale]=\"locale\" [withTime]=\"withTime\" [labels]=\"labels!\"\n [onlyFutureDates]=\"onlyFutureDates\"\n [ngModelOptions]=\"{standalone: true}\" [(ngModel)]=\"value\"\n (ngModelChange)=\"onValueChange($event)\"></yvc-datepicker>", styles: [":host{display:flex}:host yvc-datepicker{flex:1}\n"] }]
978
- }], ctorParameters: () => [], propDecorators: { onlyFutureDates: [{
979
- type: Input
980
- }], readonly: [{
981
- type: Input
982
- }], withTime: [{
983
- type: Input
984
- }] } });
372
+ args: [{ selector: 'yuv-datetime', standalone: true, imports: [FormsModule, YuvDatepickerModule, MatInputModule, MatDatepickerModule], providers: [{ provide: MatFormFieldControl, useExisting: DatetimeComponent }], template: "<yuv-datepicker\n [calendar]=\"calendar()\"\n [disabled]=\"readonly()\"\n [withTime]=\"withTime()\"\n [locale]=\"_locale()\"\n [labels]=\"labels!\"\n [onlyFutureDates]=\"onlyFutureDates()\"\n [ngModelOptions]=\"{ standalone: true }\"\n [(ngModel)]=\"value\"\n (ngModelChange)=\"onValueChange($event)\"\n></yuv-datepicker>\n", styles: [":host{display:flex;overflow-x:auto;--ymt-scrollbar-outer-size: 0px;--ymt-scrollbar-inner-size: 0px}:host yuv-datepicker{flex:1}\n"] }]
373
+ }] });
985
374
 
986
- class DatetimeRangeComponent {
375
+ class DatetimeRangeComponent extends AbstractMatFormField {
987
376
  constructor() {
988
- this.fb = inject(FormBuilder);
377
+ super(...arguments);
378
+ this.#dRef = inject(DestroyRef);
989
379
  /**
990
380
  * Enables setting time as well (default: false)
991
381
  */
@@ -995,11 +385,8 @@ class DatetimeRangeComponent {
995
385
  */
996
386
  this.readonly = false;
997
387
  this.operator = 'eq';
998
- this.rangeForm = this.fb.group({
999
- dateValue: [undefined, Validators.required],
1000
- dateValueFrom: []
1001
- });
1002
388
  this._isValid = true;
389
+ this.ngControl = injectNgControl(this);
1003
390
  // options for search situation
1004
391
  this.availableSearchOptions = [
1005
392
  { label: OperatorLabel.EQUAL, value: Operator.EQUAL },
@@ -1007,24 +394,30 @@ class DatetimeRangeComponent {
1007
394
  { label: OperatorLabel.LESS_OR_EQUAL, value: Operator.LESS_OR_EQUAL },
1008
395
  { label: OperatorLabel.INTERVAL_INCLUDE_BOTH, value: Operator.INTERVAL_INCLUDE_BOTH }
1009
396
  ];
1010
- // the selected search option
1011
- this.searchOption = this.availableSearchOptions[1].value;
397
+ this.rangeForm = new FormGroup({
398
+ dateValue: new FormControl(undefined, { nonNullable: true, validators: [Validators.required] }),
399
+ operator: new FormControl(this.availableSearchOptions[1].value, { nonNullable: true }),
400
+ dateValueFrom: new FormControl(undefined, { nonNullable: true })
401
+ });
1012
402
  // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function
1013
403
  this.propagateChange = (_) => { };
1014
404
  }
405
+ #dRef;
1015
406
  writeValue(value) {
1016
407
  if (value && (value.firstValue || value.secondValue)) {
1017
408
  const match = this.availableSearchOptions.find((o) => o.value === value.operator);
1018
- this.searchOption = match ? match.value : this.availableSearchOptions[0].value;
1019
409
  this.value = value;
1020
410
  this.rangeForm.patchValue({
1021
411
  dateValueFrom: value.secondValue && value.firstValue,
412
+ operator: match ? match.value : this.availableSearchOptions[0].value,
1022
413
  dateValue: value.secondValue || value.firstValue
1023
414
  });
1024
415
  }
1025
416
  else {
1026
- this.searchOption = this.availableSearchOptions[0].value;
1027
- this.value = undefined;
417
+ this.rangeForm.patchValue({
418
+ operator: this.availableSearchOptions[0].value
419
+ });
420
+ this.value = null;
1028
421
  this.rangeForm.reset();
1029
422
  }
1030
423
  }
@@ -1033,21 +426,17 @@ class DatetimeRangeComponent {
1033
426
  }
1034
427
  // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function
1035
428
  registerOnTouched(fn) { }
1036
- onValueChange() {
429
+ #onValueChange() {
1037
430
  const dateValue = this.rangeForm.value.dateValue || undefined;
1038
- if (this.searchOption === Operator.INTERVAL_INCLUDE_BOTH) {
431
+ const operator = this.rangeForm.value.operator;
432
+ if (operator === Operator.INTERVAL_INCLUDE_BOTH) {
1039
433
  const dateValueFrom = this.rangeForm.value.dateValueFrom || undefined;
1040
434
  if (dateValueFrom || dateValue) {
1041
435
  this._isValid = this.rangeForm.valid && !!dateValueFrom && !!dateValue;
1042
436
  this.value = !this._isValid
1043
- ? // {
1044
- // operator: this.searchOption,
1045
- // firstValue: undefined,
1046
- // secondValue: undefined
1047
- // }
1048
- undefined
437
+ ? null
1049
438
  : {
1050
- operator: this.searchOption,
439
+ operator,
1051
440
  firstValue: dateValueFrom,
1052
441
  secondValue: dateValue
1053
442
  };
@@ -1056,80 +445,67 @@ class DatetimeRangeComponent {
1056
445
  else {
1057
446
  this._isValid = this.rangeForm.valid;
1058
447
  this.value = !this._isValid
1059
- ? // {
1060
- // operator: this.searchOption,
1061
- // firstValue: undefined,
1062
- // secondValue: undefined
1063
- // }
1064
- undefined
448
+ ? null
1065
449
  : {
1066
- operator: this.searchOption,
450
+ operator,
1067
451
  firstValue: dateValue,
1068
452
  secondValue: undefined
1069
453
  };
1070
454
  }
1071
455
  this.propagateChange(this.value);
1072
456
  }
1073
- validate() {
1074
- let err;
1075
- if (this.searchOption === Operator.EQUAL) {
1076
- err = {
1077
- datecontrol: {
1078
- valid: false
1079
- }
1080
- };
1081
- }
1082
- else {
1083
- // make sure that on ranges, the first value is earlier than the last
1084
- if (this.searchOption === Operator.INTERVAL_INCLUDE_BOTH && this.value && this.value.firstValue && this.value.secondValue) {
1085
- this._isValid = new Date(this.value.firstValue).getTime() < new Date(this.value.secondValue).getTime();
457
+ #getValidator() {
458
+ return (control) => {
459
+ let err;
460
+ const operator = control.value.operator;
461
+ if (operator === Operator.EQUAL) {
1086
462
  err = {
1087
- daterangeorder: {
463
+ datecontrol: {
1088
464
  valid: false
1089
465
  }
1090
466
  };
1091
467
  }
1092
468
  else {
1093
- err = {
1094
- daterange: {
1095
- valid: false
1096
- }
1097
- };
469
+ // make sure that on ranges, the first value is earlier than the last
470
+ if (operator === Operator.INTERVAL_INCLUDE_BOTH && control.value && control.value.firstValue && control.value.secondValue) {
471
+ this._isValid = new Date(control.value.firstValue).getTime() < new Date(control.value.secondValue).getTime();
472
+ err = {
473
+ daterangeorder: {
474
+ valid: false
475
+ }
476
+ };
477
+ }
478
+ else {
479
+ err = {
480
+ daterange: {
481
+ valid: false
482
+ }
483
+ };
484
+ }
1098
485
  }
1099
- }
1100
- return this.situation === Situation.SEARCH || this._isValid ? null : err;
486
+ return this.situation === Situation.SEARCH || this._isValid ? null : err;
487
+ };
1101
488
  }
1102
489
  ngOnInit() {
1103
- this.rangeForm.valueChanges.subscribe(() => this.onValueChange());
1104
- }
1105
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DatetimeRangeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1106
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: DatetimeRangeComponent, isStandalone: true, selector: "yuv-datetime-range", inputs: { withTime: "withTime", readonly: "readonly", operator: "operator", situation: "situation" }, providers: [
1107
- {
1108
- provide: NG_VALUE_ACCESSOR,
1109
- useExisting: forwardRef(() => DatetimeRangeComponent),
1110
- multi: true
1111
- },
1112
- {
1113
- provide: NG_VALIDATORS,
1114
- useExisting: forwardRef(() => DatetimeRangeComponent),
1115
- multi: true
490
+ this.rangeForm.setValidators(this.#getValidator());
491
+ this.rangeForm.statusChanges.pipe(takeUntilDestroyed(this.#dRef)).subscribe((v) => {
492
+ this.errorState = this.situation === Situation.SEARCH || this._isValid;
493
+ if (this.ngControl?.control) {
494
+ this.ngControl.control.setErrors(this.rangeForm.errors);
1116
495
  }
1117
- ], ngImport: i0, template: "<form class=\"eo-datetime-range\" [formGroup]=\"rangeForm\">\n @if (searchOption === 'gtelte') {\n <yuv-datetime [withTime]=\"withTime\" formControlName=\"dateValueFrom\"></yuv-datetime>\n }\n <yvc-dropdown\n [disableClearButton]=\"true\"\n [(ngModel)]=\"searchOption\"\n (ngModelChange)=\"onValueChange()\"\n [ngModelOptions]=\"{ standalone: true }\"\n [options]=\"availableSearchOptions\"\n ></yvc-dropdown>\n\n <yuv-datetime [withTime]=\"withTime\" formControlName=\"dateValue\"></yuv-datetime>\n</form>\n", styles: [":host form{display:flex;flex-flow:row nowrap;gap:3px}:host form yuv-datetime{flex:1 1 auto}:host form yvc-dropdown{--yvc-form-element-border-color: var(--text-color-hint);--yvc-form-element-focus-border-color: var(--color-accent);padding:0;min-width:auto;border-radius:2px;background-color:var(--list-item-hover-background)}:host form yvc-dropdown:hover{background-color:var(--list-item-selected-background)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: YvcDropdownModule }, { kind: "component", type: i1$1.Dropdown, selector: "yvc-dropdown", inputs: ["options", "filter", "disabled", "multiple", "disableClearButton"], outputs: ["onDropdownOptionsClose"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: DatetimeComponent, selector: "yuv-datetime", inputs: ["onlyFutureDates", "readonly", "withTime"] }] }); }
496
+ });
497
+ this.rangeForm.updateValueAndValidity();
498
+ this.rangeForm.valueChanges.subscribe(() => this.#onValueChange());
499
+ }
500
+ ngOnDestroy() {
501
+ super.onNgOnDestroy();
502
+ }
503
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: DatetimeRangeComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
504
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.1", type: DatetimeRangeComponent, isStandalone: true, selector: "yuv-datetime-range", inputs: { withTime: "withTime", readonly: "readonly", operator: "operator", situation: "situation" }, providers: [{ provide: MatFormFieldControl, useExisting: DatetimeRangeComponent }], usesInheritance: true, ngImport: i0, template: "<form class=\"eo-datetime-range\" [formGroup]=\"rangeForm\">\n @if (rangeForm.value.operator === 'gtelte') {\n <yuv-datetime [withTime]=\"withTime\" formControlName=\"dateValueFrom\"></yuv-datetime>\n }\n\n <mat-select [panelWidth]=\"null\" [hideSingleSelectionIndicator]=\"true\" formControlName=\"operator\" [disabled]=\"readonly\">\n @for (o of availableSearchOptions; track $index) {\n <mat-option [value]=\"o.value\">{{ o.label }}</mat-option>\n }\n </mat-select>\n\n <yuv-datetime [withTime]=\"withTime\" formControlName=\"dateValue\"></yuv-datetime>\n</form>\n", styles: [":host form{display:inline-flex;flex-flow:row nowrap;gap:3px}:host form yuv-datetime{flex:1 1 auto}:host form mat-select{padding:0;width:calc(2ch + 1em);border-radius:2px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i1$2.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i1$2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: DatetimeComponent, selector: "yuv-datetime", inputs: ["locale", "onlyFutureDates", "readonly", "calendar", "withTime"] }] }); }
1118
505
  }
1119
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DatetimeRangeComponent, decorators: [{
506
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: DatetimeRangeComponent, decorators: [{
1120
507
  type: Component,
1121
- args: [{ selector: 'yuv-datetime-range', standalone: true, imports: [CommonModule, FormsModule, YvcDropdownModule, ReactiveFormsModule, DatetimeComponent], providers: [
1122
- {
1123
- provide: NG_VALUE_ACCESSOR,
1124
- useExisting: forwardRef(() => DatetimeRangeComponent),
1125
- multi: true
1126
- },
1127
- {
1128
- provide: NG_VALIDATORS,
1129
- useExisting: forwardRef(() => DatetimeRangeComponent),
1130
- multi: true
1131
- }
1132
- ], template: "<form class=\"eo-datetime-range\" [formGroup]=\"rangeForm\">\n @if (searchOption === 'gtelte') {\n <yuv-datetime [withTime]=\"withTime\" formControlName=\"dateValueFrom\"></yuv-datetime>\n }\n <yvc-dropdown\n [disableClearButton]=\"true\"\n [(ngModel)]=\"searchOption\"\n (ngModelChange)=\"onValueChange()\"\n [ngModelOptions]=\"{ standalone: true }\"\n [options]=\"availableSearchOptions\"\n ></yvc-dropdown>\n\n <yuv-datetime [withTime]=\"withTime\" formControlName=\"dateValue\"></yuv-datetime>\n</form>\n", styles: [":host form{display:flex;flex-flow:row nowrap;gap:3px}:host form yuv-datetime{flex:1 1 auto}:host form yvc-dropdown{--yvc-form-element-border-color: var(--text-color-hint);--yvc-form-element-focus-border-color: var(--color-accent);padding:0;min-width:auto;border-radius:2px;background-color:var(--list-item-hover-background)}:host form yvc-dropdown:hover{background-color:var(--list-item-selected-background)}\n"] }]
508
+ args: [{ selector: 'yuv-datetime-range', standalone: true, imports: [CommonModule, FormsModule, MatDatepickerModule, MatSelectModule, ReactiveFormsModule, DatetimeComponent], providers: [{ provide: MatFormFieldControl, useExisting: DatetimeRangeComponent }], template: "<form class=\"eo-datetime-range\" [formGroup]=\"rangeForm\">\n @if (rangeForm.value.operator === 'gtelte') {\n <yuv-datetime [withTime]=\"withTime\" formControlName=\"dateValueFrom\"></yuv-datetime>\n }\n\n <mat-select [panelWidth]=\"null\" [hideSingleSelectionIndicator]=\"true\" formControlName=\"operator\" [disabled]=\"readonly\">\n @for (o of availableSearchOptions; track $index) {\n <mat-option [value]=\"o.value\">{{ o.label }}</mat-option>\n }\n </mat-select>\n\n <yuv-datetime [withTime]=\"withTime\" formControlName=\"dateValue\"></yuv-datetime>\n</form>\n", styles: [":host form{display:inline-flex;flex-flow:row nowrap;gap:3px}:host form yuv-datetime{flex:1 1 auto}:host form mat-select{padding:0;width:calc(2ch + 1em);border-radius:2px}\n"] }]
1133
509
  }], propDecorators: { withTime: [{
1134
510
  type: Input
1135
511
  }], readonly: [{
@@ -1140,6 +516,183 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
1140
516
  type: Input
1141
517
  }] } });
1142
518
 
519
+ var _a;
520
+ /**
521
+ * Creates form input for number values.
522
+ *
523
+ * Implements `ControlValueAccessor` so it can be used within Angular forms.
524
+ *
525
+ * @example
526
+ * <yuv-number [scale]="2"></yuv-number>
527
+ *
528
+ */
529
+ class NumberComponent extends AbstractMatFormField {
530
+ constructor() {
531
+ super(...arguments);
532
+ this.#dRef = inject(DestroyRef);
533
+ this.translate = inject(TranslateService);
534
+ // innerValue: string | null = null;
535
+ this.validationErrors = [];
536
+ this.transformPipe = new LocaleNumberPipe(this.translate);
537
+ this.innerCtrl = new FormControl(null);
538
+ this.ngControl = injectNgControl(this);
539
+ /**
540
+ * Number of decimal places
541
+ */
542
+ this.scale = input(undefined);
543
+ this.#scale = computed(() => Math.min(this.scale() || 0, 30));
544
+ /**
545
+ * Overall amount of digits allowed (including decimal places)
546
+ */
547
+ this.precision = input(undefined);
548
+ this.#precision = computed(() => Math.min(this.precision() || 100, 100));
549
+ /**
550
+ * Set to true to group number by pattern
551
+ */
552
+ this.grouping = input(false);
553
+ this.#grouping = computed(() => this.grouping() ?? true);
554
+ /**
555
+ * The pattern to group number value by
556
+ */
557
+ this.groupPattern = input(undefined);
558
+ /**
559
+ * Will prevent the input from being changed (default: false)
560
+ */
561
+ this.readonly = input(false);
562
+ /**
563
+ * set minimum input value
564
+ */
565
+ this.minValue = input(undefined);
566
+ /**
567
+ * set maximum input value
568
+ *
569
+ */
570
+ this.maxValue = input(undefined);
571
+ /**
572
+ * classification property adds some semantics to the value of this component.
573
+ * If you provide a value of `filesize` numbers typed into the control will be
574
+ * handled like file sizes (calculates differnt units)
575
+ */
576
+ this.classifications = input([]);
577
+ this.#classificationsEffect = effect(() => {
578
+ const classifications = this.classifications();
579
+ this.transformPipe =
580
+ classifications && classifications.includes(Classification.NUMBER_FILESIZE) ? new FileSizePipe(this.translate) : new LocaleNumberPipe(this.translate);
581
+ });
582
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function
583
+ this.propagateChange = (_) => { };
584
+ }
585
+ #dRef;
586
+ #scale;
587
+ #precision;
588
+ #grouping;
589
+ #classificationsEffect;
590
+ static betweenTwoNumbers(val, minVal, maxVal) {
591
+ const min = !Utils.isEmpty(minVal) ? minVal : -Infinity;
592
+ const max = !Utils.isEmpty(maxVal) ? maxVal : Infinity;
593
+ return val >= min && val <= max;
594
+ }
595
+ writeValue(value) {
596
+ this.value = value != null ? value : null;
597
+ const innerValue = value != null ? this.transformPipe.numberToString(value, this.#grouping(), this.groupPattern(), this.#scale()) : null;
598
+ this.innerCtrl.setValue(innerValue, { emitEvent: false });
599
+ }
600
+ registerOnChange(fn) {
601
+ this.propagateChange = fn;
602
+ }
603
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
604
+ registerOnTouched() { }
605
+ // called when the input looses focus
606
+ format() {
607
+ if (!this.readonly() && typeof this.value === 'number' && this.validationErrors.length === 0) {
608
+ this.innerCtrl.patchValue(this.transformPipe.numberToString(this.value, this.#grouping(), this.groupPattern(), this.#scale()), { emitEvent: false });
609
+ }
610
+ }
611
+ // called when the input get focus
612
+ unformat() {
613
+ if (!this.readonly() && typeof this.value === 'number' && this.validationErrors.length === 0) {
614
+ this.innerCtrl.patchValue(this.transformPipe.transform(this.value, false), {
615
+ emitEvent: false
616
+ });
617
+ }
618
+ }
619
+ #getValidator() {
620
+ return (control) => {
621
+ this.validationErrors = [];
622
+ if (Utils.isEmpty(control.value))
623
+ return null;
624
+ const val = this.transformPipe.stringToNumber(control.value);
625
+ // general number validation
626
+ if (isNaN(val) || typeof val !== 'number') {
627
+ this.validationErrors.push({ key: 'number' });
628
+ }
629
+ else {
630
+ const split = control.value.replaceAll(this.transformPipe.separator, '').split(this.transformPipe.decimalSeparator);
631
+ // check precision
632
+ if (this.#precision() !== undefined) {
633
+ const prePointDigits = this.#precision() - this.#scale();
634
+ if (split[0]?.length > prePointDigits) {
635
+ this.validationErrors.push({ key: 'precision', params: { prePointDigits } });
636
+ }
637
+ }
638
+ // check scale
639
+ if (this.#scale() && split[1]?.length > this.#scale()) {
640
+ this.validationErrors.push({ key: 'scale', params: { scale: this.#scale() } });
641
+ }
642
+ // min max
643
+ if (!_a.betweenTwoNumbers(val, this.minValue(), this.maxValue())) {
644
+ if (Utils.isEmpty(this.minValue())) {
645
+ this.validationErrors.push({ key: 'maxvalue', params: { maxValue: this.maxValue() } });
646
+ }
647
+ else if (Utils.isEmpty(this.maxValue())) {
648
+ this.validationErrors.push({ key: 'minvalue', params: { minValue: this.minValue() } });
649
+ }
650
+ else {
651
+ this.validationErrors.push({ key: 'minmax', params: { minValue: this.minValue(), maxValue: this.maxValue() } });
652
+ }
653
+ }
654
+ }
655
+ const e = Utils.arrayToObject(this.validationErrors, 'key', (err) => ({ valid: false, ...err }));
656
+ return this.validationErrors.length ? e : null;
657
+ };
658
+ }
659
+ ngOnInit() {
660
+ // set up validators once all inputs are set
661
+ this.innerCtrl.setValidators(this.#getValidator());
662
+ this.innerCtrl.statusChanges.pipe(takeUntilDestroyed(this.#dRef)).subscribe((v) => {
663
+ this.errorState = this.innerCtrl.invalid;
664
+ if (this.ngControl?.control) {
665
+ this.ngControl.control.setErrors(this.innerCtrl.errors);
666
+ }
667
+ });
668
+ this.innerCtrl.updateValueAndValidity();
669
+ this.innerCtrl.valueChanges.pipe(takeUntilDestroyed(this.#dRef)).subscribe((v) => {
670
+ if (Utils.isEmpty(v)) {
671
+ this.value = null;
672
+ this.propagateChange(this.value);
673
+ }
674
+ else {
675
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
676
+ const val = this.transformPipe.stringToNumber(v);
677
+ if (this.validationErrors.length === 0 && this.value !== val) {
678
+ this.value = val;
679
+ this.propagateChange(this.value);
680
+ }
681
+ }
682
+ });
683
+ }
684
+ ngOnDestroy() {
685
+ super.onNgOnDestroy();
686
+ }
687
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: NumberComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
688
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.1", type: NumberComponent, isStandalone: true, selector: "yuv-number", inputs: { scale: { classPropertyName: "scale", publicName: "scale", isSignal: true, isRequired: false, transformFunction: null }, precision: { classPropertyName: "precision", publicName: "precision", isSignal: true, isRequired: false, transformFunction: null }, grouping: { classPropertyName: "grouping", publicName: "grouping", isSignal: true, isRequired: false, transformFunction: null }, groupPattern: { classPropertyName: "groupPattern", publicName: "groupPattern", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, minValue: { classPropertyName: "minValue", publicName: "minValue", isSignal: true, isRequired: false, transformFunction: null }, maxValue: { classPropertyName: "maxValue", publicName: "maxValue", isSignal: true, isRequired: false, transformFunction: null }, classifications: { classPropertyName: "classifications", publicName: "classifications", isSignal: true, isRequired: false, transformFunction: null } }, providers: [{ provide: MatFormFieldControl, useExisting: NumberComponent }], usesInheritance: true, ngImport: i0, template: '<input type="string" [formControl]="innerCtrl" (focus)="unformat()" (blur)="format()" [readonly]="readonly()" />', isInline: true, styles: [":host{display:flex}:host input{width:100%;border:0;outline:0;background:transparent}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }] }); }
689
+ }
690
+ _a = NumberComponent;
691
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: NumberComponent, decorators: [{
692
+ type: Component,
693
+ args: [{ selector: 'yuv-number', standalone: true, imports: [ReactiveFormsModule], template: '<input type="string" [formControl]="innerCtrl" (focus)="unformat()" (blur)="format()" [readonly]="readonly()" />', providers: [{ provide: MatFormFieldControl, useExisting: NumberComponent }], styles: [":host{display:flex}:host input{width:100%;border:0;outline:0;background:transparent}\n"] }]
694
+ }] });
695
+
1143
696
  /**
1144
697
  * Creates form input for ranges of numeric values.
1145
698
  *
@@ -1149,8 +702,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
1149
702
  * <yuv-number-range [scale]="2"></yuv-number-range>
1150
703
  *
1151
704
  */
1152
- class NumberRangeComponent {
705
+ class NumberRangeComponent extends AbstractMatFormField {
1153
706
  constructor() {
707
+ super(...arguments);
708
+ this.#dRef = inject(DestroyRef);
1154
709
  /**
1155
710
  * Set to true to group number by pattern
1156
711
  */
@@ -1165,10 +720,6 @@ class NumberRangeComponent {
1165
720
  * handled like file sizes (calculates differnt units)
1166
721
  */
1167
722
  this.classifications = [];
1168
- this.rangeForm = new UntypedFormGroup({
1169
- numberValue: new UntypedFormControl(),
1170
- numberValueFrom: new UntypedFormControl()
1171
- });
1172
723
  this.isValid = true;
1173
724
  // options for search situation
1174
725
  this.availableSearchOptions = [
@@ -1177,35 +728,44 @@ class NumberRangeComponent {
1177
728
  { label: OperatorLabel.LESS_OR_EQUAL, value: Operator.LESS_OR_EQUAL },
1178
729
  { label: OperatorLabel.INTERVAL_INCLUDE_BOTH, value: Operator.INTERVAL_INCLUDE_BOTH }
1179
730
  ];
1180
- // the selected search option
1181
- this.searchOption = this.availableSearchOptions[1].value;
731
+ this.rangeForm = new FormGroup({
732
+ numberValue: new FormControl(undefined, { nonNullable: true, validators: [Validators.required] }),
733
+ operator: new FormControl(this.availableSearchOptions[1].value, { nonNullable: true }),
734
+ numberValueFrom: new FormControl(undefined, { nonNullable: true })
735
+ });
736
+ // constructor() {
737
+ // this.rangeForm.valueChanges.forEach(() => {
738
+ // this.#onValueChange();
739
+ // });
740
+ // }
1182
741
  // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function
1183
742
  this.propagateChange = (_) => { };
1184
- this.rangeForm.valueChanges.forEach(() => {
1185
- this.onValueChange();
1186
- });
1187
743
  }
744
+ #dRef;
1188
745
  writeValue(value) {
1189
746
  if (value && (value.firstValue != null || value.secondValue != null)) {
1190
747
  const match = this.availableSearchOptions.find((o) => o.value === value.operator);
1191
- this.searchOption = match ? match.value : this.availableSearchOptions[0].value;
1192
748
  this.value = value;
1193
- if (value.secondValue == null) {
749
+ if (value.secondValue == undefined) {
1194
750
  this.rangeForm.setValue({
1195
- numberValueFrom: null,
1196
- numberValue: value.firstValue != null ? value.firstValue : null
751
+ numberValueFrom: undefined,
752
+ operator: match ? match.value : this.availableSearchOptions[0].value,
753
+ numberValue: value.firstValue || undefined
1197
754
  });
1198
755
  }
1199
756
  else {
1200
757
  this.rangeForm.setValue({
1201
- numberValueFrom: value.firstValue != null ? value.firstValue : null,
758
+ numberValueFrom: value.firstValue || undefined,
759
+ operator: match ? match.value : this.availableSearchOptions[0].value,
1202
760
  numberValue: value.secondValue
1203
761
  });
1204
762
  }
1205
763
  }
1206
764
  else {
1207
- this.searchOption = this.availableSearchOptions[0].value;
1208
- this.value = undefined;
765
+ this.rangeForm.patchValue({
766
+ operator: this.availableSearchOptions[0].value
767
+ });
768
+ this.value = null;
1209
769
  this.rangeForm.reset();
1210
770
  }
1211
771
  }
@@ -1214,18 +774,19 @@ class NumberRangeComponent {
1214
774
  }
1215
775
  // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function
1216
776
  registerOnTouched(fn) { }
1217
- onValueChange() {
777
+ #onValueChange() {
1218
778
  this.isValid = this.rangeForm.valid;
1219
- if (this.searchOption === Operator.INTERVAL_INCLUDE_BOTH) {
779
+ const operator = this.rangeForm.value.operator;
780
+ if (operator === Operator.INTERVAL_INCLUDE_BOTH) {
1220
781
  this.isValid = this.rangeForm.valid && this.rangeForm.value.numberValueFrom != null && this.rangeForm.value.numberValue != null;
1221
782
  this.value = !this.isValid
1222
783
  ? {
1223
- operator: this.searchOption,
784
+ operator,
1224
785
  firstValue: undefined,
1225
786
  secondValue: undefined
1226
787
  }
1227
788
  : {
1228
- operator: this.searchOption,
789
+ operator,
1229
790
  firstValue: this.rangeForm.value.numberValueFrom,
1230
791
  secondValue: this.rangeForm.value.numberValue
1231
792
  };
@@ -1233,25 +794,44 @@ class NumberRangeComponent {
1233
794
  else {
1234
795
  this.value = !this.isValid
1235
796
  ? {
1236
- operator: this.searchOption,
797
+ operator,
1237
798
  firstValue: undefined,
1238
799
  secondValue: undefined
1239
800
  }
1240
801
  : {
1241
- operator: this.searchOption,
802
+ operator,
1242
803
  firstValue: this.rangeForm.value.numberValue,
1243
804
  secondValue: undefined
1244
805
  };
1245
806
  }
1246
807
  this.propagateChange(this.value);
1247
808
  }
809
+ #getValidator() {
810
+ return (control) => {
811
+ let err;
812
+ const operator = control.value.operator;
813
+ if (operator === Operator.EQUAL) {
814
+ err = { number: { valid: false } };
815
+ }
816
+ else if (operator === Operator.INTERVAL_INCLUDE_BOTH && this.value?.firstValue && this.value?.secondValue) {
817
+ // make sure that on ranges, the first value is earlier than the last
818
+ this.isValid = this.value.firstValue < this.value.secondValue;
819
+ err = { numberrangeorder: { valid: false } };
820
+ }
821
+ else {
822
+ err = { numberrange: { valid: false } };
823
+ }
824
+ return this.isValid ? null : err;
825
+ };
826
+ }
1248
827
  // returns null when valid else the validation object
1249
828
  validate() {
1250
829
  let err;
1251
- if (this.searchOption === Operator.EQUAL) {
830
+ const operator = this.rangeForm.value.operator;
831
+ if (operator === Operator.EQUAL) {
1252
832
  err = { number: { valid: false } };
1253
833
  }
1254
- else if (this.searchOption === Operator.INTERVAL_INCLUDE_BOTH && this.value?.firstValue && this.value?.secondValue) {
834
+ else if (operator === Operator.INTERVAL_INCLUDE_BOTH && this.value?.firstValue && this.value?.secondValue) {
1255
835
  // make sure that on ranges, the first value is earlier than the last
1256
836
  this.isValid = this.value.firstValue < this.value.secondValue;
1257
837
  err = { numberrangeorder: { valid: false } };
@@ -1261,35 +841,27 @@ class NumberRangeComponent {
1261
841
  }
1262
842
  return this.isValid ? null : err;
1263
843
  }
1264
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NumberRangeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1265
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: NumberRangeComponent, isStandalone: true, selector: "yuv-number-range", inputs: { scale: "scale", precision: "precision", grouping: "grouping", pattern: "pattern", readonly: "readonly", classifications: "classifications", minValue: "minValue", maxValue: "maxValue" }, providers: [
1266
- {
1267
- provide: NG_VALUE_ACCESSOR,
1268
- useExisting: forwardRef(() => NumberRangeComponent),
1269
- multi: true
1270
- },
1271
- {
1272
- provide: NG_VALIDATORS,
1273
- useExisting: forwardRef(() => NumberRangeComponent),
1274
- multi: true
844
+ ngOnInit() {
845
+ this.rangeForm.setValidators(this.#getValidator());
846
+ this.rangeForm.statusChanges.pipe(takeUntilDestroyed(this.#dRef)).subscribe((v) => {
847
+ this.errorState = this.rangeForm.invalid;
848
+ if (this.ngControl?.control) {
849
+ this.ngControl.control.setErrors(this.rangeForm.errors);
1275
850
  }
1276
- ], ngImport: i0, template: "<form class=\"yuv-number-range\" [formGroup]=\"rangeForm\">\n @if(searchOption === 'gtelte'){\n <yuv-number\n class=\"first\"\n [readonly]=\"readonly\"\n [scale]=\"scale\"\n [precision]=\"precision\"\n [grouping]=\"grouping\"\n [groupPattern]=\"pattern\"\n formControlName=\"numberValueFrom\"\n [classifications]=\"classifications\"\n [minValue]=\"minValue\"\n [maxValue]=\"maxValue\"\n ></yuv-number>}\n\n <yvc-dropdown\n class=\"no-trigger\"\n [(ngModel)]=\"searchOption\"\n (ngModelChange)=\"onValueChange()\"\n [disabled]=\"readonly\"\n [disableClearButton]=\"true\"\n [ngModelOptions]=\"{ standalone: true }\"\n [options]=\"availableSearchOptions\"\n ></yvc-dropdown>\n\n <yuv-number\n [scale]=\"scale\"\n [readonly]=\"readonly\"\n [precision]=\"precision\"\n [grouping]=\"grouping\"\n [groupPattern]=\"pattern\"\n formControlName=\"numberValue\"\n [classifications]=\"classifications\"\n [minValue]=\"minValue\"\n [maxValue]=\"maxValue\"\n >\n </yuv-number>\n</form>\n", styles: [":host>form{display:flex;flex-flow:row nowrap;gap:3px}:host>form yuv-number{flex:1 1 auto}:host>form yvc-dropdown{--yvc-form-element-border-color: var(--text-color-hint);--yvc-form-element-focus-border-color: var(--color-accent);padding:0;min-width:auto;border-radius:2px;background-color:var(--list-item-hover-background)}:host>form yvc-dropdown:hover{background-color:var(--list-item-selected-background)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: NumberComponent, selector: "yuv-number", inputs: ["scale", "precision", "grouping", "groupPattern", "readonly", "minValue", "maxValue", "classifications"] }, { kind: "ngmodule", type: YvcDropdownModule }, { kind: "component", type: i1$1.Dropdown, selector: "yvc-dropdown", inputs: ["options", "filter", "disabled", "multiple", "disableClearButton"], outputs: ["onDropdownOptionsClose"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }] }); }
851
+ });
852
+ this.rangeForm.updateValueAndValidity();
853
+ this.rangeForm.valueChanges.subscribe(() => this.#onValueChange());
854
+ }
855
+ ngOnDestroy() {
856
+ super.onNgOnDestroy();
857
+ }
858
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: NumberRangeComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
859
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.1", type: NumberRangeComponent, isStandalone: true, selector: "yuv-number-range", inputs: { scale: "scale", precision: "precision", grouping: "grouping", pattern: "pattern", readonly: "readonly", classifications: "classifications", minValue: "minValue", maxValue: "maxValue" }, providers: [{ provide: MatFormFieldControl, useExisting: NumberRangeComponent }], usesInheritance: true, ngImport: i0, template: "<form class=\"yuv-number-range\" [formGroup]=\"rangeForm\">\n @if (rangeForm.value.operator === 'gtelte') {\n <yuv-number\n class=\"first\"\n [readonly]=\"readonly\"\n [scale]=\"scale\"\n [precision]=\"precision\"\n [grouping]=\"grouping\"\n [groupPattern]=\"pattern\"\n formControlName=\"numberValueFrom\"\n [classifications]=\"classifications\"\n [minValue]=\"minValue\"\n [maxValue]=\"maxValue\"\n ></yuv-number>\n }\n\n <mat-select [panelWidth]=\"null\" [hideSingleSelectionIndicator]=\"true\" formControlName=\"operator\" [disabled]=\"readonly\">\n @for (o of availableSearchOptions; track $index) {\n <mat-option [value]=\"o.value\">{{ o.label }}</mat-option>\n }\n </mat-select>\n\n <yuv-number\n [scale]=\"scale\"\n [readonly]=\"readonly\"\n [precision]=\"precision\"\n [grouping]=\"grouping\"\n [groupPattern]=\"pattern\"\n formControlName=\"numberValue\"\n [classifications]=\"classifications\"\n [minValue]=\"minValue\"\n [maxValue]=\"maxValue\"\n >\n </yuv-number>\n</form>\n", styles: [":host>form{display:inline-flex;flex-flow:row nowrap;gap:3px}:host>form yuv-number{flex:1 1 auto}:host>form mat-select{padding:0;width:calc(2ch + 1em);border-radius:2px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: NumberComponent, selector: "yuv-number", inputs: ["scale", "precision", "grouping", "groupPattern", "readonly", "minValue", "maxValue", "classifications"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i1$2.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i1$2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }] }); }
1277
860
  }
1278
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: NumberRangeComponent, decorators: [{
861
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: NumberRangeComponent, decorators: [{
1279
862
  type: Component,
1280
- args: [{ selector: 'yuv-number-range', standalone: true, imports: [CommonModule, NumberComponent, YvcDropdownModule, FormsModule, ReactiveFormsModule], providers: [
1281
- {
1282
- provide: NG_VALUE_ACCESSOR,
1283
- useExisting: forwardRef(() => NumberRangeComponent),
1284
- multi: true
1285
- },
1286
- {
1287
- provide: NG_VALIDATORS,
1288
- useExisting: forwardRef(() => NumberRangeComponent),
1289
- multi: true
1290
- }
1291
- ], template: "<form class=\"yuv-number-range\" [formGroup]=\"rangeForm\">\n @if(searchOption === 'gtelte'){\n <yuv-number\n class=\"first\"\n [readonly]=\"readonly\"\n [scale]=\"scale\"\n [precision]=\"precision\"\n [grouping]=\"grouping\"\n [groupPattern]=\"pattern\"\n formControlName=\"numberValueFrom\"\n [classifications]=\"classifications\"\n [minValue]=\"minValue\"\n [maxValue]=\"maxValue\"\n ></yuv-number>}\n\n <yvc-dropdown\n class=\"no-trigger\"\n [(ngModel)]=\"searchOption\"\n (ngModelChange)=\"onValueChange()\"\n [disabled]=\"readonly\"\n [disableClearButton]=\"true\"\n [ngModelOptions]=\"{ standalone: true }\"\n [options]=\"availableSearchOptions\"\n ></yvc-dropdown>\n\n <yuv-number\n [scale]=\"scale\"\n [readonly]=\"readonly\"\n [precision]=\"precision\"\n [grouping]=\"grouping\"\n [groupPattern]=\"pattern\"\n formControlName=\"numberValue\"\n [classifications]=\"classifications\"\n [minValue]=\"minValue\"\n [maxValue]=\"maxValue\"\n >\n </yuv-number>\n</form>\n", styles: [":host>form{display:flex;flex-flow:row nowrap;gap:3px}:host>form yuv-number{flex:1 1 auto}:host>form yvc-dropdown{--yvc-form-element-border-color: var(--text-color-hint);--yvc-form-element-focus-border-color: var(--color-accent);padding:0;min-width:auto;border-radius:2px;background-color:var(--list-item-hover-background)}:host>form yvc-dropdown:hover{background-color:var(--list-item-selected-background)}\n"] }]
1292
- }], ctorParameters: () => [], propDecorators: { scale: [{
863
+ args: [{ selector: 'yuv-number-range', standalone: true, imports: [CommonModule, NumberComponent, MatSelectModule, FormsModule, ReactiveFormsModule], providers: [{ provide: MatFormFieldControl, useExisting: NumberRangeComponent }], template: "<form class=\"yuv-number-range\" [formGroup]=\"rangeForm\">\n @if (rangeForm.value.operator === 'gtelte') {\n <yuv-number\n class=\"first\"\n [readonly]=\"readonly\"\n [scale]=\"scale\"\n [precision]=\"precision\"\n [grouping]=\"grouping\"\n [groupPattern]=\"pattern\"\n formControlName=\"numberValueFrom\"\n [classifications]=\"classifications\"\n [minValue]=\"minValue\"\n [maxValue]=\"maxValue\"\n ></yuv-number>\n }\n\n <mat-select [panelWidth]=\"null\" [hideSingleSelectionIndicator]=\"true\" formControlName=\"operator\" [disabled]=\"readonly\">\n @for (o of availableSearchOptions; track $index) {\n <mat-option [value]=\"o.value\">{{ o.label }}</mat-option>\n }\n </mat-select>\n\n <yuv-number\n [scale]=\"scale\"\n [readonly]=\"readonly\"\n [precision]=\"precision\"\n [grouping]=\"grouping\"\n [groupPattern]=\"pattern\"\n formControlName=\"numberValue\"\n [classifications]=\"classifications\"\n [minValue]=\"minValue\"\n [maxValue]=\"maxValue\"\n >\n </yuv-number>\n</form>\n", styles: [":host>form{display:inline-flex;flex-flow:row nowrap;gap:3px}:host>form yuv-number{flex:1 1 auto}:host>form mat-select{padding:0;width:calc(2ch + 1em);border-radius:2px}\n"] }]
864
+ }], propDecorators: { scale: [{
1293
865
  type: Input
1294
866
  }], precision: [{
1295
867
  type: Input
@@ -1309,85 +881,67 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
1309
881
 
1310
882
  /**
1311
883
  * Creates form input for organisation values.
1312
- * Implements `ControlValueAccessor` so it can be used within Angular forms.
1313
- *
1314
- * [Screenshot](../assets/images/yuv-organization.gif)
1315
884
  *
1316
885
  * @example
1317
886
  * <yuv-organization [multiselect]="true"></yuv-organization>
1318
887
  */
1319
- class OrganizationComponent {
888
+ class OrganizationComponent extends AbstractMatFormField {
1320
889
  constructor() {
1321
- this.system = inject(SystemService);
1322
- this.userService = inject(UserService);
890
+ super(...arguments);
891
+ this.#system = inject(SystemService);
892
+ this.#userService = inject(UserService);
1323
893
  this.translate = inject(TranslateService);
1324
894
  this.minLength = 2;
1325
- this.icons = {
1326
- organizationMulti: YUV_ICONS['group'],
1327
- organization: YUV_ICONS['user']
1328
- };
1329
- this.isValidInput = true;
1330
- this.value = null;
895
+ this.busy = signal(false);
896
+ this.acFormControl = new FormControl(undefined);
897
+ this.ngControl = injectNgControl(this);
1331
898
  this._innerValue = [];
1332
899
  this.autocompleteRes = [];
1333
- this.filterRoles = [];
1334
- /**
1335
- * Indicator that multiple strings could be inserted, they will be rendered as chips (default: false).
1336
- */
1337
- this.multiselect = false;
900
+ this.#filterRoles = [];
1338
901
  /**
1339
- * Will prevent the input from being changed (default: false)
902
+ * Possibles values are `EDIT` (default),`SEARCH`,`CREATE`. In search situation validation of the form element will be turned off, so you are able to enter search terms that do not meet the elements validators.
1340
903
  */
1341
- this.readonly = false;
904
+ this.situation = input(undefined);
1342
905
  /**
1343
- * Set this to true and the component will try to gain focus once it has been rendered.
1344
- * Notice that this is not reliable. If there are any other components that are rendered
1345
- * later and also try to be focused, they will 'win', because there can only be one focus.
906
+ * Indicator that multiple strings could be inserted, they will be rendered as chips (default: false).
1346
907
  */
1347
- this.autofocus = false;
908
+ this.multiselect = input(false);
1348
909
  /**
1349
- * Will attch the overlay to this HTMLelement
910
+ * Will prevent the input from being changed (default: false)
1350
911
  */
1351
- this.appendTo = null;
912
+ this.readonly = input(false);
1352
913
  /**
1353
914
  * Whether or not to exclude the current user from autocomplete result
1354
915
  */
1355
- this.excludeMe = false;
916
+ this.excludeMe = input(false);
1356
917
  /**
1357
918
  * Whether or not the emitted value should be an object containing id and title
1358
919
  * or, if set to false only the ID
1359
920
  */
1360
921
  this.withMetadata = input(false);
1361
- this.userSelect = new EventEmitter();
1362
922
  // eslint-disable-next-line @typescript-eslint/no-empty-function
1363
923
  this.propagateChange = (_) => { };
1364
924
  }
925
+ #system;
926
+ #userService;
1365
927
  set innerValue(iv) {
1366
928
  this._innerValue = iv || [];
1367
- this.userSelect.emit(this._innerValue.map((v) => v.user));
1368
929
  }
1369
930
  get innerValue() {
1370
931
  return this._innerValue;
1371
932
  }
1372
- // prevent ENTER from being propagated, because the component could be located
1373
- // inside some other component that also relys on ENTER
1374
- onKeydownHandler(event) {
1375
- event.stopPropagation();
1376
- }
1377
- get _inputDisabled() {
1378
- return !this.multiselect && this.innerValue?.length === 1;
1379
- }
933
+ #filterRoles;
1380
934
  set classifications(c) {
1381
935
  this._classifications = c;
1382
936
  if (c?.length) {
1383
- const classifications = this.system.getClassifications(c);
937
+ const classifications = this.#system.getClassifications(c);
1384
938
  if (classifications.has(Classification.STRING_ORGANIZATION)) {
1385
939
  const options = classifications.get(Classification.STRING_ORGANIZATION).options;
1386
- this.filterRoles = options;
940
+ this.#filterRoles = options;
1387
941
  }
1388
942
  }
1389
943
  else {
1390
- this.filterRoles = [];
944
+ this.#filterRoles = [];
1391
945
  }
1392
946
  }
1393
947
  get classifications() {
@@ -1409,29 +963,18 @@ class OrganizationComponent {
1409
963
  // eslint-disable-next-line @typescript-eslint/no-empty-function
1410
964
  registerOnTouched(fn) { }
1411
965
  propagate() {
1412
- this.propagateChange(this.#getPropagateValue());
966
+ this.value = this.#getPropagateValue();
967
+ this.propagateChange(this.value);
1413
968
  }
1414
969
  #getPropagateValue() {
1415
- return this.multiselect
1416
- ? this.withMetadata()
1417
- ? this.value
1418
- ? this._innerValue.map((v) => ({
1419
- id: v.user.id,
1420
- title: v.user.title
1421
- }))
1422
- : this.value
1423
- : this.value
1424
- : this.withMetadata()
1425
- ? this.value
1426
- ? {
1427
- id: this._innerValue[0].user.id,
1428
- title: this._innerValue[0].user.title
1429
- }
1430
- : this.value
1431
- : this.value;
1432
- }
1433
- focusInput() {
1434
- this.autoCompleteInput.focusInput();
970
+ if (this.multiselect()) {
971
+ return this.innerValue.map((v) => (this.withMetadata() ? { id: v.user.id, title: v.user.title } : v.user.id));
972
+ }
973
+ else if (this.innerValue.length) {
974
+ return this.withMetadata() ? { id: this.innerValue[0].user.id, title: this.innerValue[0].user.title } : this.innerValue[0].user.id;
975
+ }
976
+ else
977
+ return undefined;
1435
978
  }
1436
979
  resolveFn(value) {
1437
980
  const obs = (value instanceof Array ? value : [value]).map((v) => {
@@ -1439,7 +982,7 @@ class OrganizationComponent {
1439
982
  const match = this.innerValue.find((iv) => iv.user.id === valueID);
1440
983
  return match
1441
984
  ? of(match)
1442
- : this.userService.getUserById(valueID).pipe(map$1((res) => ({
985
+ : this.#userService.getUserById(valueID).pipe(map$1((res) => ({
1443
986
  user: res,
1444
987
  state: {}
1445
988
  })), catchError((e) => {
@@ -1458,24 +1001,35 @@ class OrganizationComponent {
1458
1001
  });
1459
1002
  return forkJoin(obs).subscribe((data) => {
1460
1003
  this.innerValue = data;
1461
- // setTimeout(() => this.autoCompleteInput.cd.markForCheck());
1004
+ const mapped = this.innerValue.map((u) => ({
1005
+ label: u.user.title,
1006
+ value: u
1007
+ }));
1008
+ this.acFormControl.setValue(this.multiselect() ? mapped : [mapped[0]], { emitEvent: false });
1462
1009
  });
1463
1010
  }
1464
1011
  autocompleteFn(query) {
1465
1012
  if (query.length >= this.minLength) {
1466
- this.userService.queryUser(query, this.excludeMe, this.filterRoles).subscribe({
1013
+ this.busy.set(true);
1014
+ this.#userService
1015
+ .queryUser(query, this.excludeMe(), this.#filterRoles)
1016
+ .pipe(finalize(() => {
1017
+ this.busy.set(false);
1018
+ }))
1019
+ .subscribe({
1467
1020
  next: (users) => {
1468
1021
  this.autocompleteRes = users
1469
1022
  .filter((user) => !this.innerValue.some((value) => value.user.id === user.id))
1470
1023
  .map((user) => ({
1471
- user: user,
1472
- state: {}
1024
+ label: user.title,
1025
+ value: {
1026
+ user,
1027
+ state: {}
1028
+ }
1473
1029
  }));
1474
- this.propagateValidity(this.autocompleteRes.length > 0);
1475
1030
  },
1476
1031
  error: () => {
1477
1032
  this.autocompleteRes = [];
1478
- this.propagateValidity(this.autocompleteRes.length > 0);
1479
1033
  }
1480
1034
  });
1481
1035
  }
@@ -1483,129 +1037,58 @@ class OrganizationComponent {
1483
1037
  this.autocompleteRes = [];
1484
1038
  }
1485
1039
  }
1486
- // returns null when valid else the validation object
1487
- validate() {
1488
- return this.isValidInput ? null : { empty: { valid: false } };
1489
- }
1490
- propagateValidity(valid = true) {
1491
- if (this.isValidInput !== valid) {
1492
- this.isValidInput = valid;
1040
+ ngOnInit() {
1041
+ this.acFormControl.valueChanges.subscribe((v) => {
1042
+ if (!Array.isArray(v))
1043
+ v = v ? [v] : [];
1044
+ this.innerValue = v.map((i) => i.value);
1493
1045
  this.propagate();
1494
- }
1495
- }
1496
- // handle selection changes to the model
1497
- onSelect() {
1498
- if (this.multiselect) {
1499
- this.value = this.innerValue.map((v) => v.user.id);
1500
- }
1501
- else {
1502
- // internal autocomplete control is always set to multiselect
1503
- // so the resolved value is always an array
1504
- this.innerValue = this.innerValue.slice(-1);
1505
- this.value = this.innerValue[0].user.id;
1506
- }
1507
- this.propagate();
1508
- }
1509
- // handle selection changes to the model
1510
- onUnselect(value) {
1511
- this.innerValue = this.innerValue.filter((v) => v.user.id !== value.id);
1512
- const _value = this.innerValue.map((v) => v.user.id);
1513
- this.value = this.multiselect ? _value : null;
1514
- if (!this.multiselect) {
1515
- this.clearInnerInput();
1516
- }
1517
- this.propagate();
1518
- }
1519
- onAutoCompleteBlur() {
1520
- this.clearInnerInput();
1521
- }
1522
- clearInnerInput() {
1523
- this.autoCompleteInput.clearInput();
1046
+ });
1524
1047
  }
1525
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: OrganizationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1526
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "18.2.13", type: OrganizationComponent, isStandalone: true, selector: "yuv-organization", inputs: { placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: false, isRequired: false, transformFunction: null }, situation: { classPropertyName: "situation", publicName: "situation", isSignal: false, isRequired: false, transformFunction: null }, multiselect: { classPropertyName: "multiselect", publicName: "multiselect", isSignal: false, isRequired: false, transformFunction: null }, classifications: { classPropertyName: "classifications", publicName: "classifications", isSignal: false, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: false, isRequired: false, transformFunction: null }, autofocus: { classPropertyName: "autofocus", publicName: "autofocus", isSignal: false, isRequired: false, transformFunction: null }, appendTo: { classPropertyName: "appendTo", publicName: "appendTo", isSignal: false, isRequired: false, transformFunction: null }, excludeMe: { classPropertyName: "excludeMe", publicName: "excludeMe", isSignal: false, isRequired: false, transformFunction: null }, withMetadata: { classPropertyName: "withMetadata", publicName: "withMetadata", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { userSelect: "userSelect" }, host: { listeners: { "keydown.enter": "onKeydownHandler($event)" }, properties: { "class.inputDisabled": "this._inputDisabled" } }, providers: [
1527
- {
1528
- provide: NG_VALUE_ACCESSOR,
1529
- useExisting: forwardRef(() => OrganizationComponent),
1530
- multi: true
1531
- },
1532
- {
1533
- provide: NG_VALIDATORS,
1534
- useExisting: forwardRef(() => OrganizationComponent),
1535
- multi: true
1536
- }
1537
- ], viewQueries: [{ propertyName: "autoCompleteInput", first: true, predicate: ["autocomplete"], descendants: true }], ngImport: i0, template: "<yvc-autocomplete\n [(ngModel)]=\"innerValue\"\n #autocomplete\n (suggestionSelect)=\"onSelect()\"\n [placeholder]=\"placeholder\"\n (suggestionUnselect)=\"onUnselect($event)\"\n (blur)=\"onAutoCompleteBlur()\"\n [disabled]=\"readonly\"\n [autocompleteValues]=\"autocompleteRes\"\n field=\"id\"\n [forceSelection]=\"true\"\n (autocompleteFnc)=\"autocompleteFn($event)\"\n [multiple]=\"true\"\n>\n <!-- template for item inside the dropdown -->\n <ng-template #autocompleteOptionTemplate let-item>\n <span class=\"chip\">{{ item.user.title }}</span>\n </ng-template>\n\n <!-- template for chip -->\n <ng-template #chipTemplate let-item>\n <span class=\"chip\" [ngClass]=\"{ notFound: item.state.notFound }\" [title]=\"item.titleString\">\n {{ item.user.title }}\n </span>\n </ng-template>\n</yvc-autocomplete>\n\n<yvc-icon class=\"classify\" aria-hidden=\"true\" [svg]=\"multiselect ? icons.organizationMulti : icons.organization\" (click)=\"focusInput()\"></yvc-icon>\n", styles: [":host{display:flex;align-items:center}:host .chip.notFound{color:var(--color-error);text-decoration:line-through}:host .chip.notFound:before{content:\"!\";display:inline-block;background-color:var(--color-error);color:#fff;border-radius:2px;padding-inline:.3em;text-decoration:none;margin-inline-end:.75em}:host yvc-autocomplete{flex:1;--yvc-form-element-focus-border-color: transparent;--yvc-form-element-focus-outline-color: transparent}:host yvc-icon.classify{width:18px;height:18px;padding:calc(var(--app-pane-padding) / 8);color:var(--text-color-hint)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: YvcAutocompleteModule }, { kind: "component", type: i3$1.AutoComplete, selector: "yvc-autocomplete", inputs: ["field", "placeholder", "minLength", "multiple", "typeahead", "distinctValues", "forceSelection", "autocompleteValues", "disabled"], outputs: ["autocompleteFnc", "blur", "focus", "suggestionUnselect", "suggestionSelect"] }, { kind: "ngmodule", type: YvcIconModule }, { kind: "component", type: i3.Icon, selector: "yvc-icon", inputs: ["label", "svg", "svgSrc"] }, { kind: "ngmodule", type: TranslateModule }] }); }
1048
+ ngOnDestroy() {
1049
+ super.onNgOnDestroy();
1050
+ }
1051
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: OrganizationComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
1052
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.1", type: OrganizationComponent, isStandalone: true, selector: "yuv-organization", inputs: { situation: { classPropertyName: "situation", publicName: "situation", isSignal: true, isRequired: false, transformFunction: null }, multiselect: { classPropertyName: "multiselect", publicName: "multiselect", isSignal: true, isRequired: false, transformFunction: null }, classifications: { classPropertyName: "classifications", publicName: "classifications", isSignal: false, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, excludeMe: { classPropertyName: "excludeMe", publicName: "excludeMe", isSignal: true, isRequired: false, transformFunction: null }, withMetadata: { classPropertyName: "withMetadata", publicName: "withMetadata", isSignal: true, isRequired: false, transformFunction: null } }, providers: [{ provide: MatFormFieldControl, useExisting: OrganizationComponent }], usesInheritance: true, ngImport: i0, template: "<yuv-autocomplete\n [busy]=\"busy()\"\n [formControl]=\"acFormControl\"\n #autocomplete\n [placeholder]=\"placeholder\"\n [disabled]=\"readonly()\"\n [autocompleteValues]=\"autocompleteRes\"\n [forceSelection]=\"true\"\n (autocompleteFnc)=\"autocompleteFn($event)\"\n [multiple]=\"true\"\n [maxItems]=\"multiselect() ? (-1) : 1\"\n>\n <!-- template for item inside the dropdown -->\n <ng-template #optionTemplate let-item>\n <span class=\"chip\">{{ item.value.user.title }}</span>\n </ng-template>\n\n <!-- template for chip -->\n <ng-template #chipTemplate let-item>\n <span class=\"chip\" [ngClass]=\"{ notFound: item.value.state.notFound }\" [matTooltip]=\"item.value.titleString\">\n {{ item.value.user.title || '...' }}\n </span>\n </ng-template>\n</yuv-autocomplete>\n\n<mat-icon [matTooltip]=\"'yuv.form.element.organization.classify.icon.title' | translate\">{{ multiselect() ? 'group' : 'person' }}</mat-icon>\n", styles: [":host{display:flex;align-items:center}:host .chip.notFound{color:var(--ymt-on-danger-container);text-decoration:line-through}:host .chip.notFound:before{content:\"!\";display:inline-block;background-color:var(--ymt-danger-container);color:#fff;border-radius:2px;padding-inline:.3em;text-decoration:none;margin-inline-end:.75em}:host yuv-autocomplete{flex:1}:host yuv-icon.classify{width:18px;height:18px;padding:var(--ymt-spacing-3xs);color:var(--ymt-text-color-subtle)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "ngmodule", type: YuvAutocompleteModule }, { kind: "component", type: i3$1.AutocompleteComponent, selector: "yuv-autocomplete", inputs: ["ariaLabel", "busy", "multiple", "distinctValues", "addOnBlur", "minLength", "maxItems", "forceSelection", "autocompleteValues"], outputs: ["autocompleteFnc"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i4.TranslatePipe, name: "translate" }] }); }
1538
1053
  }
1539
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: OrganizationComponent, decorators: [{
1054
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: OrganizationComponent, decorators: [{
1540
1055
  type: Component,
1541
- args: [{ selector: 'yuv-organization', standalone: true, imports: [CommonModule, FormsModule, YvcAutocompleteModule, YvcIconModule, TranslateModule], providers: [
1542
- {
1543
- provide: NG_VALUE_ACCESSOR,
1544
- useExisting: forwardRef(() => OrganizationComponent),
1545
- multi: true
1546
- },
1547
- {
1548
- provide: NG_VALIDATORS,
1549
- useExisting: forwardRef(() => OrganizationComponent),
1550
- multi: true
1551
- }
1552
- ], template: "<yvc-autocomplete\n [(ngModel)]=\"innerValue\"\n #autocomplete\n (suggestionSelect)=\"onSelect()\"\n [placeholder]=\"placeholder\"\n (suggestionUnselect)=\"onUnselect($event)\"\n (blur)=\"onAutoCompleteBlur()\"\n [disabled]=\"readonly\"\n [autocompleteValues]=\"autocompleteRes\"\n field=\"id\"\n [forceSelection]=\"true\"\n (autocompleteFnc)=\"autocompleteFn($event)\"\n [multiple]=\"true\"\n>\n <!-- template for item inside the dropdown -->\n <ng-template #autocompleteOptionTemplate let-item>\n <span class=\"chip\">{{ item.user.title }}</span>\n </ng-template>\n\n <!-- template for chip -->\n <ng-template #chipTemplate let-item>\n <span class=\"chip\" [ngClass]=\"{ notFound: item.state.notFound }\" [title]=\"item.titleString\">\n {{ item.user.title }}\n </span>\n </ng-template>\n</yvc-autocomplete>\n\n<yvc-icon class=\"classify\" aria-hidden=\"true\" [svg]=\"multiselect ? icons.organizationMulti : icons.organization\" (click)=\"focusInput()\"></yvc-icon>\n", styles: [":host{display:flex;align-items:center}:host .chip.notFound{color:var(--color-error);text-decoration:line-through}:host .chip.notFound:before{content:\"!\";display:inline-block;background-color:var(--color-error);color:#fff;border-radius:2px;padding-inline:.3em;text-decoration:none;margin-inline-end:.75em}:host yvc-autocomplete{flex:1;--yvc-form-element-focus-border-color: transparent;--yvc-form-element-focus-outline-color: transparent}:host yvc-icon.classify{width:18px;height:18px;padding:calc(var(--app-pane-padding) / 8);color:var(--text-color-hint)}\n"] }]
1553
- }], propDecorators: { autoCompleteInput: [{
1554
- type: ViewChild,
1555
- args: ['autocomplete']
1556
- }], onKeydownHandler: [{
1557
- type: HostListener,
1558
- args: ['keydown.enter', ['$event']]
1559
- }], _inputDisabled: [{
1560
- type: HostBinding,
1561
- args: ['class.inputDisabled']
1562
- }], placeholder: [{
1563
- type: Input
1564
- }], situation: [{
1565
- type: Input
1566
- }], multiselect: [{
1567
- type: Input
1568
- }], classifications: [{
1569
- type: Input
1570
- }], readonly: [{
1571
- type: Input
1572
- }], autofocus: [{
1573
- type: Input
1574
- }], appendTo: [{
1056
+ args: [{ selector: 'yuv-organization', standalone: true, imports: [CommonModule, FormsModule, YuvAutocompleteModule,
1057
+ MatTooltipModule,
1058
+ MatIconModule, ReactiveFormsModule, TranslateModule], providers: [{ provide: MatFormFieldControl, useExisting: OrganizationComponent }], template: "<yuv-autocomplete\n [busy]=\"busy()\"\n [formControl]=\"acFormControl\"\n #autocomplete\n [placeholder]=\"placeholder\"\n [disabled]=\"readonly()\"\n [autocompleteValues]=\"autocompleteRes\"\n [forceSelection]=\"true\"\n (autocompleteFnc)=\"autocompleteFn($event)\"\n [multiple]=\"true\"\n [maxItems]=\"multiselect() ? (-1) : 1\"\n>\n <!-- template for item inside the dropdown -->\n <ng-template #optionTemplate let-item>\n <span class=\"chip\">{{ item.value.user.title }}</span>\n </ng-template>\n\n <!-- template for chip -->\n <ng-template #chipTemplate let-item>\n <span class=\"chip\" [ngClass]=\"{ notFound: item.value.state.notFound }\" [matTooltip]=\"item.value.titleString\">\n {{ item.value.user.title || '...' }}\n </span>\n </ng-template>\n</yuv-autocomplete>\n\n<mat-icon [matTooltip]=\"'yuv.form.element.organization.classify.icon.title' | translate\">{{ multiselect() ? 'group' : 'person' }}</mat-icon>\n", styles: [":host{display:flex;align-items:center}:host .chip.notFound{color:var(--ymt-on-danger-container);text-decoration:line-through}:host .chip.notFound:before{content:\"!\";display:inline-block;background-color:var(--ymt-danger-container);color:#fff;border-radius:2px;padding-inline:.3em;text-decoration:none;margin-inline-end:.75em}:host yuv-autocomplete{flex:1}:host yuv-icon.classify{width:18px;height:18px;padding:var(--ymt-spacing-3xs);color:var(--ymt-text-color-subtle)}\n"] }]
1059
+ }], propDecorators: { classifications: [{
1575
1060
  type: Input
1576
- }], excludeMe: [{
1577
- type: Input
1578
- }], userSelect: [{
1579
- type: Output
1580
1061
  }] } });
1581
1062
 
1582
1063
  class DateRangePickerComponent {
1583
1064
  constructor() {
1584
- this.#oRef = inject(YvcOverlayRef);
1585
1065
  this.#fb = inject(FormBuilder);
1066
+ this.#dialogData = inject(MAT_DIALOG_DATA);
1067
+ this.#dialogRef = inject((MatDialogRef));
1586
1068
  this.form = this.#fb.group({
1587
- range: this.#fb.control(this.#oRef.data.range, Validators.required)
1069
+ range: this.#fb.control(this.#dialogData.range, Validators.required)
1588
1070
  });
1589
- this.range = input(this.#oRef.data.range);
1071
+ this.range = input(this.#dialogData.range);
1590
1072
  this.rangeChange = output();
1591
1073
  this.#rangeEffect = effect(() => {
1592
1074
  const range = this.range();
1593
1075
  this.form.patchValue({ range });
1594
1076
  });
1595
1077
  }
1596
- #oRef;
1597
1078
  #fb;
1079
+ #dialogData;
1080
+ #dialogRef;
1598
1081
  #rangeEffect;
1599
1082
  apply() {
1600
1083
  this.rangeChange.emit(this.form.value.range || undefined);
1601
- this.#oRef?.close(this.form.value.range);
1084
+ this.#dialogRef.close(this.form.value.range);
1602
1085
  }
1603
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DateRangePickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1604
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "18.2.13", type: DateRangePickerComponent, isStandalone: true, selector: "yuv-date-range-picker", inputs: { range: { classPropertyName: "range", publicName: "range", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { rangeChange: "rangeChange" }, ngImport: i0, template: "<form [formGroup]=\"form\" (ngSubmit)=\"apply()\">\n <h2>{{ 'yuv.form.element.range-select-date.custom.overlay.title' | translate }}</h2>\n <yuv-datetime-range [withTime]=\"false\" formControlName=\"range\"></yuv-datetime-range>\n <button class=\"primary\" [disabled]=\"form.invalid\">{{ 'yuv.form.element.range-select-date.custom.overlay.button.apply' | translate }}</button>\n</form>\n", styles: [":host{--form-element-border-color: transparent;--yvc-form-element-border-color: transparent}:host form{display:grid;grid-template-columns:1fr auto;grid-template-rows:repeat(3,auto);grid-template-areas:\"title title\" \"input input\" \". button\";gap:var(--app-pane-padding);padding:var(--app-pane-padding)}:host form h2{grid-area:title;margin:0}:host form yuv-datetime-range{grid-area:input;border:1px solid var(--text-color-hint);padding:1px 2px;border-radius:2px}:host form button{grid-area:button}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }, { kind: "component", type: DatetimeRangeComponent, selector: "yuv-datetime-range", inputs: ["withTime", "readonly", "operator", "situation"] }] }); }
1086
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: DateRangePickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1087
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.1", type: DateRangePickerComponent, isStandalone: true, selector: "yuv-date-range-picker", inputs: { range: { classPropertyName: "range", publicName: "range", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { rangeChange: "rangeChange" }, ngImport: i0, template: "<form [formGroup]=\"form\" (ngSubmit)=\"apply()\">\n <h2>{{ 'yuv.form.element.range-select-date.custom.overlay.title' | translate }}</h2>\n <yuv-datetime-range [withTime]=\"false\" formControlName=\"range\"></yuv-datetime-range>\n <button class=\"primary\" [disabled]=\"form.invalid\">{{ 'yuv.form.element.range-select-date.custom.overlay.button.apply' | translate }}</button>\n</form>\n", styles: [":host form{display:grid;grid-template-columns:1fr auto;grid-template-rows:repeat(3,auto);grid-template-areas:\"title title\" \"input input\" \". button\";gap:var(--ymt-spacing-m);padding:var(--ymt-spacing-m)}:host form h2{grid-area:title;margin:0}:host form yuv-datetime-range{grid-area:input;border:1px solid var(--ymt-text-color-subtle);padding:1px 2px;border-radius:2px}:host form button{grid-area:button}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i4.TranslatePipe, name: "translate" }, { kind: "component", type: DatetimeRangeComponent, selector: "yuv-datetime-range", inputs: ["withTime", "readonly", "operator", "situation"] }] }); }
1605
1088
  }
1606
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DateRangePickerComponent, decorators: [{
1089
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: DateRangePickerComponent, decorators: [{
1607
1090
  type: Component,
1608
- args: [{ selector: 'yuv-date-range-picker', standalone: true, imports: [CommonModule, ReactiveFormsModule, TranslateModule, DatetimeRangeComponent], template: "<form [formGroup]=\"form\" (ngSubmit)=\"apply()\">\n <h2>{{ 'yuv.form.element.range-select-date.custom.overlay.title' | translate }}</h2>\n <yuv-datetime-range [withTime]=\"false\" formControlName=\"range\"></yuv-datetime-range>\n <button class=\"primary\" [disabled]=\"form.invalid\">{{ 'yuv.form.element.range-select-date.custom.overlay.button.apply' | translate }}</button>\n</form>\n", styles: [":host{--form-element-border-color: transparent;--yvc-form-element-border-color: transparent}:host form{display:grid;grid-template-columns:1fr auto;grid-template-rows:repeat(3,auto);grid-template-areas:\"title title\" \"input input\" \". button\";gap:var(--app-pane-padding);padding:var(--app-pane-padding)}:host form h2{grid-area:title;margin:0}:host form yuv-datetime-range{grid-area:input;border:1px solid var(--text-color-hint);padding:1px 2px;border-radius:2px}:host form button{grid-area:button}\n"] }]
1091
+ args: [{ selector: 'yuv-date-range-picker', standalone: true, imports: [CommonModule, ReactiveFormsModule, TranslateModule, DatetimeRangeComponent], template: "<form [formGroup]=\"form\" (ngSubmit)=\"apply()\">\n <h2>{{ 'yuv.form.element.range-select-date.custom.overlay.title' | translate }}</h2>\n <yuv-datetime-range [withTime]=\"false\" formControlName=\"range\"></yuv-datetime-range>\n <button class=\"primary\" [disabled]=\"form.invalid\">{{ 'yuv.form.element.range-select-date.custom.overlay.button.apply' | translate }}</button>\n</form>\n", styles: [":host form{display:grid;grid-template-columns:1fr auto;grid-template-rows:repeat(3,auto);grid-template-areas:\"title title\" \"input input\" \". button\";gap:var(--ymt-spacing-m);padding:var(--ymt-spacing-m)}:host form h2{grid-area:title;margin:0}:host form yuv-datetime-range{grid-area:input;border:1px solid var(--ymt-text-color-subtle);padding:1px 2px;border-radius:2px}:host form button{grid-area:button}\n"] }]
1609
1092
  }] });
1610
1093
 
1611
1094
  // marker for extracting translations for the available date range options
@@ -1624,22 +1107,25 @@ marker('yuv.form.element.range-select-date.option.custom');
1624
1107
  * 'today', 'this week', 'this month', etc.
1625
1108
  * It also allows to pick a custom date range.
1626
1109
  */
1627
- class RangeSelectDateComponent {
1628
- #overlay;
1629
- #fb;
1110
+ class RangeSelectDateComponent extends AbstractMatFormField {
1111
+ #dialog;
1630
1112
  #ANY_OPTION;
1631
1113
  #CUSTOM_OPTION;
1632
1114
  #customDateRange;
1115
+ get shouldLabelFloat() {
1116
+ return true;
1117
+ }
1633
1118
  constructor() {
1119
+ super();
1634
1120
  this.translate = inject(TranslateService);
1635
- this.#overlay = inject(YvcOverlayService);
1636
- this.#fb = inject(FormBuilder);
1121
+ this.#dialog = inject(MatDialog);
1637
1122
  this.#ANY_OPTION = 'any';
1638
1123
  this.#CUSTOM_OPTION = 'custom';
1639
- this.dateOptions = signal([]);
1640
- this.innerForm = this.#fb.nonNullable.group({
1641
- range: [this.#ANY_OPTION]
1124
+ this.options = signal([]);
1125
+ this.fc = new FormControl(this.#ANY_OPTION, {
1126
+ nonNullable: true
1642
1127
  });
1128
+ this.ngControl = injectNgControl(this);
1643
1129
  /**
1644
1130
  * Range values to be used in the dropdown.
1645
1131
  */
@@ -1653,46 +1139,51 @@ class RangeSelectDateComponent {
1653
1139
  this.propagateChange = (_) => { };
1654
1140
  this.translate.onLangChange.pipe(takeUntilDestroyed()).subscribe((_) => this.#setupOptions());
1655
1141
  this.#setupOptions();
1656
- this.innerForm.valueChanges.pipe(takeUntilDestroyed()).subscribe((v) => this.#onFormValueChange(v));
1142
+ this.fc.valueChanges.pipe(takeUntilDestroyed()).subscribe((v) => this.#onFormValueChange(v));
1657
1143
  }
1658
1144
  #onFormValueChange(v) {
1659
- if (v.range === this.#CUSTOM_OPTION) {
1660
- if (!this.#customDateRange || this.dateOptions().find((o) => o.value === this.#CUSTOM_OPTION)?.label === this.#customDateRangeToString())
1145
+ if (v === this.#CUSTOM_OPTION) {
1146
+ if (!this.#customDateRange || this.options().find((o) => o.value === this.#CUSTOM_OPTION)?.label === this.#customDateRangeToString())
1661
1147
  this.#openCustomRangeDialog();
1662
1148
  else
1663
- this.propagateChange({
1149
+ this.value = {
1664
1150
  rangeValue: this.#customDateRange,
1665
1151
  label: this.#customDateRangeToString()
1666
- });
1152
+ };
1153
+ this.propagateChange(this.value);
1667
1154
  }
1668
1155
  else {
1669
- const { start, end } = SearchUtils.dateRangeStartEnd(v.range);
1670
- this.propagateChange(v.range !== this.#ANY_OPTION
1671
- ? {
1672
- rangeValue: { operator: Operator.INTERVAL_INCLUDE_BOTH, firstValue: start, secondValue: end },
1673
- label: this.translate.instant(`yuv.form.element.range-select-date.option.${v.range}`)
1674
- }
1675
- : undefined);
1156
+ const { start, end } = SearchUtils.dateRangeStartEnd(v);
1157
+ this.value =
1158
+ v !== this.#ANY_OPTION
1159
+ ? {
1160
+ rangeValue: { operator: Operator.INTERVAL_INCLUDE_BOTH, firstValue: start, secondValue: end },
1161
+ label: this.translate.instant(`yuv.form.element.range-select-date.option.${v}`)
1162
+ }
1163
+ : null;
1164
+ this.propagateChange(this.value);
1676
1165
  this.#customDateRange = undefined;
1677
1166
  this.#setupOptions();
1678
1167
  }
1679
1168
  }
1680
1169
  #openCustomRangeDialog() {
1681
1170
  // open date range picker
1682
- const o = this.#overlay.open(DateRangePickerComponent, {
1683
- range: this.#customDateRange
1171
+ const o = this.#dialog.open(DateRangePickerComponent, {
1172
+ data: {
1173
+ range: this.#customDateRange
1174
+ }
1684
1175
  });
1685
- o.afterClosed$.subscribe((res) => {
1686
- this.#customDateRange = res.data;
1687
- if (!res.data) {
1688
- this.innerForm.patchValue({ range: this.#ANY_OPTION });
1176
+ o.afterClosed().subscribe((res) => {
1177
+ this.#customDateRange = res;
1178
+ if (!res) {
1179
+ this.fc.patchValue(this.#ANY_OPTION);
1689
1180
  this.#setupOptions();
1690
1181
  }
1691
1182
  else {
1692
- this.#onFormValueChange(this.innerForm.value);
1183
+ this.#onFormValueChange(this.fc.value);
1693
1184
  this.#setupOptions(this.#customDateRangeToString());
1694
1185
  setTimeout(() => {
1695
- this.innerForm.patchValue({ range: this.#CUSTOM_OPTION }, {
1186
+ this.fc.patchValue(this.#CUSTOM_OPTION, {
1696
1187
  emitEvent: false
1697
1188
  });
1698
1189
  });
@@ -1709,7 +1200,7 @@ class RangeSelectDateComponent {
1709
1200
  label: custom || this.translate.instant('yuv.form.element.range-select-date.option.custom'),
1710
1201
  value: this.#CUSTOM_OPTION
1711
1202
  });
1712
- this.dateOptions.set([
1203
+ this.options.set([
1713
1204
  {
1714
1205
  label: this.translate.instant('yuv.form.element.range-select-date.option.any'),
1715
1206
  value: this.#ANY_OPTION
@@ -1738,18 +1229,19 @@ class RangeSelectDateComponent {
1738
1229
  return undefined;
1739
1230
  }
1740
1231
  writeValue(value) {
1232
+ this.value = value || null;
1741
1233
  if (value?.rangeValue?.operator && value?.rangeValue?.firstValue) {
1742
1234
  const dr = SearchUtils.getMatchingDateRange(value.rangeValue);
1743
1235
  if (dr) {
1744
- this.innerForm.patchValue({ range: dr });
1236
+ this.fc.patchValue(dr);
1745
1237
  }
1746
1238
  else {
1747
1239
  this.#customDateRange = value.rangeValue;
1748
- this.innerForm.patchValue({ range: this.#CUSTOM_OPTION });
1240
+ this.fc.patchValue(this.#CUSTOM_OPTION);
1749
1241
  }
1750
1242
  }
1751
1243
  else {
1752
- this.innerForm.patchValue({ range: this.#ANY_OPTION });
1244
+ this.fc.patchValue(this.#ANY_OPTION);
1753
1245
  }
1754
1246
  }
1755
1247
  registerOnChange(fn) {
@@ -1757,24 +1249,15 @@ class RangeSelectDateComponent {
1757
1249
  }
1758
1250
  // eslint-disable-next-line @typescript-eslint/no-empty-function
1759
1251
  registerOnTouched(fn) { }
1760
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: RangeSelectDateComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1761
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "18.2.13", type: RangeSelectDateComponent, isStandalone: true, selector: "yuv-range-select-date", inputs: { ranges: { classPropertyName: "ranges", publicName: "ranges", isSignal: true, isRequired: false, transformFunction: null }, customRange: { classPropertyName: "customRange", publicName: "customRange", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
1762
- {
1763
- provide: NG_VALUE_ACCESSOR,
1764
- useExisting: forwardRef(() => RangeSelectDateComponent),
1765
- multi: true
1766
- }
1767
- ], ngImport: i0, template: "<form [formGroup]=\"innerForm\">\n <yvc-dropdown formControlName=\"range\" [options]=\"dateOptions()\" [disableClearButton]=\"true\"></yvc-dropdown>\n</form>", styles: [":host form{display:flex}:host form yvc-dropdown{flex:1;outline-offset:0px;color:currentColor}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: YvcDropdownModule }, { kind: "component", type: i1$1.Dropdown, selector: "yvc-dropdown", inputs: ["options", "filter", "disabled", "multiple", "disableClearButton"], outputs: ["onDropdownOptionsClose"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }] }); }
1252
+ ngOnDestroy() {
1253
+ super.onNgOnDestroy();
1254
+ }
1255
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: RangeSelectDateComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1256
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.1", type: RangeSelectDateComponent, isStandalone: true, selector: "yuv-range-select-date", inputs: { ranges: { classPropertyName: "ranges", publicName: "ranges", isSignal: true, isRequired: false, transformFunction: null }, customRange: { classPropertyName: "customRange", publicName: "customRange", isSignal: true, isRequired: false, transformFunction: null } }, providers: [{ provide: MatFormFieldControl, useExisting: RangeSelectDateComponent }], usesInheritance: true, ngImport: i0, template: "<mat-select [formControl]=\"fc\" [panelWidth]=\"null\" [hideSingleSelectionIndicator]=\"true\">\n @for (o of options(); track $index) {\n <mat-option [value]=\"o.value\">{{ o.label }}</mat-option>\n }\n</mat-select>\n", styles: [":host{display:flex}:host mat-select{flex:1}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i1$2.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i1$2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }] }); }
1768
1257
  }
1769
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: RangeSelectDateComponent, decorators: [{
1258
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: RangeSelectDateComponent, decorators: [{
1770
1259
  type: Component,
1771
- args: [{ selector: 'yuv-range-select-date', standalone: true, imports: [CommonModule, YvcDropdownModule, ReactiveFormsModule], providers: [
1772
- {
1773
- provide: NG_VALUE_ACCESSOR,
1774
- useExisting: forwardRef(() => RangeSelectDateComponent),
1775
- multi: true
1776
- }
1777
- ], template: "<form [formGroup]=\"innerForm\">\n <yvc-dropdown formControlName=\"range\" [options]=\"dateOptions()\" [disableClearButton]=\"true\"></yvc-dropdown>\n</form>", styles: [":host form{display:flex}:host form yvc-dropdown{flex:1;outline-offset:0px;color:currentColor}\n"] }]
1260
+ args: [{ selector: 'yuv-range-select-date', standalone: true, imports: [CommonModule, MatSelectModule, ReactiveFormsModule], providers: [{ provide: MatFormFieldControl, useExisting: RangeSelectDateComponent }], template: "<mat-select [formControl]=\"fc\" [panelWidth]=\"null\" [hideSingleSelectionIndicator]=\"true\">\n @for (o of options(); track $index) {\n <mat-option [value]=\"o.value\">{{ o.label }}</mat-option>\n }\n</mat-select>\n", styles: [":host{display:flex}:host mat-select{flex:1}\n"] }]
1778
1261
  }], ctorParameters: () => [] });
1779
1262
 
1780
1263
  // marker for extracting translations for the available filesize range options
@@ -1787,17 +1270,20 @@ marker('yuv.form.element.range-select-filesize.option.verylarge');
1787
1270
  * Component for selecting a range of filesizes based on pre-defined ranges like
1788
1271
  * 'today', 'this week', 'this month', etc.
1789
1272
  */
1790
- class RangeSelectFilesizeComponent {
1791
- #fb;
1273
+ class RangeSelectFilesizeComponent extends AbstractMatFormField {
1792
1274
  #ANY_OPTION;
1275
+ get shouldLabelFloat() {
1276
+ return true;
1277
+ }
1793
1278
  constructor() {
1279
+ super();
1794
1280
  this.translate = inject(TranslateService$1);
1795
- this.#fb = inject(FormBuilder);
1796
1281
  this.#ANY_OPTION = 'any';
1797
1282
  this.options = signal([]);
1798
- this.innerForm = this.#fb.nonNullable.group({
1799
- range: [this.#ANY_OPTION]
1283
+ this.fc = new FormControl(this.#ANY_OPTION, {
1284
+ nonNullable: true
1800
1285
  });
1286
+ this.ngControl = injectNgControl(this);
1801
1287
  /**
1802
1288
  * Range values to be used in the dropdown.
1803
1289
  */
@@ -1807,14 +1293,15 @@ class RangeSelectFilesizeComponent {
1807
1293
  this.propagateChange = (_) => { };
1808
1294
  this.translate.onLangChange.pipe(takeUntilDestroyed()).subscribe((_) => this.#setupOptions());
1809
1295
  this.#setupOptions();
1810
- this.innerForm.valueChanges.pipe(takeUntilDestroyed()).subscribe((v) => this.#onFormValueChange(v));
1296
+ this.fc.valueChanges.pipe(takeUntilDestroyed()).subscribe((v) => this.#onFormValueChange(v));
1811
1297
  }
1812
1298
  #onFormValueChange(v) {
1813
- const rangeValue = v.range !== this.#ANY_OPTION ? SearchUtils.filesizeRangeToRangeValue(v.range) : undefined;
1299
+ const rangeValue = v !== this.#ANY_OPTION ? SearchUtils.filesizeRangeToRangeValue(v) : undefined;
1814
1300
  const res = rangeValue && {
1815
1301
  rangeValue,
1816
- label: this.translate.instant(`yuv.form.element.range-select-filesize.option.${v.range}`)
1302
+ label: this.translate.instant(`yuv.form.element.range-select-filesize.option.${v}`)
1817
1303
  };
1304
+ this.value = res || null;
1818
1305
  this.propagateChange(res);
1819
1306
  }
1820
1307
  #setupOptions() {
@@ -1831,105 +1318,406 @@ class RangeSelectFilesizeComponent {
1831
1318
  ]);
1832
1319
  }
1833
1320
  writeValue(value) {
1834
- const patch = { range: this.#ANY_OPTION };
1321
+ this.value = value || null;
1322
+ let patch = this.#ANY_OPTION;
1835
1323
  if (value?.rangeValue?.operator && value?.rangeValue?.firstValue) {
1836
1324
  const range = SearchUtils.getMatchingFilesizeRange(value.rangeValue);
1837
1325
  if (range)
1838
- patch.range = range;
1326
+ patch = range;
1839
1327
  }
1840
- this.innerForm.patchValue(patch);
1328
+ this.fc.patchValue(patch);
1841
1329
  }
1842
1330
  registerOnChange(fn) {
1843
1331
  this.propagateChange = fn;
1844
1332
  }
1845
1333
  // eslint-disable-next-line @typescript-eslint/no-empty-function
1846
1334
  registerOnTouched(fn) { }
1847
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: RangeSelectFilesizeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1848
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "18.2.13", type: RangeSelectFilesizeComponent, isStandalone: true, selector: "yuv-range-select-filesize", inputs: { ranges: { classPropertyName: "ranges", publicName: "ranges", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
1849
- {
1850
- provide: NG_VALUE_ACCESSOR,
1851
- useExisting: forwardRef(() => RangeSelectFilesizeComponent),
1852
- multi: true
1853
- }
1854
- ], ngImport: i0, template: "<form [formGroup]=\"innerForm\">\n <yvc-dropdown formControlName=\"range\" [options]=\"options()\" [disableClearButton]=\"true\"></yvc-dropdown>\n</form>\n", styles: [":host form{display:flex}:host form yvc-dropdown{flex:1;outline-offset:0px;color:currentColor}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: YvcDropdownModule }, { kind: "component", type: i1$1.Dropdown, selector: "yvc-dropdown", inputs: ["options", "filter", "disabled", "multiple", "disableClearButton"], outputs: ["onDropdownOptionsClose"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }] }); }
1335
+ ngOnDestroy() {
1336
+ super.onNgOnDestroy();
1337
+ }
1338
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: RangeSelectFilesizeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1339
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.1", type: RangeSelectFilesizeComponent, isStandalone: true, selector: "yuv-range-select-filesize", inputs: { ranges: { classPropertyName: "ranges", publicName: "ranges", isSignal: true, isRequired: false, transformFunction: null } }, providers: [{ provide: MatFormFieldControl, useExisting: RangeSelectFilesizeComponent }], usesInheritance: true, ngImport: i0, template: "<mat-select [panelWidth]=\"null\" [hideSingleSelectionIndicator]=\"true\" [formControl]=\"fc\">\n @for (o of options(); track $index) {\n <mat-option [value]=\"o.value\">{{ o.label }}</mat-option>\n }\n</mat-select>\n", styles: [":host{display:flex}:host mat-select{flex:1}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i1$2.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i1$2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }] }); }
1855
1340
  }
1856
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: RangeSelectFilesizeComponent, decorators: [{
1341
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: RangeSelectFilesizeComponent, decorators: [{
1857
1342
  type: Component,
1858
- args: [{ selector: 'yuv-range-select-filesize', standalone: true, imports: [CommonModule, YvcDropdownModule, ReactiveFormsModule], providers: [
1859
- {
1860
- provide: NG_VALUE_ACCESSOR,
1861
- useExisting: forwardRef(() => RangeSelectFilesizeComponent),
1862
- multi: true
1863
- }
1864
- ], template: "<form [formGroup]=\"innerForm\">\n <yvc-dropdown formControlName=\"range\" [options]=\"options()\" [disableClearButton]=\"true\"></yvc-dropdown>\n</form>\n", styles: [":host form{display:flex}:host form yvc-dropdown{flex:1;outline-offset:0px;color:currentColor}\n"] }]
1343
+ args: [{ selector: 'yuv-range-select-filesize', standalone: true, imports: [CommonModule, MatSelectModule, ReactiveFormsModule], providers: [{ provide: MatFormFieldControl, useExisting: RangeSelectFilesizeComponent }], template: "<mat-select [panelWidth]=\"null\" [hideSingleSelectionIndicator]=\"true\" [formControl]=\"fc\">\n @for (o of options(); track $index) {\n <mat-option [value]=\"o.value\">{{ o.label }}</mat-option>\n }\n</mat-select>\n", styles: [":host{display:flex}:host mat-select{flex:1}\n"] }]
1865
1344
  }], ctorParameters: () => [] });
1866
1345
 
1346
+ /**
1347
+ * Creates form input for strings. Based on the input values different kinds of inputs will be generated.
1348
+ *
1349
+ * Implements `ControlValueAccessor` so it can be used within Angular forms.
1350
+ *
1351
+ * @example
1352
+ * <!-- string input validating input to be between 5 and 10 characters -->
1353
+ * <yuv-string [minLength]="5" [maxLength]="10"></yuv-string>
1354
+ *
1355
+ * <!-- string input that only allow digits -->
1356
+ * <yuv-string [regex]="[0-9]*"></yuv-string>
1357
+ *
1358
+ * <!-- string input rendering a large textarea -->
1359
+ * <yuv-string [rows]="10"></yuv-string>
1360
+ *
1361
+ */
1362
+ class StringComponent extends AbstractMatFormField {
1363
+ constructor() {
1364
+ super(...arguments);
1365
+ this.#elRef = inject(ElementRef);
1366
+ this.#dRef = inject(DestroyRef);
1367
+ this.fc = new FormControl(undefined);
1368
+ this.separatorKeysCodes = [ENTER, COMMA];
1369
+ this.classifiytionIcons = {
1370
+ email: 'email',
1371
+ url: 'language',
1372
+ phone: 'call'
1373
+ };
1374
+ /**
1375
+ * Indicator that multiple strings could be inserted, they will be rendered as chips (default: false).
1376
+ */
1377
+ this.multiselect = false;
1378
+ /**
1379
+ * Will prevent the input from being changed (default: false)
1380
+ */
1381
+ this.readonly = false;
1382
+ /**
1383
+ * Enable autofucus for the input (default: false)
1384
+ */
1385
+ this.autofocus = false;
1386
+ this.valid = false;
1387
+ this.validationErrors = [];
1388
+ this.#classifications = [];
1389
+ this.ngControl = injectNgControl(this);
1390
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
1391
+ this.propagateChange = (_) => { };
1392
+ }
1393
+ #elRef;
1394
+ #dRef;
1395
+ /**
1396
+ * Additional semantics for the form element. Possible values are
1397
+ * `email` (validates and creates a link to send an email once there
1398
+ * is a valid email address) and `url` (validates and creates a link
1399
+ * to an URL typed into the form element).
1400
+ */
1401
+ set classifications(c) {
1402
+ this.#classifications = c;
1403
+ if (c && c.length) {
1404
+ if (c.includes(Classification.STRING_EMAIL)) {
1405
+ this.classify = {
1406
+ hrefPrefix: ClassificationPrefix.EMAIL,
1407
+ icon: this.classifiytionIcons.email
1408
+ };
1409
+ }
1410
+ else if (c.includes(Classification.STRING_URL)) {
1411
+ this.classify = {
1412
+ hrefPrefix: ClassificationPrefix.URL,
1413
+ icon: this.classifiytionIcons.url
1414
+ };
1415
+ }
1416
+ else if (c.includes(Classification.STRING_PHONE)) {
1417
+ this.classify = {
1418
+ hrefPrefix: ClassificationPrefix.PHONE,
1419
+ icon: this.classifiytionIcons.phone
1420
+ };
1421
+ }
1422
+ }
1423
+ }
1424
+ get classifications() {
1425
+ return this.#classifications;
1426
+ }
1427
+ #classifications;
1428
+ propagate() {
1429
+ this.propagateChange(this.value);
1430
+ }
1431
+ writeValue(value) {
1432
+ if (Array.isArray(value)) {
1433
+ value = value.filter((v) => typeof v === 'string' && v.trim().length > 0);
1434
+ }
1435
+ else {
1436
+ this.formatedValue = Utils.formatMailTo(value, this.classify?.hrefPrefix === ClassificationPrefix.EMAIL);
1437
+ }
1438
+ this.fc.patchValue(value);
1439
+ this.value = value || undefined;
1440
+ }
1441
+ registerOnChange(fn) {
1442
+ this.propagateChange = fn;
1443
+ }
1444
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
1445
+ registerOnTouched() { }
1446
+ #onValueChange(val) {
1447
+ this.value = val;
1448
+ this.empty = Utils.isEmpty(val);
1449
+ if (this.empty) {
1450
+ this.value = undefined;
1451
+ this.propagate();
1452
+ return;
1453
+ }
1454
+ this.formatedValue = Utils.formatMailTo(val, this.classify?.hrefPrefix === ClassificationPrefix.EMAIL);
1455
+ this.propagate();
1456
+ }
1457
+ onBlur() {
1458
+ if (!this.value)
1459
+ return;
1460
+ // only called by single item input
1461
+ const value = this.value;
1462
+ const lengthBefore = value.length;
1463
+ this.value = value.trim();
1464
+ if (this.value.length !== lengthBefore) {
1465
+ this.propagate();
1466
+ }
1467
+ }
1468
+ // chips for multiselect
1469
+ chipsAdd(event) {
1470
+ const value = (event.value || '').trim();
1471
+ if (value) {
1472
+ this.value = [...(this.value || []), value];
1473
+ this.fc.patchValue(this.value);
1474
+ }
1475
+ // Clear the input value
1476
+ event.chipInput.clear();
1477
+ }
1478
+ chipsRemove(v) {
1479
+ const currValue = this.value;
1480
+ const index = currValue.indexOf(v);
1481
+ if (index !== -1) {
1482
+ currValue.splice(index, 1);
1483
+ this.value = [...currValue];
1484
+ this.fc.patchValue(this.value);
1485
+ }
1486
+ }
1487
+ chipsEdit(v, event) {
1488
+ const value = event.value.trim();
1489
+ if (!value) {
1490
+ this.chipsRemove(v);
1491
+ return;
1492
+ }
1493
+ const currValue = this.value;
1494
+ const index = currValue.indexOf(v);
1495
+ if (index >= 0) {
1496
+ currValue[index] = value;
1497
+ this.value = [...currValue];
1498
+ this.fc.patchValue(this.value);
1499
+ }
1500
+ }
1501
+ validateClassification(string, classification) {
1502
+ if (this.situation === Situation.SEARCH) {
1503
+ return true;
1504
+ }
1505
+ else {
1506
+ let pattern;
1507
+ if (classification === Classification.STRING_EMAIL) {
1508
+ pattern =
1509
+ /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
1510
+ }
1511
+ else if (classification === Classification.STRING_URL) {
1512
+ pattern = /(http|ftp|https):\/\/[\w-]+(\.[\w-]+)?([\w.,@?^=%&amp;:\/~+#-]*[\w@?^=%&amp;\/~+#-])?/;
1513
+ }
1514
+ else if (classification === Classification.STRING_PHONE) {
1515
+ pattern = /^[+]*[(]{0,1}[0-9]{1,4}[)]{0,1}[-x\s\./0-9]*$/g;
1516
+ }
1517
+ return pattern ? pattern.test(string) : true;
1518
+ }
1519
+ }
1520
+ #getValidator() {
1521
+ return (control) => {
1522
+ this.maxEntryCountIfInvalid = undefined;
1523
+ this.validationErrors = [];
1524
+ const val = control.value;
1525
+ if (!val)
1526
+ return null;
1527
+ const multiCheck = (check) => !!(this.multiselect ? val : [val]).find((v) => check(v));
1528
+ // validate regular expression
1529
+ if (this.regex && multiCheck((v) => !RegExp(this.regex).test(v))) {
1530
+ this.validationErrors.push({ key: 'regex' });
1531
+ }
1532
+ // validate classification settings
1533
+ if (this.classifications && this.classifications.length) {
1534
+ this.classifications.forEach((c) => {
1535
+ if (multiCheck((v) => !this.validateClassification(v, c))) {
1536
+ this.validationErrors.push({ key: 'classification' + c });
1537
+ }
1538
+ });
1539
+ }
1540
+ // validate min length
1541
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
1542
+ if (!Utils.isEmpty(this.minLength) && multiCheck((v) => v.length < this.minLength)) {
1543
+ this.validationErrors.push({ key: 'minlength', params: { minLength: this.minLength } });
1544
+ }
1545
+ // validate max length
1546
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
1547
+ if (!Utils.isEmpty(this.maxLength) && multiCheck((v) => v.length > this.maxLength)) {
1548
+ this.validationErrors.push({ key: 'maxlength', params: { maxLength: this.maxLength } });
1549
+ }
1550
+ // validate invalid if only whitespaces
1551
+ if (multiCheck((v) => v.length > 0 && !v.trim().length)) {
1552
+ this.validationErrors.push({ key: 'onlyWhitespaces' });
1553
+ }
1554
+ if (this.validationErrors.length && this.multiselect && this.value) {
1555
+ // Setting maxEntryCountIfInvalid to the actual length of the value array to prevent the user to add more entries.
1556
+ this.maxEntryCountIfInvalid = this.value.length;
1557
+ }
1558
+ if (this.validationErrors.length) {
1559
+ this.valid = false;
1560
+ return Utils.arrayToObject(this.validationErrors, 'key', (err) => ({ valid: false, ...err }));
1561
+ }
1562
+ else {
1563
+ this.valid = true;
1564
+ return null;
1565
+ }
1566
+ };
1567
+ }
1568
+ ngOnInit() {
1569
+ this.fc.setValidators(this.#getValidator());
1570
+ this.fc.statusChanges.pipe(takeUntilDestroyed(this.#dRef)).subscribe((v) => {
1571
+ this.errorState = this.fc.invalid;
1572
+ if (this.ngControl?.control) {
1573
+ this.ngControl.control.setErrors(this.fc.errors);
1574
+ }
1575
+ });
1576
+ this.fc.updateValueAndValidity();
1577
+ this.fc.valueChanges.pipe(takeUntilDestroyed(this.#dRef)).subscribe((v) => this.#onValueChange(v));
1578
+ }
1579
+ ngAfterViewInit() {
1580
+ if (this.autofocus) {
1581
+ if (!this.multiselect) {
1582
+ const el = this.#elRef.nativeElement.querySelector(this.rows && this.rows > 1 ? 'textarea' : 'input');
1583
+ if (el)
1584
+ el.focus();
1585
+ }
1586
+ }
1587
+ }
1588
+ ngOnDestroy() {
1589
+ super.onNgOnDestroy();
1590
+ }
1591
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: StringComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
1592
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.1", type: StringComponent, isStandalone: true, selector: "yuv-string", inputs: { multiselect: "multiselect", rows: "rows", readonly: "readonly", autofocus: "autofocus", classifications: "classifications", situation: "situation", regex: "regex", minLength: "minLength", maxLength: "maxLength" }, providers: [{ provide: MatFormFieldControl, useExisting: StringComponent }], usesInheritance: true, ngImport: i0, template: "@if ((!rows || rows <= 1) && !multiselect) {\n <input matInput type=\"text\" (blur)=\"onBlur()\" [disabled]=\"disabled\" [readonly]=\"readonly\" [formControl]=\"fc\" />\n} @else if ((!rows || rows <= 1) && multiselect) {\n <!-- single line input with multiselect-->\n <mat-chip-grid #chipGrid [formControl]=\"fc\" [disabled]=\"disabled\">\n @for (v of value; track v) {\n <mat-chip-row (removed)=\"chipsRemove(v)\" [editable]=\"true\" (edited)=\"chipsEdit(v, $event)\">\n {{ v }}\n <button matChipRemove>\n <mat-icon>cancel</mat-icon>\n </button>\n </mat-chip-row>\n }\n <input\n [disabled]=\"disabled\"\n [matChipInputFor]=\"chipGrid\"\n [matChipInputSeparatorKeyCodes]=\"separatorKeysCodes\"\n [matChipInputAddOnBlur]=\"true\"\n (matChipInputTokenEnd)=\"chipsAdd($event)\"\n />\n </mat-chip-grid>\n} @else if (rows && rows > 1) {\n <!-- multi line text inputs -->\n <textarea\n matInput\n class=\"input-textarea\"\n (blur)=\"onBlur()\"\n [rows]=\"rows\"\n [disabled]=\"disabled\"\n [readonly]=\"readonly\"\n [formControl]=\"fc\"\n ></textarea>\n}\n\n@if (classify) {\n <div class=\"classify\">\n @if (value && !validationErrors.length && (classify.hrefPrefix !== '' || !multiselect || value.length <= 1)) {\n <a href=\"{{ classify.hrefPrefix + formatedValue }}\">\n <mat-icon>{{ classify.icon }}</mat-icon>\n </a>\n } @else {\n <mat-icon>{{ classify.icon }}</mat-icon>\n }\n </div>\n}\n", styles: [":host{display:flex;flex-flow:row nowrap;flex:1;align-items:center}:host mat-chip-grid{flex:1}:host textarea.input-textarea{width:100%;resize:vertical;background-color:transparent;border:0;outline:0}:host input{display:flex;flex-wrap:wrap;align-items:center;width:100%;border:0;outline:0;background:transparent}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatChipsModule }, { kind: "component", type: i1$3.MatChipGrid, selector: "mat-chip-grid", inputs: ["disabled", "placeholder", "required", "value", "errorStateMatcher"], outputs: ["change", "valueChange"] }, { kind: "directive", type: i1$3.MatChipInput, selector: "input[matChipInputFor]", inputs: ["matChipInputFor", "matChipInputAddOnBlur", "matChipInputSeparatorKeyCodes", "placeholder", "id", "disabled"], outputs: ["matChipInputTokenEnd"], exportAs: ["matChipInput", "matChipInputFor"] }, { kind: "directive", type: i1$3.MatChipRemove, selector: "[matChipRemove]" }, { kind: "component", type: i1$3.MatChipRow, selector: "mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]", inputs: ["editable"], outputs: ["edited"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: FormsModule }] }); }
1593
+ }
1594
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: StringComponent, decorators: [{
1595
+ type: Component,
1596
+ args: [{ selector: 'yuv-string', standalone: true, imports: [CommonModule, MatChipsModule, MatIconModule, ReactiveFormsModule, FormsModule], providers: [{ provide: MatFormFieldControl, useExisting: StringComponent }], template: "@if ((!rows || rows <= 1) && !multiselect) {\n <input matInput type=\"text\" (blur)=\"onBlur()\" [disabled]=\"disabled\" [readonly]=\"readonly\" [formControl]=\"fc\" />\n} @else if ((!rows || rows <= 1) && multiselect) {\n <!-- single line input with multiselect-->\n <mat-chip-grid #chipGrid [formControl]=\"fc\" [disabled]=\"disabled\">\n @for (v of value; track v) {\n <mat-chip-row (removed)=\"chipsRemove(v)\" [editable]=\"true\" (edited)=\"chipsEdit(v, $event)\">\n {{ v }}\n <button matChipRemove>\n <mat-icon>cancel</mat-icon>\n </button>\n </mat-chip-row>\n }\n <input\n [disabled]=\"disabled\"\n [matChipInputFor]=\"chipGrid\"\n [matChipInputSeparatorKeyCodes]=\"separatorKeysCodes\"\n [matChipInputAddOnBlur]=\"true\"\n (matChipInputTokenEnd)=\"chipsAdd($event)\"\n />\n </mat-chip-grid>\n} @else if (rows && rows > 1) {\n <!-- multi line text inputs -->\n <textarea\n matInput\n class=\"input-textarea\"\n (blur)=\"onBlur()\"\n [rows]=\"rows\"\n [disabled]=\"disabled\"\n [readonly]=\"readonly\"\n [formControl]=\"fc\"\n ></textarea>\n}\n\n@if (classify) {\n <div class=\"classify\">\n @if (value && !validationErrors.length && (classify.hrefPrefix !== '' || !multiselect || value.length <= 1)) {\n <a href=\"{{ classify.hrefPrefix + formatedValue }}\">\n <mat-icon>{{ classify.icon }}</mat-icon>\n </a>\n } @else {\n <mat-icon>{{ classify.icon }}</mat-icon>\n }\n </div>\n}\n", styles: [":host{display:flex;flex-flow:row nowrap;flex:1;align-items:center}:host mat-chip-grid{flex:1}:host textarea.input-textarea{width:100%;resize:vertical;background-color:transparent;border:0;outline:0}:host input{display:flex;flex-wrap:wrap;align-items:center;width:100%;border:0;outline:0;background:transparent}\n"] }]
1597
+ }], propDecorators: { multiselect: [{
1598
+ type: Input
1599
+ }], rows: [{
1600
+ type: Input
1601
+ }], readonly: [{
1602
+ type: Input
1603
+ }], autofocus: [{
1604
+ type: Input
1605
+ }], classifications: [{
1606
+ type: Input
1607
+ }], situation: [{
1608
+ type: Input
1609
+ }], regex: [{
1610
+ type: Input
1611
+ }], minLength: [{
1612
+ type: Input
1613
+ }], maxLength: [{
1614
+ type: Input
1615
+ }] } });
1616
+
1617
+ class CatalogComponent extends AbstractMatFormField {
1618
+ constructor() {
1619
+ super(...arguments);
1620
+ this.#system = inject(SystemService);
1621
+ this.#dRef = inject(DestroyRef);
1622
+ this.readonly = input(false);
1623
+ this.multiple = input(false);
1624
+ this._options = signal([]);
1625
+ this.options = input([]);
1626
+ this.#optionsEffect = effect(() => {
1627
+ untracked(() => {
1628
+ this._options.set(this.options() || []);
1629
+ });
1630
+ });
1631
+ /**
1632
+ * Additional semantics for the form element.
1633
+ */
1634
+ this.classifications = input([]);
1635
+ this.#classificationEffect = effect(() => {
1636
+ const cls = this.classifications();
1637
+ untracked(() => {
1638
+ const ce = this.#system.getClassifications(cls).get(Classification.STRING_CATALOG);
1639
+ if (ce && ce.options) {
1640
+ this._options.set(ce.options);
1641
+ }
1642
+ });
1643
+ });
1644
+ this.ngControl = injectNgControl(this);
1645
+ this.fc = new FormControl(undefined);
1646
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
1647
+ this.propagateChange = (_) => { };
1648
+ }
1649
+ #system;
1650
+ #dRef;
1651
+ #optionsEffect;
1652
+ #classificationEffect;
1653
+ #onValueChange(val) {
1654
+ this.value = val;
1655
+ this.propagateChange(this.value);
1656
+ }
1657
+ writeValue(value) {
1658
+ this.value = value;
1659
+ }
1660
+ registerOnChange(fn) {
1661
+ this.propagateChange = fn;
1662
+ }
1663
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
1664
+ registerOnTouched(fn) { }
1665
+ ngOnInit() {
1666
+ this.fc.valueChanges.pipe(takeUntilDestroyed(this.#dRef)).subscribe((v) => this.#onValueChange(v));
1667
+ }
1668
+ ngOnDestroy() {
1669
+ super.onNgOnDestroy();
1670
+ }
1671
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: CatalogComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
1672
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.1", type: CatalogComponent, isStandalone: true, selector: "yuv-catalog", inputs: { readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, classifications: { classPropertyName: "classifications", publicName: "classifications", isSignal: true, isRequired: false, transformFunction: null }, situation: { classPropertyName: "situation", publicName: "situation", isSignal: false, isRequired: false, transformFunction: null } }, providers: [{ provide: MatFormFieldControl, useExisting: CatalogComponent }], usesInheritance: true, ngImport: i0, template: "<mat-select [multiple]=\"multiple()\" [disabled]=\"readonly()\" [formControl]=\"fc\">\n @for (o of _options(); track o) {\n <mat-option [value]=\"o\">{{ o }}</mat-option>\n }\n</mat-select>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i1$2.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i1$2.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }] }); }
1673
+ }
1674
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: CatalogComponent, decorators: [{
1675
+ type: Component,
1676
+ args: [{ selector: 'yuv-catalog', imports: [CommonModule, MatSelectModule, ReactiveFormsModule], providers: [{ provide: MatFormFieldControl, useExisting: CatalogComponent }], template: "<mat-select [multiple]=\"multiple()\" [disabled]=\"readonly()\" [formControl]=\"fc\">\n @for (o of _options(); track o) {\n <mat-option [value]=\"o\">{{ o }}</mat-option>\n }\n</mat-select>\n" }]
1677
+ }], propDecorators: { situation: [{
1678
+ type: Input
1679
+ }] } });
1680
+
1681
+ const formElementCmps = [
1682
+ StringComponent,
1683
+ NumberComponent,
1684
+ NumberRangeComponent,
1685
+ DatetimeComponent,
1686
+ DatetimeRangeComponent,
1687
+ OrganizationComponent,
1688
+ StringComponent,
1689
+ CatalogComponent
1690
+ ];
1867
1691
  class YuvFormsModule {
1868
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: YuvFormsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
1869
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: YuvFormsModule, imports: [CommonModule,
1870
- FormsModule,
1871
- TranslateModule$1,
1872
- ReactiveFormsModule,
1873
- YvcFocusWithin,
1874
- YvcAutocompleteModule,
1875
- YvcDatepickerModule,
1876
- FormsModule,
1877
- YvcCheckboxModule,
1878
- YvcIconModule,
1879
- YvcChipsModule,
1880
- YvcDropdownModule] }); }
1881
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: YuvFormsModule, imports: [CommonModule,
1882
- FormsModule,
1883
- TranslateModule$1,
1884
- ReactiveFormsModule,
1885
- YvcAutocompleteModule,
1886
- YvcDatepickerModule,
1887
- FormsModule,
1888
- YvcCheckboxModule,
1889
- YvcIconModule,
1890
- YvcChipsModule,
1891
- YvcDropdownModule] }); }
1692
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: YuvFormsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
1693
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.1", ngImport: i0, type: YuvFormsModule, imports: [StringComponent,
1694
+ NumberComponent,
1695
+ NumberRangeComponent,
1696
+ DatetimeComponent,
1697
+ DatetimeRangeComponent,
1698
+ OrganizationComponent,
1699
+ StringComponent,
1700
+ CatalogComponent], exports: [StringComponent,
1701
+ NumberComponent,
1702
+ NumberRangeComponent,
1703
+ DatetimeComponent,
1704
+ DatetimeRangeComponent,
1705
+ OrganizationComponent,
1706
+ StringComponent,
1707
+ CatalogComponent] }); }
1708
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: YuvFormsModule, imports: [formElementCmps] }); }
1892
1709
  }
1893
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: YuvFormsModule, decorators: [{
1710
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.1", ngImport: i0, type: YuvFormsModule, decorators: [{
1894
1711
  type: NgModule,
1895
1712
  args: [{
1896
- imports: [
1897
- CommonModule,
1898
- FormsModule,
1899
- TranslateModule$1,
1900
- ReactiveFormsModule,
1901
- YvcFocusWithin,
1902
- YvcAutocompleteModule,
1903
- YvcDatepickerModule,
1904
- FormsModule,
1905
- YvcCheckboxModule,
1906
- YvcIconModule,
1907
- YvcChipsModule,
1908
- YvcDropdownModule,
1909
- ]
1713
+ imports: [...formElementCmps],
1714
+ exports: [...formElementCmps]
1910
1715
  }]
1911
1716
  }] });
1912
1717
 
1913
- // export { CatalogComponent } from './lib/elements/catalog/catalog.component';
1914
- // export { CheckboxComponent } from './lib/elements/checkbox/checkbox.component';
1915
- // export { DatetimeRangeComponent } from './lib/elements/datetime-range/datetime-range.component';
1916
- // export { DatepickerComponent } from './lib/elements/datetime/datepicker/datepicker.component';
1917
- // export { DatetimeComponent } from './lib/elements/datetime/datetime.component';
1918
- // export { YearRangeDirective } from './lib/elements/datetime/year-range/year-range.directive';
1919
- // export { DynamicCatalogManagementComponent } from './lib/elements/dynamic-catalog/dynamic-catalog-management/dynamic-catalog-management.component';
1920
- // export { DynamicCatalogComponent } from './lib/elements/dynamic-catalog/dynamic-catalog.component';
1921
- // export { NumberRangeComponent } from './lib/elements/number-range/number-range.component';
1922
- // export { NumberComponent } from './lib/elements/number/number.component';
1923
- // export { OrganizationSetComponent } from './lib/elements/organization-set/organization-set.component';
1924
- // export { OrganizationComponent } from './lib/elements/organization/organization.component';
1925
- // export { ReferenceItemComponent } from './lib/elements/reference/reference-item/reference-item.component';
1926
- // export { ReferenceComponent } from './lib/elements/reference/reference.component';
1927
- // export * from './lib/elements/reference/reference.interface';
1928
- // export { StringComponent } from './lib/elements/string/string.component';
1929
-
1930
1718
  /**
1931
1719
  * Generated bundle index. Do not edit.
1932
1720
  */
1933
1721
 
1934
- export { CatalogComponent, DataGridComponent, DatetimeComponent, DatetimeRangeComponent, FormInputComponent, NumberComponent, NumberRangeComponent, OrganizationComponent, RangeSelectDateComponent, RangeSelectFilesizeComponent, StringComponent, YuvFormsModule };
1722
+ export { CatalogComponent, DataGridComponent, DatetimeComponent, DatetimeRangeComponent, NumberComponent, NumberRangeComponent, OrganizationComponent, RangeSelectDateComponent, RangeSelectFilesizeComponent, StringComponent, YuvFormsModule };
1935
1723
  //# sourceMappingURL=yuuvis-client-framework-forms.mjs.map