@raintonic/formaui 0.4.0 → 0.9.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 (238) hide show
  1. package/CHANGELOG.md +80 -35
  2. package/README.md +22 -26
  3. package/fesm2022/raintonic-formaui-cdk-drag-drop.mjs +39 -41
  4. package/fesm2022/raintonic-formaui-cdk-drag-drop.mjs.map +1 -1
  5. package/fesm2022/raintonic-formaui-cdk-form-field.mjs +207 -3
  6. package/fesm2022/raintonic-formaui-cdk-form-field.mjs.map +1 -1
  7. package/fesm2022/raintonic-formaui-cdk-overlay.mjs +19 -1
  8. package/fesm2022/raintonic-formaui-cdk-overlay.mjs.map +1 -1
  9. package/fesm2022/raintonic-formaui-cdk-virtual-scroll.mjs +5 -12
  10. package/fesm2022/raintonic-formaui-cdk-virtual-scroll.mjs.map +1 -1
  11. package/fesm2022/raintonic-formaui-components-accordion.mjs +8 -5
  12. package/fesm2022/raintonic-formaui-components-accordion.mjs.map +1 -1
  13. package/fesm2022/raintonic-formaui-components-alert.mjs +16 -2
  14. package/fesm2022/raintonic-formaui-components-alert.mjs.map +1 -1
  15. package/fesm2022/raintonic-formaui-components-autocomplete.mjs +255 -462
  16. package/fesm2022/raintonic-formaui-components-autocomplete.mjs.map +1 -1
  17. package/fesm2022/raintonic-formaui-components-avatar.mjs +34 -59
  18. package/fesm2022/raintonic-formaui-components-avatar.mjs.map +1 -1
  19. package/fesm2022/raintonic-formaui-components-badge.mjs +2 -2
  20. package/fesm2022/raintonic-formaui-components-badge.mjs.map +1 -1
  21. package/fesm2022/raintonic-formaui-components-breadcrumb.mjs +4 -4
  22. package/fesm2022/raintonic-formaui-components-breadcrumb.mjs.map +1 -1
  23. package/fesm2022/raintonic-formaui-components-button-group.mjs +2 -2
  24. package/fesm2022/raintonic-formaui-components-button-group.mjs.map +1 -1
  25. package/fesm2022/raintonic-formaui-components-button.mjs +15 -20
  26. package/fesm2022/raintonic-formaui-components-button.mjs.map +1 -1
  27. package/fesm2022/raintonic-formaui-components-card.mjs +2 -2
  28. package/fesm2022/raintonic-formaui-components-card.mjs.map +1 -1
  29. package/fesm2022/raintonic-formaui-components-checkbox.mjs +2 -2
  30. package/fesm2022/raintonic-formaui-components-checkbox.mjs.map +1 -1
  31. package/fesm2022/raintonic-formaui-components-chip.mjs +97 -0
  32. package/fesm2022/raintonic-formaui-components-chip.mjs.map +1 -0
  33. package/fesm2022/raintonic-formaui-components-data-table.mjs +69 -29
  34. package/fesm2022/raintonic-formaui-components-data-table.mjs.map +1 -1
  35. package/fesm2022/raintonic-formaui-components-date-picker.mjs +223 -144
  36. package/fesm2022/raintonic-formaui-components-date-picker.mjs.map +1 -1
  37. package/fesm2022/raintonic-formaui-components-divider.mjs +2 -2
  38. package/fesm2022/raintonic-formaui-components-divider.mjs.map +1 -1
  39. package/fesm2022/raintonic-formaui-components-drawer.mjs +2 -2
  40. package/fesm2022/raintonic-formaui-components-drawer.mjs.map +1 -1
  41. package/fesm2022/raintonic-formaui-components-dropdown-menu.mjs +888 -0
  42. package/fesm2022/raintonic-formaui-components-dropdown-menu.mjs.map +1 -0
  43. package/fesm2022/raintonic-formaui-components-dual-tier-navigation.mjs +774 -0
  44. package/fesm2022/raintonic-formaui-components-dual-tier-navigation.mjs.map +1 -0
  45. package/fesm2022/raintonic-formaui-components-empty-state.mjs +2 -2
  46. package/fesm2022/raintonic-formaui-components-empty-state.mjs.map +1 -1
  47. package/fesm2022/raintonic-formaui-components-file-upload.mjs +2 -2
  48. package/fesm2022/raintonic-formaui-components-file-upload.mjs.map +1 -1
  49. package/fesm2022/raintonic-formaui-components-form-field.mjs +81 -50
  50. package/fesm2022/raintonic-formaui-components-form-field.mjs.map +1 -1
  51. package/fesm2022/raintonic-formaui-components-icon.mjs +2 -2
  52. package/fesm2022/raintonic-formaui-components-icon.mjs.map +1 -1
  53. package/fesm2022/raintonic-formaui-components-input.mjs +47 -12
  54. package/fesm2022/raintonic-formaui-components-input.mjs.map +1 -1
  55. package/fesm2022/raintonic-formaui-components-list.mjs +4 -4
  56. package/fesm2022/raintonic-formaui-components-list.mjs.map +1 -1
  57. package/fesm2022/raintonic-formaui-components-number-input.mjs +20 -12
  58. package/fesm2022/raintonic-formaui-components-number-input.mjs.map +1 -1
  59. package/fesm2022/raintonic-formaui-components-paginator.mjs +2 -2
  60. package/fesm2022/raintonic-formaui-components-paginator.mjs.map +1 -1
  61. package/fesm2022/raintonic-formaui-components-password-input.mjs +35 -110
  62. package/fesm2022/raintonic-formaui-components-password-input.mjs.map +1 -1
  63. package/fesm2022/raintonic-formaui-components-popover.mjs +3 -2
  64. package/fesm2022/raintonic-formaui-components-popover.mjs.map +1 -1
  65. package/fesm2022/raintonic-formaui-components-progressbar.mjs +3 -2
  66. package/fesm2022/raintonic-formaui-components-progressbar.mjs.map +1 -1
  67. package/fesm2022/raintonic-formaui-components-radio.mjs +5 -6
  68. package/fesm2022/raintonic-formaui-components-radio.mjs.map +1 -1
  69. package/fesm2022/raintonic-formaui-components-select.mjs +257 -412
  70. package/fesm2022/raintonic-formaui-components-select.mjs.map +1 -1
  71. package/fesm2022/raintonic-formaui-components-side-panel.mjs +2 -2
  72. package/fesm2022/raintonic-formaui-components-side-panel.mjs.map +1 -1
  73. package/fesm2022/raintonic-formaui-components-sidebar-nav-menu.mjs +525 -0
  74. package/fesm2022/raintonic-formaui-components-sidebar-nav-menu.mjs.map +1 -0
  75. package/fesm2022/raintonic-formaui-components-skeleton.mjs +2 -2
  76. package/fesm2022/raintonic-formaui-components-skeleton.mjs.map +1 -1
  77. package/fesm2022/raintonic-formaui-components-slider.mjs +2 -2
  78. package/fesm2022/raintonic-formaui-components-slider.mjs.map +1 -1
  79. package/fesm2022/raintonic-formaui-components-spinner.mjs +2 -2
  80. package/fesm2022/raintonic-formaui-components-spinner.mjs.map +1 -1
  81. package/fesm2022/raintonic-formaui-components-stepper.mjs +50 -45
  82. package/fesm2022/raintonic-formaui-components-stepper.mjs.map +1 -1
  83. package/fesm2022/raintonic-formaui-components-strength-meter.mjs +149 -0
  84. package/fesm2022/raintonic-formaui-components-strength-meter.mjs.map +1 -0
  85. package/fesm2022/raintonic-formaui-components-tab.mjs +2 -2
  86. package/fesm2022/raintonic-formaui-components-tab.mjs.map +1 -1
  87. package/fesm2022/raintonic-formaui-components-time-picker.mjs +194 -154
  88. package/fesm2022/raintonic-formaui-components-time-picker.mjs.map +1 -1
  89. package/fesm2022/raintonic-formaui-components-toggle-group.mjs +302 -0
  90. package/fesm2022/raintonic-formaui-components-toggle-group.mjs.map +1 -0
  91. package/fesm2022/raintonic-formaui-components-toggle.mjs +2 -2
  92. package/fesm2022/raintonic-formaui-components-toggle.mjs.map +1 -1
  93. package/fesm2022/raintonic-formaui-components-toolbar.mjs +2 -2
  94. package/fesm2022/raintonic-formaui-components-toolbar.mjs.map +1 -1
  95. package/fesm2022/raintonic-formaui-components-tooltip.mjs +10 -4
  96. package/fesm2022/raintonic-formaui-components-tooltip.mjs.map +1 -1
  97. package/fesm2022/raintonic-formaui-components-topbar.mjs +60 -0
  98. package/fesm2022/raintonic-formaui-components-topbar.mjs.map +1 -0
  99. package/fesm2022/raintonic-formaui-components-tree-select.mjs +59 -69
  100. package/fesm2022/raintonic-formaui-components-tree-select.mjs.map +1 -1
  101. package/fesm2022/raintonic-formaui-components-tree-table.mjs +2 -2
  102. package/fesm2022/raintonic-formaui-components-tree-table.mjs.map +1 -1
  103. package/fesm2022/raintonic-formaui-components-tree.mjs +31 -5
  104. package/fesm2022/raintonic-formaui-components-tree.mjs.map +1 -1
  105. package/fesm2022/raintonic-formaui-core.mjs +279 -1
  106. package/fesm2022/raintonic-formaui-core.mjs.map +1 -1
  107. package/fesm2022/raintonic-formaui-services-breakpoint.mjs +93 -0
  108. package/fesm2022/raintonic-formaui-services-breakpoint.mjs.map +1 -0
  109. package/fesm2022/raintonic-formaui-services-dialog.mjs +314 -16
  110. package/fesm2022/raintonic-formaui-services-dialog.mjs.map +1 -1
  111. package/fesm2022/raintonic-formaui-services-notification.mjs +93 -29
  112. package/fesm2022/raintonic-formaui-services-notification.mjs.map +1 -1
  113. package/fesm2022/raintonic-formaui-services-theme.mjs +46 -196
  114. package/fesm2022/raintonic-formaui-services-theme.mjs.map +1 -1
  115. package/fesm2022/raintonic-formaui.mjs +1 -1
  116. package/fesm2022/raintonic-formaui.mjs.map +1 -1
  117. package/llms-full.txt +2329 -450
  118. package/llms.txt +36 -33
  119. package/package.json +42 -19
  120. package/styles/fonts/Geist-Bold.woff2 +0 -0
  121. package/styles/fonts/Geist-Italic.woff2 +0 -0
  122. package/styles/fonts/Geist-Light.woff2 +0 -0
  123. package/styles/fonts/Geist-Medium.woff2 +0 -0
  124. package/styles/fonts/Geist-Regular.woff2 +0 -0
  125. package/styles/fonts/Geist-SemiBold.woff2 +0 -0
  126. package/styles/fonts/GeistMono-Regular.woff2 +0 -0
  127. package/styles/generated/_tokens.scss +906 -0
  128. package/styles/index.scss +11 -10
  129. package/styles/partials/_brand.scss +46 -0
  130. package/styles/partials/_constants.scss +22 -20
  131. package/styles/partials/_fonts.scss +54 -10
  132. package/styles/partials/_grid.scss +29 -18
  133. package/styles/partials/_mixins.scss +69 -27
  134. package/styles/partials/_motion.scss +28 -33
  135. package/styles/partials/_theme.scss +28 -255
  136. package/styles/partials/_type.scss +117 -0
  137. package/styles/partials/_typography.scss +45 -45
  138. package/styles/partials/_utilities.scss +198 -98
  139. package/styles/partials/components/_button.scss +144 -75
  140. package/styles/partials/components/_dialog.scss +181 -180
  141. package/styles/partials/components/_overlay.scss +87 -87
  142. package/styles/partials/themes/_dark.scss +3 -268
  143. package/styles/partials/themes/_light.scss +4 -268
  144. package/styles/styles.css +7744 -0
  145. package/styles/styles.entry.scss +3 -0
  146. package/styles/utilities.css +4802 -0
  147. package/styles/utilities.entry.scss +3 -0
  148. package/types/raintonic-formaui-cdk-drag-drop.d.ts +0 -1
  149. package/types/raintonic-formaui-cdk-drag-drop.d.ts.map +1 -1
  150. package/types/raintonic-formaui-cdk-form-field.d.ts +118 -2
  151. package/types/raintonic-formaui-cdk-form-field.d.ts.map +1 -1
  152. package/types/raintonic-formaui-cdk-overlay.d.ts +2 -0
  153. package/types/raintonic-formaui-cdk-overlay.d.ts.map +1 -1
  154. package/types/raintonic-formaui-cdk-virtual-scroll.d.ts +0 -1
  155. package/types/raintonic-formaui-cdk-virtual-scroll.d.ts.map +1 -1
  156. package/types/raintonic-formaui-components-accordion.d.ts +1 -1
  157. package/types/raintonic-formaui-components-accordion.d.ts.map +1 -1
  158. package/types/raintonic-formaui-components-alert.d.ts +6 -1
  159. package/types/raintonic-formaui-components-alert.d.ts.map +1 -1
  160. package/types/raintonic-formaui-components-autocomplete.d.ts +73 -116
  161. package/types/raintonic-formaui-components-autocomplete.d.ts.map +1 -1
  162. package/types/raintonic-formaui-components-avatar.d.ts +13 -31
  163. package/types/raintonic-formaui-components-avatar.d.ts.map +1 -1
  164. package/types/raintonic-formaui-components-button.d.ts +4 -10
  165. package/types/raintonic-formaui-components-button.d.ts.map +1 -1
  166. package/types/raintonic-formaui-components-chip.d.ts +43 -0
  167. package/types/raintonic-formaui-components-chip.d.ts.map +1 -0
  168. package/types/raintonic-formaui-components-data-table.d.ts +48 -11
  169. package/types/raintonic-formaui-components-data-table.d.ts.map +1 -1
  170. package/types/raintonic-formaui-components-date-picker.d.ts +59 -23
  171. package/types/raintonic-formaui-components-date-picker.d.ts.map +1 -1
  172. package/types/raintonic-formaui-components-dropdown-menu.d.ts +394 -0
  173. package/types/raintonic-formaui-components-dropdown-menu.d.ts.map +1 -0
  174. package/types/raintonic-formaui-components-dual-tier-navigation.d.ts +87 -0
  175. package/types/raintonic-formaui-components-dual-tier-navigation.d.ts.map +1 -0
  176. package/types/raintonic-formaui-components-form-field.d.ts +51 -21
  177. package/types/raintonic-formaui-components-form-field.d.ts.map +1 -1
  178. package/types/raintonic-formaui-components-input.d.ts +20 -11
  179. package/types/raintonic-formaui-components-input.d.ts.map +1 -1
  180. package/types/raintonic-formaui-components-number-input.d.ts +5 -3
  181. package/types/raintonic-formaui-components-number-input.d.ts.map +1 -1
  182. package/types/raintonic-formaui-components-password-input.d.ts +18 -32
  183. package/types/raintonic-formaui-components-password-input.d.ts.map +1 -1
  184. package/types/raintonic-formaui-components-popover.d.ts.map +1 -1
  185. package/types/raintonic-formaui-components-progressbar.d.ts +1 -1
  186. package/types/raintonic-formaui-components-progressbar.d.ts.map +1 -1
  187. package/types/raintonic-formaui-components-radio.d.ts +1 -2
  188. package/types/raintonic-formaui-components-radio.d.ts.map +1 -1
  189. package/types/raintonic-formaui-components-select.d.ts +107 -76
  190. package/types/raintonic-formaui-components-select.d.ts.map +1 -1
  191. package/types/raintonic-formaui-components-sidebar-nav-menu.d.ts +223 -0
  192. package/types/raintonic-formaui-components-sidebar-nav-menu.d.ts.map +1 -0
  193. package/types/raintonic-formaui-components-stepper.d.ts +4 -2
  194. package/types/raintonic-formaui-components-stepper.d.ts.map +1 -1
  195. package/types/raintonic-formaui-components-strength-meter.d.ts +78 -0
  196. package/types/raintonic-formaui-components-strength-meter.d.ts.map +1 -0
  197. package/types/raintonic-formaui-components-time-picker.d.ts +44 -24
  198. package/types/raintonic-formaui-components-time-picker.d.ts.map +1 -1
  199. package/types/raintonic-formaui-components-toggle-group.d.ts +100 -0
  200. package/types/raintonic-formaui-components-toggle-group.d.ts.map +1 -0
  201. package/types/raintonic-formaui-components-tooltip.d.ts +2 -1
  202. package/types/raintonic-formaui-components-tooltip.d.ts.map +1 -1
  203. package/types/raintonic-formaui-components-topbar.d.ts +48 -0
  204. package/types/raintonic-formaui-components-topbar.d.ts.map +1 -0
  205. package/types/raintonic-formaui-components-tree-select.d.ts +25 -9
  206. package/types/raintonic-formaui-components-tree-select.d.ts.map +1 -1
  207. package/types/raintonic-formaui-components-tree.d.ts +12 -1
  208. package/types/raintonic-formaui-components-tree.d.ts.map +1 -1
  209. package/types/raintonic-formaui-core.d.ts +243 -5
  210. package/types/raintonic-formaui-core.d.ts.map +1 -1
  211. package/types/raintonic-formaui-services-breakpoint.d.ts +44 -0
  212. package/types/raintonic-formaui-services-breakpoint.d.ts.map +1 -0
  213. package/types/raintonic-formaui-services-dialog.d.ts +141 -2
  214. package/types/raintonic-formaui-services-dialog.d.ts.map +1 -1
  215. package/types/raintonic-formaui-services-notification.d.ts +24 -2
  216. package/types/raintonic-formaui-services-notification.d.ts.map +1 -1
  217. package/types/raintonic-formaui-services-theme.d.ts +13 -103
  218. package/types/raintonic-formaui-services-theme.d.ts.map +1 -1
  219. package/types/raintonic-formaui.d.ts +1 -1
  220. package/fesm2022/raintonic-formaui-components-big-menu.mjs +0 -86
  221. package/fesm2022/raintonic-formaui-components-big-menu.mjs.map +0 -1
  222. package/fesm2022/raintonic-formaui-components-menu.mjs +0 -896
  223. package/fesm2022/raintonic-formaui-components-menu.mjs.map +0 -1
  224. package/fesm2022/raintonic-formaui-components-sidebar.mjs +0 -275
  225. package/fesm2022/raintonic-formaui-components-sidebar.mjs.map +0 -1
  226. package/fesm2022/raintonic-formaui-components-tag.mjs +0 -95
  227. package/fesm2022/raintonic-formaui-components-tag.mjs.map +0 -1
  228. package/styles/_fonts-entry.scss +0 -3
  229. package/styles/fonts/inter-tight-latin-italic.woff2 +0 -0
  230. package/styles/fonts/inter-tight-latin.woff2 +0 -0
  231. package/types/raintonic-formaui-components-big-menu.d.ts +0 -73
  232. package/types/raintonic-formaui-components-big-menu.d.ts.map +0 -1
  233. package/types/raintonic-formaui-components-menu.d.ts +0 -403
  234. package/types/raintonic-formaui-components-menu.d.ts.map +0 -1
  235. package/types/raintonic-formaui-components-sidebar.d.ts +0 -185
  236. package/types/raintonic-formaui-components-sidebar.d.ts.map +0 -1
  237. package/types/raintonic-formaui-components-tag.d.ts +0 -43
  238. package/types/raintonic-formaui-components-tag.d.ts.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"raintonic-formaui-components-dual-tier-navigation.mjs","sources":["../../../lib/components/dual-tier-navigation/dual-tier-navigation-trigger.component.ts","../../../lib/components/dual-tier-navigation/dual-tier-navigation-submenu-header.component.ts","../../../lib/components/dual-tier-navigation/dual-tier-navigation-submenu-item.component.ts","../../../lib/components/dual-tier-navigation/dual-tier-navigation-submenu.component.ts","../../../lib/components/dual-tier-navigation/dual-tier-navigation.component.ts","../../../lib/components/dual-tier-navigation/raintonic-formaui-components-dual-tier-navigation.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, computed, input, output } from '@angular/core';\r\nimport { RouterLink } from '@angular/router';\r\nimport { FuiIconComponent } from '@raintonic/formaui/components/icon';\r\nimport { MenuItem } from '@raintonic/formaui/core';\r\nimport { FuiTooltipDirective } from '@raintonic/formaui/components/tooltip';\r\n\r\n/**\r\n * Renders a single top-level trigger item for the dual-tier navigation bar.\r\n * Extracted so the main component stays under 200 lines.\r\n */\r\n@Component({\r\n selector: 'fui-dual-tier-nav-trigger',\r\n standalone: true,\r\n imports: [RouterLink, FuiIconComponent, FuiTooltipDirective],\r\n styles: `\r\n :host {\r\n display: contents;\r\n }\r\n .fui-dual-tier-nav__trigger {\r\n display: flex;\r\n align-items: center;\r\n gap: var(--fui-spacing-2);\r\n padding: var(--fui-spacing-5) var(--fui-spacing-5);\r\n cursor: pointer;\r\n user-select: none;\r\n text-decoration: none;\r\n color: var(--fui-text-secondary);\r\n background: transparent;\r\n border: none;\r\n border-radius: var(--fui-radius-xs);\r\n font-family: var(--fui-font-sans);\r\n font-size: var(--fui-text-sm);\r\n font-weight: var(--fui-weight-medium);\r\n line-height: var(--fui-leading-normal);\r\n text-align: left;\r\n white-space: nowrap;\r\n outline: none;\r\n transition:\r\n background-color var(--fui-duration-fast) var(--fui-ease-out),\r\n color var(--fui-duration-fast) var(--fui-ease-out);\r\n }\r\n .fui-dual-tier-nav__trigger:hover:not(.fui-dual-tier-nav__trigger--disabled) {\r\n color: var(--fui-text-primary);\r\n }\r\n .fui-dual-tier-nav__trigger:hover:not(.fui-dual-tier-nav__trigger--disabled) fui-icon {\r\n background-color: var(--fui-bg-muted);\r\n }\r\n .fui-dual-tier-nav__trigger:active:not(.fui-dual-tier-nav__trigger--disabled),\r\n .fui-dual-tier-nav__trigger--expanded {\r\n color: var(--fui-text-primary);\r\n }\r\n .fui-dual-tier-nav__trigger:active:not(.fui-dual-tier-nav__trigger--disabled) fui-icon,\r\n .fui-dual-tier-nav__trigger--expanded fui-icon {\r\n background-color: var(--fui-bg-primary);\r\n color: var(--fui-text-link);\r\n }\r\n .fui-dual-tier-nav__trigger--expanded:hover fui-icon {\r\n background-color: var(--fui-state-selected-bg);\r\n }\r\n .fui-dual-tier-nav__trigger:hover {\r\n text-decoration: none;\r\n }\r\n .fui-dual-tier-nav__trigger:focus-visible {\r\n outline: 2px solid var(--fui-state-focus-ring);\r\n outline-offset: -2px;\r\n }\r\n .fui-dual-tier-nav__trigger--disabled {\r\n color: var(--fui-text-disabled);\r\n opacity: var(--fui-state-disabled-opacity);\r\n pointer-events: none;\r\n cursor: default;\r\n }\r\n\r\n .fui-dual-tier-nav__trigger-content {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: stretch;\r\n gap: var(--fui-spacing-2);\r\n max-width: 44px;\r\n }\r\n .fui-dual-tier-nav__trigger-icon {\r\n width: 44px;\r\n height: 44px;\r\n flex-shrink: 0;\r\n align-self: center;\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n border-radius: var(--fui-radius-xs);\r\n }\r\n .fui-dual-tier-nav__trigger-label {\r\n max-width: 100%;\r\n min-width: 0;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n text-align: center;\r\n }\r\n `,\r\n template: `\r\n @if (hasChildren()) {\r\n <button\r\n class=\"fui-dual-tier-nav__trigger\"\r\n type=\"button\"\r\n role=\"menuitem\"\r\n [class.fui-dual-tier-nav__trigger--expanded]=\"isExpanded()\"\r\n [class.fui-dual-tier-nav__trigger--disabled]=\"item().disabled\"\r\n [attr.aria-haspopup]=\"true\"\r\n [attr.aria-expanded]=\"isExpanded()\"\r\n [attr.aria-controls]=\"isExpanded() ? 'fui-dtn-flyout-' + flyoutId() : null\"\r\n [disabled]=\"item().disabled\"\r\n (click)=\"onClick($event)\"\r\n (keydown)=\"onKeydown($event)\"\r\n [fuiTooltip]=\"item().label ?? ''\"\r\n >\r\n <div class=\"fui-dual-tier-nav__trigger-content\">\r\n @if (item().icon) {\r\n <fui-icon class=\"fui-dual-tier-nav__trigger-icon\" [name]=\"item().icon ?? ''\" size=\"md\" aria-hidden=\"true\" />\r\n }\r\n <span class=\"fui-dual-tier-nav__trigger-label\">{{ item().label }}</span>\r\n </div>\r\n </button>\r\n } @else if (item().routerLink) {\r\n <a\r\n class=\"fui-dual-tier-nav__trigger\"\r\n role=\"menuitem\"\r\n [class.fui-dual-tier-nav__trigger--disabled]=\"item().disabled\"\r\n [attr.aria-disabled]=\"item().disabled || null\"\r\n [routerLink]=\"item().routerLink\"\r\n [queryParams]=\"item().queryParams || undefined\"\r\n [fragment]=\"item().fragment || undefined\"\r\n [target]=\"item().target\"\r\n (click)=\"onClick($event)\"\r\n (keydown)=\"onKeydown($event)\"\r\n [fuiTooltip]=\"item().label ?? ''\"\r\n >\r\n <span class=\"fui-dual-tier-nav__trigger-content\">\r\n @if (item().icon) {\r\n <fui-icon class=\"fui-dual-tier-nav__trigger-icon\" [name]=\"item().icon ?? ''\" size=\"md\" aria-hidden=\"true\" />\r\n }\r\n <span class=\"fui-dual-tier-nav__trigger-label\">{{ item().label }}</span>\r\n </span>\r\n </a>\r\n } @else {\r\n <button\r\n class=\"fui-dual-tier-nav__trigger\"\r\n type=\"button\"\r\n role=\"menuitem\"\r\n [class.fui-dual-tier-nav__trigger--disabled]=\"item().disabled\"\r\n [attr.aria-disabled]=\"item().disabled || null\"\r\n [title]=\"item().title\"\r\n [disabled]=\"item().disabled\"\r\n (click)=\"onClick($event)\"\r\n (keydown)=\"onKeydown($event)\"\r\n [fuiTooltip]=\"item().label ?? ''\"\r\n >\r\n <span class=\"fui-dual-tier-nav__trigger-content\">\r\n @if (item().icon) {\r\n <fui-icon class=\"fui-dual-tier-nav__trigger-icon\" [name]=\"item().icon ?? ''\" size=\"md\" aria-hidden=\"true\" />\r\n }\r\n <span class=\"fui-dual-tier-nav__trigger-label\">{{ item().label }}</span>\r\n </span>\r\n </button>\r\n }\r\n `,\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n host: { class: 'fui-dual-tier-nav__bar-item', role: 'none' },\r\n})\r\nexport class DualTierNavTriggerComponent {\r\n readonly item = input.required<MenuItem>();\r\n readonly isExpanded = input(false);\r\n readonly flyoutId = input('');\r\n readonly itemClick = output<MenuItem>();\r\n readonly toggle = output<Event>();\r\n readonly keydown = output<KeyboardEvent>();\r\n\r\n readonly hasChildren = computed(() => !!this.item().items?.length);\r\n\r\n onClick(event: Event): void {\r\n const it = this.item();\r\n if (it.disabled) {\r\n event.preventDefault();\r\n return;\r\n }\r\n if (this.hasChildren()) {\r\n this.toggle.emit(event);\r\n return;\r\n }\r\n it.command?.(event);\r\n this.itemClick.emit(it);\r\n }\r\n\r\n onKeydown(event: KeyboardEvent): void {\r\n if (this.item().disabled) {\r\n return;\r\n }\r\n // bubble up and handle in dual-tier-navigation\r\n this.keydown.emit(event);\r\n }\r\n}\r\n","import { ChangeDetectionStrategy, Component, input, output } from '@angular/core';\r\nimport { FuiIconComponent } from '@raintonic/formaui/components/icon';\r\n\r\n@Component({\r\n selector: 'fui-dual-tier-nav-submenu-header',\r\n standalone: true,\r\n imports: [FuiIconComponent],\r\n styles: [\r\n `\r\n .fui-dtn-submenu__header {\r\n display: flex;\r\n justify-content: space-between;\r\n margin-top: var(--fui-spacing-8);\r\n align-items: center;\r\n padding: 0 var(--fui-spacing-2);\r\n }\r\n .fui-dtn-submenu__title {\r\n margin: 0;\r\n font-family: var(--fui-font-sans);\r\n font-size: var(--fui-text-base);\r\n font-weight: var(--fui-weight-semibold);\r\n line-height: var(--fui-leading-normal);\r\n letter-spacing: var(--fui-tracking-wide);\r\n color: var(--fui-text-primary);\r\n }\r\n .fui-dtn-submenu__close {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n background: none;\r\n border: none;\r\n cursor: pointer;\r\n padding: 8px;\r\n border-radius: var(--fui-radius-sm);\r\n color: var(--fui-text-secondary);\r\n outline: none;\r\n transition:\r\n background-color var(--fui-duration-fast) var(--fui-ease-out),\r\n color var(--fui-duration-fast) var(--fui-ease-out);\r\n }\r\n .fui-dtn-submenu__close:hover {\r\n background-color: var(--fui-bg-muted);\r\n color: var(--fui-text-primary);\r\n }\r\n .fui-dtn-submenu__close:focus-visible {\r\n outline: 2px solid var(--fui-state-focus-ring);\r\n outline-offset: -2px;\r\n }\r\n `,\r\n ],\r\n template: `\r\n <div class=\"fui-dtn-submenu__header\">\r\n <h6 class=\"fui-dtn-submenu__title\">{{ title() }}</h6>\r\n @if (closable()) {\r\n <button type=\"button\" class=\"fui-dtn-submenu__close\" aria-label=\"Close menu\" (click)=\"close.emit()\">\r\n <fui-icon name=\"caret-double-left\" size=\"sm\" aria-hidden=\"true\" />\r\n </button>\r\n }\r\n </div>\r\n `,\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n host: { class: 'fui-dtn-submenu__header-wrapper' },\r\n})\r\nexport class DualTierNavSubmenuHeaderComponent {\r\n readonly title = input.required<string>();\r\n readonly closable = input(true);\r\n readonly close = output();\r\n}\r\n","import { ChangeDetectionStrategy, Component, input, output } from '@angular/core';\r\nimport { RouterLink, RouterLinkActive } from '@angular/router';\r\nimport { FuiIconComponent } from '@raintonic/formaui/components/icon';\r\nimport { MenuItem } from '@raintonic/formaui/core';\r\n\r\n@Component({\r\n selector: 'fui-dual-tier-nav-submenu-item',\r\n standalone: true,\r\n imports: [RouterLink, RouterLinkActive, FuiIconComponent],\r\n styles: [\r\n `\r\n :host {\r\n display: flex;\r\n flex-direction: column;\r\n }\r\n\r\n .fui-dtn-item {\r\n display: flex;\r\n align-items: center;\r\n gap: var(--fui-spacing-6);\r\n padding: var(--fui-spacing-4) var(--fui-spacing-6) var(--fui-spacing-4) var(--fui-spacing-3);\r\n cursor: pointer;\r\n user-select: none;\r\n text-decoration: none;\r\n color: var(--fui-text-secondary);\r\n background: transparent;\r\n border: none;\r\n border-radius: var(--fui-radius-sm);\r\n font-family: var(--fui-font-sans);\r\n font-size: var(--fui-text-base);\r\n font-weight: var(--fui-weight-medium);\r\n line-height: var(--fui-leading-normal);\r\n text-align: left;\r\n width: 100%;\r\n box-sizing: border-box;\r\n outline: none;\r\n transition:\r\n background-color var(--fui-duration-fast) var(--fui-ease-out),\r\n color var(--fui-duration-fast) var(--fui-ease-out);\r\n }\r\n .fui-dtn-item:hover {\r\n background-color: var(--fui-bg-muted);\r\n text-decoration: none;\r\n }\r\n .fui-dtn-item:active {\r\n background-color: var(--fui-bg-primary);\r\n }\r\n .fui-dtn-item:focus-visible {\r\n outline: 2px solid var(--fui-state-focus-ring);\r\n outline-offset: -2px;\r\n }\r\n .fui-dtn-item--active {\r\n color: var(--fui-text-primary);\r\n background-color: var(--fui-state-selected-bg);\r\n }\r\n .fui-dtn-item--disabled {\r\n color: var(--fui-text-disabled);\r\n opacity: var(--fui-state-disabled-opacity);\r\n pointer-events: none;\r\n cursor: default;\r\n }\r\n\r\n .fui-dtn-item--parent-expanded {\r\n color: var(--fui-text-primary);\r\n background-color: var(--fui-bg-muted);\r\n }\r\n\r\n .fui-dtn-item__label {\r\n flex: 1;\r\n min-width: 0;\r\n white-space: nowrap;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n }\r\n\r\n .fui-dtn-item__chevron {\r\n flex-shrink: 0;\r\n color: inherit;\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n transition: transform var(--fui-duration-base) var(--fui-ease-out);\r\n }\r\n .fui-dtn-item__chevron--expanded {\r\n transform: rotate(90deg);\r\n }\r\n `,\r\n ],\r\n template: `\r\n @if (hasChildren()) {\r\n <button\r\n class=\"fui-dtn-item fui-dtn-item--parent\"\r\n type=\"button\"\r\n role=\"menuitem\"\r\n [class.fui-dtn-item--disabled]=\"item().disabled\"\r\n [class.fui-dtn-item--parent-expanded]=\"isExpanded()\"\r\n [attr.aria-haspopup]=\"true\"\r\n [attr.aria-expanded]=\"isExpanded()\"\r\n [disabled]=\"item().disabled\"\r\n (click)=\"_onClick($event)\"\r\n (keydown)=\"_onKeydown($event)\"\r\n >\r\n <span class=\"fui-dtn-item__label\">{{ item().label }}</span>\r\n <fui-icon\r\n class=\"fui-dtn-item__chevron\"\r\n [class.fui-dtn-item__chevron--expanded]=\"isExpanded()\"\r\n name=\"caret-right\"\r\n size=\"sm\"\r\n aria-hidden=\"true\"\r\n />\r\n </button>\r\n } @else if (item().routerLink) {\r\n <a\r\n class=\"fui-dtn-item\"\r\n role=\"menuitem\"\r\n routerLinkActive=\"fui-dtn-item--active\"\r\n [class.fui-dtn-item--disabled]=\"item().disabled\"\r\n [tabindex]=\"item().disabled ? -1 : 0\"\r\n [attr.aria-disabled]=\"item().disabled || null\"\r\n [routerLink]=\"item().routerLink\"\r\n [queryParams]=\"item().queryParams ?? undefined\"\r\n [fragment]=\"item().fragment ?? undefined\"\r\n [target]=\"item().target\"\r\n [title]=\"item().title\"\r\n (click)=\"_onClick($event)\"\r\n (keydown)=\"_onKeydown($event)\"\r\n >\r\n <span class=\"fui-dtn-item__label\">{{ item().label }}</span>\r\n </a>\r\n } @else {\r\n <button\r\n class=\"fui-dtn-item\"\r\n type=\"button\"\r\n role=\"menuitem\"\r\n [class.fui-dtn-item--disabled]=\"item().disabled\"\r\n [tabindex]=\"item().disabled ? -1 : 0\"\r\n [attr.aria-disabled]=\"item().disabled || null\"\r\n [title]=\"item().title\"\r\n [disabled]=\"item().disabled\"\r\n (click)=\"_onClick($event)\"\r\n (keydown)=\"_onKeydown($event)\"\r\n >\r\n <span class=\"fui-dtn-item__label\">{{ item().label }}</span>\r\n </button>\r\n }\r\n `,\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n host: { role: 'none' },\r\n})\r\nexport class DualTierNavSubmenuItemComponent {\r\n readonly item = input.required<MenuItem>();\r\n readonly isExpanded = input(false);\r\n readonly clickItem = output<MenuItem>();\r\n readonly toggleExpand = output<{ item: MenuItem; sourceEl?: HTMLElement }>();\r\n readonly keydown = output<KeyboardEvent>();\r\n\r\n hasChildren(): boolean {\r\n return !!this.item()?.items?.length;\r\n }\r\n\r\n _onClick(event: Event): void {\r\n const it = this.item();\r\n if (it?.disabled) {\r\n event.preventDefault();\r\n return;\r\n }\r\n if (this.hasChildren()) {\r\n this.toggleExpand.emit({ item: it, sourceEl: event.currentTarget as HTMLElement | undefined });\r\n } else {\r\n if (it.command) it.command(event);\r\n this.clickItem.emit(it);\r\n }\r\n }\r\n\r\n _onKeydown(event: KeyboardEvent): void {\r\n if (this.item()?.disabled) return;\r\n switch (event.key) {\r\n case 'ArrowRight':\r\n event.preventDefault();\r\n if (this.hasChildren())\r\n this.toggleExpand.emit({ item: this.item(), sourceEl: event.currentTarget as HTMLElement | undefined });\r\n break;\r\n case 'ArrowLeft':\r\n event.preventDefault();\r\n // Delegate to parent: collapse if expanded, close panel otherwise\r\n this.keydown.emit(event);\r\n break;\r\n case 'ArrowDown':\r\n case 'ArrowUp':\r\n // Let the list-level handler navigate between items\r\n break;\r\n case 'Enter':\r\n case ' ':\r\n if (this.hasChildren()) {\r\n event.preventDefault();\r\n this.toggleExpand.emit({ item: this.item(), sourceEl: event.currentTarget as HTMLElement | undefined });\r\n }\r\n break;\r\n default:\r\n this.keydown.emit(event);\r\n }\r\n }\r\n}\r\n","import {\r\n afterNextRender,\r\n ChangeDetectionStrategy,\r\n Component,\r\n computed,\r\n effect,\r\n inject,\r\n Injector,\r\n input,\r\n output,\r\n signal,\r\n} from '@angular/core';\r\nimport { MenuItem } from '@raintonic/formaui/core';\r\nimport { DualTierNavSubmenuHeaderComponent } from './dual-tier-navigation-submenu-header.component';\r\nimport { DualTierNavSubmenuItemComponent } from './dual-tier-navigation-submenu-item.component';\r\n\r\n@Component({\r\n selector: 'fui-dual-tier-nav-submenu',\r\n standalone: true,\r\n imports: [DualTierNavSubmenuHeaderComponent, DualTierNavSubmenuItemComponent],\r\n styles: [\r\n `\r\n :host {\r\n display: contents;\r\n }\r\n .fui-dtn-submenu {\r\n display: flex;\r\n flex-direction: column;\r\n padding-top: var(--fui-spacing-2);\r\n padding-left: var(--fui-spacing-4);\r\n }\r\n .fui-dtn-submenu__list {\r\n display: flex;\r\n flex-direction: column;\r\n list-style: none;\r\n margin: 0;\r\n gap: var(--fui-spacing-2);\r\n }\r\n `,\r\n `\r\n @keyframes fui-dtn-nested-enter {\r\n from {\r\n opacity: 0;\r\n max-height: 0;\r\n }\r\n to {\r\n opacity: 1;\r\n max-height: 500px;\r\n }\r\n }\r\n @keyframes fui-dtn-nested-leave {\r\n from {\r\n opacity: 1;\r\n max-height: 500px;\r\n }\r\n to {\r\n opacity: 0;\r\n max-height: 0;\r\n }\r\n }\r\n .fui-dtn-nested--enter {\r\n animation: fui-dtn-nested-enter var(--fui-duration-moderate) var(--fui-ease-out);\r\n overflow: hidden;\r\n }\r\n .fui-dtn-nested--leave {\r\n animation: fui-dtn-nested-leave var(--fui-duration-fast) var(--fui-ease-in);\r\n overflow: hidden;\r\n }\r\n `,\r\n ],\r\n template: `\r\n <div class=\"fui-dtn-submenu\">\r\n @if (showHeader()) {\r\n <fui-dual-tier-nav-submenu-header [title]=\"title()\" [closable]=\"closable()\" (close)=\"_onClose()\" />\r\n }\r\n <ul class=\"fui-dtn-submenu__list\" role=\"menu\" aria-orientation=\"vertical\" (keydown)=\"_onListKeydown($event)\">\r\n @for (item of visibleItems(); track item.id) {\r\n <li role=\"none\">\r\n <fui-dual-tier-nav-submenu-item\r\n [item]=\"item\"\r\n [isExpanded]=\"_isExpanded(item)\"\r\n (clickItem)=\"_onClickItem($event)\"\r\n (toggleExpand)=\"_onToggleExpand($event.item, $event.sourceEl)\"\r\n (keydown)=\"_onItemKeydown($event, item)\"\r\n />\r\n @if (_hasChildren(item) && _isExpanded(item)) {\r\n <div\r\n class=\"fui-dtn-submenu__nested\"\r\n animate.enter=\"fui-dtn-nested--enter\"\r\n animate.leave=\"fui-dtn-nested--leave\"\r\n >\r\n <fui-dual-tier-nav-submenu\r\n [title]=\"item.label ?? ''\"\r\n [items]=\"item.items ?? []\"\r\n [showHeader]=\"false\"\r\n [closable]=\"false\"\r\n (itemClick)=\"itemClick.emit($event)\"\r\n (closePanel)=\"closePanel.emit()\"\r\n />\r\n </div>\r\n }\r\n </li>\r\n }\r\n </ul>\r\n </div>\r\n `,\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n})\r\nexport class DualTierNavSubmenuComponent {\r\n private readonly _injector = inject(Injector);\r\n\r\n readonly title = input.required<string>();\r\n readonly items = input<MenuItem[]>([]);\r\n readonly showHeader = input(true);\r\n readonly closable = input(true);\r\n readonly itemClick = output<MenuItem>();\r\n readonly closePanel = output();\r\n\r\n readonly visibleItems = computed(() => this.items().filter((it) => it.visible !== false));\r\n readonly _expanded = signal(new Set<string>());\r\n\r\n constructor() {\r\n effect(() => {\r\n const expanded = new Set<string>();\r\n const walk = (list: MenuItem[]) => {\r\n for (const it of list) {\r\n if (it.expanded && it.items?.length) expanded.add(it.id!);\r\n if (it.items) walk(it.items);\r\n }\r\n };\r\n walk(this.items());\r\n this._expanded.set(expanded);\r\n });\r\n }\r\n\r\n _hasChildren(item: MenuItem): boolean {\r\n return !!item.items?.length;\r\n }\r\n\r\n _isExpanded(item: MenuItem): boolean {\r\n return this._hasChildren(item) && this._expanded().has(item.id!);\r\n }\r\n\r\n _onClose(): void {\r\n this.closePanel.emit();\r\n }\r\n\r\n _onClickItem(item: MenuItem): void {\r\n this.itemClick.emit(item);\r\n }\r\n\r\n _onToggleExpand(item: MenuItem, toggleSourceEl?: HTMLElement): void {\r\n const id = item.id;\r\n if (!id) return;\r\n const wasExpanded = this._expanded().has(id);\r\n this._expanded.update((s) => {\r\n const next = new Set(s);\r\n if (next.has(id)) next.delete(id);\r\n else next.add(id);\r\n return next;\r\n });\r\n // ponytail: afterNextRender to wait for the nested submenu to be rendered.\r\n // Ceiling: if the nested submenu has no visible items, focus stays on the toggle.\r\n if (!wasExpanded && toggleSourceEl) {\r\n afterNextRender(\r\n () => {\r\n const li = toggleSourceEl.closest('li');\r\n const selector = '.fui-dtn-item:not(.fui-dtn-item--disabled)';\r\n const nested = li?.querySelector<HTMLElement>(':scope > .fui-dtn-submenu__nested ' + selector);\r\n nested?.focus();\r\n },\r\n { injector: this._injector },\r\n );\r\n }\r\n }\r\n\r\n _onListKeydown(event: KeyboardEvent): void {\r\n if (!['ArrowDown', 'ArrowUp', 'Home', 'End'].includes(event.key)) return;\r\n\r\n event.stopPropagation();\r\n\r\n const listEl = (event.currentTarget as HTMLElement)?.closest('ul');\r\n if (!listEl) return;\r\n\r\n // ponytail: querySelectorAll on every keydown — acceptable for small submenu lists (<50 items).\r\n // Upgrade path: precompute items list on mutation and reuse.\r\n const items = Array.from(\r\n listEl.querySelectorAll<HTMLElement>(':scope > li > fui-dual-tier-nav-submenu-item > .fui-dtn-item'),\r\n );\r\n const idx = items.indexOf(document.activeElement as HTMLElement);\r\n\r\n switch (event.key) {\r\n case 'ArrowDown':\r\n event.preventDefault();\r\n this._focusItem(items, idx + 1, 1);\r\n break;\r\n case 'ArrowUp':\r\n event.preventDefault();\r\n this._focusItem(items, idx - 1, -1);\r\n break;\r\n case 'Home':\r\n event.preventDefault();\r\n this._focusItem(items, 0, 1);\r\n break;\r\n case 'End':\r\n event.preventDefault();\r\n this._focusItem(items, items.length - 1, -1);\r\n break;\r\n }\r\n }\r\n\r\n _onItemKeydown(event: KeyboardEvent, item: MenuItem): void {\r\n switch (event.key) {\r\n case 'ArrowLeft':\r\n event.preventDefault();\r\n if (this._hasChildren(item) && this._isExpanded(item)) {\r\n this._expanded.update((s) => {\r\n const next = new Set(s);\r\n next.delete(item.id!);\r\n return next;\r\n });\r\n } else {\r\n this.closePanel.emit();\r\n }\r\n break;\r\n }\r\n }\r\n\r\n private _focusItem(items: HTMLElement[], start: number, step: 1 | -1): void {\r\n let i = start;\r\n while (i >= 0 && i < items.length) {\r\n if (!items[i].classList.contains('fui-dtn-item--disabled')) {\r\n items[i].focus();\r\n return;\r\n }\r\n i += step;\r\n }\r\n }\r\n}\r\n","import {\r\n afterNextRender,\r\n ChangeDetectionStrategy,\r\n Component,\r\n computed,\r\n inject,\r\n Injector,\r\n input,\r\n output,\r\n signal,\r\n} from '@angular/core';\r\nimport { MenuItem } from '@raintonic/formaui/core';\r\nimport { DualTierNavTriggerComponent } from './dual-tier-navigation-trigger.component';\r\nimport { DualTierNavSubmenuComponent } from './dual-tier-navigation-submenu.component';\r\n\r\n@Component({\r\n selector: 'fui-dual-tier-navigation',\r\n standalone: true,\r\n imports: [DualTierNavTriggerComponent, DualTierNavSubmenuComponent],\r\n styles: `\r\n :host {\r\n --fui-dtn-bg: var(--fui-bg-subtle);\r\n --fui-dtn-flyout-width: 200px;\r\n\r\n display: flex;\r\n flex-direction: row;\r\n background-color: var(--fui-dtn-bg);\r\n box-sizing: border-box;\r\n }\r\n .fui-dual-tier-nav__bar {\r\n display: flex;\r\n flex-direction: column;\r\n list-style: none;\r\n margin: 0;\r\n padding: var(--fui-spacing-4) var(--fui-spacing-4);\r\n gap: var(--fui-spacing-2);\r\n flex-shrink: 0;\r\n border-right: 1px solid var(--fui-border-default);\r\n }\r\n .fui-dual-tier-nav__flyout {\r\n display: flex;\r\n flex-direction: column;\r\n width: 0;\r\n flex-shrink: 0;\r\n background: var(--fui-dtn-bg);\r\n clip-path: inset(0 100% 0 0);\r\n overflow: hidden;\r\n transition:\r\n width var(--fui-duration-moderate) cubic-bezier(0.16, 1, 0.3, 1),\r\n clip-path var(--fui-duration-moderate) cubic-bezier(0.16, 1, 0.3, 1);\r\n }\r\n .fui-dual-tier-nav__flyout--open {\r\n width: var(--fui-dtn-flyout-width);\r\n clip-path: inset(0 0 0 0);\r\n overflow-y: auto;\r\n padding-right: var(--fui-spacing-2);\r\n }\r\n\r\n @keyframes fui-dtn-flyout-content-enter {\r\n from {\r\n opacity: 0;\r\n }\r\n to {\r\n opacity: 1;\r\n }\r\n }\r\n @keyframes fui-dtn-flyout-content-leave {\r\n from {\r\n opacity: 1;\r\n }\r\n to {\r\n opacity: 0;\r\n }\r\n }\r\n .fui-dtn-flyout-content--enter {\r\n animation: fui-dtn-flyout-content-enter var(--fui-duration-fast) var(--fui-ease-out);\r\n }\r\n .fui-dtn-flyout-content--leave {\r\n animation: fui-dtn-flyout-content-leave var(--fui-duration-fast) var(--fui-ease-in);\r\n }\r\n `,\r\n template: `\r\n <ul class=\"fui-dual-tier-nav__bar\" role=\"menu\" aria-orientation=\"vertical\">\r\n @for (item of _readyItems(); track item.id) {\r\n <fui-dual-tier-nav-trigger\r\n [item]=\"item\"\r\n [isExpanded]=\"_expandedId() === item.id\"\r\n [flyoutId]=\"item.id ?? ''\"\r\n (toggle)=\"_onToggle($event, item)\"\r\n (itemClick)=\"_onItemClick($event)\"\r\n (keydown)=\"_onTriggerKeydown($event, item)\"\r\n />\r\n }\r\n </ul>\r\n <div\r\n class=\"fui-dual-tier-nav__flyout\"\r\n role=\"menu\"\r\n [class.fui-dual-tier-nav__flyout--open]=\"!!_expandedItem()\"\r\n [id]=\"_expandedItem() ? 'fui-dtn-flyout-' + (_expandedItem()!.id ?? '') : null\"\r\n [attr.aria-label]=\"_expandedItem()?.label ?? null\"\r\n >\r\n @if (_expandedItem(); as expanded) {\r\n <div animate.enter=\"fui-dtn-flyout-content--enter\" animate.leave=\"fui-dtn-flyout-content--leave\">\r\n <fui-dual-tier-nav-submenu\r\n [title]=\"expanded.label ?? ''\"\r\n [items]=\"expanded.items ?? []\"\r\n (itemClick)=\"_onItemClick($event)\"\r\n (closePanel)=\"_closeFlyout()\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n `,\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n host: {\r\n role: 'navigation',\r\n '[attr.aria-label]': 'ariaLabel()',\r\n class: 'fui-dual-tier-navigation',\r\n },\r\n})\r\nexport class FuiDualTierNavigationComponent {\r\n private readonly _injector = inject(Injector);\r\n\r\n readonly items = input<MenuItem[]>([]);\r\n readonly ariaLabel = input('Dual tier navigation');\r\n readonly itemClick = output<MenuItem>();\r\n\r\n readonly _readyItems = computed(() => {\r\n let counter = 0;\r\n const assignIds = (list: readonly MenuItem[]): MenuItem[] =>\r\n list\r\n .filter((it) => it.visible !== false)\r\n .map((it) => {\r\n const copy = { ...it, id: it.id ?? `fui-dtn-${++counter}` };\r\n if (copy.items) {\r\n return { ...copy, items: assignIds(copy.items) };\r\n }\r\n return copy;\r\n });\r\n\r\n return assignIds(this.items());\r\n });\r\n\r\n readonly _expandedId = signal<string | undefined>(undefined);\r\n\r\n readonly _expandedItem = computed(() => {\r\n const id = this._expandedId();\r\n if (!id) return undefined;\r\n return this._findItemById(this._readyItems(), id);\r\n });\r\n\r\n private _findItemById(items: readonly MenuItem[], id: string): MenuItem | undefined {\r\n for (const item of items) {\r\n if (item.id === id) return item;\r\n if (item.items?.length) {\r\n const found = this._findItemById(item.items, id);\r\n if (found) return found;\r\n }\r\n }\r\n return undefined;\r\n }\r\n\r\n _closeFlyout(): void {\r\n const activeId = this._expandedId();\r\n this._expandedId.set(undefined);\r\n if (activeId) {\r\n afterNextRender(\r\n () => {\r\n document.querySelector<HTMLElement>('[aria-controls=\"fui-dtn-flyout-' + activeId + '\"]')?.focus();\r\n },\r\n { injector: this._injector },\r\n );\r\n }\r\n }\r\n\r\n _onItemClick(item: MenuItem): void {\r\n this.itemClick.emit(item);\r\n }\r\n\r\n _onToggle(event: Event, item: MenuItem): void {\r\n event.stopPropagation();\r\n this._expandedId.update((current) => (current === item.id ? undefined : item.id));\r\n this.itemClick.emit(item);\r\n }\r\n\r\n _onTriggerKeydown(event: KeyboardEvent, item: MenuItem): void {\r\n const triggerEl = (event.currentTarget as HTMLElement | null)?.closest('[role=\"menuitem\"]') as HTMLElement | null;\r\n if (!triggerEl) return;\r\n\r\n const barEl = triggerEl.closest('.fui-dual-tier-nav__bar');\r\n if (!barEl) return;\r\n\r\n // ponytail: querySelectorAll on every keydown — acceptable for small trigger lists (<20 items).\r\n // Upgrade path: precompute triggers list on mutation and reuse.\r\n const triggers = Array.from(barEl.querySelectorAll<HTMLElement>('[role=\"menuitem\"]'));\r\n const idx = triggers.indexOf(triggerEl);\r\n\r\n const closeFlyout = () => {\r\n if (this._expandedId()) {\r\n this._expandedId.set(undefined);\r\n triggerEl.focus();\r\n }\r\n };\r\n\r\n const focusFirstFlyoutItem = () => {\r\n afterNextRender(\r\n () => {\r\n const selector = '.fui-dtn-item:not(.fui-dtn-item--disabled)';\r\n const el = document.getElementById(`fui-dtn-flyout-${item.id}`)?.querySelector<HTMLElement>(selector);\r\n el?.focus();\r\n },\r\n { injector: this._injector },\r\n );\r\n };\r\n\r\n switch (event.key) {\r\n case ' ':\r\n case 'Enter':\r\n case 'ArrowRight':\r\n event.preventDefault();\r\n if (item.items?.length) {\r\n this._expandedId.set(item.id);\r\n focusFirstFlyoutItem();\r\n } else {\r\n // Leaf item: forward click-like activation\r\n if (item.command) item.command(event);\r\n this.itemClick.emit(item);\r\n }\r\n break;\r\n case 'ArrowDown':\r\n event.preventDefault();\r\n triggers[idx + 1]?.focus();\r\n break;\r\n case 'ArrowUp':\r\n event.preventDefault();\r\n triggers[idx - 1]?.focus();\r\n break;\r\n case 'ArrowLeft':\r\n case 'Escape':\r\n event.preventDefault();\r\n closeFlyout();\r\n break;\r\n case 'Home':\r\n event.preventDefault();\r\n triggers[0]?.focus();\r\n break;\r\n case 'End':\r\n event.preventDefault();\r\n triggers[triggers.length - 1]?.focus();\r\n break;\r\n }\r\n }\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -12,7 +12,7 @@ class FuiEmptyStateComponent {
12
12
  return s === 'sm' ? 'md' : 'lg';
13
13
  }, ...(ngDevMode ? [{ debugName: "iconSize" }] : /* istanbul ignore next */ []));
14
14
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: FuiEmptyStateComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
15
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: FuiEmptyStateComponent, isStandalone: true, selector: "fui-empty-state", inputs: { icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "status" }, properties: { "class.fui-empty-state--sm": "size() === \"sm\"", "class.fui-empty-state--md": "size() === \"md\"", "class.fui-empty-state--lg": "size() === \"lg\"" }, classAttribute: "fui-empty-state" }, ngImport: i0, template: "<div class=\"fui-empty-state__content\">\r\n @if (icon()) {\r\n <div class=\"fui-empty-state__icon\" aria-hidden=\"true\">\r\n <fui-icon [name]=\"icon()!\" [size]=\"iconSize()\" weight=\"light\" />\r\n </div>\r\n }\r\n @if (title()) {\r\n <h3 class=\"fui-empty-state__title\">{{ title() }}</h3>\r\n }\r\n @if (description()) {\r\n <p class=\"fui-empty-state__description\">{{ description() }}</p>\r\n }\r\n <div class=\"fui-empty-state__actions\">\r\n <ng-content></ng-content>\r\n </div>\r\n</div>\r\n", styles: [".fui-empty-state{display:flex;align-items:center;justify-content:center;padding:var(--fui-padding-48, 3rem);text-align:center}.fui-empty-state__content{display:flex;flex-direction:column;align-items:center;gap:var(--fui-gap-12, .75rem);max-width:24rem}.fui-empty-state__icon{color:var(--fui-text-disabled);margin-bottom:var(--fui-gap-8, .5rem)}.fui-empty-state__title{font-family:var(--fui-font-family-sans);font-size:var(--fui-font-size-04);font-weight:var(--fui-font-weight-semibold, 600);color:var(--fui-text-primary);margin:0}.fui-empty-state__description{font-size:var(--fui-font-size-02);color:var(--fui-text-secondary);margin:0;line-height:1.5}.fui-empty-state__actions{margin-top:var(--fui-gap-16, 1rem);display:flex;gap:var(--fui-gap-8, .5rem)}.fui-empty-state--sm{padding:var(--fui-padding-24, 1.5rem)}.fui-empty-state--sm .fui-empty-state__title{font-size:var(--fui-font-size-03)}.fui-empty-state--lg{padding:4.5rem}.fui-empty-state--lg .fui-empty-state__title{font-size:var(--fui-font-size-05)}\n"], dependencies: [{ kind: "component", type: FuiIconComponent, selector: "fui-icon", inputs: ["name", "size", "weight", "color", "ariaLabel", "spin", "pulse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
15
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: FuiEmptyStateComponent, isStandalone: true, selector: "fui-empty-state", inputs: { icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "status" }, properties: { "class.fui-empty-state--sm": "size() === \"sm\"", "class.fui-empty-state--md": "size() === \"md\"", "class.fui-empty-state--lg": "size() === \"lg\"" }, classAttribute: "fui-empty-state" }, ngImport: i0, template: "<div class=\"fui-empty-state__content\">\r\n @if (icon()) {\r\n <div class=\"fui-empty-state__icon\" aria-hidden=\"true\">\r\n <fui-icon [name]=\"icon()!\" [size]=\"iconSize()\" weight=\"light\" />\r\n </div>\r\n }\r\n @if (title()) {\r\n <h3 class=\"fui-empty-state__title\">{{ title() }}</h3>\r\n }\r\n @if (description()) {\r\n <p class=\"fui-empty-state__description\">{{ description() }}</p>\r\n }\r\n <div class=\"fui-empty-state__actions\">\r\n <ng-content></ng-content>\r\n </div>\r\n</div>\r\n", styles: [".fui-empty-state{display:flex;align-items:center;justify-content:center;padding:var(--fui-spacing-13, 3rem);text-align:center}.fui-empty-state__content{display:flex;flex-direction:column;align-items:center;gap:var(--fui-spacing-6, .75rem);max-width:24rem}.fui-empty-state__icon{color:var(--fui-text-disabled);margin-bottom:var(--fui-spacing-4, .5rem)}.fui-empty-state__title{font-family:var(--fui-font-sans);font-size:var(--fui-text-lg);font-weight:var(--fui-weight-semibold, 600);color:var(--fui-text-primary);margin:0}.fui-empty-state__description{font-size:var(--fui-text-base);color:var(--fui-text-secondary);margin:0;line-height:var(--fui-leading-normal)}.fui-empty-state__actions{margin-top:var(--fui-spacing-7, 1rem);display:flex;gap:var(--fui-spacing-4, .5rem)}.fui-empty-state--sm{padding:var(--fui-spacing-9, 1.5rem)}.fui-empty-state--sm .fui-empty-state__title{font-size:var(--fui-text-md)}.fui-empty-state--lg{padding:4.5rem}.fui-empty-state--lg .fui-empty-state__title{font-size:var(--fui-text-xl)}\n"], dependencies: [{ kind: "component", type: FuiIconComponent, selector: "fui-icon", inputs: ["name", "size", "weight", "color", "ariaLabel", "spin", "pulse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
16
16
  }
17
17
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: FuiEmptyStateComponent, decorators: [{
18
18
  type: Component,
@@ -22,7 +22,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImpor
22
22
  '[class.fui-empty-state--md]': 'size() === "md"',
23
23
  '[class.fui-empty-state--lg]': 'size() === "lg"',
24
24
  role: 'status',
25
- }, template: "<div class=\"fui-empty-state__content\">\r\n @if (icon()) {\r\n <div class=\"fui-empty-state__icon\" aria-hidden=\"true\">\r\n <fui-icon [name]=\"icon()!\" [size]=\"iconSize()\" weight=\"light\" />\r\n </div>\r\n }\r\n @if (title()) {\r\n <h3 class=\"fui-empty-state__title\">{{ title() }}</h3>\r\n }\r\n @if (description()) {\r\n <p class=\"fui-empty-state__description\">{{ description() }}</p>\r\n }\r\n <div class=\"fui-empty-state__actions\">\r\n <ng-content></ng-content>\r\n </div>\r\n</div>\r\n", styles: [".fui-empty-state{display:flex;align-items:center;justify-content:center;padding:var(--fui-padding-48, 3rem);text-align:center}.fui-empty-state__content{display:flex;flex-direction:column;align-items:center;gap:var(--fui-gap-12, .75rem);max-width:24rem}.fui-empty-state__icon{color:var(--fui-text-disabled);margin-bottom:var(--fui-gap-8, .5rem)}.fui-empty-state__title{font-family:var(--fui-font-family-sans);font-size:var(--fui-font-size-04);font-weight:var(--fui-font-weight-semibold, 600);color:var(--fui-text-primary);margin:0}.fui-empty-state__description{font-size:var(--fui-font-size-02);color:var(--fui-text-secondary);margin:0;line-height:1.5}.fui-empty-state__actions{margin-top:var(--fui-gap-16, 1rem);display:flex;gap:var(--fui-gap-8, .5rem)}.fui-empty-state--sm{padding:var(--fui-padding-24, 1.5rem)}.fui-empty-state--sm .fui-empty-state__title{font-size:var(--fui-font-size-03)}.fui-empty-state--lg{padding:4.5rem}.fui-empty-state--lg .fui-empty-state__title{font-size:var(--fui-font-size-05)}\n"] }]
25
+ }, template: "<div class=\"fui-empty-state__content\">\r\n @if (icon()) {\r\n <div class=\"fui-empty-state__icon\" aria-hidden=\"true\">\r\n <fui-icon [name]=\"icon()!\" [size]=\"iconSize()\" weight=\"light\" />\r\n </div>\r\n }\r\n @if (title()) {\r\n <h3 class=\"fui-empty-state__title\">{{ title() }}</h3>\r\n }\r\n @if (description()) {\r\n <p class=\"fui-empty-state__description\">{{ description() }}</p>\r\n }\r\n <div class=\"fui-empty-state__actions\">\r\n <ng-content></ng-content>\r\n </div>\r\n</div>\r\n", styles: [".fui-empty-state{display:flex;align-items:center;justify-content:center;padding:var(--fui-spacing-13, 3rem);text-align:center}.fui-empty-state__content{display:flex;flex-direction:column;align-items:center;gap:var(--fui-spacing-6, .75rem);max-width:24rem}.fui-empty-state__icon{color:var(--fui-text-disabled);margin-bottom:var(--fui-spacing-4, .5rem)}.fui-empty-state__title{font-family:var(--fui-font-sans);font-size:var(--fui-text-lg);font-weight:var(--fui-weight-semibold, 600);color:var(--fui-text-primary);margin:0}.fui-empty-state__description{font-size:var(--fui-text-base);color:var(--fui-text-secondary);margin:0;line-height:var(--fui-leading-normal)}.fui-empty-state__actions{margin-top:var(--fui-spacing-7, 1rem);display:flex;gap:var(--fui-spacing-4, .5rem)}.fui-empty-state--sm{padding:var(--fui-spacing-9, 1.5rem)}.fui-empty-state--sm .fui-empty-state__title{font-size:var(--fui-text-md)}.fui-empty-state--lg{padding:4.5rem}.fui-empty-state--lg .fui-empty-state__title{font-size:var(--fui-text-xl)}\n"] }]
26
26
  }], propDecorators: { icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], description: [{ type: i0.Input, args: [{ isSignal: true, alias: "description", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }] } });
27
27
 
28
28
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"raintonic-formaui-components-empty-state.mjs","sources":["../../../lib/components/empty-state/empty-state.component.ts","../../../lib/components/empty-state/empty-state.component.html","../../../lib/components/empty-state/raintonic-formaui-components-empty-state.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, ViewEncapsulation, computed, input } from '@angular/core';\r\nimport { FuiIconComponent } from '@raintonic/formaui/components/icon';\r\n\r\n@Component({\r\n selector: 'fui-empty-state',\r\n standalone: true,\r\n imports: [FuiIconComponent],\r\n templateUrl: './empty-state.component.html',\r\n styleUrls: ['./empty-state.component.scss'],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n encapsulation: ViewEncapsulation.None,\r\n host: {\r\n class: 'fui-empty-state',\r\n '[class.fui-empty-state--sm]': 'size() === \"sm\"',\r\n '[class.fui-empty-state--md]': 'size() === \"md\"',\r\n '[class.fui-empty-state--lg]': 'size() === \"lg\"',\r\n role: 'status',\r\n },\r\n})\r\nexport class FuiEmptyStateComponent {\r\n readonly icon = input<string | null>(null);\r\n readonly title = input<string | null>(null);\r\n readonly description = input<string | null>(null);\r\n readonly size = input<'sm' | 'md' | 'lg'>('md');\r\n\r\n readonly iconSize = computed(() => {\r\n const s = this.size();\r\n return s === 'sm' ? 'md' : 'lg';\r\n });\r\n}\r\n","<div class=\"fui-empty-state__content\">\r\n @if (icon()) {\r\n <div class=\"fui-empty-state__icon\" aria-hidden=\"true\">\r\n <fui-icon [name]=\"icon()!\" [size]=\"iconSize()\" weight=\"light\" />\r\n </div>\r\n }\r\n @if (title()) {\r\n <h3 class=\"fui-empty-state__title\">{{ title() }}</h3>\r\n }\r\n @if (description()) {\r\n <p class=\"fui-empty-state__description\">{{ description() }}</p>\r\n }\r\n <div class=\"fui-empty-state__actions\">\r\n <ng-content></ng-content>\r\n </div>\r\n</div>\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;MAmBa,sBAAsB,CAAA;AACxB,IAAA,IAAI,GAAG,KAAK,CAAgB,IAAI,2EAAC;AACjC,IAAA,KAAK,GAAG,KAAK,CAAgB,IAAI,4EAAC;AAClC,IAAA,WAAW,GAAG,KAAK,CAAgB,IAAI,kFAAC;AACxC,IAAA,IAAI,GAAG,KAAK,CAAqB,IAAI,2EAAC;AAEtC,IAAA,QAAQ,GAAG,QAAQ,CAAC,MAAK;AAChC,QAAA,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE;QACrB,OAAO,CAAC,KAAK,IAAI,GAAG,IAAI,GAAG,IAAI;AACjC,IAAA,CAAC,+EAAC;uGATS,sBAAsB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;2FAAtB,sBAAsB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,KAAA,EAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,UAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,MAAA,EAAA,QAAA,EAAA,EAAA,UAAA,EAAA,EAAA,2BAAA,EAAA,mBAAA,EAAA,2BAAA,EAAA,mBAAA,EAAA,2BAAA,EAAA,mBAAA,EAAA,EAAA,cAAA,EAAA,iBAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,ECnBnC,ohBAgBA,EAAA,MAAA,EAAA,CAAA,k/BAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EDVY,gBAAgB,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,QAAA,EAAA,OAAA,EAAA,WAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,aAAA,EAAA,EAAA,CAAA,iBAAA,CAAA,IAAA,EAAA,CAAA;;2FAaf,sBAAsB,EAAA,UAAA,EAAA,CAAA;kBAhBlC,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,iBAAiB,EAAA,UAAA,EACf,IAAI,EAAA,OAAA,EACP,CAAC,gBAAgB,CAAC,EAAA,eAAA,EAGV,uBAAuB,CAAC,MAAM,EAAA,aAAA,EAChC,iBAAiB,CAAC,IAAI,EAAA,IAAA,EAC/B;AACJ,wBAAA,KAAK,EAAE,iBAAiB;AACxB,wBAAA,6BAA6B,EAAE,iBAAiB;AAChD,wBAAA,6BAA6B,EAAE,iBAAiB;AAChD,wBAAA,6BAA6B,EAAE,iBAAiB;AAChD,wBAAA,IAAI,EAAE,QAAQ;AACf,qBAAA,EAAA,QAAA,EAAA,ohBAAA,EAAA,MAAA,EAAA,CAAA,k/BAAA,CAAA,EAAA;;;AEjBH;;AAEG;;;;"}
1
+ {"version":3,"file":"raintonic-formaui-components-empty-state.mjs","sources":["../../../lib/components/empty-state/empty-state.component.ts","../../../lib/components/empty-state/empty-state.component.html","../../../lib/components/empty-state/raintonic-formaui-components-empty-state.ts"],"sourcesContent":["import { ChangeDetectionStrategy, Component, ViewEncapsulation, computed, input } from '@angular/core';\r\nimport { FuiIconComponent } from '@raintonic/formaui/components/icon';\r\n\r\n@Component({\r\n selector: 'fui-empty-state',\r\n standalone: true,\r\n imports: [FuiIconComponent],\r\n templateUrl: './empty-state.component.html',\r\n styleUrls: ['./empty-state.component.scss'],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n encapsulation: ViewEncapsulation.None,\r\n host: {\r\n class: 'fui-empty-state',\r\n '[class.fui-empty-state--sm]': 'size() === \"sm\"',\r\n '[class.fui-empty-state--md]': 'size() === \"md\"',\r\n '[class.fui-empty-state--lg]': 'size() === \"lg\"',\r\n role: 'status',\r\n },\r\n})\r\nexport class FuiEmptyStateComponent {\r\n readonly icon = input<string | null>(null);\r\n readonly title = input<string | null>(null);\r\n readonly description = input<string | null>(null);\r\n readonly size = input<'sm' | 'md' | 'lg'>('md');\r\n\r\n readonly iconSize = computed(() => {\r\n const s = this.size();\r\n return s === 'sm' ? 'md' : 'lg';\r\n });\r\n}\r\n","<div class=\"fui-empty-state__content\">\r\n @if (icon()) {\r\n <div class=\"fui-empty-state__icon\" aria-hidden=\"true\">\r\n <fui-icon [name]=\"icon()!\" [size]=\"iconSize()\" weight=\"light\" />\r\n </div>\r\n }\r\n @if (title()) {\r\n <h3 class=\"fui-empty-state__title\">{{ title() }}</h3>\r\n }\r\n @if (description()) {\r\n <p class=\"fui-empty-state__description\">{{ description() }}</p>\r\n }\r\n <div class=\"fui-empty-state__actions\">\r\n <ng-content></ng-content>\r\n </div>\r\n</div>\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;MAmBa,sBAAsB,CAAA;AACxB,IAAA,IAAI,GAAG,KAAK,CAAgB,IAAI,2EAAC;AACjC,IAAA,KAAK,GAAG,KAAK,CAAgB,IAAI,4EAAC;AAClC,IAAA,WAAW,GAAG,KAAK,CAAgB,IAAI,kFAAC;AACxC,IAAA,IAAI,GAAG,KAAK,CAAqB,IAAI,2EAAC;AAEtC,IAAA,QAAQ,GAAG,QAAQ,CAAC,MAAK;AAChC,QAAA,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE;QACrB,OAAO,CAAC,KAAK,IAAI,GAAG,IAAI,GAAG,IAAI;AACjC,IAAA,CAAC,+EAAC;uGATS,sBAAsB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;2FAAtB,sBAAsB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,KAAA,EAAA,EAAA,iBAAA,EAAA,OAAA,EAAA,UAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,IAAA,EAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,MAAA,EAAA,QAAA,EAAA,EAAA,UAAA,EAAA,EAAA,2BAAA,EAAA,mBAAA,EAAA,2BAAA,EAAA,mBAAA,EAAA,2BAAA,EAAA,mBAAA,EAAA,EAAA,cAAA,EAAA,iBAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,ECnBnC,ohBAgBA,EAAA,MAAA,EAAA,CAAA,u/BAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EDVY,gBAAgB,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,QAAA,EAAA,OAAA,EAAA,WAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,aAAA,EAAA,EAAA,CAAA,iBAAA,CAAA,IAAA,EAAA,CAAA;;2FAaf,sBAAsB,EAAA,UAAA,EAAA,CAAA;kBAhBlC,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,iBAAiB,EAAA,UAAA,EACf,IAAI,EAAA,OAAA,EACP,CAAC,gBAAgB,CAAC,EAAA,eAAA,EAGV,uBAAuB,CAAC,MAAM,EAAA,aAAA,EAChC,iBAAiB,CAAC,IAAI,EAAA,IAAA,EAC/B;AACJ,wBAAA,KAAK,EAAE,iBAAiB;AACxB,wBAAA,6BAA6B,EAAE,iBAAiB;AAChD,wBAAA,6BAA6B,EAAE,iBAAiB;AAChD,wBAAA,6BAA6B,EAAE,iBAAiB;AAChD,wBAAA,IAAI,EAAE,QAAQ;AACf,qBAAA,EAAA,QAAA,EAAA,ohBAAA,EAAA,MAAA,EAAA,CAAA,u/BAAA,CAAA,EAAA;;;AEjBH;;AAEG;;;;"}
@@ -246,7 +246,7 @@ class FuiFileUploadComponent {
246
246
  return URL.createObjectURL(file);
247
247
  }
248
248
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: FuiFileUploadComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
249
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: FuiFileUploadComponent, isStandalone: true, selector: "fui-file-upload", inputs: { accept: { classPropertyName: "accept", publicName: "accept", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, maxFileSize: { classPropertyName: "maxFileSize", publicName: "maxFileSize", isSignal: true, isRequired: false, transformFunction: null }, maxFiles: { classPropertyName: "maxFiles", publicName: "maxFiles", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, showPreview: { classPropertyName: "showPreview", publicName: "showPreview", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { filesSelected: "filesSelected", fileRemoved: "fileRemoved", filesDropped: "filesDropped", validationErrors: "validationErrors" }, host: { properties: { "class.fui-file-upload--disabled": "disabled()", "class.fui-file-upload--drag-over": "_isDragOver()", "class.fui-file-upload--has-files": "_files().length > 0" }, classAttribute: "fui-file-upload" }, viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true, isSignal: true }], ngImport: i0, template: "<input\r\n #fileInput\r\n type=\"file\"\r\n class=\"fui-file-upload__native-input\"\r\n [attr.accept]=\"accept()\"\r\n [attr.multiple]=\"multiple() ? '' : null\"\r\n [attr.disabled]=\"disabled() ? '' : null\"\r\n (change)=\"_onFileInputChange($event)\"\r\n tabindex=\"-1\"\r\n aria-hidden=\"true\"\r\n/>\r\n\r\n<div\r\n class=\"fui-file-upload__dropzone\"\r\n (click)=\"browse()\"\r\n (dragenter)=\"_onDragEnter($event)\"\r\n (dragover)=\"_onDragOver($event)\"\r\n (dragleave)=\"_onDragLeave($event)\"\r\n (drop)=\"_onDrop($event)\"\r\n (keydown.enter)=\"browse()\"\r\n (keydown.space)=\"browse(); $event.preventDefault()\"\r\n [attr.tabindex]=\"disabled() ? -1 : 0\"\r\n role=\"button\"\r\n [attr.aria-label]=\"intl.dropzoneAriaLabel\"\r\n [attr.aria-disabled]=\"disabled()\"\r\n>\r\n <fui-icon name=\"upload-simple\" size=\"lg\" class=\"fui-file-upload__icon\"></fui-icon>\r\n <span class=\"fui-file-upload__text\"> Drag &amp; drop files here or <strong>browse</strong> </span>\r\n @if (accept()) {\r\n <span class=\"fui-file-upload__hint\">Accepted: {{ accept() }}</span>\r\n }\r\n @if (maxFileSize() > 0) {\r\n <span class=\"fui-file-upload__hint\">Max size: {{ _formatFileSize(maxFileSize()) }}</span>\r\n }\r\n</div>\r\n\r\n@if (_files().length > 0) {\r\n <ul class=\"fui-file-upload__file-list\" role=\"list\">\r\n @for (fileItem of _files(); track fileItem.name; let i = $index) {\r\n <li class=\"fui-file-upload__file-item\" [class.fui-file-upload__file-item--error]=\"fileItem.error\">\r\n @if (showPreview() && fileItem.previewUrl) {\r\n <img [src]=\"fileItem.previewUrl\" class=\"fui-file-upload__preview\" [alt]=\"fileItem.name\" />\r\n } @else {\r\n <fui-icon name=\"file\" size=\"sm\" class=\"fui-file-upload__file-icon\"></fui-icon>\r\n }\r\n <div class=\"fui-file-upload__file-info\">\r\n <span class=\"fui-file-upload__file-name\">{{ fileItem.name }}</span>\r\n <span class=\"fui-file-upload__file-size\">{{ _formatFileSize(fileItem.size) }}</span>\r\n @if (fileItem.error) {\r\n <span class=\"fui-file-upload__file-error\">{{ fileItem.error }}</span>\r\n }\r\n </div>\r\n <button\r\n type=\"button\"\r\n class=\"fui-file-upload__remove-btn\"\r\n (click)=\"removeFile(i); $event.stopPropagation()\"\r\n [attr.aria-label]=\"intl.removeFileAriaLabel(fileItem.name)\"\r\n [disabled]=\"disabled()\"\r\n >\r\n <fui-icon name=\"x\" size=\"sm\"></fui-icon>\r\n </button>\r\n </li>\r\n }\r\n </ul>\r\n}\r\n", styles: ["@keyframes fui-skeleton-pulse{0%{opacity:1}50%{opacity:.4}to{opacity:1}}@keyframes fui-spin{to{transform:rotate(360deg)}}@keyframes fui-shake{0%,to{transform:translate(0)}10%,30%,50%,70%,90%{transform:translate(-2px)}20%,40%,60%,80%{transform:translate(2px)}}.fui-motion-fade-in{transition:opacity var(--fui-duration-fast-02) var(--fui-ease-entrance) 0ms}.fui-motion-fade-out{transition:opacity var(--fui-duration-fast-01) var(--fui-ease-exit) 0ms}.fui-motion-slide-in-bottom{transition:transform var(--fui-duration-moderate-01) var(--fui-ease-entrance) 0ms;transform:translateY(0)}.fui-motion-slide-in-bottom.fui-motion-entering{transform:translateY(1rem)}.fui-motion-slide-in-top{transition:transform var(--fui-duration-moderate-01) var(--fui-ease-entrance) 0ms;transform:translateY(0)}.fui-motion-slide-in-top.fui-motion-entering{transform:translateY(-1rem)}.fui-motion-scale-in{transition:transform,opacity var(--fui-duration-moderate-01) var(--fui-ease-entrance) 0ms;transform:scale(1);opacity:1}.fui-motion-scale-in.fui-motion-entering{transform:scale(.95);opacity:0}.fui-no-motion{transition:none!important;animation:none!important}@media(prefers-reduced-motion:reduce){*,*:before,*:after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}}@keyframes fui-pulse{0%{transform:scale(1);opacity:1}50%{transform:scale(1.05)}to{transform:scale(1);opacity:1}}@keyframes fui-slide-in{0%{transform:translate(120%)}to{transform:translate(0)}}.fui-slide-in{animation:fui-slide-in var(--fui-duration-moderate-01) var(--fui-ease-entrance)}@keyframes fui-popover-enter{0%{opacity:0;transform:translateY(-14px)}60%{opacity:1}to{opacity:1;transform:translateY(0)}}.fui-file-upload{display:block;width:100%}.fui-file-upload__native-input{position:absolute!important;width:1px!important;height:1px!important;padding:0!important;margin:-1px!important;overflow:hidden!important;clip:rect(0,0,0,0)!important;white-space:nowrap!important;border:0!important}.fui-file-upload__dropzone{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--fui-gap-8);padding:var(--fui-padding-32, 2rem);border:2px dashed var(--fui-border-color);border-radius:var(--fui-border-radius-md);background-color:var(--fui-surface-bg);cursor:pointer;text-align:center;transition:border-color,background-color var(--fui-duration-fast-02) var(--fui-ease-standard) 0ms}.fui-file-upload__dropzone:hover{border-color:var(--fui-primary-60, var(--fui-primary));background-color:var(--fui-primary-10, rgba(124, 58, 237, .04))}.fui-file-upload__dropzone:focus-visible{outline:2px solid var(--fui-primary);outline-offset:2px}.fui-file-upload__icon{color:var(--fui-text-secondary)}.fui-file-upload__text{font-family:var(--fui-font-family-sans);font-size:var(--fui-font-size-02);color:var(--fui-text-secondary)}.fui-file-upload__text strong{color:var(--fui-primary);font-weight:var(--fui-font-weight-semibold, 600)}.fui-file-upload__hint{font-family:var(--fui-font-family-sans);font-size:var(--fui-font-size-01);color:var(--fui-text-disabled)}.fui-file-upload__file-list{list-style:none;margin:var(--fui-gap-12, .75rem) 0 0;padding:0;display:flex;flex-direction:column;gap:var(--fui-gap-4)}.fui-file-upload__file-item{display:flex;align-items:center;gap:var(--fui-gap-12, .75rem);padding:var(--fui-padding-8, .5rem) var(--fui-padding-12, .75rem);border:1px solid var(--fui-border-color);border-radius:var(--fui-border-radius-sm);background-color:var(--fui-surface-card, var(--fui-surface-01));transition:border-color,background-color var(--fui-duration-fast-02) var(--fui-ease-standard) 0ms}.fui-file-upload__file-item--error{border-color:var(--fui-state-error);background-color:var(--fui-danger-10, rgba(239, 68, 68, .04))}.fui-file-upload__preview{width:48px;height:48px;object-fit:cover;border-radius:var(--fui-border-radius-sm);flex-shrink:0}.fui-file-upload__file-icon{flex-shrink:0;color:var(--fui-text-secondary)}.fui-file-upload__file-info{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.fui-file-upload__file-name{font-family:var(--fui-font-family-sans);font-size:var(--fui-font-size-02);font-weight:var(--fui-font-weight-medium, 500);color:var(--fui-text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fui-file-upload__file-size{font-family:var(--fui-font-family-sans);font-size:var(--fui-font-size-01);color:var(--fui-text-secondary)}.fui-file-upload__file-error{font-family:var(--fui-font-family-sans);font-size:var(--fui-font-size-01);color:var(--fui-state-error)}.fui-file-upload__remove-btn{background:none;border:none;padding:0;margin:0;font:inherit;color:inherit;cursor:pointer;outline:none}.fui-file-upload__remove-btn{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:1.5rem;height:1.5rem;border-radius:var(--fui-border-radius-sm);color:var(--fui-text-secondary);opacity:.7;transition:opacity,color var(--fui-duration-fast-02) var(--fui-ease-standard) 0ms}.fui-file-upload__remove-btn:hover:not(:disabled){opacity:1;color:var(--fui-state-error)}.fui-file-upload__remove-btn:focus-visible{outline:2px solid var(--fui-primary);outline-offset:2px}.fui-file-upload__remove-btn:disabled{opacity:.4;cursor:not-allowed}.fui-file-upload--drag-over .fui-file-upload__dropzone{border-color:var(--fui-primary);border-style:solid;background-color:var(--fui-primary-10, rgba(124, 58, 237, .08))}.fui-file-upload--disabled{opacity:var(--fui-opacity-disabled, .5)}.fui-file-upload--disabled .fui-file-upload__dropzone{cursor:not-allowed;pointer-events:none}.fui-file-upload--disabled .fui-file-upload__remove-btn{cursor:not-allowed}@media(prefers-reduced-motion:reduce){.fui-file-upload__dropzone,.fui-file-upload__file-item,.fui-file-upload__remove-btn{transition:none}}\n"], dependencies: [{ kind: "component", type: FuiIconComponent, selector: "fui-icon", inputs: ["name", "size", "weight", "color", "ariaLabel", "spin", "pulse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
249
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.6", type: FuiFileUploadComponent, isStandalone: true, selector: "fui-file-upload", inputs: { accept: { classPropertyName: "accept", publicName: "accept", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, maxFileSize: { classPropertyName: "maxFileSize", publicName: "maxFileSize", isSignal: true, isRequired: false, transformFunction: null }, maxFiles: { classPropertyName: "maxFiles", publicName: "maxFiles", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, showPreview: { classPropertyName: "showPreview", publicName: "showPreview", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { filesSelected: "filesSelected", fileRemoved: "fileRemoved", filesDropped: "filesDropped", validationErrors: "validationErrors" }, host: { properties: { "class.fui-file-upload--disabled": "disabled()", "class.fui-file-upload--drag-over": "_isDragOver()", "class.fui-file-upload--has-files": "_files().length > 0" }, classAttribute: "fui-file-upload" }, viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true, isSignal: true }], ngImport: i0, template: "<input\r\n #fileInput\r\n type=\"file\"\r\n class=\"fui-file-upload__native-input\"\r\n [attr.accept]=\"accept()\"\r\n [attr.multiple]=\"multiple() ? '' : null\"\r\n [attr.disabled]=\"disabled() ? '' : null\"\r\n (change)=\"_onFileInputChange($event)\"\r\n tabindex=\"-1\"\r\n aria-hidden=\"true\"\r\n/>\r\n\r\n<div\r\n class=\"fui-file-upload__dropzone\"\r\n (click)=\"browse()\"\r\n (dragenter)=\"_onDragEnter($event)\"\r\n (dragover)=\"_onDragOver($event)\"\r\n (dragleave)=\"_onDragLeave($event)\"\r\n (drop)=\"_onDrop($event)\"\r\n (keydown.enter)=\"browse()\"\r\n (keydown.space)=\"browse(); $event.preventDefault()\"\r\n [attr.tabindex]=\"disabled() ? -1 : 0\"\r\n role=\"button\"\r\n [attr.aria-label]=\"intl.dropzoneAriaLabel\"\r\n [attr.aria-disabled]=\"disabled()\"\r\n>\r\n <fui-icon name=\"upload-simple\" size=\"lg\" class=\"fui-file-upload__icon\"></fui-icon>\r\n <span class=\"fui-file-upload__text\"> Drag &amp; drop files here or <strong>browse</strong> </span>\r\n @if (accept()) {\r\n <span class=\"fui-file-upload__hint\">Accepted: {{ accept() }}</span>\r\n }\r\n @if (maxFileSize() > 0) {\r\n <span class=\"fui-file-upload__hint\">Max size: {{ _formatFileSize(maxFileSize()) }}</span>\r\n }\r\n</div>\r\n\r\n@if (_files().length > 0) {\r\n <ul class=\"fui-file-upload__file-list\" role=\"list\">\r\n @for (fileItem of _files(); track fileItem.name; let i = $index) {\r\n <li class=\"fui-file-upload__file-item\" [class.fui-file-upload__file-item--error]=\"fileItem.error\">\r\n @if (showPreview() && fileItem.previewUrl) {\r\n <img [src]=\"fileItem.previewUrl\" class=\"fui-file-upload__preview\" [alt]=\"fileItem.name\" />\r\n } @else {\r\n <fui-icon name=\"file\" size=\"sm\" class=\"fui-file-upload__file-icon\"></fui-icon>\r\n }\r\n <div class=\"fui-file-upload__file-info\">\r\n <span class=\"fui-file-upload__file-name\">{{ fileItem.name }}</span>\r\n <span class=\"fui-file-upload__file-size\">{{ _formatFileSize(fileItem.size) }}</span>\r\n @if (fileItem.error) {\r\n <span class=\"fui-file-upload__file-error\">{{ fileItem.error }}</span>\r\n }\r\n </div>\r\n <button\r\n type=\"button\"\r\n class=\"fui-file-upload__remove-btn\"\r\n (click)=\"removeFile(i); $event.stopPropagation()\"\r\n [attr.aria-label]=\"intl.removeFileAriaLabel(fileItem.name)\"\r\n [disabled]=\"disabled()\"\r\n >\r\n <fui-icon name=\"x\" size=\"sm\"></fui-icon>\r\n </button>\r\n </li>\r\n }\r\n </ul>\r\n}\r\n", styles: ["@keyframes fui-skeleton-pulse{0%{opacity:1}50%{opacity:.4}to{opacity:1}}@keyframes fui-spin{to{transform:rotate(360deg)}}@keyframes fui-shake{0%,to{transform:translate(0)}10%,30%,50%,70%,90%{transform:translate(-2px)}20%,40%,60%,80%{transform:translate(2px)}}.fui-motion-fade-in{transition-property:opacity;transition-duration:var(--fui-duration-fast);transition-timing-function:var(--fui-ease-out);transition-delay:0ms}.fui-motion-fade-out{transition-property:opacity;transition-duration:var(--fui-duration-fast);transition-timing-function:var(--fui-ease-in);transition-delay:0ms}.fui-motion-slide-in-bottom{transition-property:transform;transition-duration:var(--fui-duration-base);transition-timing-function:var(--fui-ease-out);transition-delay:0ms;transform:translateY(0)}.fui-motion-slide-in-bottom.fui-motion-entering{transform:translateY(1rem)}.fui-motion-slide-in-top{transition-property:transform;transition-duration:var(--fui-duration-base);transition-timing-function:var(--fui-ease-out);transition-delay:0ms;transform:translateY(0)}.fui-motion-slide-in-top.fui-motion-entering{transform:translateY(-1rem)}.fui-motion-scale-in{transition-property:transform,opacity;transition-duration:var(--fui-duration-base);transition-timing-function:var(--fui-ease-out);transition-delay:0ms;transform:scale(1);opacity:1}.fui-motion-scale-in.fui-motion-entering{transform:scale(.95);opacity:0}.fui-no-motion{transition:none!important;animation:none!important}@media(prefers-reduced-motion:reduce){*,*:before,*:after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}}@keyframes fui-pulse{0%{transform:scale(1);opacity:1}50%{transform:scale(1.05)}to{transform:scale(1);opacity:1}}@keyframes fui-slide-in{0%{transform:translate(120%)}to{transform:translate(0)}}.fui-slide-in{animation:fui-slide-in var(--fui-duration-base) var(--fui-ease-out)}@keyframes fui-popover-enter{0%{opacity:0;transform:translateY(-14px)}60%{opacity:1}to{opacity:1;transform:translateY(0)}}.fui-file-upload{display:block;width:100%}.fui-file-upload__native-input{position:absolute!important;width:1px!important;height:1px!important;padding:0!important;margin:-1px!important;overflow:hidden!important;clip:rect(0,0,0,0)!important;white-space:nowrap!important;border:0!important}.fui-file-upload__dropzone{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--fui-spacing-4);padding:var(--fui-spacing-11, 2rem);border:var(--fui-border-width-md) dashed var(--fui-border-default);border-radius:var(--fui-radius-md);background-color:var(--fui-bg-subtle);cursor:pointer;text-align:center;transition-property:border-color,background-color;transition-duration:var(--fui-duration-fast);transition-timing-function:var(--fui-ease-in-out);transition-delay:0ms}.fui-file-upload__dropzone:hover{border-color:var(--fui-primary-60, var(--fui-border-primary));background-color:var(--fui-primary-10, rgba(124, 58, 237, .04))}.fui-file-upload__dropzone:focus-visible{outline:2px solid var(--fui-primary-10)}.fui-file-upload__icon{color:var(--fui-text-secondary)}.fui-file-upload__text{font-family:var(--fui-font-sans);font-size:var(--fui-text-base);color:var(--fui-text-secondary)}.fui-file-upload__text strong{color:var(--fui-primary-fg);font-weight:var(--fui-weight-semibold, 600)}.fui-file-upload__hint{font-family:var(--fui-font-sans);font-size:var(--fui-text-sm);color:var(--fui-text-disabled)}.fui-file-upload__file-list{list-style:none;margin:var(--fui-spacing-6, .75rem) 0 0;padding:0;display:flex;flex-direction:column;gap:var(--fui-spacing-2)}.fui-file-upload__file-item{display:flex;align-items:center;gap:var(--fui-spacing-6, .75rem);padding:var(--fui-spacing-4, .5rem) var(--fui-spacing-6, .75rem);border:var(--fui-border-width-sm) solid var(--fui-border-default);border-radius:var(--fui-radius-sm);background-color:var(--fui-bg-default, var(--fui-bg-default));transition-property:border-color,background-color;transition-duration:var(--fui-duration-fast);transition-timing-function:var(--fui-ease-in-out);transition-delay:0ms}.fui-file-upload__file-item--error{border-color:var(--fui-border-error);background-color:var(--fui-error-10, rgba(239, 68, 68, .04))}.fui-file-upload__preview{width:48px;height:48px;object-fit:cover;border-radius:var(--fui-radius-sm);flex-shrink:0}.fui-file-upload__file-icon{flex-shrink:0;color:var(--fui-text-secondary)}.fui-file-upload__file-info{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.fui-file-upload__file-name{font-family:var(--fui-font-sans);font-size:var(--fui-text-base);font-weight:var(--fui-weight-medium, 500);color:var(--fui-text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fui-file-upload__file-size{font-family:var(--fui-font-sans);font-size:var(--fui-text-sm);color:var(--fui-text-secondary)}.fui-file-upload__file-error{font-family:var(--fui-font-sans);font-size:var(--fui-text-sm);color:var(--fui-text-error)}.fui-file-upload__remove-btn{background:none;border:none;padding:0;margin:0;font:inherit;color:inherit;cursor:pointer;outline:none}.fui-file-upload__remove-btn{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:1.5rem;height:1.5rem;border-radius:var(--fui-radius-sm);color:var(--fui-text-secondary);opacity:.7;transition-property:opacity,color;transition-duration:var(--fui-duration-fast);transition-timing-function:var(--fui-ease-in-out);transition-delay:0ms}.fui-file-upload__remove-btn:hover:not(:disabled){opacity:1;color:var(--fui-text-error)}.fui-file-upload__remove-btn:focus-visible{outline:2px solid var(--fui-primary-10)}.fui-file-upload__remove-btn:disabled{opacity:.4;cursor:not-allowed}.fui-file-upload--drag-over .fui-file-upload__dropzone{border-color:var(--fui-border-primary);border-style:solid;background-color:var(--fui-primary-10, rgba(124, 58, 237, .08))}.fui-file-upload--disabled{opacity:var(--fui-state-disabled-opacity, .5)}.fui-file-upload--disabled .fui-file-upload__dropzone{cursor:not-allowed;pointer-events:none}.fui-file-upload--disabled .fui-file-upload__remove-btn{cursor:not-allowed}@media(prefers-reduced-motion:reduce){.fui-file-upload__dropzone,.fui-file-upload__file-item,.fui-file-upload__remove-btn{transition:none}}\n"], dependencies: [{ kind: "component", type: FuiIconComponent, selector: "fui-icon", inputs: ["name", "size", "weight", "color", "ariaLabel", "spin", "pulse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
250
250
  }
251
251
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImport: i0, type: FuiFileUploadComponent, decorators: [{
252
252
  type: Component,
@@ -255,7 +255,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.6", ngImpor
255
255
  '[class.fui-file-upload--disabled]': 'disabled()',
256
256
  '[class.fui-file-upload--drag-over]': '_isDragOver()',
257
257
  '[class.fui-file-upload--has-files]': '_files().length > 0',
258
- }, template: "<input\r\n #fileInput\r\n type=\"file\"\r\n class=\"fui-file-upload__native-input\"\r\n [attr.accept]=\"accept()\"\r\n [attr.multiple]=\"multiple() ? '' : null\"\r\n [attr.disabled]=\"disabled() ? '' : null\"\r\n (change)=\"_onFileInputChange($event)\"\r\n tabindex=\"-1\"\r\n aria-hidden=\"true\"\r\n/>\r\n\r\n<div\r\n class=\"fui-file-upload__dropzone\"\r\n (click)=\"browse()\"\r\n (dragenter)=\"_onDragEnter($event)\"\r\n (dragover)=\"_onDragOver($event)\"\r\n (dragleave)=\"_onDragLeave($event)\"\r\n (drop)=\"_onDrop($event)\"\r\n (keydown.enter)=\"browse()\"\r\n (keydown.space)=\"browse(); $event.preventDefault()\"\r\n [attr.tabindex]=\"disabled() ? -1 : 0\"\r\n role=\"button\"\r\n [attr.aria-label]=\"intl.dropzoneAriaLabel\"\r\n [attr.aria-disabled]=\"disabled()\"\r\n>\r\n <fui-icon name=\"upload-simple\" size=\"lg\" class=\"fui-file-upload__icon\"></fui-icon>\r\n <span class=\"fui-file-upload__text\"> Drag &amp; drop files here or <strong>browse</strong> </span>\r\n @if (accept()) {\r\n <span class=\"fui-file-upload__hint\">Accepted: {{ accept() }}</span>\r\n }\r\n @if (maxFileSize() > 0) {\r\n <span class=\"fui-file-upload__hint\">Max size: {{ _formatFileSize(maxFileSize()) }}</span>\r\n }\r\n</div>\r\n\r\n@if (_files().length > 0) {\r\n <ul class=\"fui-file-upload__file-list\" role=\"list\">\r\n @for (fileItem of _files(); track fileItem.name; let i = $index) {\r\n <li class=\"fui-file-upload__file-item\" [class.fui-file-upload__file-item--error]=\"fileItem.error\">\r\n @if (showPreview() && fileItem.previewUrl) {\r\n <img [src]=\"fileItem.previewUrl\" class=\"fui-file-upload__preview\" [alt]=\"fileItem.name\" />\r\n } @else {\r\n <fui-icon name=\"file\" size=\"sm\" class=\"fui-file-upload__file-icon\"></fui-icon>\r\n }\r\n <div class=\"fui-file-upload__file-info\">\r\n <span class=\"fui-file-upload__file-name\">{{ fileItem.name }}</span>\r\n <span class=\"fui-file-upload__file-size\">{{ _formatFileSize(fileItem.size) }}</span>\r\n @if (fileItem.error) {\r\n <span class=\"fui-file-upload__file-error\">{{ fileItem.error }}</span>\r\n }\r\n </div>\r\n <button\r\n type=\"button\"\r\n class=\"fui-file-upload__remove-btn\"\r\n (click)=\"removeFile(i); $event.stopPropagation()\"\r\n [attr.aria-label]=\"intl.removeFileAriaLabel(fileItem.name)\"\r\n [disabled]=\"disabled()\"\r\n >\r\n <fui-icon name=\"x\" size=\"sm\"></fui-icon>\r\n </button>\r\n </li>\r\n }\r\n </ul>\r\n}\r\n", styles: ["@keyframes fui-skeleton-pulse{0%{opacity:1}50%{opacity:.4}to{opacity:1}}@keyframes fui-spin{to{transform:rotate(360deg)}}@keyframes fui-shake{0%,to{transform:translate(0)}10%,30%,50%,70%,90%{transform:translate(-2px)}20%,40%,60%,80%{transform:translate(2px)}}.fui-motion-fade-in{transition:opacity var(--fui-duration-fast-02) var(--fui-ease-entrance) 0ms}.fui-motion-fade-out{transition:opacity var(--fui-duration-fast-01) var(--fui-ease-exit) 0ms}.fui-motion-slide-in-bottom{transition:transform var(--fui-duration-moderate-01) var(--fui-ease-entrance) 0ms;transform:translateY(0)}.fui-motion-slide-in-bottom.fui-motion-entering{transform:translateY(1rem)}.fui-motion-slide-in-top{transition:transform var(--fui-duration-moderate-01) var(--fui-ease-entrance) 0ms;transform:translateY(0)}.fui-motion-slide-in-top.fui-motion-entering{transform:translateY(-1rem)}.fui-motion-scale-in{transition:transform,opacity var(--fui-duration-moderate-01) var(--fui-ease-entrance) 0ms;transform:scale(1);opacity:1}.fui-motion-scale-in.fui-motion-entering{transform:scale(.95);opacity:0}.fui-no-motion{transition:none!important;animation:none!important}@media(prefers-reduced-motion:reduce){*,*:before,*:after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}}@keyframes fui-pulse{0%{transform:scale(1);opacity:1}50%{transform:scale(1.05)}to{transform:scale(1);opacity:1}}@keyframes fui-slide-in{0%{transform:translate(120%)}to{transform:translate(0)}}.fui-slide-in{animation:fui-slide-in var(--fui-duration-moderate-01) var(--fui-ease-entrance)}@keyframes fui-popover-enter{0%{opacity:0;transform:translateY(-14px)}60%{opacity:1}to{opacity:1;transform:translateY(0)}}.fui-file-upload{display:block;width:100%}.fui-file-upload__native-input{position:absolute!important;width:1px!important;height:1px!important;padding:0!important;margin:-1px!important;overflow:hidden!important;clip:rect(0,0,0,0)!important;white-space:nowrap!important;border:0!important}.fui-file-upload__dropzone{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--fui-gap-8);padding:var(--fui-padding-32, 2rem);border:2px dashed var(--fui-border-color);border-radius:var(--fui-border-radius-md);background-color:var(--fui-surface-bg);cursor:pointer;text-align:center;transition:border-color,background-color var(--fui-duration-fast-02) var(--fui-ease-standard) 0ms}.fui-file-upload__dropzone:hover{border-color:var(--fui-primary-60, var(--fui-primary));background-color:var(--fui-primary-10, rgba(124, 58, 237, .04))}.fui-file-upload__dropzone:focus-visible{outline:2px solid var(--fui-primary);outline-offset:2px}.fui-file-upload__icon{color:var(--fui-text-secondary)}.fui-file-upload__text{font-family:var(--fui-font-family-sans);font-size:var(--fui-font-size-02);color:var(--fui-text-secondary)}.fui-file-upload__text strong{color:var(--fui-primary);font-weight:var(--fui-font-weight-semibold, 600)}.fui-file-upload__hint{font-family:var(--fui-font-family-sans);font-size:var(--fui-font-size-01);color:var(--fui-text-disabled)}.fui-file-upload__file-list{list-style:none;margin:var(--fui-gap-12, .75rem) 0 0;padding:0;display:flex;flex-direction:column;gap:var(--fui-gap-4)}.fui-file-upload__file-item{display:flex;align-items:center;gap:var(--fui-gap-12, .75rem);padding:var(--fui-padding-8, .5rem) var(--fui-padding-12, .75rem);border:1px solid var(--fui-border-color);border-radius:var(--fui-border-radius-sm);background-color:var(--fui-surface-card, var(--fui-surface-01));transition:border-color,background-color var(--fui-duration-fast-02) var(--fui-ease-standard) 0ms}.fui-file-upload__file-item--error{border-color:var(--fui-state-error);background-color:var(--fui-danger-10, rgba(239, 68, 68, .04))}.fui-file-upload__preview{width:48px;height:48px;object-fit:cover;border-radius:var(--fui-border-radius-sm);flex-shrink:0}.fui-file-upload__file-icon{flex-shrink:0;color:var(--fui-text-secondary)}.fui-file-upload__file-info{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.fui-file-upload__file-name{font-family:var(--fui-font-family-sans);font-size:var(--fui-font-size-02);font-weight:var(--fui-font-weight-medium, 500);color:var(--fui-text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fui-file-upload__file-size{font-family:var(--fui-font-family-sans);font-size:var(--fui-font-size-01);color:var(--fui-text-secondary)}.fui-file-upload__file-error{font-family:var(--fui-font-family-sans);font-size:var(--fui-font-size-01);color:var(--fui-state-error)}.fui-file-upload__remove-btn{background:none;border:none;padding:0;margin:0;font:inherit;color:inherit;cursor:pointer;outline:none}.fui-file-upload__remove-btn{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:1.5rem;height:1.5rem;border-radius:var(--fui-border-radius-sm);color:var(--fui-text-secondary);opacity:.7;transition:opacity,color var(--fui-duration-fast-02) var(--fui-ease-standard) 0ms}.fui-file-upload__remove-btn:hover:not(:disabled){opacity:1;color:var(--fui-state-error)}.fui-file-upload__remove-btn:focus-visible{outline:2px solid var(--fui-primary);outline-offset:2px}.fui-file-upload__remove-btn:disabled{opacity:.4;cursor:not-allowed}.fui-file-upload--drag-over .fui-file-upload__dropzone{border-color:var(--fui-primary);border-style:solid;background-color:var(--fui-primary-10, rgba(124, 58, 237, .08))}.fui-file-upload--disabled{opacity:var(--fui-opacity-disabled, .5)}.fui-file-upload--disabled .fui-file-upload__dropzone{cursor:not-allowed;pointer-events:none}.fui-file-upload--disabled .fui-file-upload__remove-btn{cursor:not-allowed}@media(prefers-reduced-motion:reduce){.fui-file-upload__dropzone,.fui-file-upload__file-item,.fui-file-upload__remove-btn{transition:none}}\n"] }]
258
+ }, template: "<input\r\n #fileInput\r\n type=\"file\"\r\n class=\"fui-file-upload__native-input\"\r\n [attr.accept]=\"accept()\"\r\n [attr.multiple]=\"multiple() ? '' : null\"\r\n [attr.disabled]=\"disabled() ? '' : null\"\r\n (change)=\"_onFileInputChange($event)\"\r\n tabindex=\"-1\"\r\n aria-hidden=\"true\"\r\n/>\r\n\r\n<div\r\n class=\"fui-file-upload__dropzone\"\r\n (click)=\"browse()\"\r\n (dragenter)=\"_onDragEnter($event)\"\r\n (dragover)=\"_onDragOver($event)\"\r\n (dragleave)=\"_onDragLeave($event)\"\r\n (drop)=\"_onDrop($event)\"\r\n (keydown.enter)=\"browse()\"\r\n (keydown.space)=\"browse(); $event.preventDefault()\"\r\n [attr.tabindex]=\"disabled() ? -1 : 0\"\r\n role=\"button\"\r\n [attr.aria-label]=\"intl.dropzoneAriaLabel\"\r\n [attr.aria-disabled]=\"disabled()\"\r\n>\r\n <fui-icon name=\"upload-simple\" size=\"lg\" class=\"fui-file-upload__icon\"></fui-icon>\r\n <span class=\"fui-file-upload__text\"> Drag &amp; drop files here or <strong>browse</strong> </span>\r\n @if (accept()) {\r\n <span class=\"fui-file-upload__hint\">Accepted: {{ accept() }}</span>\r\n }\r\n @if (maxFileSize() > 0) {\r\n <span class=\"fui-file-upload__hint\">Max size: {{ _formatFileSize(maxFileSize()) }}</span>\r\n }\r\n</div>\r\n\r\n@if (_files().length > 0) {\r\n <ul class=\"fui-file-upload__file-list\" role=\"list\">\r\n @for (fileItem of _files(); track fileItem.name; let i = $index) {\r\n <li class=\"fui-file-upload__file-item\" [class.fui-file-upload__file-item--error]=\"fileItem.error\">\r\n @if (showPreview() && fileItem.previewUrl) {\r\n <img [src]=\"fileItem.previewUrl\" class=\"fui-file-upload__preview\" [alt]=\"fileItem.name\" />\r\n } @else {\r\n <fui-icon name=\"file\" size=\"sm\" class=\"fui-file-upload__file-icon\"></fui-icon>\r\n }\r\n <div class=\"fui-file-upload__file-info\">\r\n <span class=\"fui-file-upload__file-name\">{{ fileItem.name }}</span>\r\n <span class=\"fui-file-upload__file-size\">{{ _formatFileSize(fileItem.size) }}</span>\r\n @if (fileItem.error) {\r\n <span class=\"fui-file-upload__file-error\">{{ fileItem.error }}</span>\r\n }\r\n </div>\r\n <button\r\n type=\"button\"\r\n class=\"fui-file-upload__remove-btn\"\r\n (click)=\"removeFile(i); $event.stopPropagation()\"\r\n [attr.aria-label]=\"intl.removeFileAriaLabel(fileItem.name)\"\r\n [disabled]=\"disabled()\"\r\n >\r\n <fui-icon name=\"x\" size=\"sm\"></fui-icon>\r\n </button>\r\n </li>\r\n }\r\n </ul>\r\n}\r\n", styles: ["@keyframes fui-skeleton-pulse{0%{opacity:1}50%{opacity:.4}to{opacity:1}}@keyframes fui-spin{to{transform:rotate(360deg)}}@keyframes fui-shake{0%,to{transform:translate(0)}10%,30%,50%,70%,90%{transform:translate(-2px)}20%,40%,60%,80%{transform:translate(2px)}}.fui-motion-fade-in{transition-property:opacity;transition-duration:var(--fui-duration-fast);transition-timing-function:var(--fui-ease-out);transition-delay:0ms}.fui-motion-fade-out{transition-property:opacity;transition-duration:var(--fui-duration-fast);transition-timing-function:var(--fui-ease-in);transition-delay:0ms}.fui-motion-slide-in-bottom{transition-property:transform;transition-duration:var(--fui-duration-base);transition-timing-function:var(--fui-ease-out);transition-delay:0ms;transform:translateY(0)}.fui-motion-slide-in-bottom.fui-motion-entering{transform:translateY(1rem)}.fui-motion-slide-in-top{transition-property:transform;transition-duration:var(--fui-duration-base);transition-timing-function:var(--fui-ease-out);transition-delay:0ms;transform:translateY(0)}.fui-motion-slide-in-top.fui-motion-entering{transform:translateY(-1rem)}.fui-motion-scale-in{transition-property:transform,opacity;transition-duration:var(--fui-duration-base);transition-timing-function:var(--fui-ease-out);transition-delay:0ms;transform:scale(1);opacity:1}.fui-motion-scale-in.fui-motion-entering{transform:scale(.95);opacity:0}.fui-no-motion{transition:none!important;animation:none!important}@media(prefers-reduced-motion:reduce){*,*:before,*:after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}}@keyframes fui-pulse{0%{transform:scale(1);opacity:1}50%{transform:scale(1.05)}to{transform:scale(1);opacity:1}}@keyframes fui-slide-in{0%{transform:translate(120%)}to{transform:translate(0)}}.fui-slide-in{animation:fui-slide-in var(--fui-duration-base) var(--fui-ease-out)}@keyframes fui-popover-enter{0%{opacity:0;transform:translateY(-14px)}60%{opacity:1}to{opacity:1;transform:translateY(0)}}.fui-file-upload{display:block;width:100%}.fui-file-upload__native-input{position:absolute!important;width:1px!important;height:1px!important;padding:0!important;margin:-1px!important;overflow:hidden!important;clip:rect(0,0,0,0)!important;white-space:nowrap!important;border:0!important}.fui-file-upload__dropzone{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:var(--fui-spacing-4);padding:var(--fui-spacing-11, 2rem);border:var(--fui-border-width-md) dashed var(--fui-border-default);border-radius:var(--fui-radius-md);background-color:var(--fui-bg-subtle);cursor:pointer;text-align:center;transition-property:border-color,background-color;transition-duration:var(--fui-duration-fast);transition-timing-function:var(--fui-ease-in-out);transition-delay:0ms}.fui-file-upload__dropzone:hover{border-color:var(--fui-primary-60, var(--fui-border-primary));background-color:var(--fui-primary-10, rgba(124, 58, 237, .04))}.fui-file-upload__dropzone:focus-visible{outline:2px solid var(--fui-primary-10)}.fui-file-upload__icon{color:var(--fui-text-secondary)}.fui-file-upload__text{font-family:var(--fui-font-sans);font-size:var(--fui-text-base);color:var(--fui-text-secondary)}.fui-file-upload__text strong{color:var(--fui-primary-fg);font-weight:var(--fui-weight-semibold, 600)}.fui-file-upload__hint{font-family:var(--fui-font-sans);font-size:var(--fui-text-sm);color:var(--fui-text-disabled)}.fui-file-upload__file-list{list-style:none;margin:var(--fui-spacing-6, .75rem) 0 0;padding:0;display:flex;flex-direction:column;gap:var(--fui-spacing-2)}.fui-file-upload__file-item{display:flex;align-items:center;gap:var(--fui-spacing-6, .75rem);padding:var(--fui-spacing-4, .5rem) var(--fui-spacing-6, .75rem);border:var(--fui-border-width-sm) solid var(--fui-border-default);border-radius:var(--fui-radius-sm);background-color:var(--fui-bg-default, var(--fui-bg-default));transition-property:border-color,background-color;transition-duration:var(--fui-duration-fast);transition-timing-function:var(--fui-ease-in-out);transition-delay:0ms}.fui-file-upload__file-item--error{border-color:var(--fui-border-error);background-color:var(--fui-error-10, rgba(239, 68, 68, .04))}.fui-file-upload__preview{width:48px;height:48px;object-fit:cover;border-radius:var(--fui-radius-sm);flex-shrink:0}.fui-file-upload__file-icon{flex-shrink:0;color:var(--fui-text-secondary)}.fui-file-upload__file-info{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px}.fui-file-upload__file-name{font-family:var(--fui-font-sans);font-size:var(--fui-text-base);font-weight:var(--fui-weight-medium, 500);color:var(--fui-text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fui-file-upload__file-size{font-family:var(--fui-font-sans);font-size:var(--fui-text-sm);color:var(--fui-text-secondary)}.fui-file-upload__file-error{font-family:var(--fui-font-sans);font-size:var(--fui-text-sm);color:var(--fui-text-error)}.fui-file-upload__remove-btn{background:none;border:none;padding:0;margin:0;font:inherit;color:inherit;cursor:pointer;outline:none}.fui-file-upload__remove-btn{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:1.5rem;height:1.5rem;border-radius:var(--fui-radius-sm);color:var(--fui-text-secondary);opacity:.7;transition-property:opacity,color;transition-duration:var(--fui-duration-fast);transition-timing-function:var(--fui-ease-in-out);transition-delay:0ms}.fui-file-upload__remove-btn:hover:not(:disabled){opacity:1;color:var(--fui-text-error)}.fui-file-upload__remove-btn:focus-visible{outline:2px solid var(--fui-primary-10)}.fui-file-upload__remove-btn:disabled{opacity:.4;cursor:not-allowed}.fui-file-upload--drag-over .fui-file-upload__dropzone{border-color:var(--fui-border-primary);border-style:solid;background-color:var(--fui-primary-10, rgba(124, 58, 237, .08))}.fui-file-upload--disabled{opacity:var(--fui-state-disabled-opacity, .5)}.fui-file-upload--disabled .fui-file-upload__dropzone{cursor:not-allowed;pointer-events:none}.fui-file-upload--disabled .fui-file-upload__remove-btn{cursor:not-allowed}@media(prefers-reduced-motion:reduce){.fui-file-upload__dropzone,.fui-file-upload__file-item,.fui-file-upload__remove-btn{transition:none}}\n"] }]
259
259
  }], ctorParameters: () => [], propDecorators: { accept: [{ type: i0.Input, args: [{ isSignal: true, alias: "accept", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], maxFileSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxFileSize", required: false }] }], maxFiles: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxFiles", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], showPreview: [{ type: i0.Input, args: [{ isSignal: true, alias: "showPreview", required: false }] }], filesSelected: [{ type: i0.Output, args: ["filesSelected"] }], fileRemoved: [{ type: i0.Output, args: ["fileRemoved"] }], filesDropped: [{ type: i0.Output, args: ["filesDropped"] }], validationErrors: [{ type: i0.Output, args: ["validationErrors"] }], fileInput: [{ type: i0.ViewChild, args: ['fileInput', { isSignal: true }] }] } });
260
260
 
261
261
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"raintonic-formaui-components-file-upload.mjs","sources":["../../../lib/components/file-upload/file-upload.intl.ts","../../../lib/components/file-upload/file-upload.component.ts","../../../lib/components/file-upload/file-upload.component.html","../../../lib/components/file-upload/raintonic-formaui-components-file-upload.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\r\nimport { FuiIntlBase } from '@raintonic/formaui/core';\r\n\r\n@Injectable({ providedIn: 'root' })\r\nexport class FuiFileUploadIntl extends FuiIntlBase {\r\n dropzoneAriaLabel = 'Drop files here or click to browse';\r\n removeFileAriaLabel(name: string): string {\r\n return `Remove ${name}`;\r\n }\r\n}\r\n","import {\r\n Component,\r\n ChangeDetectionStrategy,\r\n ChangeDetectorRef,\r\n ViewEncapsulation,\r\n inject,\r\n input,\r\n output,\r\n signal,\r\n viewChild,\r\n ElementRef,\r\n WritableSignal,\r\n booleanAttribute,\r\n} from '@angular/core';\r\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\r\n\r\nimport { FuiIconComponent } from '@raintonic/formaui/components/icon';\r\nimport { FileUploadFile, FileUploadValidationError } from './file-upload.types';\r\nimport { FuiFileUploadIntl } from './file-upload.intl';\r\n\r\n/**\r\n * # FuiFileUploadComponent\r\n *\r\n * A file upload component with drag-and-drop support, file previews, and validation.\r\n *\r\n * ## Features\r\n * - Drag & drop file upload\r\n * - Click to browse\r\n * - File type, size, and count validation\r\n * - Image preview thumbnails\r\n * - Accessible (keyboard, ARIA)\r\n *\r\n * ## Usage\r\n *\r\n * ### Basic\r\n * ```html\r\n * <fui-file-upload\r\n * accept=\"image/*,.pdf\"\r\n * [multiple]=\"true\"\r\n * [maxFileSize]=\"5242880\"\r\n * (filesSelected)=\"onFiles($event)\"\r\n * ></fui-file-upload>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'fui-file-upload',\r\n standalone: true,\r\n imports: [FuiIconComponent],\r\n templateUrl: './file-upload.component.html',\r\n styleUrls: ['./file-upload.component.scss'],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n encapsulation: ViewEncapsulation.None,\r\n host: {\r\n class: 'fui-file-upload',\r\n '[class.fui-file-upload--disabled]': 'disabled()',\r\n '[class.fui-file-upload--drag-over]': '_isDragOver()',\r\n '[class.fui-file-upload--has-files]': '_files().length > 0',\r\n },\r\n})\r\nexport class FuiFileUploadComponent {\r\n readonly intl = inject(FuiFileUploadIntl);\r\n private readonly _cdr = inject(ChangeDetectorRef);\r\n\r\n constructor() {\r\n this.intl.changes.pipe(takeUntilDestroyed()).subscribe(() => { this._cdr.markForCheck(); });\r\n }\r\n\r\n // Inputs\r\n readonly accept = input('');\r\n readonly multiple = input<boolean, unknown>(false, { transform: booleanAttribute });\r\n readonly maxFileSize = input(0);\r\n readonly maxFiles = input(0);\r\n readonly disabled = input<boolean, unknown>(false, { transform: booleanAttribute });\r\n readonly showPreview = input<boolean, unknown>(true, { transform: booleanAttribute });\r\n\r\n // Outputs\r\n readonly filesSelected = output<FileUploadFile[]>();\r\n readonly fileRemoved = output<FileUploadFile>();\r\n readonly filesDropped = output<FileUploadFile[]>();\r\n readonly validationErrors = output<FileUploadValidationError[]>();\r\n\r\n // Internal state\r\n readonly _files: WritableSignal<FileUploadFile[]> = signal([]);\r\n readonly _isDragOver: WritableSignal<boolean> = signal(false);\r\n\r\n // ViewChild\r\n readonly fileInput = viewChild<ElementRef<HTMLInputElement>>('fileInput');\r\n\r\n // Public methods\r\n browse(): void {\r\n if (this.disabled()) return;\r\n this.fileInput()?.nativeElement.click();\r\n }\r\n\r\n removeFile(index: number): void {\r\n if (this.disabled()) return;\r\n const files = [...this._files()];\r\n const removed = files.splice(index, 1)[0];\r\n if (removed) {\r\n if (removed.previewUrl) {\r\n URL.revokeObjectURL(removed.previewUrl);\r\n }\r\n this._files.set(files);\r\n this.fileRemoved.emit(removed);\r\n }\r\n }\r\n\r\n clearAll(): void {\r\n const files = this._files();\r\n for (const f of files) {\r\n if (f.previewUrl) {\r\n URL.revokeObjectURL(f.previewUrl);\r\n }\r\n }\r\n this._files.set([]);\r\n }\r\n\r\n getFiles(): FileUploadFile[] {\r\n return this._files();\r\n }\r\n\r\n // Template event handlers\r\n _onFileInputChange(event: Event): void {\r\n const input = event.target as HTMLInputElement;\r\n if (input.files && input.files.length > 0) {\r\n this._processFiles(input.files);\r\n }\r\n // Reset input so the same file can be selected again\r\n input.value = '';\r\n }\r\n\r\n _onDragEnter(event: DragEvent): void {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n if (!this.disabled()) {\r\n this._isDragOver.set(true);\r\n }\r\n }\r\n\r\n _onDragOver(event: DragEvent): void {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n if (!this.disabled()) {\r\n this._isDragOver.set(true);\r\n }\r\n }\r\n\r\n _onDragLeave(event: DragEvent): void {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n this._isDragOver.set(false);\r\n }\r\n\r\n _onDrop(event: DragEvent): void {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n this._isDragOver.set(false);\r\n\r\n if (this.disabled()) return;\r\n\r\n const files = event.dataTransfer?.files;\r\n if (files && files.length > 0) {\r\n this._processFiles(files);\r\n this.filesDropped.emit(this._files());\r\n }\r\n }\r\n\r\n _formatFileSize(bytes: number): string {\r\n if (bytes === 0) return '0 B';\r\n const units = ['B', 'KB', 'MB', 'GB'];\r\n const k = 1024;\r\n const i = Math.floor(Math.log(bytes) / Math.log(k));\r\n const size = parseFloat((bytes / Math.pow(k, i)).toFixed(1));\r\n return `${size} ${units[i]}`;\r\n }\r\n\r\n // Private methods\r\n private _processFiles(fileList: FileList): void {\r\n const newFiles: FileUploadFile[] = [];\r\n const errors: FileUploadValidationError[] = [];\r\n const currentFiles = this._files();\r\n\r\n const filesToProcess = Array.from(fileList);\r\n\r\n for (const file of filesToProcess) {\r\n // Max files check\r\n const maxFiles = this.maxFiles();\r\n if (maxFiles > 0 && currentFiles.length + newFiles.length >= maxFiles) {\r\n errors.push({\r\n file,\r\n error: 'maxFiles',\r\n message: `Maximum ${maxFiles} file(s) allowed`,\r\n });\r\n continue;\r\n }\r\n\r\n const validationError = this._validateFile(file);\r\n if (validationError) {\r\n errors.push(validationError);\r\n continue;\r\n }\r\n\r\n const uploadFile: FileUploadFile = {\r\n file,\r\n name: file.name,\r\n size: file.size,\r\n type: file.type,\r\n };\r\n\r\n if (this.showPreview() && this._isImage(file)) {\r\n uploadFile.previewUrl = this._generatePreview(file);\r\n }\r\n\r\n newFiles.push(uploadFile);\r\n }\r\n\r\n if (errors.length > 0) {\r\n this.validationErrors.emit(errors);\r\n }\r\n\r\n if (newFiles.length > 0) {\r\n if (this.multiple()) {\r\n this._files.set([...currentFiles, ...newFiles]);\r\n } else {\r\n // Single mode: replace existing\r\n for (const f of currentFiles) {\r\n if (f.previewUrl) URL.revokeObjectURL(f.previewUrl);\r\n }\r\n this._files.set([newFiles[0]]);\r\n }\r\n this.filesSelected.emit(this._files());\r\n }\r\n }\r\n\r\n private _validateFile(file: File): FileUploadValidationError | null {\r\n // Type check\r\n const accept = this.accept();\r\n if (accept && !this._matchesAccept(file, accept)) {\r\n return {\r\n file,\r\n error: 'type',\r\n message: `File type \"${file.type || file.name.split('.').pop()}\" is not allowed`,\r\n };\r\n }\r\n\r\n // Size check\r\n const maxSize = this.maxFileSize();\r\n if (maxSize > 0 && file.size > maxSize) {\r\n return {\r\n file,\r\n error: 'size',\r\n message: `File size ${this._formatFileSize(file.size)} exceeds maximum ${this._formatFileSize(maxSize)}`,\r\n };\r\n }\r\n\r\n return null;\r\n }\r\n\r\n private _matchesAccept(file: File, accept: string): boolean {\r\n const acceptTypes = accept.split(',').map((t) => t.trim().toLowerCase());\r\n\r\n for (const acceptType of acceptTypes) {\r\n // Wildcard MIME type (e.g. \"image/*\")\r\n if (acceptType.endsWith('/*')) {\r\n const category = acceptType.slice(0, acceptType.indexOf('/'));\r\n if (file.type.toLowerCase().startsWith(category + '/')) {\r\n return true;\r\n }\r\n }\r\n // Extension match (e.g. \".pdf\")\r\n else if (acceptType.startsWith('.')) {\r\n if (file.name.toLowerCase().endsWith(acceptType)) {\r\n return true;\r\n }\r\n }\r\n // Exact MIME match\r\n else if (file.type.toLowerCase() === acceptType) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n private _isImage(file: File): boolean {\r\n return file.type.startsWith('image/');\r\n }\r\n\r\n private _generatePreview(file: File): string {\r\n return URL.createObjectURL(file);\r\n }\r\n}\r\n","<input\r\n #fileInput\r\n type=\"file\"\r\n class=\"fui-file-upload__native-input\"\r\n [attr.accept]=\"accept()\"\r\n [attr.multiple]=\"multiple() ? '' : null\"\r\n [attr.disabled]=\"disabled() ? '' : null\"\r\n (change)=\"_onFileInputChange($event)\"\r\n tabindex=\"-1\"\r\n aria-hidden=\"true\"\r\n/>\r\n\r\n<div\r\n class=\"fui-file-upload__dropzone\"\r\n (click)=\"browse()\"\r\n (dragenter)=\"_onDragEnter($event)\"\r\n (dragover)=\"_onDragOver($event)\"\r\n (dragleave)=\"_onDragLeave($event)\"\r\n (drop)=\"_onDrop($event)\"\r\n (keydown.enter)=\"browse()\"\r\n (keydown.space)=\"browse(); $event.preventDefault()\"\r\n [attr.tabindex]=\"disabled() ? -1 : 0\"\r\n role=\"button\"\r\n [attr.aria-label]=\"intl.dropzoneAriaLabel\"\r\n [attr.aria-disabled]=\"disabled()\"\r\n>\r\n <fui-icon name=\"upload-simple\" size=\"lg\" class=\"fui-file-upload__icon\"></fui-icon>\r\n <span class=\"fui-file-upload__text\"> Drag &amp; drop files here or <strong>browse</strong> </span>\r\n @if (accept()) {\r\n <span class=\"fui-file-upload__hint\">Accepted: {{ accept() }}</span>\r\n }\r\n @if (maxFileSize() > 0) {\r\n <span class=\"fui-file-upload__hint\">Max size: {{ _formatFileSize(maxFileSize()) }}</span>\r\n }\r\n</div>\r\n\r\n@if (_files().length > 0) {\r\n <ul class=\"fui-file-upload__file-list\" role=\"list\">\r\n @for (fileItem of _files(); track fileItem.name; let i = $index) {\r\n <li class=\"fui-file-upload__file-item\" [class.fui-file-upload__file-item--error]=\"fileItem.error\">\r\n @if (showPreview() && fileItem.previewUrl) {\r\n <img [src]=\"fileItem.previewUrl\" class=\"fui-file-upload__preview\" [alt]=\"fileItem.name\" />\r\n } @else {\r\n <fui-icon name=\"file\" size=\"sm\" class=\"fui-file-upload__file-icon\"></fui-icon>\r\n }\r\n <div class=\"fui-file-upload__file-info\">\r\n <span class=\"fui-file-upload__file-name\">{{ fileItem.name }}</span>\r\n <span class=\"fui-file-upload__file-size\">{{ _formatFileSize(fileItem.size) }}</span>\r\n @if (fileItem.error) {\r\n <span class=\"fui-file-upload__file-error\">{{ fileItem.error }}</span>\r\n }\r\n </div>\r\n <button\r\n type=\"button\"\r\n class=\"fui-file-upload__remove-btn\"\r\n (click)=\"removeFile(i); $event.stopPropagation()\"\r\n [attr.aria-label]=\"intl.removeFileAriaLabel(fileItem.name)\"\r\n [disabled]=\"disabled()\"\r\n >\r\n <fui-icon name=\"x\" size=\"sm\"></fui-icon>\r\n </button>\r\n </li>\r\n }\r\n </ul>\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;AAIM,MAAO,iBAAkB,SAAQ,WAAW,CAAA;IAChD,iBAAiB,GAAG,oCAAoC;AACxD,IAAA,mBAAmB,CAAC,IAAY,EAAA;QAC9B,OAAO,CAAA,OAAA,EAAU,IAAI,CAAA,CAAE;IACzB;uGAJW,iBAAiB,EAAA,IAAA,EAAA,IAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA;AAAjB,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,iBAAiB,cADJ,MAAM,EAAA,CAAA;;2FACnB,iBAAiB,EAAA,UAAA,EAAA,CAAA;kBAD7B,UAAU;mBAAC,EAAE,UAAU,EAAE,MAAM,EAAE;;;ACiBlC;;;;;;;;;;;;;;;;;;;;;;;AAuBG;MAgBU,sBAAsB,CAAA;AACxB,IAAA,IAAI,GAAG,MAAM,CAAC,iBAAiB,CAAC;AACxB,IAAA,IAAI,GAAG,MAAM,CAAC,iBAAiB,CAAC;AAEjD,IAAA,WAAA,GAAA;QACE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC,CAAC,SAAS,CAAC,MAAK,EAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,CAAC;IAC7F;;AAGS,IAAA,MAAM,GAAG,KAAK,CAAC,EAAE,6EAAC;IAClB,QAAQ,GAAG,KAAK,CAAmB,KAAK,gFAAI,SAAS,EAAE,gBAAgB,EAAA,CAAG;AAC1E,IAAA,WAAW,GAAG,KAAK,CAAC,CAAC,kFAAC;AACtB,IAAA,QAAQ,GAAG,KAAK,CAAC,CAAC,+EAAC;IACnB,QAAQ,GAAG,KAAK,CAAmB,KAAK,gFAAI,SAAS,EAAE,gBAAgB,EAAA,CAAG;IAC1E,WAAW,GAAG,KAAK,CAAmB,IAAI,mFAAI,SAAS,EAAE,gBAAgB,EAAA,CAAG;;IAG5E,aAAa,GAAG,MAAM,EAAoB;IAC1C,WAAW,GAAG,MAAM,EAAkB;IACtC,YAAY,GAAG,MAAM,EAAoB;IACzC,gBAAgB,GAAG,MAAM,EAA+B;;AAGxD,IAAA,MAAM,GAAqC,MAAM,CAAC,EAAE,6EAAC;AACrD,IAAA,WAAW,GAA4B,MAAM,CAAC,KAAK,kFAAC;;AAGpD,IAAA,SAAS,GAAG,SAAS,CAA+B,WAAW,gFAAC;;IAGzE,MAAM,GAAA;QACJ,IAAI,IAAI,CAAC,QAAQ,EAAE;YAAE;QACrB,IAAI,CAAC,SAAS,EAAE,EAAE,aAAa,CAAC,KAAK,EAAE;IACzC;AAEA,IAAA,UAAU,CAAC,KAAa,EAAA;QACtB,IAAI,IAAI,CAAC,QAAQ,EAAE;YAAE;QACrB,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;AAChC,QAAA,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACzC,IAAI,OAAO,EAAE;AACX,YAAA,IAAI,OAAO,CAAC,UAAU,EAAE;AACtB,gBAAA,GAAG,CAAC,eAAe,CAAC,OAAO,CAAC,UAAU,CAAC;YACzC;AACA,YAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC;AACtB,YAAA,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC;QAChC;IACF;IAEA,QAAQ,GAAA;AACN,QAAA,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE;AAC3B,QAAA,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE;AACrB,YAAA,IAAI,CAAC,CAAC,UAAU,EAAE;AAChB,gBAAA,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,UAAU,CAAC;YACnC;QACF;AACA,QAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;IACrB;IAEA,QAAQ,GAAA;AACN,QAAA,OAAO,IAAI,CAAC,MAAM,EAAE;IACtB;;AAGA,IAAA,kBAAkB,CAAC,KAAY,EAAA;AAC7B,QAAA,MAAM,KAAK,GAAG,KAAK,CAAC,MAA0B;AAC9C,QAAA,IAAI,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE;AACzC,YAAA,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,KAAK,CAAC;QACjC;;AAEA,QAAA,KAAK,CAAC,KAAK,GAAG,EAAE;IAClB;AAEA,IAAA,YAAY,CAAC,KAAgB,EAAA;QAC3B,KAAK,CAAC,cAAc,EAAE;QACtB,KAAK,CAAC,eAAe,EAAE;AACvB,QAAA,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE;AACpB,YAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC;QAC5B;IACF;AAEA,IAAA,WAAW,CAAC,KAAgB,EAAA;QAC1B,KAAK,CAAC,cAAc,EAAE;QACtB,KAAK,CAAC,eAAe,EAAE;AACvB,QAAA,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE;AACpB,YAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC;QAC5B;IACF;AAEA,IAAA,YAAY,CAAC,KAAgB,EAAA;QAC3B,KAAK,CAAC,cAAc,EAAE;QACtB,KAAK,CAAC,eAAe,EAAE;AACvB,QAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC;IAC7B;AAEA,IAAA,OAAO,CAAC,KAAgB,EAAA;QACtB,KAAK,CAAC,cAAc,EAAE;QACtB,KAAK,CAAC,eAAe,EAAE;AACvB,QAAA,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC;QAE3B,IAAI,IAAI,CAAC,QAAQ,EAAE;YAAE;AAErB,QAAA,MAAM,KAAK,GAAG,KAAK,CAAC,YAAY,EAAE,KAAK;QACvC,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE;AAC7B,YAAA,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC;YACzB,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QACvC;IACF;AAEA,IAAA,eAAe,CAAC,KAAa,EAAA;QAC3B,IAAI,KAAK,KAAK,CAAC;AAAE,YAAA,OAAO,KAAK;QAC7B,MAAM,KAAK,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC;QACrC,MAAM,CAAC,GAAG,IAAI;QACd,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACnD,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;QAC5D,OAAO,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,KAAK,CAAC,CAAC,CAAC,EAAE;IAC9B;;AAGQ,IAAA,aAAa,CAAC,QAAkB,EAAA;QACtC,MAAM,QAAQ,GAAqB,EAAE;QACrC,MAAM,MAAM,GAAgC,EAAE;AAC9C,QAAA,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,EAAE;QAElC,MAAM,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC;AAE3C,QAAA,KAAK,MAAM,IAAI,IAAI,cAAc,EAAE;;AAEjC,YAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE;AAChC,YAAA,IAAI,QAAQ,GAAG,CAAC,IAAI,YAAY,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,IAAI,QAAQ,EAAE;gBACrE,MAAM,CAAC,IAAI,CAAC;oBACV,IAAI;AACJ,oBAAA,KAAK,EAAE,UAAU;oBACjB,OAAO,EAAE,CAAA,QAAA,EAAW,QAAQ,CAAA,gBAAA,CAAkB;AAC/C,iBAAA,CAAC;gBACF;YACF;YAEA,MAAM,eAAe,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC;YAChD,IAAI,eAAe,EAAE;AACnB,gBAAA,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC;gBAC5B;YACF;AAEA,YAAA,MAAM,UAAU,GAAmB;gBACjC,IAAI;gBACJ,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,IAAI,EAAE,IAAI,CAAC,IAAI;aAChB;AAED,YAAA,IAAI,IAAI,CAAC,WAAW,EAAE,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;gBAC7C,UAAU,CAAC,UAAU,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC;YACrD;AAEA,YAAA,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC;QAC3B;AAEA,QAAA,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE;AACrB,YAAA,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC;QACpC;AAEA,QAAA,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE;AACvB,YAAA,IAAI,IAAI,CAAC,QAAQ,EAAE,EAAE;AACnB,gBAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,YAAY,EAAE,GAAG,QAAQ,CAAC,CAAC;YACjD;iBAAO;;AAEL,gBAAA,KAAK,MAAM,CAAC,IAAI,YAAY,EAAE;oBAC5B,IAAI,CAAC,CAAC,UAAU;AAAE,wBAAA,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,UAAU,CAAC;gBACrD;AACA,gBAAA,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;YAChC;YACA,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QACxC;IACF;AAEQ,IAAA,aAAa,CAAC,IAAU,EAAA;;AAE9B,QAAA,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE;AAC5B,QAAA,IAAI,MAAM,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE;YAChD,OAAO;gBACL,IAAI;AACJ,gBAAA,KAAK,EAAE,MAAM;AACb,gBAAA,OAAO,EAAE,CAAA,WAAA,EAAc,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAA,gBAAA,CAAkB;aACjF;QACH;;AAGA,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,EAAE;QAClC,IAAI,OAAO,GAAG,CAAC,IAAI,IAAI,CAAC,IAAI,GAAG,OAAO,EAAE;YACtC,OAAO;gBACL,IAAI;AACJ,gBAAA,KAAK,EAAE,MAAM;AACb,gBAAA,OAAO,EAAE,CAAA,UAAA,EAAa,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,oBAAoB,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAA,CAAE;aACzG;QACH;AAEA,QAAA,OAAO,IAAI;IACb;IAEQ,cAAc,CAAC,IAAU,EAAE,MAAc,EAAA;QAC/C,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AAExE,QAAA,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE;;AAEpC,YAAA,IAAI,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;AAC7B,gBAAA,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;AAC7D,gBAAA,IAAI,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,QAAQ,GAAG,GAAG,CAAC,EAAE;AACtD,oBAAA,OAAO,IAAI;gBACb;YACF;;AAEK,iBAAA,IAAI,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE;AACnC,gBAAA,IAAI,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE;AAChD,oBAAA,OAAO,IAAI;gBACb;YACF;;iBAEK,IAAI,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,UAAU,EAAE;AAC/C,gBAAA,OAAO,IAAI;YACb;QACF;AAEA,QAAA,OAAO,KAAK;IACd;AAEQ,IAAA,QAAQ,CAAC,IAAU,EAAA;QACzB,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;IACvC;AAEQ,IAAA,gBAAgB,CAAC,IAAU,EAAA;AACjC,QAAA,OAAO,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC;IAClC;uGAvOW,sBAAsB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;2FAAtB,sBAAsB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,iBAAA,EAAA,MAAA,EAAA,EAAA,MAAA,EAAA,EAAA,iBAAA,EAAA,QAAA,EAAA,UAAA,EAAA,QAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,QAAA,EAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,QAAA,EAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,QAAA,EAAA,EAAA,iBAAA,EAAA,UAAA,EAAA,UAAA,EAAA,UAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,aAAA,EAAA,eAAA,EAAA,WAAA,EAAA,aAAA,EAAA,YAAA,EAAA,cAAA,EAAA,gBAAA,EAAA,kBAAA,EAAA,EAAA,IAAA,EAAA,EAAA,UAAA,EAAA,EAAA,iCAAA,EAAA,YAAA,EAAA,kCAAA,EAAA,eAAA,EAAA,kCAAA,EAAA,qBAAA,EAAA,EAAA,cAAA,EAAA,iBAAA,EAAA,EAAA,WAAA,EAAA,CAAA,EAAA,YAAA,EAAA,WAAA,EAAA,KAAA,EAAA,IAAA,EAAA,SAAA,EAAA,CAAA,WAAA,CAAA,EAAA,WAAA,EAAA,IAAA,EAAA,QAAA,EAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EC3DnC,olFAiEA,EAAA,MAAA,EAAA,CAAA,ypLAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EDlBY,gBAAgB,EAAA,QAAA,EAAA,UAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,MAAA,EAAA,QAAA,EAAA,OAAA,EAAA,WAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,aAAA,EAAA,EAAA,CAAA,iBAAA,CAAA,IAAA,EAAA,CAAA;;2FAYf,sBAAsB,EAAA,UAAA,EAAA,CAAA;kBAflC,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,iBAAiB,EAAA,UAAA,EACf,IAAI,EAAA,OAAA,EACP,CAAC,gBAAgB,CAAC,EAAA,eAAA,EAGV,uBAAuB,CAAC,MAAM,EAAA,aAAA,EAChC,iBAAiB,CAAC,IAAI,EAAA,IAAA,EAC/B;AACJ,wBAAA,KAAK,EAAE,iBAAiB;AACxB,wBAAA,mCAAmC,EAAE,YAAY;AACjD,wBAAA,oCAAoC,EAAE,eAAe;AACrD,wBAAA,oCAAoC,EAAE,qBAAqB;AAC5D,qBAAA,EAAA,QAAA,EAAA,olFAAA,EAAA,MAAA,EAAA,CAAA,ypLAAA,CAAA,EAAA;q6BA6B4D,WAAW,EAAA,EAAA,QAAA,EAAA,IAAA,EAAA,CAAA,EAAA,CAAA,EAAA,EAAA,CAAA;;AEtF1E;;AAEG;;;;"}
1
+ {"version":3,"file":"raintonic-formaui-components-file-upload.mjs","sources":["../../../lib/components/file-upload/file-upload.intl.ts","../../../lib/components/file-upload/file-upload.component.ts","../../../lib/components/file-upload/file-upload.component.html","../../../lib/components/file-upload/raintonic-formaui-components-file-upload.ts"],"sourcesContent":["import { Injectable } from '@angular/core';\r\nimport { FuiIntlBase } from '@raintonic/formaui/core';\r\n\r\n@Injectable({ providedIn: 'root' })\r\nexport class FuiFileUploadIntl extends FuiIntlBase {\r\n dropzoneAriaLabel = 'Drop files here or click to browse';\r\n removeFileAriaLabel(name: string): string {\r\n return `Remove ${name}`;\r\n }\r\n}\r\n","import {\r\n Component,\r\n ChangeDetectionStrategy,\r\n ChangeDetectorRef,\r\n ViewEncapsulation,\r\n inject,\r\n input,\r\n output,\r\n signal,\r\n viewChild,\r\n ElementRef,\r\n WritableSignal,\r\n booleanAttribute,\r\n} from '@angular/core';\r\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\r\n\r\nimport { FuiIconComponent } from '@raintonic/formaui/components/icon';\r\nimport { FileUploadFile, FileUploadValidationError } from './file-upload.types';\r\nimport { FuiFileUploadIntl } from './file-upload.intl';\r\n\r\n/**\r\n * # FuiFileUploadComponent\r\n *\r\n * A file upload component with drag-and-drop support, file previews, and validation.\r\n *\r\n * ## Features\r\n * - Drag & drop file upload\r\n * - Click to browse\r\n * - File type, size, and count validation\r\n * - Image preview thumbnails\r\n * - Accessible (keyboard, ARIA)\r\n *\r\n * ## Usage\r\n *\r\n * ### Basic\r\n * ```html\r\n * <fui-file-upload\r\n * accept=\"image/*,.pdf\"\r\n * [multiple]=\"true\"\r\n * [maxFileSize]=\"5242880\"\r\n * (filesSelected)=\"onFiles($event)\"\r\n * ></fui-file-upload>\r\n * ```\r\n */\r\n@Component({\r\n selector: 'fui-file-upload',\r\n standalone: true,\r\n imports: [FuiIconComponent],\r\n templateUrl: './file-upload.component.html',\r\n styleUrls: ['./file-upload.component.scss'],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n encapsulation: ViewEncapsulation.None,\r\n host: {\r\n class: 'fui-file-upload',\r\n '[class.fui-file-upload--disabled]': 'disabled()',\r\n '[class.fui-file-upload--drag-over]': '_isDragOver()',\r\n '[class.fui-file-upload--has-files]': '_files().length > 0',\r\n },\r\n})\r\nexport class FuiFileUploadComponent {\r\n readonly intl = inject(FuiFileUploadIntl);\r\n private readonly _cdr = inject(ChangeDetectorRef);\r\n\r\n constructor() {\r\n this.intl.changes.pipe(takeUntilDestroyed()).subscribe(() => { this._cdr.markForCheck(); });\r\n }\r\n\r\n // Inputs\r\n readonly accept = input('');\r\n readonly multiple = input<boolean, unknown>(false, { transform: booleanAttribute });\r\n readonly maxFileSize = input(0);\r\n readonly maxFiles = input(0);\r\n readonly disabled = input<boolean, unknown>(false, { transform: booleanAttribute });\r\n readonly showPreview = input<boolean, unknown>(true, { transform: booleanAttribute });\r\n\r\n // Outputs\r\n readonly filesSelected = output<FileUploadFile[]>();\r\n readonly fileRemoved = output<FileUploadFile>();\r\n readonly filesDropped = output<FileUploadFile[]>();\r\n readonly validationErrors = output<FileUploadValidationError[]>();\r\n\r\n // Internal state\r\n readonly _files: WritableSignal<FileUploadFile[]> = signal([]);\r\n readonly _isDragOver: WritableSignal<boolean> = signal(false);\r\n\r\n // ViewChild\r\n readonly fileInput = viewChild<ElementRef<HTMLInputElement>>('fileInput');\r\n\r\n // Public methods\r\n browse(): void {\r\n if (this.disabled()) return;\r\n this.fileInput()?.nativeElement.click();\r\n }\r\n\r\n removeFile(index: number): void {\r\n if (this.disabled()) return;\r\n const files = [...this._files()];\r\n const removed = files.splice(index, 1)[0];\r\n if (removed) {\r\n if (removed.previewUrl) {\r\n URL.revokeObjectURL(removed.previewUrl);\r\n }\r\n this._files.set(files);\r\n this.fileRemoved.emit(removed);\r\n }\r\n }\r\n\r\n clearAll(): void {\r\n const files = this._files();\r\n for (const f of files) {\r\n if (f.previewUrl) {\r\n URL.revokeObjectURL(f.previewUrl);\r\n }\r\n }\r\n this._files.set([]);\r\n }\r\n\r\n getFiles(): FileUploadFile[] {\r\n return this._files();\r\n }\r\n\r\n // Template event handlers\r\n _onFileInputChange(event: Event): void {\r\n const input = event.target as HTMLInputElement;\r\n if (input.files && input.files.length > 0) {\r\n this._processFiles(input.files);\r\n }\r\n // Reset input so the same file can be selected again\r\n input.value = '';\r\n }\r\n\r\n _onDragEnter(event: DragEvent): void {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n if (!this.disabled()) {\r\n this._isDragOver.set(true);\r\n }\r\n }\r\n\r\n _onDragOver(event: DragEvent): void {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n if (!this.disabled()) {\r\n this._isDragOver.set(true);\r\n }\r\n }\r\n\r\n _onDragLeave(event: DragEvent): void {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n this._isDragOver.set(false);\r\n }\r\n\r\n _onDrop(event: DragEvent): void {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n this._isDragOver.set(false);\r\n\r\n if (this.disabled()) return;\r\n\r\n const files = event.dataTransfer?.files;\r\n if (files && files.length > 0) {\r\n this._processFiles(files);\r\n this.filesDropped.emit(this._files());\r\n }\r\n }\r\n\r\n _formatFileSize(bytes: number): string {\r\n if (bytes === 0) return '0 B';\r\n const units = ['B', 'KB', 'MB', 'GB'];\r\n const k = 1024;\r\n const i = Math.floor(Math.log(bytes) / Math.log(k));\r\n const size = parseFloat((bytes / Math.pow(k, i)).toFixed(1));\r\n return `${size} ${units[i]}`;\r\n }\r\n\r\n // Private methods\r\n private _processFiles(fileList: FileList): void {\r\n const newFiles: FileUploadFile[] = [];\r\n const errors: FileUploadValidationError[] = [];\r\n const currentFiles = this._files();\r\n\r\n const filesToProcess = Array.from(fileList);\r\n\r\n for (const file of filesToProcess) {\r\n // Max files check\r\n const maxFiles = this.maxFiles();\r\n if (maxFiles > 0 && currentFiles.length + newFiles.length >= maxFiles) {\r\n errors.push({\r\n file,\r\n error: 'maxFiles',\r\n message: `Maximum ${maxFiles} file(s) allowed`,\r\n });\r\n continue;\r\n }\r\n\r\n const validationError = this._validateFile(file);\r\n if (validationError) {\r\n errors.push(validationError);\r\n continue;\r\n }\r\n\r\n const uploadFile: FileUploadFile = {\r\n file,\r\n name: file.name,\r\n size: file.size,\r\n type: file.type,\r\n };\r\n\r\n if (this.showPreview() && this._isImage(file)) {\r\n uploadFile.previewUrl = this._generatePreview(file);\r\n }\r\n\r\n newFiles.push(uploadFile);\r\n }\r\n\r\n if (errors.length > 0) {\r\n this.validationErrors.emit(errors);\r\n }\r\n\r\n if (newFiles.length > 0) {\r\n if (this.multiple()) {\r\n this._files.set([...currentFiles, ...newFiles]);\r\n } else {\r\n // Single mode: replace existing\r\n for (const f of currentFiles) {\r\n if (f.previewUrl) URL.revokeObjectURL(f.previewUrl);\r\n }\r\n this._files.set([newFiles[0]]);\r\n }\r\n this.filesSelected.emit(this._files());\r\n }\r\n }\r\n\r\n private _validateFile(file: File): FileUploadValidationError | null {\r\n // Type check\r\n const accept = this.accept();\r\n if (accept && !this._matchesAccept(file, accept)) {\r\n return {\r\n file,\r\n error: 'type',\r\n message: `File type \"${file.type || file.name.split('.').pop()}\" is not allowed`,\r\n };\r\n }\r\n\r\n // Size check\r\n const maxSize = this.maxFileSize();\r\n if (maxSize > 0 && file.size > maxSize) {\r\n return {\r\n file,\r\n error: 'size',\r\n message: `File size ${this._formatFileSize(file.size)} exceeds maximum ${this._formatFileSize(maxSize)}`,\r\n };\r\n }\r\n\r\n return null;\r\n }\r\n\r\n private _matchesAccept(file: File, accept: string): boolean {\r\n const acceptTypes = accept.split(',').map((t) => t.trim().toLowerCase());\r\n\r\n for (const acceptType of acceptTypes) {\r\n // Wildcard MIME type (e.g. \"image/*\")\r\n if (acceptType.endsWith('/*')) {\r\n const category = acceptType.slice(0, acceptType.indexOf('/'));\r\n if (file.type.toLowerCase().startsWith(category + '/')) {\r\n return true;\r\n }\r\n }\r\n // Extension match (e.g. \".pdf\")\r\n else if (acceptType.startsWith('.')) {\r\n if (file.name.toLowerCase().endsWith(acceptType)) {\r\n return true;\r\n }\r\n }\r\n // Exact MIME match\r\n else if (file.type.toLowerCase() === acceptType) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n private _isImage(file: File): boolean {\r\n return file.type.startsWith('image/');\r\n }\r\n\r\n private _generatePreview(file: File): string {\r\n return URL.createObjectURL(file);\r\n }\r\n}\r\n","<input\r\n #fileInput\r\n type=\"file\"\r\n class=\"fui-file-upload__native-input\"\r\n [attr.accept]=\"accept()\"\r\n [attr.multiple]=\"multiple() ? '' : null\"\r\n [attr.disabled]=\"disabled() ? '' : null\"\r\n (change)=\"_onFileInputChange($event)\"\r\n tabindex=\"-1\"\r\n aria-hidden=\"true\"\r\n/>\r\n\r\n<div\r\n class=\"fui-file-upload__dropzone\"\r\n (click)=\"browse()\"\r\n (dragenter)=\"_onDragEnter($event)\"\r\n (dragover)=\"_onDragOver($event)\"\r\n (dragleave)=\"_onDragLeave($event)\"\r\n (drop)=\"_onDrop($event)\"\r\n (keydown.enter)=\"browse()\"\r\n (keydown.space)=\"browse(); $event.preventDefault()\"\r\n [attr.tabindex]=\"disabled() ? -1 : 0\"\r\n role=\"button\"\r\n [attr.aria-label]=\"intl.dropzoneAriaLabel\"\r\n [attr.aria-disabled]=\"disabled()\"\r\n>\r\n <fui-icon name=\"upload-simple\" size=\"lg\" class=\"fui-file-upload__icon\"></fui-icon>\r\n <span class=\"fui-file-upload__text\"> Drag &amp; drop files here or <strong>browse</strong> </span>\r\n @if (accept()) {\r\n <span class=\"fui-file-upload__hint\">Accepted: {{ accept() }}</span>\r\n }\r\n @if (maxFileSize() > 0) {\r\n <span class=\"fui-file-upload__hint\">Max size: {{ _formatFileSize(maxFileSize()) }}</span>\r\n }\r\n</div>\r\n\r\n@if (_files().length > 0) {\r\n <ul class=\"fui-file-upload__file-list\" role=\"list\">\r\n @for (fileItem of _files(); track fileItem.name; let i = $index) {\r\n <li class=\"fui-file-upload__file-item\" [class.fui-file-upload__file-item--error]=\"fileItem.error\">\r\n @if (showPreview() && fileItem.previewUrl) {\r\n <img [src]=\"fileItem.previewUrl\" class=\"fui-file-upload__preview\" [alt]=\"fileItem.name\" />\r\n } @else {\r\n <fui-icon name=\"file\" size=\"sm\" class=\"fui-file-upload__file-icon\"></fui-icon>\r\n }\r\n <div class=\"fui-file-upload__file-info\">\r\n <span class=\"fui-file-upload__file-name\">{{ fileItem.name }}</span>\r\n <span class=\"fui-file-upload__file-size\">{{ _formatFileSize(fileItem.size) }}</span>\r\n @if (fileItem.error) {\r\n <span class=\"fui-file-upload__file-error\">{{ fileItem.error }}</span>\r\n }\r\n </div>\r\n <button\r\n type=\"button\"\r\n class=\"fui-file-upload__remove-btn\"\r\n (click)=\"removeFile(i); $event.stopPropagation()\"\r\n [attr.aria-label]=\"intl.removeFileAriaLabel(fileItem.name)\"\r\n [disabled]=\"disabled()\"\r\n >\r\n <fui-icon name=\"x\" size=\"sm\"></fui-icon>\r\n </button>\r\n </li>\r\n }\r\n </ul>\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}