@vadem/ui 0.0.0-stage → 0.0.1

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 (289) hide show
  1. package/LICENSE-lucide.txt +43 -0
  2. package/README.md +19 -2
  3. package/fesm2022/vadem-ui-accordion.mjs +139 -0
  4. package/fesm2022/vadem-ui-accordion.mjs.map +1 -0
  5. package/fesm2022/vadem-ui-active-filters.mjs +355 -0
  6. package/fesm2022/vadem-ui-active-filters.mjs.map +1 -0
  7. package/fesm2022/vadem-ui-alert-dialog.mjs +433 -0
  8. package/fesm2022/vadem-ui-alert-dialog.mjs.map +1 -0
  9. package/fesm2022/vadem-ui-alert.mjs +266 -0
  10. package/fesm2022/vadem-ui-alert.mjs.map +1 -0
  11. package/fesm2022/vadem-ui-autocomplete.mjs +715 -0
  12. package/fesm2022/vadem-ui-autocomplete.mjs.map +1 -0
  13. package/fesm2022/vadem-ui-avatar.mjs +219 -0
  14. package/fesm2022/vadem-ui-avatar.mjs.map +1 -0
  15. package/fesm2022/vadem-ui-badge.mjs +86 -0
  16. package/fesm2022/vadem-ui-badge.mjs.map +1 -0
  17. package/fesm2022/vadem-ui-breadcrumbs.mjs +61 -0
  18. package/fesm2022/vadem-ui-breadcrumbs.mjs.map +1 -0
  19. package/fesm2022/vadem-ui-button.mjs +220 -0
  20. package/fesm2022/vadem-ui-button.mjs.map +1 -0
  21. package/fesm2022/vadem-ui-calendar.mjs +1314 -0
  22. package/fesm2022/vadem-ui-calendar.mjs.map +1 -0
  23. package/fesm2022/vadem-ui-card.mjs +271 -0
  24. package/fesm2022/vadem-ui-card.mjs.map +1 -0
  25. package/fesm2022/vadem-ui-character-count.mjs +269 -0
  26. package/fesm2022/vadem-ui-character-count.mjs.map +1 -0
  27. package/fesm2022/vadem-ui-chart.mjs +1984 -0
  28. package/fesm2022/vadem-ui-chart.mjs.map +1 -0
  29. package/fesm2022/vadem-ui-checkbox.mjs +67 -0
  30. package/fesm2022/vadem-ui-checkbox.mjs.map +1 -0
  31. package/fesm2022/vadem-ui-color-picker.mjs +815 -0
  32. package/fesm2022/vadem-ui-color-picker.mjs.map +1 -0
  33. package/fesm2022/vadem-ui-command.mjs +735 -0
  34. package/fesm2022/vadem-ui-command.mjs.map +1 -0
  35. package/fesm2022/vadem-ui-copy-button.mjs +375 -0
  36. package/fesm2022/vadem-ui-copy-button.mjs.map +1 -0
  37. package/fesm2022/vadem-ui-date-range-picker.mjs +1011 -0
  38. package/fesm2022/vadem-ui-date-range-picker.mjs.map +1 -0
  39. package/fesm2022/vadem-ui-description-list.mjs +59 -0
  40. package/fesm2022/vadem-ui-description-list.mjs.map +1 -0
  41. package/fesm2022/vadem-ui-dialog.mjs +587 -0
  42. package/fesm2022/vadem-ui-dialog.mjs.map +1 -0
  43. package/fesm2022/vadem-ui-dropzone.mjs +176 -0
  44. package/fesm2022/vadem-ui-dropzone.mjs.map +1 -0
  45. package/fesm2022/vadem-ui-editable-text.mjs +641 -0
  46. package/fesm2022/vadem-ui-editable-text.mjs.map +1 -0
  47. package/fesm2022/vadem-ui-empty-state.mjs +175 -0
  48. package/fesm2022/vadem-ui-empty-state.mjs.map +1 -0
  49. package/fesm2022/vadem-ui-expandable-text.mjs +244 -0
  50. package/fesm2022/vadem-ui-expandable-text.mjs.map +1 -0
  51. package/fesm2022/vadem-ui-field.mjs +583 -0
  52. package/fesm2022/vadem-ui-field.mjs.map +1 -0
  53. package/fesm2022/vadem-ui-file-preview.mjs +532 -0
  54. package/fesm2022/vadem-ui-file-preview.mjs.map +1 -0
  55. package/fesm2022/vadem-ui-file-size.mjs +83 -0
  56. package/fesm2022/vadem-ui-file-size.mjs.map +1 -0
  57. package/fesm2022/vadem-ui-form-error-summary.mjs +201 -0
  58. package/fesm2022/vadem-ui-form-error-summary.mjs.map +1 -0
  59. package/fesm2022/vadem-ui-icon.mjs +303 -0
  60. package/fesm2022/vadem-ui-icon.mjs.map +1 -0
  61. package/fesm2022/vadem-ui-input.mjs +120 -0
  62. package/fesm2022/vadem-ui-input.mjs.map +1 -0
  63. package/fesm2022/vadem-ui-kbd.mjs +286 -0
  64. package/fesm2022/vadem-ui-kbd.mjs.map +1 -0
  65. package/fesm2022/vadem-ui-keyboard.mjs +105 -0
  66. package/fesm2022/vadem-ui-keyboard.mjs.map +1 -0
  67. package/fesm2022/vadem-ui-locale.mjs +443 -0
  68. package/fesm2022/vadem-ui-locale.mjs.map +1 -0
  69. package/fesm2022/vadem-ui-menu.mjs +637 -0
  70. package/fesm2022/vadem-ui-menu.mjs.map +1 -0
  71. package/fesm2022/vadem-ui-navigation-list.mjs +130 -0
  72. package/fesm2022/vadem-ui-navigation-list.mjs.map +1 -0
  73. package/fesm2022/vadem-ui-number-input.mjs +264 -0
  74. package/fesm2022/vadem-ui-number-input.mjs.map +1 -0
  75. package/fesm2022/vadem-ui-otp-input.mjs +86 -0
  76. package/fesm2022/vadem-ui-otp-input.mjs.map +1 -0
  77. package/fesm2022/vadem-ui-pagination.mjs +353 -0
  78. package/fesm2022/vadem-ui-pagination.mjs.map +1 -0
  79. package/fesm2022/vadem-ui-password-input.mjs +213 -0
  80. package/fesm2022/vadem-ui-password-input.mjs.map +1 -0
  81. package/fesm2022/vadem-ui-popover.mjs +178 -0
  82. package/fesm2022/vadem-ui-popover.mjs.map +1 -0
  83. package/fesm2022/vadem-ui-progress.mjs +331 -0
  84. package/fesm2022/vadem-ui-progress.mjs.map +1 -0
  85. package/fesm2022/vadem-ui-radio.mjs +39 -0
  86. package/fesm2022/vadem-ui-radio.mjs.map +1 -0
  87. package/fesm2022/vadem-ui-range-slider.mjs +561 -0
  88. package/fesm2022/vadem-ui-range-slider.mjs.map +1 -0
  89. package/fesm2022/vadem-ui-rating.mjs +404 -0
  90. package/fesm2022/vadem-ui-rating.mjs.map +1 -0
  91. package/fesm2022/vadem-ui-relative-time.mjs +217 -0
  92. package/fesm2022/vadem-ui-relative-time.mjs.map +1 -0
  93. package/fesm2022/vadem-ui-reorder-list.mjs +601 -0
  94. package/fesm2022/vadem-ui-reorder-list.mjs.map +1 -0
  95. package/fesm2022/vadem-ui-scroll-area.mjs +65 -0
  96. package/fesm2022/vadem-ui-scroll-area.mjs.map +1 -0
  97. package/fesm2022/vadem-ui-search-input.mjs +307 -0
  98. package/fesm2022/vadem-ui-search-input.mjs.map +1 -0
  99. package/fesm2022/vadem-ui-segmented.mjs +297 -0
  100. package/fesm2022/vadem-ui-segmented.mjs.map +1 -0
  101. package/fesm2022/vadem-ui-select.mjs +1462 -0
  102. package/fesm2022/vadem-ui-select.mjs.map +1 -0
  103. package/fesm2022/vadem-ui-sidebar.mjs +493 -0
  104. package/fesm2022/vadem-ui-sidebar.mjs.map +1 -0
  105. package/fesm2022/vadem-ui-skeleton.mjs +106 -0
  106. package/fesm2022/vadem-ui-skeleton.mjs.map +1 -0
  107. package/fesm2022/vadem-ui-slider.mjs +60 -0
  108. package/fesm2022/vadem-ui-slider.mjs.map +1 -0
  109. package/fesm2022/vadem-ui-splitter.mjs +438 -0
  110. package/fesm2022/vadem-ui-splitter.mjs.map +1 -0
  111. package/fesm2022/vadem-ui-stat.mjs +369 -0
  112. package/fesm2022/vadem-ui-stat.mjs.map +1 -0
  113. package/fesm2022/vadem-ui-stepper.mjs +483 -0
  114. package/fesm2022/vadem-ui-stepper.mjs.map +1 -0
  115. package/fesm2022/vadem-ui-switch.mjs +45 -0
  116. package/fesm2022/vadem-ui-switch.mjs.map +1 -0
  117. package/fesm2022/vadem-ui-table.mjs +593 -0
  118. package/fesm2022/vadem-ui-table.mjs.map +1 -0
  119. package/fesm2022/vadem-ui-tabs.mjs +405 -0
  120. package/fesm2022/vadem-ui-tabs.mjs.map +1 -0
  121. package/fesm2022/vadem-ui-tag-input.mjs +685 -0
  122. package/fesm2022/vadem-ui-tag-input.mjs.map +1 -0
  123. package/fesm2022/vadem-ui-text-highlight.mjs +126 -0
  124. package/fesm2022/vadem-ui-text-highlight.mjs.map +1 -0
  125. package/fesm2022/vadem-ui-time-input.mjs +430 -0
  126. package/fesm2022/vadem-ui-time-input.mjs.map +1 -0
  127. package/fesm2022/vadem-ui-timeline.mjs +313 -0
  128. package/fesm2022/vadem-ui-timeline.mjs.map +1 -0
  129. package/fesm2022/vadem-ui-toast.mjs +397 -0
  130. package/fesm2022/vadem-ui-toast.mjs.map +1 -0
  131. package/fesm2022/vadem-ui-toolbar.mjs +396 -0
  132. package/fesm2022/vadem-ui-toolbar.mjs.map +1 -0
  133. package/fesm2022/vadem-ui-tooltip.mjs +218 -0
  134. package/fesm2022/vadem-ui-tooltip.mjs.map +1 -0
  135. package/fesm2022/vadem-ui-tree.mjs +551 -0
  136. package/fesm2022/vadem-ui-tree.mjs.map +1 -0
  137. package/fesm2022/vadem-ui-upload-list.mjs +408 -0
  138. package/fesm2022/vadem-ui-upload-list.mjs.map +1 -0
  139. package/fesm2022/vadem-ui.mjs +4 -0
  140. package/fesm2022/vadem-ui.mjs.map +1 -0
  141. package/fonts/jetbrains-mono/OFL.txt +93 -0
  142. package/fonts/jetbrains-mono/jetbrains-mono-cyrillic.woff2 +0 -0
  143. package/fonts/jetbrains-mono/jetbrains-mono-latin.woff2 +0 -0
  144. package/fonts/manrope/OFL.txt +93 -0
  145. package/fonts/manrope/manrope-cyrillic.woff2 +0 -0
  146. package/fonts/manrope/manrope-latin.woff2 +0 -0
  147. package/package.json +306 -3
  148. package/styles/base.css +160 -0
  149. package/styles/components/accordion.css +130 -0
  150. package/styles/components/active-filters.css +42 -0
  151. package/styles/components/alert-dialog.css +34 -0
  152. package/styles/components/alert.css +159 -0
  153. package/styles/components/autocomplete.css +97 -0
  154. package/styles/components/avatar.css +90 -0
  155. package/styles/components/badge.css +91 -0
  156. package/styles/components/breadcrumbs.css +94 -0
  157. package/styles/components/button.css +174 -0
  158. package/styles/components/calendar.css +186 -0
  159. package/styles/components/card.css +206 -0
  160. package/styles/components/character-count.css +41 -0
  161. package/styles/components/chart.css +308 -0
  162. package/styles/components/checkbox.css +115 -0
  163. package/styles/components/color-picker.css +158 -0
  164. package/styles/components/command.css +175 -0
  165. package/styles/components/copy-button.css +58 -0
  166. package/styles/components/date-range-picker.css +153 -0
  167. package/styles/components/description-list.css +69 -0
  168. package/styles/components/dialog.css +334 -0
  169. package/styles/components/dropzone.css +89 -0
  170. package/styles/components/editable-text.css +58 -0
  171. package/styles/components/empty-state.css +72 -0
  172. package/styles/components/expandable-text.css +24 -0
  173. package/styles/components/field.css +148 -0
  174. package/styles/components/file-preview.css +65 -0
  175. package/styles/components/form-error-summary.css +71 -0
  176. package/styles/components/icon.css +38 -0
  177. package/styles/components/index.css +80 -0
  178. package/styles/components/input.css +171 -0
  179. package/styles/components/kbd.css +42 -0
  180. package/styles/components/menu.css +168 -0
  181. package/styles/components/multi-select.css +156 -0
  182. package/styles/components/navigation-list.css +147 -0
  183. package/styles/components/number-input.css +33 -0
  184. package/styles/components/otp-input.css +26 -0
  185. package/styles/components/pagination.css +127 -0
  186. package/styles/components/password-input.css +20 -0
  187. package/styles/components/popover.css +93 -0
  188. package/styles/components/progress-ring.css +112 -0
  189. package/styles/components/progress.css +162 -0
  190. package/styles/components/radio.css +117 -0
  191. package/styles/components/range-slider.css +158 -0
  192. package/styles/components/rating.css +100 -0
  193. package/styles/components/reorder-list.css +143 -0
  194. package/styles/components/scroll-area.css +39 -0
  195. package/styles/components/search-input.css +25 -0
  196. package/styles/components/segmented.css +136 -0
  197. package/styles/components/select.css +257 -0
  198. package/styles/components/sidebar.css +105 -0
  199. package/styles/components/skeleton.css +83 -0
  200. package/styles/components/slider.css +132 -0
  201. package/styles/components/splitter.css +83 -0
  202. package/styles/components/stat.css +62 -0
  203. package/styles/components/stepper.css +236 -0
  204. package/styles/components/switch.css +107 -0
  205. package/styles/components/table.css +195 -0
  206. package/styles/components/tabs.css +198 -0
  207. package/styles/components/tag-input.css +138 -0
  208. package/styles/components/text-highlight.css +22 -0
  209. package/styles/components/time-input.css +96 -0
  210. package/styles/components/timeline.css +182 -0
  211. package/styles/components/toast.css +146 -0
  212. package/styles/components/toolbar.css +72 -0
  213. package/styles/components/tooltip.css +93 -0
  214. package/styles/components/tree.css +88 -0
  215. package/styles/components/upload-list.css +113 -0
  216. package/styles/fonts.css +67 -0
  217. package/styles/index.css +14 -0
  218. package/styles/reset.css +57 -0
  219. package/styles/tokens/primitives.css +364 -0
  220. package/styles/tokens/semantic.css +233 -0
  221. package/types/vadem-ui-accordion.d.ts +43 -0
  222. package/types/vadem-ui-active-filters.d.ts +73 -0
  223. package/types/vadem-ui-alert-dialog.d.ts +87 -0
  224. package/types/vadem-ui-alert.d.ts +64 -0
  225. package/types/vadem-ui-autocomplete.d.ts +156 -0
  226. package/types/vadem-ui-avatar.d.ts +59 -0
  227. package/types/vadem-ui-badge.d.ts +25 -0
  228. package/types/vadem-ui-breadcrumbs.d.ts +22 -0
  229. package/types/vadem-ui-button.d.ts +52 -0
  230. package/types/vadem-ui-calendar.d.ts +327 -0
  231. package/types/vadem-ui-card.d.ts +58 -0
  232. package/types/vadem-ui-character-count.d.ts +71 -0
  233. package/types/vadem-ui-chart.d.ts +452 -0
  234. package/types/vadem-ui-checkbox.d.ts +20 -0
  235. package/types/vadem-ui-color-picker.d.ts +171 -0
  236. package/types/vadem-ui-command.d.ts +145 -0
  237. package/types/vadem-ui-copy-button.d.ts +90 -0
  238. package/types/vadem-ui-date-range-picker.d.ts +216 -0
  239. package/types/vadem-ui-description-list.d.ts +15 -0
  240. package/types/vadem-ui-dialog.d.ts +174 -0
  241. package/types/vadem-ui-dropzone.d.ts +73 -0
  242. package/types/vadem-ui-editable-text.d.ts +141 -0
  243. package/types/vadem-ui-empty-state.d.ts +34 -0
  244. package/types/vadem-ui-expandable-text.d.ts +52 -0
  245. package/types/vadem-ui-field.d.ts +180 -0
  246. package/types/vadem-ui-file-preview.d.ts +108 -0
  247. package/types/vadem-ui-file-size.d.ts +18 -0
  248. package/types/vadem-ui-form-error-summary.d.ts +46 -0
  249. package/types/vadem-ui-icon.d.ts +152 -0
  250. package/types/vadem-ui-input.d.ts +31 -0
  251. package/types/vadem-ui-kbd.d.ts +66 -0
  252. package/types/vadem-ui-keyboard.d.ts +61 -0
  253. package/types/vadem-ui-locale.d.ts +241 -0
  254. package/types/vadem-ui-menu.d.ts +132 -0
  255. package/types/vadem-ui-navigation-list.d.ts +28 -0
  256. package/types/vadem-ui-number-input.d.ts +39 -0
  257. package/types/vadem-ui-otp-input.d.ts +15 -0
  258. package/types/vadem-ui-pagination.d.ts +96 -0
  259. package/types/vadem-ui-password-input.d.ts +36 -0
  260. package/types/vadem-ui-popover.d.ts +48 -0
  261. package/types/vadem-ui-progress.d.ts +95 -0
  262. package/types/vadem-ui-radio.d.ts +11 -0
  263. package/types/vadem-ui-range-slider.d.ts +136 -0
  264. package/types/vadem-ui-rating.d.ts +95 -0
  265. package/types/vadem-ui-relative-time.d.ts +58 -0
  266. package/types/vadem-ui-reorder-list.d.ts +120 -0
  267. package/types/vadem-ui-scroll-area.d.ts +13 -0
  268. package/types/vadem-ui-search-input.d.ts +58 -0
  269. package/types/vadem-ui-segmented.d.ts +76 -0
  270. package/types/vadem-ui-select.d.ts +303 -0
  271. package/types/vadem-ui-sidebar.d.ts +70 -0
  272. package/types/vadem-ui-skeleton.d.ts +28 -0
  273. package/types/vadem-ui-slider.d.ts +17 -0
  274. package/types/vadem-ui-splitter.d.ts +99 -0
  275. package/types/vadem-ui-stat.d.ts +101 -0
  276. package/types/vadem-ui-stepper.d.ts +108 -0
  277. package/types/vadem-ui-switch.d.ts +10 -0
  278. package/types/vadem-ui-table.d.ts +172 -0
  279. package/types/vadem-ui-tabs.d.ts +101 -0
  280. package/types/vadem-ui-tag-input.d.ts +170 -0
  281. package/types/vadem-ui-text-highlight.d.ts +27 -0
  282. package/types/vadem-ui-time-input.d.ts +47 -0
  283. package/types/vadem-ui-timeline.d.ts +54 -0
  284. package/types/vadem-ui-toast.d.ts +104 -0
  285. package/types/vadem-ui-toolbar.d.ts +80 -0
  286. package/types/vadem-ui-tooltip.d.ts +71 -0
  287. package/types/vadem-ui-tree.d.ts +123 -0
  288. package/types/vadem-ui-upload-list.d.ts +70 -0
  289. package/types/vadem-ui.d.ts +1 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vadem-ui-tag-input.mjs","names":[],"sources":["../../../projects/ui/tag-input/src/core/tags.ts","../../../projects/ui/tag-input/src/tag-input.ts"],"sourcesContent":["/** Canonical display/editing identity without discarding accents or internal whitespace. */\nexport function vdTagKey(tag: string): string {\n return tag.trim().normalize('NFC').toLowerCase();\n}\n\nexport function vdNormalizeTags(value: readonly string[] | null | undefined): string[] {\n const seen = new Set<string>();\n return (value ?? [])\n .filter((tag) => {\n if (typeof tag !== 'string') return false;\n const key = vdTagKey(tag);\n if (!key || seen.has(key)) return false;\n seen.add(key);\n return true;\n })\n .map((tag) => tag.trim().normalize('NFC'));\n}\n\nexport function vdAddTag(\n value: readonly string[],\n draft: string,\n):\n | { kind: 'empty'; tag: string }\n | { kind: 'duplicate'; tag: string }\n | { kind: 'added'; tag: string; value: string[] } {\n const tag = draft.trim().normalize('NFC');\n if (!tag) return { kind: 'empty', tag };\n const tags = vdNormalizeTags(value);\n if (tags.some((item) => vdTagKey(item) === vdTagKey(tag))) return { kind: 'duplicate', tag };\n return { kind: 'added', tag, value: [...tags, tag] };\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n DestroyRef,\n ElementRef,\n Injector,\n OnInit,\n Signal,\n ViewEncapsulation,\n afterRenderEffect,\n booleanAttribute,\n computed,\n inject,\n input,\n model,\n output,\n signal,\n untracked,\n viewChild,\n viewChildren,\n} from '@angular/core';\nimport { NgControl } from '@angular/forms';\nimport { FormField, FormValueControl } from '@angular/forms/signals';\nimport {\n VD_FIELD,\n VdFieldControl,\n VdNgControlState,\n vdNgControlState,\n vdUniqueId,\n} from '@vadem/ui/field';\nimport { VdIcon } from '@vadem/ui/icon';\nimport { vdAddTag, vdNormalizeTags, vdTagKey } from './core/tags';\nimport { vdTexts } from '@vadem/ui/locale';\n\nexport type VdTagInputSize = 'sm' | 'md' | 'lg';\n\n/** User-defined tags with explicit editing actions. Spec: specs/tag-input.md. */\n@Component({\n selector: 'vd-tag-input',\n imports: [VdIcon],\n template: `\n <div class=\"vd-input-group vd-tag-input__field\" (pointerdown)=\"onFieldPointerDown($event)\">\n @if (tags().length) {\n <ul class=\"vd-tag-input__tags\" role=\"list\" [attr.aria-label]=\"t().tagsLabel\">\n @for (tag of tags(); track tagKey(tag)) {\n <li class=\"vd-tag-input__tag\">\n <span class=\"vd-tag-input__label\">{{ tag }}</span>\n <button\n #removeButton\n class=\"vd-tag-input__remove\"\n type=\"button\"\n [disabled]=\"locked()\"\n [attr.aria-label]=\"t().removeLabel(tag)\"\n (click)=\"remove(tag)\"\n (keydown.escape)=\"returnToInput($event)\"\n >\n <vd-icon name=\"x\" />\n </button>\n </li>\n }\n </ul>\n }\n <input\n #draftInput\n type=\"text\"\n class=\"vd-input vd-tag-input__input\"\n autocomplete=\"off\"\n [id]=\"controlId\"\n [attr.data-size]=\"size()\"\n [value]=\"draft()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"isDisabled()\"\n [readOnly]=\"readonly()\"\n [attr.data-invalid]=\"showInvalid() ? '' : null\"\n [attr.aria-invalid]=\"showInvalid() || null\"\n [attr.aria-required]=\"isRequired() || null\"\n [attr.aria-describedby]=\"descriptionIds()\"\n [attr.aria-label]=\"ariaLabel() ?? null\"\n [attr.aria-labelledby]=\"ariaLabelledby() ?? null\"\n (input)=\"onInput($event)\"\n (keydown)=\"onKeydown($event)\"\n (compositionstart)=\"composing = true\"\n (compositionend)=\"composing = false\"\n />\n <button\n class=\"vd-button vd-tag-input__add\"\n type=\"button\"\n data-variant=\"ghost\"\n [attr.data-size]=\"size()\"\n [disabled]=\"locked() || !draft().trim()\"\n (click)=\"add()\"\n >\n {{ t().addLabel }}\n </button>\n </div>\n <p\n class=\"vd-tag-input__feedback\"\n [id]=\"feedbackId\"\n role=\"status\"\n aria-atomic=\"true\"\n [textContent]=\"feedback()\"\n ></p>\n `,\n host: {\n class: 'vd-tag-input',\n '[attr.data-size]': 'size()',\n '[attr.data-invalid]': 'showInvalid() ? \"\" : null',\n '[attr.data-disabled]': 'isDisabled() ? \"\" : null',\n '[attr.data-readonly]': 'readonly() ? \"\" : null',\n '[attr.aria-label]': 'null',\n '[attr.aria-labelledby]': 'null',\n '(focusout)': 'onFocusOut($event)',\n },\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n})\nexport class VdTagInput implements FormValueControl<string[]>, OnInit {\n readonly value = model<string[]>([]);\n readonly size = input<VdTagInputSize>('md');\n readonly disabled = input(false, { transform: booleanAttribute });\n readonly readonly = input(false, { transform: booleanAttribute });\n readonly invalid = input(false, { transform: booleanAttribute });\n readonly touched = input(false, { transform: booleanAttribute });\n readonly required = input(false, { transform: booleanAttribute });\n readonly placeholder = input('');\n readonly ariaLabel = input<string | undefined>(undefined, { alias: 'aria-label' });\n readonly ariaLabelledby = input<string | undefined>(undefined, { alias: 'aria-labelledby' });\n readonly addLabel = input<string>();\n readonly tagsLabel = input<string>();\n readonly removeLabel = input<(tag: string) => string>();\n readonly addedMessage = input<(tag: string) => string>();\n readonly removedMessage = input<(tag: string) => string>();\n readonly duplicateMessage = input<(tag: string) => string>();\n /** Text inputs resolved against the active VD_LOCALE. */\n protected readonly t = vdTexts('tagInput', {\n addLabel: this.addLabel,\n tagsLabel: this.tagsLabel,\n removeLabel: this.removeLabel,\n addedMessage: this.addedMessage,\n removedMessage: this.removedMessage,\n duplicateMessage: this.duplicateMessage,\n });\n readonly touch = output<void>();\n\n readonly controlId = vdUniqueId('vd-tags');\n protected readonly feedbackId = vdUniqueId('vd-tags-feedback');\n protected readonly tagKey = vdTagKey;\n protected readonly tags = computed(() => vdNormalizeTags(this.value()));\n protected readonly draft = signal('');\n protected readonly feedback = signal('');\n protected composing = false;\n private readonly pendingFeedback = signal<string | null>(null);\n private readonly inputRef = viewChild<ElementRef<HTMLInputElement>>('draftInput');\n private readonly removeButtons = viewChildren<ElementRef<HTMLButtonElement>>('removeButton');\n private readonly hostEl: HTMLElement = inject(ElementRef).nativeElement;\n private readonly field = inject(VD_FIELD, { optional: true });\n private readonly injector = inject(Injector);\n private readonly destroyRef = inject(DestroyRef);\n private readonly formBound = signal(false);\n private readonly ngSource = signal<Signal<VdNgControlState> | null>(null);\n private readonly ngState = computed(\n () =>\n this.ngSource()?.() ?? { invalid: false, touched: false, disabled: false, required: false },\n );\n protected readonly isDisabled = computed(() => this.disabled() || this.ngState().disabled);\n protected readonly locked = computed(() => this.isDisabled() || this.readonly());\n protected readonly showInvalid = computed(\n () =>\n (this.invalid() && (!this.formBound() || this.touched())) ||\n (this.ngState().invalid && this.ngState().touched),\n );\n protected readonly isRequired = computed(() => this.required() || this.ngState().required);\n protected readonly descriptionIds = computed(\n () =>\n [this.field?.describedBy(), this.feedback() ? this.feedbackId : null]\n .filter(Boolean)\n .join(' ') || null,\n );\n private lastValue: string[] | null = null;\n\n constructor() {\n const control: VdFieldControl = {\n id: signal(this.controlId),\n invalid: this.showInvalid,\n required: this.isRequired,\n disabled: this.isDisabled,\n };\n this.field?.register(control);\n this.destroyRef.onDestroy(() => this.field?.unregister(control));\n // All form APIs bind the model directly. External replacements clear pending editing.\n afterRenderEffect(() => {\n const value = this.value();\n if (value !== this.lastValue) {\n this.lastValue = value;\n untracked(() => this.reset());\n }\n });\n // An empty render separates repeated identical status messages; no timers or SSR DOM access.\n afterRenderEffect(() => {\n const message = this.pendingFeedback();\n if (message !== null) {\n this.pendingFeedback.set(null);\n this.feedback.set(message);\n }\n });\n }\n\n ngOnInit(): void {\n const ng = this.injector.get(NgControl, null, { self: true, optional: true });\n this.formBound.set(\n !!ng || !!this.injector.get(FormField, null, { self: true, optional: true }),\n );\n this.ngSource.set(vdNgControlState(ng, this.destroyRef));\n }\n\n focus(options?: FocusOptions): void {\n this.inputRef()?.nativeElement.focus(options);\n }\n reset(): void {\n this.draft.set('');\n // Reset the native draft even if input and reset happened before a binding render.\n const input = this.inputRef()?.nativeElement;\n if (input) input.value = '';\n this.feedback.set('');\n this.pendingFeedback.set(null);\n this.composing = false;\n }\n protected onInput(event: Event): void {\n this.draft.set((event.target as HTMLInputElement).value);\n this.feedback.set('');\n this.pendingFeedback.set(null);\n }\n protected add(): void {\n if (this.locked() || this.composing) return;\n const result = vdAddTag(this.tags(), this.draft());\n if (result.kind === 'empty') return;\n if (result.kind === 'duplicate') this.announce(this.t().duplicateMessage(result.tag));\n else {\n this.commit(result.value);\n this.draft.set('');\n this.announce(this.t().addedMessage(result.tag));\n }\n this.focus();\n }\n protected remove(tag: string): void {\n if (this.locked() || !this.tags().includes(tag)) return;\n this.commit(this.tags().filter((item) => item !== tag));\n this.focus();\n this.announce(this.t().removedMessage(tag));\n }\n protected returnToInput(event: Event): void {\n event.preventDefault();\n event.stopPropagation();\n this.focus();\n }\n protected onKeydown(event: KeyboardEvent): void {\n if (\n event.isComposing ||\n this.composing ||\n this.locked() ||\n event.altKey ||\n event.ctrlKey ||\n event.metaKey ||\n event.shiftKey\n )\n return;\n if (event.key === 'Enter') {\n event.preventDefault();\n this.add();\n } else if (event.key === 'Backspace' && this.draft() === '') {\n const last = this.removeButtons().at(-1);\n if (last) {\n event.preventDefault();\n last.nativeElement.focus();\n }\n }\n }\n protected onFocusOut(event: FocusEvent): void {\n if (event.relatedTarget && this.hostEl.contains(event.relatedTarget as Node)) return;\n this.touch.emit();\n }\n protected onFieldPointerDown(event: PointerEvent): void {\n if (!this.isDisabled() && event.target === event.currentTarget) {\n event.preventDefault();\n this.focus();\n }\n }\n private commit(value: string[]): void {\n this.lastValue = value;\n this.value.set(value);\n }\n private announce(message: string): void {\n this.feedback.set('');\n this.pendingFeedback.set(message);\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,126 @@
1
+ import * as i0 from "@angular/core";
2
+ import { ChangeDetectionStrategy, Component, ViewEncapsulation, computed, input } from "@angular/core";
3
+ function vdTextHighlightParts(text, query) {
4
+ if (!text) return [];
5
+ if (!query) return [{
6
+ text,
7
+ matched: false
8
+ }];
9
+ const pattern = new RegExp(query.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "giu");
10
+ const parts = [];
11
+ let cursor = 0;
12
+ for (const match of text.matchAll(pattern)) {
13
+ if (match.index > cursor) parts.push({
14
+ text: text.slice(cursor, match.index),
15
+ matched: false
16
+ });
17
+ parts.push({
18
+ text: match[0],
19
+ matched: true
20
+ });
21
+ cursor = match.index + match[0].length;
22
+ }
23
+ if (cursor < text.length) parts.push({
24
+ text: text.slice(cursor),
25
+ matched: false
26
+ });
27
+ return parts;
28
+ }
29
+ var VdTextHighlight = class VdTextHighlight {
30
+ text = input.required(...ngDevMode ? [{ debugName: "text" }] : /* istanbul ignore next */ []);
31
+ query = input("", ...ngDevMode ? [{ debugName: "query" }] : /* istanbul ignore next */ []);
32
+ parts = computed(() => vdTextHighlightParts(this.text(), this.query()), ...ngDevMode ? [{ debugName: "parts" }] : /* istanbul ignore next */ []);
33
+ matched = computed(() => this.parts().some((part) => part.matched), ...ngDevMode ? [{ debugName: "matched" }] : /* istanbul ignore next */ []);
34
+ static ɵfac = i0.ɵɵngDeclareFactory({
35
+ minVersion: "12.0.0",
36
+ version: "22.2.1",
37
+ ngImport: i0,
38
+ type: VdTextHighlight,
39
+ deps: [],
40
+ target: i0.ɵɵFactoryTarget.Component
41
+ });
42
+ static ɵcmp = i0.ɵɵngDeclareComponent({
43
+ minVersion: "17.0.0",
44
+ version: "22.2.1",
45
+ type: VdTextHighlight,
46
+ isStandalone: true,
47
+ selector: "vd-text-highlight",
48
+ inputs: {
49
+ text: {
50
+ classPropertyName: "text",
51
+ publicName: "text",
52
+ isSignal: true,
53
+ isRequired: true,
54
+ transformFunction: null
55
+ },
56
+ query: {
57
+ classPropertyName: "query",
58
+ publicName: "query",
59
+ isSignal: true,
60
+ isRequired: false,
61
+ transformFunction: null
62
+ }
63
+ },
64
+ host: {
65
+ properties: { "attr.data-state": "!text() ? \"empty\" : matched() ? \"matched\" : \"plain\"" },
66
+ classAttribute: "vd-text-highlight"
67
+ },
68
+ ngImport: i0,
69
+ template: `@for (part of parts(); track $index) {
70
+ @if (part.matched) {
71
+ <mark class="vd-text-highlight__match">{{ part.text }}</mark>
72
+ } @else {
73
+ <ng-container>{{ part.text }}</ng-container>
74
+ }
75
+ }`,
76
+ isInline: true,
77
+ changeDetection: i0.ChangeDetectionStrategy.OnPush,
78
+ encapsulation: i0.ViewEncapsulation.None
79
+ });
80
+ };
81
+ i0.ɵɵngDeclareClassMetadata({
82
+ minVersion: "12.0.0",
83
+ version: "22.2.1",
84
+ ngImport: i0,
85
+ type: VdTextHighlight,
86
+ decorators: [{
87
+ type: Component,
88
+ args: [{
89
+ selector: "vd-text-highlight",
90
+ changeDetection: ChangeDetectionStrategy.OnPush,
91
+ encapsulation: ViewEncapsulation.None,
92
+ host: {
93
+ class: "vd-text-highlight",
94
+ "[attr.data-state]": "!text() ? \"empty\" : matched() ? \"matched\" : \"plain\""
95
+ },
96
+ template: `@for (part of parts(); track $index) {
97
+ @if (part.matched) {
98
+ <mark class="vd-text-highlight__match">{{ part.text }}</mark>
99
+ } @else {
100
+ <ng-container>{{ part.text }}</ng-container>
101
+ }
102
+ }`
103
+ }]
104
+ }],
105
+ propDecorators: {
106
+ text: [{
107
+ type: i0.Input,
108
+ args: [{
109
+ isSignal: true,
110
+ alias: "text",
111
+ required: true
112
+ }]
113
+ }],
114
+ query: [{
115
+ type: i0.Input,
116
+ args: [{
117
+ isSignal: true,
118
+ alias: "query",
119
+ required: false
120
+ }]
121
+ }]
122
+ }
123
+ });
124
+ export { VdTextHighlight };
125
+
126
+ //# sourceMappingURL=vadem-ui-text-highlight.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vadem-ui-text-highlight.mjs","names":[],"sources":["../../../projects/ui/text-highlight/src/core/text-highlight.ts","../../../projects/ui/text-highlight/src/text-highlight.ts"],"sourcesContent":["export interface VdTextHighlightPart {\n readonly text: string;\n readonly matched: boolean;\n}\n\n/** Unicode simple case folding keeps match indices tied to the original source. */\nexport function vdTextHighlightParts(text: string, query: string): readonly VdTextHighlightPart[] {\n if (!text) return [];\n if (!query) return [{ text, matched: false }];\n const pattern = new RegExp(query.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'), 'giu');\n const parts: VdTextHighlightPart[] = [];\n let cursor = 0;\n for (const match of text.matchAll(pattern)) {\n if (match.index > cursor) parts.push({ text: text.slice(cursor, match.index), matched: false });\n parts.push({ text: match[0], matched: true });\n cursor = match.index + match[0].length;\n }\n if (cursor < text.length) parts.push({ text: text.slice(cursor), matched: false });\n return parts;\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n ViewEncapsulation,\n computed,\n input,\n} from '@angular/core';\nimport { vdTextHighlightParts } from './core/text-highlight';\n\n/** Preserves plain text while marking every literal, case-insensitive query match. */\n@Component({\n selector: 'vd-text-highlight',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n host: {\n class: 'vd-text-highlight',\n '[attr.data-state]': '!text() ? \"empty\" : matched() ? \"matched\" : \"plain\"',\n },\n template: `@for (part of parts(); track $index) {\n @if (part.matched) {\n <mark class=\"vd-text-highlight__match\">{{ part.text }}</mark>\n } @else {\n <ng-container>{{ part.text }}</ng-container>\n }\n }`,\n})\nexport class VdTextHighlight {\n readonly text = input.required<string>();\n readonly query = input('');\n protected readonly parts = computed(() => vdTextHighlightParts(this.text(), this.query()));\n protected readonly matched = computed(() => this.parts().some((part) => part.matched));\n}\n"],"mappings":";;AAMA,SAAgB,qBAAqB,MAAc,OAAa;CAC9D,IAAI,CAAC,MAAM,OAAO,CAAA;CAClB,IAAI,CAAC,OAAO,OAAO,CAAC;EAAE;EAAM,SAAS;CAAK,CAAE;CAC5C,MAAM,UAAU,IAAI,OAAO,MAAM,QAAQ,uBAAuB,MAAM,GAAG,KAAK;CAC9E,MAAM,QAA+B,CAAA;CACrC,IAAI,SAAS;CACb,KAAK,MAAM,SAAS,KAAK,SAAS,OAAO,GAAG;EAC1C,IAAI,MAAM,QAAQ,QAAQ,MAAM,KAAK;GAAE,MAAM,KAAK,MAAM,QAAQ,MAAM,KAAK;GAAG,SAAS;EAAK,CAAE;EAC9F,MAAM,KAAK;GAAE,MAAM,MAAM;GAAI,SAAS;EAAI,CAAE;EAC5C,SAAS,MAAM,QAAQ,MAAM,EAAE,CAAC;CAClC;CACA,IAAI,SAAS,KAAK,QAAQ,MAAM,KAAK;EAAE,MAAM,KAAK,MAAM,MAAM;EAAG,SAAS;CAAK,CAAE;CACjF,OAAO;AACT;ACOA,IAAa,kBAAb,MAAa,gBAAe;CACjB,OAAO,MAAM,SAAkB,GAAA,YAAA,CAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;CAC/B,QAAQ,MAAM,IAAG,GAAA,YAAA,CAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CACP,QAAQ,eAAe,qBAAqB,KAAK,KAAI,GAAI,KAAK,MAAK,CAAE,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CACvE,UAAU,eAAe,KAAK,MAAK,CAAE,CAAC,MAAM,SAAS,KAAK,OAAO,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CAJ3E,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAe,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAf,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAe,cAAA;EAAA,UAAA;EAAA,QAAA;GAAA,MAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,OAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;EAAA;EAAA,MAAA;GAAA,YAAA,EAAA,mBAAA,4DAAA;GAAA,gBAAA;EAAA;EAAA,UAAA;EAAA,UARhB;;;;;;;EAMR,UAAA;EAAA,iBAAA,GAAA,wBAAA;EAAA,eAAA,GAAA,kBAAA;CAAA,CAAA;;AAES,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAe,YAAA,CAAA;EAhB3B,MAAA;EAAU,MAAA,CAAA;GACT,UAAU;GACV,iBAAiB,wBAAwB;GACzC,eAAe,kBAAkB;GACjC,MAAM;IACJ,OAAO;IACP,qBAAqB;GACtB;GACD,UAAU;;;;;;;EAOX,CAAA"}
@@ -0,0 +1,430 @@
1
+ import * as i0 from "@angular/core";
2
+ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Directive, ElementRef, ViewContainerRef, ViewEncapsulation, afterNextRender, computed, inject, input, signal } from "@angular/core";
3
+ import { VdInput } from "@vadem/ui/input";
4
+ import { VdIcon } from "@vadem/ui/icon";
5
+ import { VdPopover } from "@vadem/ui/popover";
6
+ import { vdTexts } from "@vadem/ui/locale";
7
+ function timeOptions(min, max, step, initial) {
8
+ const seconds = (value) => {
9
+ if (!/^\d{2}:\d{2}(?::\d{2}(?:\.\d{1,3})?)?$/.test(value)) return void 0;
10
+ const [h, m, s = 0] = value.split(":").map(Number);
11
+ return h < 24 && m < 60 && s < 60 ? h * 3600 + m * 60 + s : void 0;
12
+ };
13
+ const low = seconds(min), high = seconds(max), base = low ?? seconds(initial) ?? 0;
14
+ const increment = step === "any" ? 0 : Number(step) > 0 ? Number(step) : 60;
15
+ const result = [];
16
+ for (let minute = 0; minute < 1440; minute++) {
17
+ const value = minute * 60;
18
+ const inRange = low !== void 0 && high !== void 0 && low > high ? value >= low || value <= high : (low === void 0 || value >= low) && (high === void 0 || value <= high);
19
+ const quotient = increment ? (value - base) / increment : 0;
20
+ if (inRange && Math.abs(quotient - Math.round(quotient)) < 1e-7) result.push(`${String(Math.floor(minute / 60)).padStart(2, "0")}:${String(minute % 60).padStart(2, "0")}`);
21
+ }
22
+ return result;
23
+ }
24
+ var VdTimePicker = class VdTimePicker {
25
+ label = signal("Choose time", ...ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []);
26
+ emptyLabel = signal("No available times", ...ngDevMode ? [{ debugName: "emptyLabel" }] : /* istanbul ignore next */ []);
27
+ options = signal([], ...ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []);
28
+ selected = signal("", ...ngDevMode ? [{ debugName: "selected" }] : /* istanbul ignore next */ []);
29
+ hoursLabel = signal("Hours", ...ngDevMode ? [{ debugName: "hoursLabel" }] : /* istanbul ignore next */ []);
30
+ minutesLabel = signal("Minutes", ...ngDevMode ? [{ debugName: "minutesLabel" }] : /* istanbul ignore next */ []);
31
+ hour = signal("", ...ngDevMode ? [{ debugName: "hour" }] : /* istanbul ignore next */ []);
32
+ minute = signal("", ...ngDevMode ? [{ debugName: "minute" }] : /* istanbul ignore next */ []);
33
+ activeHour = signal(0, ...ngDevMode ? [{ debugName: "activeHour" }] : /* istanbul ignore next */ []);
34
+ activeMinute = signal(0, ...ngDevMode ? [{ debugName: "activeMinute" }] : /* istanbul ignore next */ []);
35
+ hours = computed(() => [...new Set(this.options().map((time) => time.slice(0, 2)))], ...ngDevMode ? [{ debugName: "hours" }] : /* istanbul ignore next */ []);
36
+ minutes = computed(() => this.options().filter((time) => time.startsWith(this.hour() + ":")).map((time) => time.slice(3)), ...ngDevMode ? [{ debugName: "minutes" }] : /* istanbul ignore next */ []);
37
+ changeDetector = inject(ChangeDetectorRef);
38
+ host = inject(ElementRef).nativeElement;
39
+ target;
40
+ onState;
41
+ get panel() {
42
+ return this.host.querySelector(".vd-time-picker");
43
+ }
44
+ open(target, label, emptyLabel, hoursLabel, minutesLabel) {
45
+ this.target = target;
46
+ this.label.set(label);
47
+ this.hoursLabel.set(hoursLabel);
48
+ this.minutesLabel.set(minutesLabel);
49
+ this.emptyLabel.set(emptyLabel);
50
+ this.options.set(timeOptions(target.min, target.max, target.step, target.getAttribute("value") ?? ""));
51
+ this.selected.set(target.value);
52
+ const initial = this.options().includes(target.value) ? target.value : this.options()[0] ?? "";
53
+ this.hour.set(initial.slice(0, 2));
54
+ this.minute.set(initial.slice(3));
55
+ this.activeHour.set(Math.max(0, this.hours().indexOf(this.hour())));
56
+ this.activeMinute.set(Math.max(0, this.minutes().indexOf(this.minute())));
57
+ }
58
+ show() {
59
+ if (!this.target || this.panel.matches(":popover-open")) return;
60
+ this.panel.showPopover({ source: this.target });
61
+ this.focusActive("hours");
62
+ }
63
+ toggled(event) {
64
+ this.onState?.(event.newState === "open");
65
+ }
66
+ leave(event) {
67
+ const next = event.relatedTarget;
68
+ if (next && next !== this.target && !this.panel.contains(next) && this.panel.matches(":popover-open")) this.panel.hidePopover();
69
+ }
70
+ choose(time) {
71
+ const target = this.target;
72
+ if (!target || target.disabled || target.readOnly || !timeOptions(target.min, target.max, target.step, target.getAttribute("value") ?? "").includes(time)) return;
73
+ target.value = time;
74
+ target.dispatchEvent(new Event("input", { bubbles: true }));
75
+ target.dispatchEvent(new Event("change", { bubbles: true }));
76
+ this.panel.hidePopover();
77
+ target.focus();
78
+ }
79
+ parts(column) {
80
+ return column === "hours" ? this.hours() : this.minutes();
81
+ }
82
+ activeIndex(column) {
83
+ return column === "hours" ? this.activeHour() : this.activeMinute();
84
+ }
85
+ setActive(column, index) {
86
+ (column === "hours" ? this.activeHour : this.activeMinute).set(index);
87
+ }
88
+ pick(part, column) {
89
+ if (column === "minutes") {
90
+ this.choose(`${this.hour()}:${part}`);
91
+ return;
92
+ }
93
+ this.hour.set(part);
94
+ if (!this.minutes().includes(this.minute())) this.minute.set(this.minutes()[0] ?? "");
95
+ this.activeMinute.set(Math.max(0, this.minutes().indexOf(this.minute())));
96
+ this.changeDetector.detectChanges();
97
+ this.focusActive("minutes");
98
+ }
99
+ navigate(event, column) {
100
+ if (event.key === "Enter" || event.key === " ") {
101
+ event.preventDefault();
102
+ this.pick(this.parts(column)[this.activeIndex(column)], column);
103
+ return;
104
+ }
105
+ const size = this.parts(column).length;
106
+ let next;
107
+ switch (event.key) {
108
+ case "ArrowDown":
109
+ next = Math.min(size - 1, this.activeIndex(column) + 1);
110
+ break;
111
+ case "ArrowUp":
112
+ next = Math.max(0, this.activeIndex(column) - 1);
113
+ break;
114
+ case "Home":
115
+ next = 0;
116
+ break;
117
+ case "End":
118
+ next = size - 1;
119
+ break;
120
+ default: return;
121
+ }
122
+ event.preventDefault();
123
+ this.setActive(column, next);
124
+ this.focusActive(column);
125
+ }
126
+ focusActive(column) {
127
+ const option = this.panel.querySelectorAll(`[data-column=${column}] [role=option]`)[this.activeIndex(column)];
128
+ if (option) {
129
+ option.focus({ preventScroll: true });
130
+ option.scrollIntoView({
131
+ block: "nearest",
132
+ behavior: "instant"
133
+ });
134
+ } else this.panel.focus();
135
+ }
136
+ static ɵfac = i0.ɵɵngDeclareFactory({
137
+ minVersion: "12.0.0",
138
+ version: "22.2.1",
139
+ ngImport: i0,
140
+ type: VdTimePicker,
141
+ deps: [],
142
+ target: i0.ɵɵFactoryTarget.Component
143
+ });
144
+ static ɵcmp = i0.ɵɵngDeclareComponent({
145
+ minVersion: "17.0.0",
146
+ version: "22.2.1",
147
+ type: VdTimePicker,
148
+ isStandalone: true,
149
+ selector: "vd-time-picker",
150
+ ngImport: i0,
151
+ template: `
152
+ <div
153
+ vdPopover
154
+ class="vd-time-picker"
155
+ [attr.aria-label]="label()"
156
+ (toggle)="toggled($event)"
157
+ (focusout)="leave($event)"
158
+ >
159
+ <div class="vd-time-picker__heading">{{ label() }}</div>
160
+ @if (options().length) {
161
+ <div class="vd-time-picker__columns">
162
+ @for (column of ['hours', 'minutes']; track column) {
163
+ <div class="vd-time-picker__column">
164
+ <div class="vd-time-picker__column-label">
165
+ {{ column === 'hours' ? hoursLabel() : minutesLabel() }}
166
+ </div>
167
+ <div
168
+ class="vd-time-picker__list"
169
+ role="listbox"
170
+ [attr.data-column]="column"
171
+ [attr.aria-label]="column === 'hours' ? hoursLabel() : minutesLabel()"
172
+ >
173
+ @for (part of parts(column); track part; let i = $index) {
174
+ <div
175
+ class="vd-time-picker__option"
176
+ role="option"
177
+ [attr.aria-selected]="part === (column === 'hours' ? hour() : minute())"
178
+ [attr.tabindex]="i === activeIndex(column) ? 0 : -1"
179
+ (keydown)="navigate($event, column)"
180
+ (focus)="setActive(column, i)"
181
+ (click)="pick(part, column)"
182
+ >
183
+ <span>{{ part }}</span
184
+ ><vd-icon class="vd-time-picker__mark" name="check" />
185
+ </div>
186
+ }
187
+ </div>
188
+ </div>
189
+ }
190
+ </div>
191
+ } @else {
192
+ <p class="vd-time-picker__empty" role="status">{{ emptyLabel() }}</p>
193
+ }
194
+ </div>
195
+ `,
196
+ isInline: true,
197
+ dependencies: [{
198
+ kind: "directive",
199
+ type: VdPopover,
200
+ selector: "[vdPopover]",
201
+ inputs: ["placement"],
202
+ exportAs: ["vdPopover"]
203
+ }, {
204
+ kind: "component",
205
+ type: VdIcon,
206
+ selector: "vd-icon",
207
+ inputs: ["name", "label"]
208
+ }],
209
+ changeDetection: i0.ChangeDetectionStrategy.OnPush,
210
+ encapsulation: i0.ViewEncapsulation.None
211
+ });
212
+ };
213
+ i0.ɵɵngDeclareClassMetadata({
214
+ minVersion: "12.0.0",
215
+ version: "22.2.1",
216
+ ngImport: i0,
217
+ type: VdTimePicker,
218
+ decorators: [{
219
+ type: Component,
220
+ args: [{
221
+ selector: "vd-time-picker",
222
+ imports: [VdPopover, VdIcon],
223
+ changeDetection: ChangeDetectionStrategy.OnPush,
224
+ encapsulation: ViewEncapsulation.None,
225
+ template: `
226
+ <div
227
+ vdPopover
228
+ class="vd-time-picker"
229
+ [attr.aria-label]="label()"
230
+ (toggle)="toggled($event)"
231
+ (focusout)="leave($event)"
232
+ >
233
+ <div class="vd-time-picker__heading">{{ label() }}</div>
234
+ @if (options().length) {
235
+ <div class="vd-time-picker__columns">
236
+ @for (column of ['hours', 'minutes']; track column) {
237
+ <div class="vd-time-picker__column">
238
+ <div class="vd-time-picker__column-label">
239
+ {{ column === 'hours' ? hoursLabel() : minutesLabel() }}
240
+ </div>
241
+ <div
242
+ class="vd-time-picker__list"
243
+ role="listbox"
244
+ [attr.data-column]="column"
245
+ [attr.aria-label]="column === 'hours' ? hoursLabel() : minutesLabel()"
246
+ >
247
+ @for (part of parts(column); track part; let i = $index) {
248
+ <div
249
+ class="vd-time-picker__option"
250
+ role="option"
251
+ [attr.aria-selected]="part === (column === 'hours' ? hour() : minute())"
252
+ [attr.tabindex]="i === activeIndex(column) ? 0 : -1"
253
+ (keydown)="navigate($event, column)"
254
+ (focus)="setActive(column, i)"
255
+ (click)="pick(part, column)"
256
+ >
257
+ <span>{{ part }}</span
258
+ ><vd-icon class="vd-time-picker__mark" name="check" />
259
+ </div>
260
+ }
261
+ </div>
262
+ </div>
263
+ }
264
+ </div>
265
+ } @else {
266
+ <p class="vd-time-picker__empty" role="status">{{ emptyLabel() }}</p>
267
+ }
268
+ </div>
269
+ `
270
+ }]
271
+ }]
272
+ });
273
+ var VdTimeInput = class VdTimeInput extends VdInput {
274
+ pickerLabel = input(...ngDevMode ? [void 0, { debugName: "pickerLabel" }] : /* istanbul ignore next */ []);
275
+ hoursLabel = input(...ngDevMode ? [void 0, { debugName: "hoursLabel" }] : /* istanbul ignore next */ []);
276
+ minutesLabel = input(...ngDevMode ? [void 0, { debugName: "minutesLabel" }] : /* istanbul ignore next */ []);
277
+ emptyLabel = input(...ngDevMode ? [void 0, { debugName: "emptyLabel" }] : /* istanbul ignore next */ []);
278
+ t = vdTexts("timeInput", {
279
+ pickerLabel: this.pickerLabel,
280
+ hoursLabel: this.hoursLabel,
281
+ minutesLabel: this.minutesLabel,
282
+ emptyLabel: this.emptyLabel
283
+ });
284
+ open = signal(false, ...ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []);
285
+ panelId = signal(null, ...ngDevMode ? [{ debugName: "panelId" }] : /* istanbul ignore next */ []);
286
+ element = inject(ElementRef).nativeElement;
287
+ container = inject(ViewContainerRef);
288
+ picker;
289
+ constructor() {
290
+ super();
291
+ afterNextRender(() => {
292
+ this.picker = this.container.createComponent(VdTimePicker);
293
+ this.picker.changeDetectorRef.detectChanges();
294
+ const panel = this.picker.instance.panel;
295
+ const anchor = `--${panel.id}`;
296
+ this.element.style.setProperty("anchor-name", anchor);
297
+ panel.style.setProperty("position-anchor", anchor);
298
+ panel.setAttribute("tabindex", "-1");
299
+ this.panelId.set(panel.id);
300
+ this.picker.instance.onState = (open) => this.open.set(open);
301
+ });
302
+ }
303
+ showPicker(event) {
304
+ if (this.element.disabled || this.element.readOnly || !this.picker) return;
305
+ event.preventDefault();
306
+ this.picker.instance.open(this.element, this.t().pickerLabel, this.t().emptyLabel, this.t().hoursLabel, this.t().minutesLabel);
307
+ this.picker.changeDetectorRef.detectChanges();
308
+ this.picker.instance.show();
309
+ }
310
+ onKeydown(event) {
311
+ if (event.altKey && event.key === "ArrowDown") this.showPicker(event);
312
+ }
313
+ static ɵfac = i0.ɵɵngDeclareFactory({
314
+ minVersion: "12.0.0",
315
+ version: "22.2.1",
316
+ ngImport: i0,
317
+ type: VdTimeInput,
318
+ deps: [],
319
+ target: i0.ɵɵFactoryTarget.Directive
320
+ });
321
+ static ɵdir = i0.ɵɵngDeclareDirective({
322
+ minVersion: "17.1.0",
323
+ version: "22.2.1",
324
+ type: VdTimeInput,
325
+ isStandalone: true,
326
+ selector: "input[type=time][vdTimeInput]",
327
+ inputs: {
328
+ pickerLabel: {
329
+ classPropertyName: "pickerLabel",
330
+ publicName: "pickerLabel",
331
+ isSignal: true,
332
+ isRequired: false,
333
+ transformFunction: null
334
+ },
335
+ hoursLabel: {
336
+ classPropertyName: "hoursLabel",
337
+ publicName: "hoursLabel",
338
+ isSignal: true,
339
+ isRequired: false,
340
+ transformFunction: null
341
+ },
342
+ minutesLabel: {
343
+ classPropertyName: "minutesLabel",
344
+ publicName: "minutesLabel",
345
+ isSignal: true,
346
+ isRequired: false,
347
+ transformFunction: null
348
+ },
349
+ emptyLabel: {
350
+ classPropertyName: "emptyLabel",
351
+ publicName: "emptyLabel",
352
+ isSignal: true,
353
+ isRequired: false,
354
+ transformFunction: null
355
+ }
356
+ },
357
+ host: {
358
+ attributes: { "aria-haspopup": "dialog" },
359
+ listeners: {
360
+ "click": "showPicker($event)",
361
+ "keydown": "onKeydown($event)"
362
+ },
363
+ properties: {
364
+ "attr.data-state": "open() ? \"open\" : \"closed\"",
365
+ "attr.aria-controls": "panelId()"
366
+ },
367
+ classAttribute: "vd-time-input"
368
+ },
369
+ usesInheritance: true,
370
+ ngImport: i0
371
+ });
372
+ };
373
+ i0.ɵɵngDeclareClassMetadata({
374
+ minVersion: "12.0.0",
375
+ version: "22.2.1",
376
+ ngImport: i0,
377
+ type: VdTimeInput,
378
+ decorators: [{
379
+ type: Directive,
380
+ args: [{
381
+ selector: "input[type=time][vdTimeInput]",
382
+ host: {
383
+ class: "vd-time-input",
384
+ "aria-haspopup": "dialog",
385
+ "[attr.data-state]": "open() ? \"open\" : \"closed\"",
386
+ "[attr.aria-controls]": "panelId()",
387
+ "(click)": "showPicker($event)",
388
+ "(keydown)": "onKeydown($event)"
389
+ }
390
+ }]
391
+ }],
392
+ ctorParameters: () => [],
393
+ propDecorators: {
394
+ pickerLabel: [{
395
+ type: i0.Input,
396
+ args: [{
397
+ isSignal: true,
398
+ alias: "pickerLabel",
399
+ required: false
400
+ }]
401
+ }],
402
+ hoursLabel: [{
403
+ type: i0.Input,
404
+ args: [{
405
+ isSignal: true,
406
+ alias: "hoursLabel",
407
+ required: false
408
+ }]
409
+ }],
410
+ minutesLabel: [{
411
+ type: i0.Input,
412
+ args: [{
413
+ isSignal: true,
414
+ alias: "minutesLabel",
415
+ required: false
416
+ }]
417
+ }],
418
+ emptyLabel: [{
419
+ type: i0.Input,
420
+ args: [{
421
+ isSignal: true,
422
+ alias: "emptyLabel",
423
+ required: false
424
+ }]
425
+ }]
426
+ }
427
+ });
428
+ export { VdTimeInput };
429
+
430
+ //# sourceMappingURL=vadem-ui-time-input.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vadem-ui-time-input.mjs","names":[],"sources":["../../../projects/ui/time-input/src/core/time-options.ts","../../../projects/ui/time-input/src/time-picker.ts","../../../projects/ui/time-input/src/time-input.ts"],"sourcesContent":["/** Minute-resolution choices matching the native time input's periodic range and step base. */\nexport function timeOptions(min: string, max: string, step: string, initial: string): string[] {\n const seconds = (value: string): number | undefined => {\n if (!/^\\d{2}:\\d{2}(?::\\d{2}(?:\\.\\d{1,3})?)?$/.test(value)) return undefined;\n const [h, m, s = 0] = value.split(':').map(Number);\n return h < 24 && m < 60 && s < 60 ? h * 3600 + m * 60 + s : undefined;\n };\n const low = seconds(min),\n high = seconds(max),\n base = low ?? seconds(initial) ?? 0;\n const increment = step === 'any' ? 0 : Number(step) > 0 ? Number(step) : 60;\n const result: string[] = [];\n for (let minute = 0; minute < 1440; minute++) {\n const value = minute * 60;\n const inRange =\n low !== undefined && high !== undefined && low > high\n ? value >= low || value <= high\n : (low === undefined || value >= low) && (high === undefined || value <= high);\n const quotient = increment ? (value - base) / increment : 0;\n if (inRange && Math.abs(quotient - Math.round(quotient)) < 1e-7)\n result.push(\n `${String(Math.floor(minute / 60)).padStart(2, '0')}:${String(minute % 60).padStart(2, '0')}`,\n );\n }\n return result;\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n ViewEncapsulation,\n inject,\n computed,\n ChangeDetectorRef,\n signal,\n} from '@angular/core';\nimport { VdIcon } from '@vadem/ui/icon';\nimport { VdPopover } from '@vadem/ui/popover';\nimport { timeOptions } from './core/time-options';\n\n/** Internal view; the input remains the sole form control and value owner. */\n@Component({\n selector: 'vd-time-picker',\n imports: [VdPopover, VdIcon],\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n template: `\n <div\n vdPopover\n class=\"vd-time-picker\"\n [attr.aria-label]=\"label()\"\n (toggle)=\"toggled($event)\"\n (focusout)=\"leave($event)\"\n >\n <div class=\"vd-time-picker__heading\">{{ label() }}</div>\n @if (options().length) {\n <div class=\"vd-time-picker__columns\">\n @for (column of ['hours', 'minutes']; track column) {\n <div class=\"vd-time-picker__column\">\n <div class=\"vd-time-picker__column-label\">\n {{ column === 'hours' ? hoursLabel() : minutesLabel() }}\n </div>\n <div\n class=\"vd-time-picker__list\"\n role=\"listbox\"\n [attr.data-column]=\"column\"\n [attr.aria-label]=\"column === 'hours' ? hoursLabel() : minutesLabel()\"\n >\n @for (part of parts(column); track part; let i = $index) {\n <div\n class=\"vd-time-picker__option\"\n role=\"option\"\n [attr.aria-selected]=\"part === (column === 'hours' ? hour() : minute())\"\n [attr.tabindex]=\"i === activeIndex(column) ? 0 : -1\"\n (keydown)=\"navigate($event, column)\"\n (focus)=\"setActive(column, i)\"\n (click)=\"pick(part, column)\"\n >\n <span>{{ part }}</span\n ><vd-icon class=\"vd-time-picker__mark\" name=\"check\" />\n </div>\n }\n </div>\n </div>\n }\n </div>\n } @else {\n <p class=\"vd-time-picker__empty\" role=\"status\">{{ emptyLabel() }}</p>\n }\n </div>\n `,\n})\nexport class VdTimePicker {\n readonly label = signal('Choose time');\n readonly emptyLabel = signal('No available times');\n readonly options = signal<string[]>([]);\n readonly selected = signal('');\n readonly hoursLabel = signal('Hours');\n readonly minutesLabel = signal('Minutes');\n readonly hour = signal('');\n readonly minute = signal('');\n readonly activeHour = signal(0);\n readonly activeMinute = signal(0);\n readonly hours = computed(() => [...new Set(this.options().map((time) => time.slice(0, 2)))]);\n readonly minutes = computed(() =>\n this.options()\n .filter((time) => time.startsWith(this.hour() + ':'))\n .map((time) => time.slice(3)),\n );\n private readonly changeDetector = inject(ChangeDetectorRef);\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef).nativeElement;\n private target?: HTMLInputElement;\n onState?: (open: boolean) => void;\n get panel(): HTMLElement {\n return this.host.querySelector('.vd-time-picker')!;\n }\n\n open(\n target: HTMLInputElement,\n label: string,\n emptyLabel: string,\n hoursLabel: string,\n minutesLabel: string,\n ): void {\n this.target = target;\n this.label.set(label);\n this.hoursLabel.set(hoursLabel);\n this.minutesLabel.set(minutesLabel);\n this.emptyLabel.set(emptyLabel);\n this.options.set(\n timeOptions(target.min, target.max, target.step, target.getAttribute('value') ?? ''),\n );\n this.selected.set(target.value);\n const initial = this.options().includes(target.value)\n ? target.value\n : (this.options()[0] ?? '');\n this.hour.set(initial.slice(0, 2));\n this.minute.set(initial.slice(3));\n this.activeHour.set(Math.max(0, this.hours().indexOf(this.hour())));\n this.activeMinute.set(Math.max(0, this.minutes().indexOf(this.minute())));\n }\n show(): void {\n if (!this.target || this.panel.matches(':popover-open')) return;\n this.panel.showPopover({ source: this.target } as ShowPopoverOptions);\n this.focusActive('hours');\n }\n toggled(event: Event): void {\n this.onState?.((event as ToggleEvent).newState === 'open');\n }\n leave(event: FocusEvent): void {\n const next = event.relatedTarget as Node | null;\n if (\n next &&\n next !== this.target &&\n !this.panel.contains(next) &&\n this.panel.matches(':popover-open')\n )\n this.panel.hidePopover();\n }\n choose(time: string): void {\n const target = this.target;\n // Recheck live properties and constraints in case the form changed while open.\n if (\n !target ||\n target.disabled ||\n target.readOnly ||\n !timeOptions(\n target.min,\n target.max,\n target.step,\n target.getAttribute('value') ?? '',\n ).includes(time)\n )\n return;\n target.value = time;\n target.dispatchEvent(new Event('input', { bubbles: true }));\n target.dispatchEvent(new Event('change', { bubbles: true }));\n this.panel.hidePopover();\n target.focus();\n }\n parts(column: string): string[] {\n return column === 'hours' ? this.hours() : this.minutes();\n }\n activeIndex(column: string): number {\n return column === 'hours' ? this.activeHour() : this.activeMinute();\n }\n setActive(column: string, index: number): void {\n (column === 'hours' ? this.activeHour : this.activeMinute).set(index);\n }\n pick(part: string, column: string): void {\n if (column === 'minutes') {\n this.choose(`${this.hour()}:${part}`);\n return;\n }\n this.hour.set(part);\n if (!this.minutes().includes(this.minute())) this.minute.set(this.minutes()[0] ?? '');\n this.activeMinute.set(Math.max(0, this.minutes().indexOf(this.minute())));\n this.changeDetector.detectChanges();\n this.focusActive('minutes');\n }\n navigate(event: KeyboardEvent, column: string): void {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n this.pick(this.parts(column)[this.activeIndex(column)], column);\n return;\n }\n const size = this.parts(column).length;\n let next: number;\n switch (event.key) {\n case 'ArrowDown':\n next = Math.min(size - 1, this.activeIndex(column) + 1);\n break;\n case 'ArrowUp':\n next = Math.max(0, this.activeIndex(column) - 1);\n break;\n case 'Home':\n next = 0;\n break;\n case 'End':\n next = size - 1;\n break;\n default:\n return;\n }\n event.preventDefault();\n this.setActive(column, next);\n this.focusActive(column);\n }\n private focusActive(column: string): void {\n const option = this.panel.querySelectorAll<HTMLElement>(\n `[data-column=${column}] [role=option]`,\n )[this.activeIndex(column)];\n if (option) {\n option.focus({ preventScroll: true });\n option.scrollIntoView({ block: 'nearest', behavior: 'instant' });\n } else this.panel.focus();\n }\n}\n","import {\n ComponentRef,\n Directive,\n ElementRef,\n ViewContainerRef,\n afterNextRender,\n inject,\n input,\n signal,\n} from '@angular/core';\nimport { VdInput } from '@vadem/ui/input';\nimport { VdTimePicker } from './time-picker';\nimport { vdTexts } from '@vadem/ui/locale';\n\n/** Native editor and accessors with a themed, minute-resolution selection popover. */\n@Directive({\n selector: 'input[type=time][vdTimeInput]',\n host: {\n class: 'vd-time-input',\n 'aria-haspopup': 'dialog',\n '[attr.data-state]': 'open() ? \"open\" : \"closed\"',\n '[attr.aria-controls]': 'panelId()',\n '(click)': 'showPicker($event)',\n '(keydown)': 'onKeydown($event)',\n },\n})\nexport class VdTimeInput extends VdInput {\n readonly pickerLabel = input<string>();\n readonly hoursLabel = input<string>();\n readonly minutesLabel = input<string>();\n readonly emptyLabel = input<string>();\n /** Text inputs resolved against the active VD_LOCALE. */\n protected readonly t = vdTexts('timeInput', {\n pickerLabel: this.pickerLabel,\n hoursLabel: this.hoursLabel,\n minutesLabel: this.minutesLabel,\n emptyLabel: this.emptyLabel,\n });\n protected readonly open = signal(false);\n protected readonly panelId = signal<string | null>(null);\n private readonly element = inject<ElementRef<HTMLInputElement>>(ElementRef).nativeElement;\n private readonly container = inject(ViewContainerRef);\n private picker?: ComponentRef<VdTimePicker>;\n\n constructor() {\n super();\n afterNextRender(() => {\n this.picker = this.container.createComponent(VdTimePicker);\n this.picker.changeDetectorRef.detectChanges();\n const panel = this.picker.instance.panel;\n const anchor = `--${panel.id}`;\n this.element.style.setProperty('anchor-name', anchor);\n panel.style.setProperty('position-anchor', anchor);\n panel.setAttribute('tabindex', '-1');\n this.panelId.set(panel.id);\n this.picker.instance.onState = (open) => this.open.set(open);\n });\n }\n protected showPicker(event: Event): void {\n if (this.element.disabled || this.element.readOnly || !this.picker) return;\n event.preventDefault();\n this.picker.instance.open(\n this.element,\n this.t().pickerLabel,\n this.t().emptyLabel,\n this.t().hoursLabel,\n this.t().minutesLabel,\n );\n this.picker.changeDetectorRef.detectChanges();\n this.picker.instance.show();\n }\n protected onKeydown(event: KeyboardEvent): void {\n if (event.altKey && event.key === 'ArrowDown') this.showPicker(event);\n }\n}\n"],"mappings":";;;;;;AACA,SAAgB,YAAY,KAAa,KAAa,MAAc,SAAe;CACjF,MAAM,WAAW,UAAqC;EACpD,IAAI,CAAC,yCAAyC,KAAK,KAAK,GAAG,OAAO;EAClE,MAAM,CAAC,GAAG,GAAG,IAAI,KAAK,MAAM,MAAM,GAAG,CAAC,CAAC,IAAI,MAAM;EACjD,OAAO,IAAI,MAAM,IAAI,MAAM,IAAI,KAAK,IAAI,OAAO,IAAI,KAAK,IAAI;CAC9D;CACA,MAAM,MAAM,QAAQ,GAAG,GACrB,OAAO,QAAQ,GAAG,GAClB,OAAO,OAAO,QAAQ,OAAO,KAAK;CACpC,MAAM,YAAY,SAAS,QAAQ,IAAI,OAAO,IAAI,IAAI,IAAI,OAAO,IAAI,IAAI;CACzE,MAAM,SAAmB,CAAA;CACzB,KAAK,IAAI,SAAS,GAAG,SAAS,MAAM,UAAU;EAC5C,MAAM,QAAQ,SAAS;EACvB,MAAM,UACJ,QAAQ,UAAa,SAAS,UAAa,MAAM,OAC7C,SAAS,OAAO,SAAS,QACxB,QAAQ,UAAa,SAAS,SAAS,SAAS,UAAa,SAAS;EAC7E,MAAM,WAAW,aAAa,QAAQ,QAAQ,YAAY;EAC1D,IAAI,WAAW,KAAK,IAAI,WAAW,KAAK,MAAM,QAAQ,CAAC,IAAI,MACzD,OAAO,KACL,GAAG,OAAO,KAAK,MAAM,SAAS,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,GAAG,EAAC,GAAI,OAAO,SAAS,EAAE,CAAC,CAAC,SAAS,GAAG,GAAG,GAAG;CAEnG;CACA,OAAO;AACT;ACyCA,IAAa,eAAb,MAAa,aAAY;CACd,QAAQ,OAAO,eAAc,GAAA,YAAA,CAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CAC7B,aAAa,OAAO,sBAAqB,GAAA,YAAA,CAAA,EAAA,WAAA,aAAA,CAAA,+BAAA,CAAA,CAAA;CACzC,UAAU,OAAiB,CAAA,GAAG,GAAA,YAAA,CAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CAC9B,WAAW,OAAO,IAAG,GAAA,YAAA,CAAA,EAAA,WAAA,WAAA,CAAA,+BAAA,CAAA,CAAA;CACrB,aAAa,OAAO,SAAQ,GAAA,YAAA,CAAA,EAAA,WAAA,aAAA,CAAA,+BAAA,CAAA,CAAA;CAC5B,eAAe,OAAO,WAAU,GAAA,YAAA,CAAA,EAAA,WAAA,eAAA,CAAA,+BAAA,CAAA,CAAA;CAChC,OAAO,OAAO,IAAG,GAAA,YAAA,CAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;CACjB,SAAS,OAAO,IAAG,GAAA,YAAA,CAAA,EAAA,WAAA,SAAA,CAAA,+BAAA,CAAA,CAAA;CACnB,aAAa,OAAO,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,aAAA,CAAA,+BAAA,CAAA,CAAA;CACtB,eAAe,OAAO,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,eAAA,CAAA,+BAAA,CAAA,CAAA;CACxB,QAAQ,eAAe,CAAC,GAAG,IAAI,IAAI,KAAK,QAAO,CAAE,CAAC,KAAK,SAAS,KAAK,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,QAAA,CAAA,+BAAA,CAAA,CAAA;CACpF,UAAU,eACjB,KAAK,QAAO,CAAE,CACX,QAAQ,SAAS,KAAK,WAAW,KAAK,KAAI,IAAK,GAAG,CAAC,CAAC,CACpD,KAAK,SAAS,KAAK,MAAM,CAAC,CAAC,GAC/B,GAAA,YAAA,CAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CACgB,iBAAiB,OAAO,iBAAiB;CACzC,OAAO,OAAgC,UAAU,CAAC,CAAC;CAC5D;CACR;CACA,IAAI,QAAK;EACP,OAAO,KAAK,KAAK,cAAc,iBAAiB;CAClD;CAEA,KACE,QACA,OACA,YACA,YACA,cAAoB;EAEpB,KAAK,SAAS;EACd,KAAK,MAAM,IAAI,KAAK;EACpB,KAAK,WAAW,IAAI,UAAU;EAC9B,KAAK,aAAa,IAAI,YAAY;EAClC,KAAK,WAAW,IAAI,UAAU;EAC9B,KAAK,QAAQ,IACX,YAAY,OAAO,KAAK,OAAO,KAAK,OAAO,MAAM,OAAO,aAAa,OAAO,KAAK,EAAE,CAAC;EAEtF,KAAK,SAAS,IAAI,OAAO,KAAK;EAC9B,MAAM,UAAU,KAAK,QAAO,CAAE,CAAC,SAAS,OAAO,KAAK,IAChD,OAAO,QACN,KAAK,QAAO,CAAE,CAAC,MAAM;EAC1B,KAAK,KAAK,IAAI,QAAQ,MAAM,GAAG,CAAC,CAAC;EACjC,KAAK,OAAO,IAAI,QAAQ,MAAM,CAAC,CAAC;EAChC,KAAK,WAAW,IAAI,KAAK,IAAI,GAAG,KAAK,MAAK,CAAE,CAAC,QAAQ,KAAK,KAAI,CAAE,CAAC,CAAC;EAClE,KAAK,aAAa,IAAI,KAAK,IAAI,GAAG,KAAK,QAAO,CAAE,CAAC,QAAQ,KAAK,OAAM,CAAE,CAAC,CAAC;CAC1E;CACA,OAAI;EACF,IAAI,CAAC,KAAK,UAAU,KAAK,MAAM,QAAQ,eAAe,GAAG;EACzD,KAAK,MAAM,YAAY,EAAE,QAAQ,KAAK,OAAM,CAAwB;EACpE,KAAK,YAAY,OAAO;CAC1B;CACA,QAAQ,OAAY;EAClB,KAAK,UAAW,MAAsB,aAAa,MAAM;CAC3D;CACA,MAAM,OAAiB;EACrB,MAAM,OAAO,MAAM;EACnB,IACE,QACA,SAAS,KAAK,UACd,CAAC,KAAK,MAAM,SAAS,IAAI,KACzB,KAAK,MAAM,QAAQ,eAAe,GAElC,KAAK,MAAM,YAAW;CAC1B;CACA,OAAO,MAAY;EACjB,MAAM,SAAS,KAAK;EAEpB,IACE,CAAC,UACD,OAAO,YACP,OAAO,YACP,CAAC,YACC,OAAO,KACP,OAAO,KACP,OAAO,MACP,OAAO,aAAa,OAAO,KAAK,EAAE,CACnC,CAAC,SAAS,IAAI,GAEf;EACF,OAAO,QAAQ;EACf,OAAO,cAAc,IAAI,MAAM,SAAS,EAAE,SAAS,KAAI,CAAE,CAAC;EAC1D,OAAO,cAAc,IAAI,MAAM,UAAU,EAAE,SAAS,KAAI,CAAE,CAAC;EAC3D,KAAK,MAAM,YAAW;EACtB,OAAO,MAAK;CACd;CACA,MAAM,QAAc;EAClB,OAAO,WAAW,UAAU,KAAK,MAAK,IAAK,KAAK,QAAO;CACzD;CACA,YAAY,QAAc;EACxB,OAAO,WAAW,UAAU,KAAK,WAAU,IAAK,KAAK,aAAY;CACnE;CACA,UAAU,QAAgB,OAAa;EACrC,CAAC,WAAW,UAAU,KAAK,aAAa,KAAK,aAAA,CAAc,IAAI,KAAK;CACtE;CACA,KAAK,MAAc,QAAc;EAC/B,IAAI,WAAW,WAAW;GACxB,KAAK,OAAO,GAAG,KAAK,KAAI,EAAE,GAAI,MAAM;GACpC;EACF;EACA,KAAK,KAAK,IAAI,IAAI;EAClB,IAAI,CAAC,KAAK,QAAO,CAAE,CAAC,SAAS,KAAK,OAAM,CAAE,GAAG,KAAK,OAAO,IAAI,KAAK,QAAO,CAAE,CAAC,MAAM,EAAE;EACpF,KAAK,aAAa,IAAI,KAAK,IAAI,GAAG,KAAK,QAAO,CAAE,CAAC,QAAQ,KAAK,OAAM,CAAE,CAAC,CAAC;EACxE,KAAK,eAAe,cAAa;EACjC,KAAK,YAAY,SAAS;CAC5B;CACA,SAAS,OAAsB,QAAc;EAC3C,IAAI,MAAM,QAAQ,WAAW,MAAM,QAAQ,KAAK;GAC9C,MAAM,eAAc;GACpB,KAAK,KAAK,KAAK,MAAM,MAAM,CAAC,CAAC,KAAK,YAAY,MAAM,IAAI,MAAM;GAC9D;EACF;EACA,MAAM,OAAO,KAAK,MAAM,MAAM,CAAC,CAAC;EAChC,IAAI;EACJ,QAAQ,MAAM,KAAd;GACE,KAAK;IACH,OAAO,KAAK,IAAI,OAAO,GAAG,KAAK,YAAY,MAAM,IAAI,CAAC;IACtD;GACF,KAAK;IACH,OAAO,KAAK,IAAI,GAAG,KAAK,YAAY,MAAM,IAAI,CAAC;IAC/C;GACF,KAAK;IACH,OAAO;IACP;GACF,KAAK;IACH,OAAO,OAAO;IACd;GACF,SACE;EACJ;EACA,MAAM,eAAc;EACpB,KAAK,UAAU,QAAQ,IAAI;EAC3B,KAAK,YAAY,MAAM;CACzB;CACQ,YAAY,QAAc;EAChC,MAAM,SAAS,KAAK,MAAM,iBACxB,gBAAgB,OAAM,gBAAiB,CACxC,CAAC,KAAK,YAAY,MAAM;EACzB,IAAI,QAAQ;GACV,OAAO,MAAM,EAAE,eAAe,KAAI,CAAE;GACpC,OAAO,eAAe;IAAE,OAAO;IAAW,UAAU;GAAS,CAAE;EACjE,OAAO,KAAK,MAAM,MAAK;CACzB;CAhJW,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAY,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAZ,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAY,cAAA;EAAA,UAAA;EAAA,UAAA;EAAA,UA9Cb;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4CT,UAAA;EAAA,cAAA,CAAA;GAAA,MAAA;GAAA,MA/CS;GAAS,UAAA;GAAA,QAAA,CAAA,WAAA;GAAA,UAAA,CAAA,WAAA;EAAA,GAAA;GAAA,MAAA;GAAA,MAAE;GAAM,UAAA;GAAA,QAAA,CAAA,QAAA,OAAA;EAAA,CAAA;EAAA,iBAAA,GAAA,wBAAA;EAAA,eAAA,GAAA,kBAAA;CAAA,CAAA;;AAiDhB,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAY,YAAA,CAAA;EAnDxB,MAAA;EAAU,MAAA,CAAA;GACT,UAAU;GACV,SAAS,CAAC,WAAW,MAAM;GAC3B,iBAAiB,wBAAwB;GACzC,eAAe,kBAAkB;GACjC,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA6CX,CAAA;;;ACvCD,IAAa,cAAb,MAAa,oBAAoB,QAAO;CAC7B,cAAc,MAAe,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,cAAA,CAAA,+BAAA,CAAA,CAAA;CAC7B,aAAa,MAAe,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,aAAA,CAAA,+BAAA,CAAA,CAAA;CAC5B,eAAe,MAAe,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,eAAA,CAAA,+BAAA,CAAA,CAAA;CAC9B,aAAa,MAAe,GAAA,YAAA,CAAA,QAAA,EAAA,WAAA,aAAA,CAAA,+BAAA,CAAA,CAAA;CAElB,IAAI,QAAQ,aAAa;EAC1C,aAAa,KAAK;EAClB,YAAY,KAAK;EACjB,cAAc,KAAK;EACnB,YAAY,KAAK;CAClB,CAAA;CACkB,OAAO,OAAO,OAAM,GAAA,YAAA,CAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;CACpB,UAAU,OAAsB,MAAK,GAAA,YAAA,CAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CACvC,UAAU,OAAqC,UAAU,CAAC,CAAC;CAC3D,YAAY,OAAO,gBAAgB;CAC5C;CAER,cAAA;EACE,MAAK;EACL,sBAAqB;GACnB,KAAK,SAAS,KAAK,UAAU,gBAAgB,YAAY;GACzD,KAAK,OAAO,kBAAkB,cAAa;GAC3C,MAAM,QAAQ,KAAK,OAAO,SAAS;GACnC,MAAM,SAAS,KAAK,MAAM;GAC1B,KAAK,QAAQ,MAAM,YAAY,eAAe,MAAM;GACpD,MAAM,MAAM,YAAY,mBAAmB,MAAM;GACjD,MAAM,aAAa,YAAY,IAAI;GACnC,KAAK,QAAQ,IAAI,MAAM,EAAE;GACzB,KAAK,OAAO,SAAS,WAAW,SAAS,KAAK,KAAK,IAAI,IAAI;EAC7D,CAAC;CACH;CACU,WAAW,OAAY;EAC/B,IAAI,KAAK,QAAQ,YAAY,KAAK,QAAQ,YAAY,CAAC,KAAK,QAAQ;EACpE,MAAM,eAAc;EACpB,KAAK,OAAO,SAAS,KACnB,KAAK,SACL,KAAK,EAAC,CAAE,CAAC,aACT,KAAK,EAAC,CAAE,CAAC,YACT,KAAK,EAAC,CAAE,CAAC,YACT,KAAK,EAAC,CAAE,CAAC,YAAY;EAEvB,KAAK,OAAO,kBAAkB,cAAa;EAC3C,KAAK,OAAO,SAAS,KAAI;CAC3B;CACU,UAAU,OAAoB;EACtC,IAAI,MAAM,UAAU,MAAM,QAAQ,aAAa,KAAK,WAAW,KAAK;CACtE;CA/CW,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAW,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAAX,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAW,cAAA;EAAA,UAAA;EAAA,QAAA;GAAA,aAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,YAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,cAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,YAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;EAAA;EAAA,MAAA;GAAA,YAAA,EAAA,iBAAA,SAAA;GAAA,WAAA;IAAA,SAAA;IAAA,WAAA;GAAA;GAAA,YAAA;IAAA,mBAAA;IAAA,sBAAA;GAAA;GAAA,gBAAA;EAAA;EAAA,iBAAA;EAAA,UAAA;CAAA,CAAA;;AAAX,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAW,YAAA,CAAA;EAXvB,MAAA;EAAU,MAAA,CAAA;GACT,UAAU;GACV,MAAM;IACJ,OAAO;IACP,iBAAiB;IACjB,qBAAqB;IACrB,wBAAwB;IACxB,WAAW;IACX,aAAa;GACd;EACF,CAAA"}