@ahrowe/ui 0.41.2 → 0.43.0

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 (328) hide show
  1. package/CHANGELOG.md +934 -0
  2. package/README.md +11 -10
  3. package/dist/cjs-types/common/accordion/accordion.types.d.ts +17 -2
  4. package/dist/cjs-types/common/actionButtons/actionButtons.types.d.ts +7 -1
  5. package/dist/cjs-types/common/actionIcon/actionIcon.d.ts +1 -1
  6. package/dist/cjs-types/common/actionIcon/actionIcon.types.d.ts +7 -9
  7. package/dist/cjs-types/common/alert/alert.types.d.ts +6 -8
  8. package/dist/cjs-types/common/animatedLogo/animatedLogo.types.d.ts +3 -2
  9. package/dist/cjs-types/common/badge/badge.types.d.ts +10 -6
  10. package/dist/cjs-types/common/button/button.types.d.ts +14 -4
  11. package/dist/cjs-types/common/calendar/calendar.types.d.ts +25 -10
  12. package/dist/cjs-types/common/calendar/components/agendaList/agendaList.d.ts +1 -1
  13. package/dist/cjs-types/common/calendar/components/agendaList/agendaList.types.d.ts +3 -0
  14. package/dist/cjs-types/common/calendar/components/calendarHeader/calendarHeader.d.ts +1 -1
  15. package/dist/cjs-types/common/calendar/components/calendarHeader/calendarHeader.types.d.ts +2 -0
  16. package/dist/cjs-types/common/calendar/components/compactMonth/compactMonth.d.ts +1 -1
  17. package/dist/cjs-types/common/calendar/components/monthView/monthView.d.ts +1 -1
  18. package/dist/cjs-types/common/calendar/components/monthView/monthView.types.d.ts +3 -2
  19. package/dist/cjs-types/common/calendar/components/timeGrid/timeGrid.d.ts +1 -1
  20. package/dist/cjs-types/common/calendar/components/timeGrid/timeGrid.types.d.ts +9 -1
  21. package/dist/cjs-types/common/calendar/dates.d.ts +21 -5
  22. package/dist/cjs-types/common/calendar/format.d.ts +3 -2
  23. package/dist/cjs-types/common/calendar/layout.d.ts +5 -0
  24. package/dist/cjs-types/common/calendar/useNow.d.ts +4 -0
  25. package/dist/cjs-types/common/calendar/view.types.d.ts +9 -2
  26. package/dist/cjs-types/common/card/card.types.d.ts +16 -2
  27. package/dist/cjs-types/common/chip/chip.types.d.ts +10 -5
  28. package/dist/cjs-types/common/copyButton/copyButton.types.d.ts +5 -4
  29. package/dist/cjs-types/common/fab/components/fabBase/fabBase.d.ts +1 -1
  30. package/dist/cjs-types/common/fab/components/fabBase/fabBase.types.d.ts +2 -1
  31. package/dist/cjs-types/common/floorPlan/floorPlan.graph.d.ts +10 -3
  32. package/dist/cjs-types/common/floorPlan/floorPlan.plan.d.ts +5 -0
  33. package/dist/cjs-types/common/floorPlan/floorPlan.rooms.d.ts +6 -2
  34. package/dist/cjs-types/common/floorPlan/floorPlan.snap.d.ts +1 -3
  35. package/dist/cjs-types/common/floorPlan/index.d.ts +1 -3
  36. package/dist/cjs-types/common/planCanvas/planCanvas.types.d.ts +1 -1
  37. package/dist/cjs-types/common/progressBar/progressBar.d.ts +0 -1
  38. package/dist/cjs-types/common/progressBar/progressBar.types.d.ts +3 -1
  39. package/dist/cjs-types/common/roomDrawer/roomDrawer.types.d.ts +29 -8
  40. package/dist/cjs-types/common/roomViewer/roomViewer.types.d.ts +4 -2
  41. package/dist/cjs-types/common/splitButton/splitButton.types.d.ts +4 -1
  42. package/dist/cjs-types/common/styles/tone.d.ts +11 -0
  43. package/dist/cjs-types/common/themeProvider/color.types.d.ts +20 -0
  44. package/dist/cjs-types/common/themeProvider/index.d.ts +2 -0
  45. package/dist/cjs-types/common/themeProvider/theme.types.d.ts +3 -6
  46. package/dist/cjs-types/common/timeline/timeline.types.d.ts +3 -10
  47. package/dist/cjs-types/common/toast/index.d.ts +1 -1
  48. package/dist/cjs-types/common/toast/toast.types.d.ts +7 -3
  49. package/dist/cjs-types/common/types/actions.types.d.ts +1 -1
  50. package/dist/cjs-types/common/utils/dismissClick.d.ts +4 -0
  51. package/dist/cjs-types/common/utils/isDev.d.ts +1 -0
  52. package/dist/esm/common/accordion/accordion.mjs +1 -1
  53. package/dist/esm/common/accordion/accordion.mjs.map +1 -1
  54. package/dist/esm/common/accordion/accordion.module.mjs +1 -1
  55. package/dist/esm/common/accordion/accordion.module.mjs.map +1 -1
  56. package/dist/esm/common/accordion/accordion.types.mjs +1 -1
  57. package/dist/esm/common/accordion/accordion.types.mjs.map +1 -1
  58. package/dist/esm/common/actionButtons/actionButtons.mjs +1 -1
  59. package/dist/esm/common/actionButtons/actionButtons.mjs.map +1 -1
  60. package/dist/esm/common/actionIcon/actionIcon.mjs +1 -1
  61. package/dist/esm/common/actionIcon/actionIcon.mjs.map +1 -1
  62. package/dist/esm/common/actionIcon/actionIcon.module.mjs +1 -1
  63. package/dist/esm/common/actionIcon/actionIcon.module.mjs.map +1 -1
  64. package/dist/esm/common/alert/alert.mjs +1 -1
  65. package/dist/esm/common/alert/alert.mjs.map +1 -1
  66. package/dist/esm/common/alert/alert.module.mjs +1 -1
  67. package/dist/esm/common/alert/alert.module.mjs.map +1 -1
  68. package/dist/esm/common/animatedLogo/animatedLogo.mjs +1 -1
  69. package/dist/esm/common/animatedLogo/animatedLogo.mjs.map +1 -1
  70. package/dist/esm/common/avatar/avatar.mjs +1 -1
  71. package/dist/esm/common/avatar/avatar.mjs.map +1 -1
  72. package/dist/esm/common/badge/badge.mjs +1 -1
  73. package/dist/esm/common/badge/badge.mjs.map +1 -1
  74. package/dist/esm/common/badge/badge.module.mjs +1 -1
  75. package/dist/esm/common/badge/badge.module.mjs.map +1 -1
  76. package/dist/esm/common/badge/badge.types.mjs +1 -1
  77. package/dist/esm/common/badge/badge.types.mjs.map +1 -1
  78. package/dist/esm/common/bodyEnd/bodyEnd.mjs +1 -1
  79. package/dist/esm/common/bodyEnd/bodyEnd.mjs.map +1 -1
  80. package/dist/esm/common/breadcrumb/breadcrumb.mjs +1 -1
  81. package/dist/esm/common/breadcrumb/breadcrumb.mjs.map +1 -1
  82. package/dist/esm/common/breadcrumb/breadcrumb.module.mjs.map +1 -1
  83. package/dist/esm/common/button/button.mjs +1 -1
  84. package/dist/esm/common/button/button.mjs.map +1 -1
  85. package/dist/esm/common/button/button.module.mjs +1 -1
  86. package/dist/esm/common/button/button.module.mjs.map +1 -1
  87. package/dist/esm/common/button/button.types.mjs +1 -1
  88. package/dist/esm/common/button/button.types.mjs.map +1 -1
  89. package/dist/esm/common/calendar/calendar.mjs +1 -1
  90. package/dist/esm/common/calendar/calendar.mjs.map +1 -1
  91. package/dist/esm/common/calendar/calendar.module.mjs.map +1 -1
  92. package/dist/esm/common/calendar/calendar.types.mjs.map +1 -1
  93. package/dist/esm/common/calendar/components/agendaList/agendaList.mjs +1 -1
  94. package/dist/esm/common/calendar/components/agendaList/agendaList.mjs.map +1 -1
  95. package/dist/esm/common/calendar/components/agendaList/agendaList.module.mjs.map +1 -1
  96. package/dist/esm/common/calendar/components/calendarHeader/calendarHeader.mjs +1 -1
  97. package/dist/esm/common/calendar/components/calendarHeader/calendarHeader.mjs.map +1 -1
  98. package/dist/esm/common/calendar/components/calendarHeader/calendarHeader.module.mjs +1 -1
  99. package/dist/esm/common/calendar/components/calendarHeader/calendarHeader.module.mjs.map +1 -1
  100. package/dist/esm/common/calendar/components/compactMonth/compactMonth.mjs +1 -1
  101. package/dist/esm/common/calendar/components/compactMonth/compactMonth.mjs.map +1 -1
  102. package/dist/esm/common/calendar/components/compactMonth/compactMonth.module.mjs +1 -1
  103. package/dist/esm/common/calendar/components/compactMonth/compactMonth.module.mjs.map +1 -1
  104. package/dist/esm/common/calendar/components/monthView/monthView.mjs +1 -1
  105. package/dist/esm/common/calendar/components/monthView/monthView.mjs.map +1 -1
  106. package/dist/esm/common/calendar/components/monthView/monthView.module.mjs +1 -1
  107. package/dist/esm/common/calendar/components/monthView/monthView.module.mjs.map +1 -1
  108. package/dist/esm/common/calendar/components/timeGrid/timeGrid.mjs +1 -1
  109. package/dist/esm/common/calendar/components/timeGrid/timeGrid.mjs.map +1 -1
  110. package/dist/esm/common/calendar/components/timeGrid/timeGrid.module.mjs +1 -1
  111. package/dist/esm/common/calendar/components/timeGrid/timeGrid.module.mjs.map +1 -1
  112. package/dist/esm/common/calendar/dates.mjs +1 -1
  113. package/dist/esm/common/calendar/dates.mjs.map +1 -1
  114. package/dist/esm/common/calendar/format.mjs +1 -1
  115. package/dist/esm/common/calendar/format.mjs.map +1 -1
  116. package/dist/esm/common/calendar/layout.mjs +1 -1
  117. package/dist/esm/common/calendar/layout.mjs.map +1 -1
  118. package/dist/esm/common/calendar/useNow.mjs +2 -0
  119. package/dist/esm/common/calendar/useNow.mjs.map +1 -0
  120. package/dist/esm/common/card/Card.mjs +1 -1
  121. package/dist/esm/common/card/Card.mjs.map +1 -1
  122. package/dist/esm/common/card/CardActions.mjs +1 -1
  123. package/dist/esm/common/card/CardActions.mjs.map +1 -1
  124. package/dist/esm/common/card/CardHeader.mjs.map +1 -1
  125. package/dist/esm/common/card/card.module.mjs +1 -1
  126. package/dist/esm/common/card/card.module.mjs.map +1 -1
  127. package/dist/esm/common/card/card.types.mjs +1 -1
  128. package/dist/esm/common/card/card.types.mjs.map +1 -1
  129. package/dist/esm/common/carousel/carousel.mjs +1 -1
  130. package/dist/esm/common/carousel/carousel.mjs.map +1 -1
  131. package/dist/esm/common/carousel/carousel.module.mjs.map +1 -1
  132. package/dist/esm/common/chip/chip.mjs +1 -1
  133. package/dist/esm/common/chip/chip.mjs.map +1 -1
  134. package/dist/esm/common/chip/chip.module.mjs +1 -1
  135. package/dist/esm/common/chip/chip.module.mjs.map +1 -1
  136. package/dist/esm/common/chip/chip.types.mjs +1 -1
  137. package/dist/esm/common/chip/chip.types.mjs.map +1 -1
  138. package/dist/esm/common/colorPicker/colorPicker.mjs +1 -1
  139. package/dist/esm/common/colorPicker/colorPicker.mjs.map +1 -1
  140. package/dist/esm/common/colorPicker/colorPicker.module.mjs.map +1 -1
  141. package/dist/esm/common/confirmModal/confirmModal.mjs +1 -1
  142. package/dist/esm/common/confirmModal/confirmModal.mjs.map +1 -1
  143. package/dist/esm/common/copyButton/copyButton.mjs +1 -1
  144. package/dist/esm/common/copyButton/copyButton.mjs.map +1 -1
  145. package/dist/esm/common/copyButton/copyButton.module.mjs +1 -1
  146. package/dist/esm/common/copyButton/copyButton.module.mjs.map +1 -1
  147. package/dist/esm/common/errorBoundary/errorBoundary.mjs +2 -2
  148. package/dist/esm/common/errorBoundary/errorBoundary.mjs.map +1 -1
  149. package/dist/esm/common/fab/components/fabBase/fabBase.mjs +1 -1
  150. package/dist/esm/common/fab/components/fabBase/fabBase.mjs.map +1 -1
  151. package/dist/esm/common/fab/fab.mjs +1 -1
  152. package/dist/esm/common/fab/fab.mjs.map +1 -1
  153. package/dist/esm/common/flip/flip.mjs +1 -1
  154. package/dist/esm/common/flip/flip.mjs.map +1 -1
  155. package/dist/esm/common/floorPlan/floorPlan.faces.mjs +1 -1
  156. package/dist/esm/common/floorPlan/floorPlan.faces.mjs.map +1 -1
  157. package/dist/esm/common/floorPlan/floorPlan.geometry.mjs +1 -1
  158. package/dist/esm/common/floorPlan/floorPlan.geometry.mjs.map +1 -1
  159. package/dist/esm/common/floorPlan/floorPlan.graph.mjs +1 -1
  160. package/dist/esm/common/floorPlan/floorPlan.graph.mjs.map +1 -1
  161. package/dist/esm/common/floorPlan/floorPlan.hit.mjs +1 -1
  162. package/dist/esm/common/floorPlan/floorPlan.hit.mjs.map +1 -1
  163. package/dist/esm/common/floorPlan/floorPlan.json.mjs +1 -1
  164. package/dist/esm/common/floorPlan/floorPlan.json.mjs.map +1 -1
  165. package/dist/esm/common/floorPlan/floorPlan.mesh.mjs +1 -1
  166. package/dist/esm/common/floorPlan/floorPlan.mesh.mjs.map +1 -1
  167. package/dist/esm/common/floorPlan/floorPlan.path.mjs +1 -1
  168. package/dist/esm/common/floorPlan/floorPlan.path.mjs.map +1 -1
  169. package/dist/esm/common/floorPlan/floorPlan.plan.mjs +1 -1
  170. package/dist/esm/common/floorPlan/floorPlan.plan.mjs.map +1 -1
  171. package/dist/esm/common/floorPlan/floorPlan.rooms.mjs +1 -1
  172. package/dist/esm/common/floorPlan/floorPlan.rooms.mjs.map +1 -1
  173. package/dist/esm/common/floorPlan/floorPlan.snap.mjs +1 -1
  174. package/dist/esm/common/floorPlan/floorPlan.snap.mjs.map +1 -1
  175. package/dist/esm/common/floorPlan/floorPlan.triangulate.mjs +1 -1
  176. package/dist/esm/common/floorPlan/floorPlan.triangulate.mjs.map +1 -1
  177. package/dist/esm/common/floorPlan/floorPlan.types.mjs +1 -1
  178. package/dist/esm/common/floorPlan/floorPlan.types.mjs.map +1 -1
  179. package/dist/esm/common/klipyPicker/klipyPicker.mjs +1 -1
  180. package/dist/esm/common/klipyPicker/klipyPicker.mjs.map +1 -1
  181. package/dist/esm/common/modal/modal.mjs +1 -1
  182. package/dist/esm/common/modal/modal.mjs.map +1 -1
  183. package/dist/esm/common/modal/modal.module.mjs.map +1 -1
  184. package/dist/esm/common/numberInput/numberInput.mjs +1 -1
  185. package/dist/esm/common/numberInput/numberInput.mjs.map +1 -1
  186. package/dist/esm/common/numberInput/numberInput.module.mjs.map +1 -1
  187. package/dist/esm/common/planCanvas/planCanvas.mjs +1 -1
  188. package/dist/esm/common/planCanvas/planCanvas.mjs.map +1 -1
  189. package/dist/esm/common/popover/popover.mjs +1 -1
  190. package/dist/esm/common/popover/popover.mjs.map +1 -1
  191. package/dist/esm/common/progressBar/progressBar.mjs +1 -1
  192. package/dist/esm/common/progressBar/progressBar.mjs.map +1 -1
  193. package/dist/esm/common/progressBar/progressBar.module.mjs +1 -1
  194. package/dist/esm/common/progressBar/progressBar.module.mjs.map +1 -1
  195. package/dist/esm/common/roomDrawer/roomDrawer.mjs +1 -1
  196. package/dist/esm/common/roomDrawer/roomDrawer.mjs.map +1 -1
  197. package/dist/esm/common/roomDrawer/roomDrawer.module.mjs.map +1 -1
  198. package/dist/esm/common/roomViewer/roomViewer.mjs +1 -1
  199. package/dist/esm/common/roomViewer/roomViewer.mjs.map +1 -1
  200. package/dist/esm/common/sectionHeader/sectionHeader.mjs.map +1 -1
  201. package/dist/esm/common/splitButton/splitButton.mjs +1 -1
  202. package/dist/esm/common/splitButton/splitButton.mjs.map +1 -1
  203. package/dist/esm/common/styles/tone.mjs +4 -0
  204. package/dist/esm/common/styles/tone.mjs.map +1 -0
  205. package/dist/esm/common/styles/tone.module.mjs +2 -0
  206. package/dist/esm/common/styles/tone.module.mjs.map +1 -0
  207. package/dist/esm/common/themeProvider/color.types.mjs +2 -0
  208. package/dist/esm/common/themeProvider/color.types.mjs.map +1 -0
  209. package/dist/esm/common/themeProvider/defaultTheme.mjs +1 -1
  210. package/dist/esm/common/themeProvider/defaultTheme.mjs.map +1 -1
  211. package/dist/esm/common/tilt/tilt.mjs +1 -1
  212. package/dist/esm/common/tilt/tilt.mjs.map +1 -1
  213. package/dist/esm/common/timeInput/timeInput.mjs +1 -1
  214. package/dist/esm/common/timeInput/timeInput.mjs.map +1 -1
  215. package/dist/esm/common/timeline/timeline.mjs +1 -1
  216. package/dist/esm/common/timeline/timeline.mjs.map +1 -1
  217. package/dist/esm/common/timeline/timeline.module.mjs +1 -1
  218. package/dist/esm/common/timeline/timeline.module.mjs.map +1 -1
  219. package/dist/esm/common/timeline/timeline.types.mjs +1 -1
  220. package/dist/esm/common/timeline/timeline.types.mjs.map +1 -1
  221. package/dist/esm/common/timer/timer.mjs +1 -1
  222. package/dist/esm/common/timer/timer.mjs.map +1 -1
  223. package/dist/esm/common/timer/timer.module.mjs +1 -1
  224. package/dist/esm/common/timer/timer.module.mjs.map +1 -1
  225. package/dist/esm/common/toast/toast.mjs +1 -1
  226. package/dist/esm/common/toast/toast.mjs.map +1 -1
  227. package/dist/esm/common/toast/toast.module.mjs +1 -1
  228. package/dist/esm/common/toast/toast.module.mjs.map +1 -1
  229. package/dist/esm/common/toast/toastHost.mjs +1 -1
  230. package/dist/esm/common/toast/toastHost.mjs.map +1 -1
  231. package/dist/esm/common/utils/dismissClick.mjs +2 -0
  232. package/dist/esm/common/utils/dismissClick.mjs.map +1 -0
  233. package/dist/esm/common/utils/isDev.mjs +2 -0
  234. package/dist/esm/common/utils/isDev.mjs.map +1 -0
  235. package/dist/esm/floor-plan.mjs +1 -0
  236. package/dist/esm/index.mjs +1 -1
  237. package/dist/esm/services/formValidation/FormValidatorGroupWithForm.mjs +1 -1
  238. package/dist/esm/services/formValidation/FormValidatorGroupWithForm.mjs.map +1 -1
  239. package/dist/floor-plan.cjs +1 -0
  240. package/dist/floorPlan-DLe5XAx6.cjs +2 -0
  241. package/dist/floorPlan-DLe5XAx6.cjs.map +1 -0
  242. package/dist/index.cjs +5 -3
  243. package/dist/index.cjs.map +1 -1
  244. package/dist/style.css +1 -1
  245. package/dist/types/common/accordion/accordion.types.d.ts +17 -2
  246. package/dist/types/common/actionButtons/actionButtons.types.d.ts +7 -1
  247. package/dist/types/common/actionIcon/actionIcon.d.ts +1 -1
  248. package/dist/types/common/actionIcon/actionIcon.types.d.ts +7 -9
  249. package/dist/types/common/alert/alert.types.d.ts +6 -8
  250. package/dist/types/common/animatedLogo/animatedLogo.types.d.ts +3 -2
  251. package/dist/types/common/badge/badge.types.d.ts +10 -6
  252. package/dist/types/common/button/button.types.d.ts +14 -4
  253. package/dist/types/common/calendar/calendar.types.d.ts +25 -10
  254. package/dist/types/common/calendar/components/agendaList/agendaList.d.ts +1 -1
  255. package/dist/types/common/calendar/components/agendaList/agendaList.types.d.ts +3 -0
  256. package/dist/types/common/calendar/components/calendarHeader/calendarHeader.d.ts +1 -1
  257. package/dist/types/common/calendar/components/calendarHeader/calendarHeader.types.d.ts +2 -0
  258. package/dist/types/common/calendar/components/compactMonth/compactMonth.d.ts +1 -1
  259. package/dist/types/common/calendar/components/monthView/monthView.d.ts +1 -1
  260. package/dist/types/common/calendar/components/monthView/monthView.types.d.ts +3 -2
  261. package/dist/types/common/calendar/components/timeGrid/timeGrid.d.ts +1 -1
  262. package/dist/types/common/calendar/components/timeGrid/timeGrid.types.d.ts +9 -1
  263. package/dist/types/common/calendar/dates.d.ts +21 -5
  264. package/dist/types/common/calendar/format.d.ts +3 -2
  265. package/dist/types/common/calendar/layout.d.ts +5 -0
  266. package/dist/types/common/calendar/useNow.d.ts +4 -0
  267. package/dist/types/common/calendar/view.types.d.ts +9 -2
  268. package/dist/types/common/card/card.types.d.ts +16 -2
  269. package/dist/types/common/chip/chip.types.d.ts +10 -5
  270. package/dist/types/common/copyButton/copyButton.types.d.ts +5 -4
  271. package/dist/types/common/fab/components/fabBase/fabBase.d.ts +1 -1
  272. package/dist/types/common/fab/components/fabBase/fabBase.types.d.ts +2 -1
  273. package/dist/types/common/floorPlan/floorPlan.graph.d.ts +10 -3
  274. package/dist/types/common/floorPlan/floorPlan.plan.d.ts +5 -0
  275. package/dist/types/common/floorPlan/floorPlan.rooms.d.ts +6 -2
  276. package/dist/types/common/floorPlan/floorPlan.snap.d.ts +1 -3
  277. package/dist/types/common/floorPlan/index.d.ts +1 -3
  278. package/dist/types/common/planCanvas/planCanvas.types.d.ts +1 -1
  279. package/dist/types/common/progressBar/progressBar.d.ts +0 -1
  280. package/dist/types/common/progressBar/progressBar.types.d.ts +3 -1
  281. package/dist/types/common/roomDrawer/roomDrawer.types.d.ts +29 -8
  282. package/dist/types/common/roomViewer/roomViewer.types.d.ts +4 -2
  283. package/dist/types/common/splitButton/splitButton.types.d.ts +4 -1
  284. package/dist/types/common/styles/tone.d.ts +11 -0
  285. package/dist/types/common/themeProvider/color.types.d.ts +20 -0
  286. package/dist/types/common/themeProvider/index.d.ts +2 -0
  287. package/dist/types/common/themeProvider/theme.types.d.ts +3 -6
  288. package/dist/types/common/timeline/timeline.types.d.ts +3 -10
  289. package/dist/types/common/toast/index.d.ts +1 -1
  290. package/dist/types/common/toast/toast.types.d.ts +7 -3
  291. package/dist/types/common/types/actions.types.d.ts +1 -1
  292. package/dist/types/common/utils/dismissClick.d.ts +4 -0
  293. package/dist/types/common/utils/isDev.d.ts +1 -0
  294. package/docs/Accordion.md +74 -5
  295. package/docs/ActionButtons.md +6 -3
  296. package/docs/ActionIcon.md +39 -14
  297. package/docs/Alert.md +27 -17
  298. package/docs/AnimatedLogo.md +1 -1
  299. package/docs/Badge.md +24 -7
  300. package/docs/Button.md +98 -40
  301. package/docs/ButtonGroup.md +18 -18
  302. package/docs/CLAUDE.md +24 -12
  303. package/docs/Calendar.md +35 -17
  304. package/docs/Card.md +53 -14
  305. package/docs/Chip.md +24 -9
  306. package/docs/ConfigProvider.md +3 -3
  307. package/docs/CopyButton.md +6 -5
  308. package/docs/FloorPlan.md +18 -14
  309. package/docs/ProgressBar.md +7 -4
  310. package/docs/RoomDrawer.md +42 -13
  311. package/docs/RoomViewer.md +1 -14
  312. package/docs/SectionHeader.md +1 -1
  313. package/docs/SplitButton.md +6 -5
  314. package/docs/ThemeColor.md +103 -0
  315. package/docs/ThemeProvider.md +5 -5
  316. package/docs/Timeline.md +18 -9
  317. package/docs/Toast.md +25 -11
  318. package/package.json +20 -2
  319. package/dist/cjs-types/common/floorPlan/legacySvg.d.ts +0 -27
  320. package/dist/esm/common/accordion/accordion.plain.module.mjs +0 -2
  321. package/dist/esm/common/accordion/accordion.plain.module.mjs.map +0 -1
  322. package/dist/esm/common/accordion/accordion.primary.module.mjs +0 -2
  323. package/dist/esm/common/accordion/accordion.primary.module.mjs.map +0 -1
  324. package/dist/esm/common/alert/alert.types.mjs +0 -2
  325. package/dist/esm/common/alert/alert.types.mjs.map +0 -1
  326. package/dist/esm/common/floorPlan/legacySvg.mjs +0 -2
  327. package/dist/esm/common/floorPlan/legacySvg.mjs.map +0 -1
  328. package/dist/types/common/floorPlan/legacySvg.d.ts +0 -27
@@ -1 +1 @@
1
- {"version":3,"file":"timeInput.mjs","names":[],"sources":["../../../../package/common/timeInput/timeInput.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef } from 'react';\nimport cx from 'classnames';\nimport MaskedInput from '../maskedInput';\nimport type { BeforeMaskedStateChangeStates, MaskState } from '../maskedInput';\nimport { faClock } from '@fortawesome/free-solid-svg-icons';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport Input from '../input';\nimport Modal from '../modal';\nimport Popover from '../popover';\nimport Button from '../button';\nimport { ButtonStyleType } from '../button/button.types';\nimport Tooltip from '../tooltip';\nimport ClockDial from './components/clockDial';\nimport { PopoverAlign, PopoverPlacement } from '../popover/popover.types';\nimport { type TimeValue, parseTimeString, formatTime, snapMinute, clampToRange, clampHour } from './timeFunctions';\nimport type { TimeInputProps } from './timeInput.types';\n\nimport styles from './timeInput.module.pcss';\n\ntype ClockMode = 'hours' | 'minutes';\n\nexport default function TimeInput({\n value,\n selected,\n onChange = () => null,\n onSelect = () => null,\n formValidator = null,\n isInline = false,\n isModal = false,\n noInput = false,\n noHeader = false,\n showClearButton = false,\n showNowButton = false,\n minuteStep = 1,\n use24Hour = true,\n minTime = null,\n maxTime = null,\n label = '',\n isValid = true,\n errorMessage = '',\n isRequired = false,\n disabled = false,\n className = '',\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: TimeInputProps) {\n const getExternalString = (): string => {\n if (formValidator) return (formValidator.value as string) || '';\n return value ?? selected ?? '';\n };\n\n const [currentTimeString, setCurrentTimeString] = useState(getExternalString);\n const [isPickerOpen, setIsPickerOpen] = useState(false);\n const [mode, setMode] = useState<ClockMode>('hours');\n const [isFocused, setIsFocused] = useState(false);\n const [isHovered, setIsHovered] = useState(false);\n const [, forceUpdate] = useState(0);\n\n const externalString = getExternalString();\n const [prevExternal, setPrevExternal] = useState(externalString);\n const fvRef = useRef(formValidator);\n\n // Sync when the controlled value changes externally.\n if (!formValidator && prevExternal !== externalString) {\n setPrevExternal(externalString);\n setCurrentTimeString(externalString);\n }\n\n useEffect(() => {\n fvRef.current = formValidator;\n if (!formValidator) return;\n const listener = () => {\n setCurrentTimeString((formValidator.value as string) || '');\n forceUpdate((n) => n + 1);\n };\n formValidator.registerOnUpdateListener(listener);\n return () => formValidator.removeOnUpdateListener(listener);\n }, [formValidator]);\n\n const hasError = (): boolean =>\n formValidator ? formValidator.touched && formValidator.hasError() : !isValid || !!errorMessage;\n\n const computedIsRequired = (): boolean =>\n !!(isRequired || formValidator?.validators.find((v) => (v as { validatorId?: string }).validatorId === 'required'));\n\n /** Push a value out to formValidator/onChange without touching the input string. */\n const emit = (time: TimeValue | null) => {\n const str = time ? formatTime(time) : null;\n if (formValidator) formValidator.set(str);\n onChange?.(str);\n };\n\n const applyTime = (time: TimeValue | null) => {\n setCurrentTimeString(time ? formatTime(time) : '');\n emit(time);\n };\n\n const parsed = parseTimeString(currentTimeString);\n const dialTime: TimeValue = parsed ?? { hours: 12, minutes: 0 };\n\n const handleDialChange = (time: TimeValue) => {\n const snapped = { hours: time.hours, minutes: snapMinute(time.minutes, minuteStep) };\n applyTime(clampToRange(snapped, minTime, maxTime));\n };\n\n const handleDialCommit = (time: TimeValue) => {\n const snapped = { hours: time.hours, minutes: snapMinute(time.minutes, minuteStep) };\n const next = clampToRange(snapped, minTime, maxTime);\n applyTime(next);\n if (mode === 'hours') {\n setMode('minutes');\n return;\n }\n onSelect?.(formatTime(next));\n if (!isInline) setIsPickerOpen(false);\n };\n\n const openPicker = () => {\n if (disabled) return;\n setMode('hours');\n setIsPickerOpen(true);\n };\n\n const beforeMaskedStateChange = ({ previousState, nextState }: BeforeMaskedStateChangeStates): MaskState => {\n if (nextState.value === previousState.value) return nextState;\n let v = nextState.value;\n const hourStr = v.slice(0, 2);\n if (/^\\d\\d$/.test(hourStr) && Number(hourStr) > 23) v = `23${v.slice(2)}`;\n const minStr = v.slice(3, 5);\n if (/^\\d\\d$/.test(minStr) && Number(minStr) > 59) v = `${v.slice(0, 3)}59`;\n return v === nextState.value ? nextState : { ...nextState, value: v };\n };\n\n const handleInputChange = (v: string) => {\n setCurrentTimeString(v);\n const t = parseTimeString(v);\n if (t) emit(t);\n };\n\n const handleBlur = () => {\n if (fvRef.current) fvRef.current.touched = true;\n setIsFocused(false);\n emit(parseTimeString(currentTimeString));\n };\n\n const setMeridiem = (pm: boolean) => {\n const isPm = dialTime.hours >= 12;\n if (pm === isPm) return;\n applyTime({ hours: clampHour(dialTime.hours + (pm ? 12 : -12)), minutes: dialTime.minutes });\n };\n\n const hasErr = hasError();\n const displayHours = parsed\n ? String(use24Hour ? parsed.hours : ((parsed.hours + 11) % 12) + 1).padStart(2, '0')\n : '--';\n const displayMinutes = parsed ? String(parsed.minutes).padStart(2, '0') : '--';\n\n const header = noHeader ? null : (\n <div className={cx(styles.timeInputClockHeader, classNames?.clockHeader)} style={slotStyles?.clockHeader}>\n <button\n type='button'\n className={cx(\n styles.timeInputHeaderSegment,\n mode === 'hours' && styles.timeInputHeaderSegmentActive,\n classNames?.headerSegment,\n )}\n style={slotStyles?.headerSegment}\n onClick={() => setMode('hours')}\n >\n {displayHours}\n </button>\n <span className={styles.timeInputHeaderColon}>:</span>\n <button\n type='button'\n className={cx(\n styles.timeInputHeaderSegment,\n mode === 'minutes' && styles.timeInputHeaderSegmentActive,\n classNames?.headerSegment,\n )}\n style={slotStyles?.headerSegment}\n onClick={() => setMode('minutes')}\n >\n {displayMinutes}\n </button>\n {!use24Hour && (\n <div className={cx(styles.timeInputMeridiem, classNames?.meridiem)} style={slotStyles?.meridiem}>\n <button\n type='button'\n className={cx(dialTime.hours < 12 && styles.timeInputMeridiemActive)}\n onClick={() => setMeridiem(false)}\n >\n AM\n </button>\n <button\n type='button'\n className={cx(dialTime.hours >= 12 && styles.timeInputMeridiemActive)}\n onClick={() => setMeridiem(true)}\n >\n PM\n </button>\n </div>\n )}\n </div>\n );\n\n const footer =\n showClearButton || showNowButton ? (\n <div className={cx(styles.timeInputFooter, classNames?.footer)} style={slotStyles?.footer}>\n {showNowButton && (\n <Button\n styleType={ButtonStyleType.Default}\n onClick={() => {\n const now = new Date();\n handleDialChange({ hours: now.getHours(), minutes: now.getMinutes() });\n }}\n >\n Now\n </Button>\n )}\n {showClearButton && (\n <Button\n styleType={ButtonStyleType.Default}\n onClick={() => {\n applyTime(null);\n onSelect?.(null);\n }}\n >\n Clear\n </Button>\n )}\n </div>\n ) : null;\n\n const pickerContent = (\n <div className={cx(styles.timeInputClock, classNames?.clock)} style={slotStyles?.clock}>\n {header}\n <ClockDial\n time={dialTime}\n mode={mode}\n use24Hour={use24Hour}\n minuteStep={minuteStep}\n onChange={handleDialChange}\n onCommit={handleDialCommit}\n classNames={classNames}\n styles={slotStyles}\n />\n {footer}\n </div>\n );\n\n const input = noInput ? null : (\n <Input\n autoComplete='off'\n label={`${label}${computedIsRequired() ? ' *' : ''}`}\n value={currentTimeString}\n icon={<FontAwesomeIcon icon={faClock} />}\n onIconClick={openPicker}\n onClick={openPicker}\n readOnly={isModal}\n disabled={disabled}\n isValid={!hasErr}\n customInput={<MaskedInput mask='99:99' beforeMaskedStateChange={beforeMaskedStateChange} />}\n onChange={(v) => handleInputChange(v as string)}\n onBlur={handleBlur}\n onFocus={() => setIsFocused(true)}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n />\n );\n\n const picker = (() => {\n if (isInline) return pickerContent;\n if (isModal) {\n return (\n <Modal hideHeader isOpen={isPickerOpen} onClose={() => setIsPickerOpen(false)}>\n {pickerContent}\n </Modal>\n );\n }\n return (\n <Popover\n isOpen={isPickerOpen}\n onOpenChange={setIsPickerOpen}\n content={pickerContent}\n placement={PopoverPlacement.Bottom}\n align={PopoverAlign.Start}\n // A click to place the caret in the field must not take the panel away.\n // The focus stays there on its own: Popover only follows a keyboard open.\n closeOnTriggerClick={false}\n constrainWidth={false}\n >\n {input}\n </Popover>\n );\n })();\n\n return (\n <div\n className={cx(styles.timeInput, classNames?.root, className)}\n style={{ ...slotStyles?.root, ...style }}\n {...rest}\n >\n {(isModal || isInline) && input}\n {picker}\n <Tooltip\n variant='error'\n message={formValidator ? (formValidator.getCurrentErrorMessage() ?? '') : errorMessage || ''}\n isVisible={hasErr && (isFocused || isHovered)}\n />\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"timeInput.mjs","names":[],"sources":["../../../../package/common/timeInput/timeInput.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef } from 'react';\nimport cx from 'classnames';\nimport MaskedInput from '../maskedInput';\nimport type { BeforeMaskedStateChangeStates, MaskState } from '../maskedInput';\nimport { faClock } from '@fortawesome/free-solid-svg-icons';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport Input from '../input';\nimport Modal from '../modal';\nimport Popover from '../popover';\nimport Button from '../button';\nimport Tooltip from '../tooltip';\nimport ClockDial from './components/clockDial';\nimport { PopoverAlign, PopoverPlacement } from '../popover/popover.types';\nimport { type TimeValue, parseTimeString, formatTime, snapMinute, clampToRange, clampHour } from './timeFunctions';\nimport type { TimeInputProps } from './timeInput.types';\n\nimport styles from './timeInput.module.pcss';\n\ntype ClockMode = 'hours' | 'minutes';\n\nexport default function TimeInput({\n value,\n selected,\n onChange = () => null,\n onSelect = () => null,\n formValidator = null,\n isInline = false,\n isModal = false,\n noInput = false,\n noHeader = false,\n showClearButton = false,\n showNowButton = false,\n minuteStep = 1,\n use24Hour = true,\n minTime = null,\n maxTime = null,\n label = '',\n isValid = true,\n errorMessage = '',\n isRequired = false,\n disabled = false,\n className = '',\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: TimeInputProps) {\n const getExternalString = (): string => {\n if (formValidator) return (formValidator.value as string) || '';\n return value ?? selected ?? '';\n };\n\n const [currentTimeString, setCurrentTimeString] = useState(getExternalString);\n const [isPickerOpen, setIsPickerOpen] = useState(false);\n const [mode, setMode] = useState<ClockMode>('hours');\n const [isFocused, setIsFocused] = useState(false);\n const [isHovered, setIsHovered] = useState(false);\n const [, forceUpdate] = useState(0);\n\n const externalString = getExternalString();\n const [prevExternal, setPrevExternal] = useState(externalString);\n const fvRef = useRef(formValidator);\n\n // Sync when the controlled value changes externally.\n if (!formValidator && prevExternal !== externalString) {\n setPrevExternal(externalString);\n setCurrentTimeString(externalString);\n }\n\n useEffect(() => {\n fvRef.current = formValidator;\n if (!formValidator) return;\n const listener = () => {\n setCurrentTimeString((formValidator.value as string) || '');\n forceUpdate((n) => n + 1);\n };\n formValidator.registerOnUpdateListener(listener);\n return () => formValidator.removeOnUpdateListener(listener);\n }, [formValidator]);\n\n const hasError = (): boolean =>\n formValidator ? formValidator.touched && formValidator.hasError() : !isValid || !!errorMessage;\n\n const computedIsRequired = (): boolean =>\n !!(isRequired || formValidator?.validators.find((v) => (v as { validatorId?: string }).validatorId === 'required'));\n\n /** Push a value out to formValidator/onChange without touching the input string. */\n const emit = (time: TimeValue | null) => {\n const str = time ? formatTime(time) : null;\n if (formValidator) formValidator.set(str);\n onChange?.(str);\n };\n\n const applyTime = (time: TimeValue | null) => {\n setCurrentTimeString(time ? formatTime(time) : '');\n emit(time);\n };\n\n const parsed = parseTimeString(currentTimeString);\n const dialTime: TimeValue = parsed ?? { hours: 12, minutes: 0 };\n\n const handleDialChange = (time: TimeValue) => {\n const snapped = { hours: time.hours, minutes: snapMinute(time.minutes, minuteStep) };\n applyTime(clampToRange(snapped, minTime, maxTime));\n };\n\n const handleDialCommit = (time: TimeValue) => {\n const snapped = { hours: time.hours, minutes: snapMinute(time.minutes, minuteStep) };\n const next = clampToRange(snapped, minTime, maxTime);\n applyTime(next);\n if (mode === 'hours') {\n setMode('minutes');\n return;\n }\n onSelect?.(formatTime(next));\n if (!isInline) setIsPickerOpen(false);\n };\n\n const openPicker = () => {\n if (disabled) return;\n setMode('hours');\n setIsPickerOpen(true);\n };\n\n const beforeMaskedStateChange = ({ previousState, nextState }: BeforeMaskedStateChangeStates): MaskState => {\n if (nextState.value === previousState.value) return nextState;\n let v = nextState.value;\n const hourStr = v.slice(0, 2);\n if (/^\\d\\d$/.test(hourStr) && Number(hourStr) > 23) v = `23${v.slice(2)}`;\n const minStr = v.slice(3, 5);\n if (/^\\d\\d$/.test(minStr) && Number(minStr) > 59) v = `${v.slice(0, 3)}59`;\n return v === nextState.value ? nextState : { ...nextState, value: v };\n };\n\n const handleInputChange = (v: string) => {\n setCurrentTimeString(v);\n const t = parseTimeString(v);\n if (t) emit(t);\n };\n\n const handleBlur = () => {\n if (fvRef.current) fvRef.current.touched = true;\n setIsFocused(false);\n emit(parseTimeString(currentTimeString));\n };\n\n const setMeridiem = (pm: boolean) => {\n const isPm = dialTime.hours >= 12;\n if (pm === isPm) return;\n applyTime({ hours: clampHour(dialTime.hours + (pm ? 12 : -12)), minutes: dialTime.minutes });\n };\n\n const hasErr = hasError();\n const displayHours = parsed\n ? String(use24Hour ? parsed.hours : ((parsed.hours + 11) % 12) + 1).padStart(2, '0')\n : '--';\n const displayMinutes = parsed ? String(parsed.minutes).padStart(2, '0') : '--';\n\n const header = noHeader ? null : (\n <div className={cx(styles.timeInputClockHeader, classNames?.clockHeader)} style={slotStyles?.clockHeader}>\n <button\n type='button'\n className={cx(\n styles.timeInputHeaderSegment,\n mode === 'hours' && styles.timeInputHeaderSegmentActive,\n classNames?.headerSegment,\n )}\n style={slotStyles?.headerSegment}\n onClick={() => setMode('hours')}\n >\n {displayHours}\n </button>\n <span className={styles.timeInputHeaderColon}>:</span>\n <button\n type='button'\n className={cx(\n styles.timeInputHeaderSegment,\n mode === 'minutes' && styles.timeInputHeaderSegmentActive,\n classNames?.headerSegment,\n )}\n style={slotStyles?.headerSegment}\n onClick={() => setMode('minutes')}\n >\n {displayMinutes}\n </button>\n {!use24Hour && (\n <div className={cx(styles.timeInputMeridiem, classNames?.meridiem)} style={slotStyles?.meridiem}>\n <button\n type='button'\n className={cx(dialTime.hours < 12 && styles.timeInputMeridiemActive)}\n onClick={() => setMeridiem(false)}\n >\n AM\n </button>\n <button\n type='button'\n className={cx(dialTime.hours >= 12 && styles.timeInputMeridiemActive)}\n onClick={() => setMeridiem(true)}\n >\n PM\n </button>\n </div>\n )}\n </div>\n );\n\n const footer =\n showClearButton || showNowButton ? (\n <div className={cx(styles.timeInputFooter, classNames?.footer)} style={slotStyles?.footer}>\n {showNowButton && (\n <Button\n onClick={() => {\n const now = new Date();\n handleDialChange({ hours: now.getHours(), minutes: now.getMinutes() });\n }}\n >\n Now\n </Button>\n )}\n {showClearButton && (\n <Button\n onClick={() => {\n applyTime(null);\n onSelect?.(null);\n }}\n >\n Clear\n </Button>\n )}\n </div>\n ) : null;\n\n const pickerContent = (\n <div className={cx(styles.timeInputClock, classNames?.clock)} style={slotStyles?.clock}>\n {header}\n <ClockDial\n time={dialTime}\n mode={mode}\n use24Hour={use24Hour}\n minuteStep={minuteStep}\n onChange={handleDialChange}\n onCommit={handleDialCommit}\n classNames={classNames}\n styles={slotStyles}\n />\n {footer}\n </div>\n );\n\n const input = noInput ? null : (\n <Input\n autoComplete='off'\n label={`${label}${computedIsRequired() ? ' *' : ''}`}\n value={currentTimeString}\n icon={<FontAwesomeIcon icon={faClock} />}\n onIconClick={openPicker}\n onClick={openPicker}\n readOnly={isModal}\n disabled={disabled}\n isValid={!hasErr}\n customInput={<MaskedInput mask='99:99' beforeMaskedStateChange={beforeMaskedStateChange} />}\n onChange={(v) => handleInputChange(v as string)}\n onBlur={handleBlur}\n onFocus={() => setIsFocused(true)}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n />\n );\n\n const picker = (() => {\n if (isInline) return pickerContent;\n if (isModal) {\n return (\n <Modal hideHeader isOpen={isPickerOpen} onClose={() => setIsPickerOpen(false)}>\n {pickerContent}\n </Modal>\n );\n }\n return (\n <Popover\n isOpen={isPickerOpen}\n onOpenChange={setIsPickerOpen}\n content={pickerContent}\n placement={PopoverPlacement.Bottom}\n align={PopoverAlign.Start}\n // A click to place the caret in the field must not take the panel away.\n // The focus stays there on its own: Popover only follows a keyboard open.\n closeOnTriggerClick={false}\n constrainWidth={false}\n >\n {input}\n </Popover>\n );\n })();\n\n return (\n <div\n className={cx(styles.timeInput, classNames?.root, className)}\n style={{ ...slotStyles?.root, ...style }}\n {...rest}\n >\n {(isModal || isInline) && input}\n {picker}\n <Tooltip\n variant='error'\n message={formValidator ? (formValidator.getCurrentErrorMessage() ?? '') : errorMessage || ''}\n isVisible={hasErr && (isFocused || isHovered)}\n />\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use client";import{renderIcon as e}from"../utils/renderIcon.mjs";import t from"../interactableDiv/index.mjs";import n from"./timeline.module.mjs";import{TimelineAlignment as r,TimelineItemStatus as i}from"./timeline.types.mjs";import"react";import a from"classnames";import{Fragment as o,jsx as s,jsxs as c}from"react/jsx-runtime";var l={[i.Primary]:n.timelineDotPrimary,[i.Success]:n.timelineDotSuccess,[i.Warn]:n.timelineDotWarn,[i.Error]:n.timelineDotError};function u({items:u=[],alignment:d=r.Left,className:f,style:p,classNames:m,styles:h,...g}){let _=u.some(e=>!!e.icon);return s(`div`,{...g,className:a(n.timeline,{[n.timelineRight]:d===r.Right,[n.timelineAlternate]:d===r.Alternate,[n.timelineWithIcons]:_},m?.root,f),style:{...h?.root,...p},children:u.map((f,p)=>{let g=f.id??p,_=p===u.length-1,v=d===r.Alternate&&p%2==1,y=!!f.onClick&&!f.disabled,b=c(o,{children:[c(`div`,{className:a(n.timelineMarker,m?.marker),style:h?.marker,children:[s(`div`,{className:a(n.timelineDot,{[n.timelineDotWithIcon]:!!f.icon},l[f.status??i.Default],m?.dot),style:h?.dot,children:f.icon?e(f.icon):null}),!_&&s(`div`,{className:a(n.timelineConnector,m?.connector),style:h?.connector})]}),c(`div`,{className:a(n.timelineContent,m?.content),style:h?.content,children:[c(`div`,{className:n.timelineHeader,children:[s(`div`,{className:a(n.timelineTitle,m?.title),style:h?.title,children:f.title}),f.timestamp!=null&&s(`div`,{className:a(n.timelineTimestamp,m?.timestamp),style:h?.timestamp,children:f.timestamp})]}),f.description!=null&&s(`div`,{className:a(n.timelineDescription,m?.description),style:h?.description,children:f.description}),f.content]})]}),x=a(n.timelineItem,{[n.timelineItemRight]:v},{[n.timelineItemClickable]:y},{[n.timelineItemDisabled]:f.disabled},m?.item);return y?s(t,{className:x,style:h?.item,onClick:f.onClick,children:b},g):s(`div`,{className:x,style:h?.item,"aria-disabled":f.disabled||void 0,children:b},g)})})}export{u as default};
1
+ "use client";import{toneProps as e,useToneCheck as t}from"../styles/tone.mjs";import{renderIcon as n}from"../utils/renderIcon.mjs";import r from"../interactableDiv/index.mjs";import i from"./timeline.module.mjs";import{TimelineAlignment as a}from"./timeline.types.mjs";import"react";import o from"classnames";import{Fragment as s,jsx as c,jsxs as l}from"react/jsx-runtime";function u({items:u=[],alignment:d=a.Left,className:f,style:p,classNames:m,styles:h,...g}){let _=u.some(e=>!!e.icon);return t(`Timeline`,u.map(e=>e.color)),c(`div`,{...g,className:o(i.timeline,{[i.timelineRight]:d===a.Right,[i.timelineAlternate]:d===a.Alternate,[i.timelineWithIcons]:_},m?.root,f),style:{...h?.root,...p},children:u.map((t,f)=>{let p=t.id??f,g=f===u.length-1,_=d===a.Alternate&&f%2==1,v=!!t.onClick&&!t.disabled,y=t.color?e(t.color):void 0,b=l(s,{children:[l(`div`,{className:o(i.timelineMarker,m?.marker),style:h?.marker,children:[c(`div`,{className:o(i.timelineDot,{[i.timelineDotWithIcon]:!!t.icon},y&&[y.className,i.timelineDotToned],m?.dot),style:{...y?.style,...h?.dot},children:t.icon?n(t.icon):null}),!g&&c(`div`,{className:o(i.timelineConnector,m?.connector),style:h?.connector})]}),l(`div`,{className:o(i.timelineContent,m?.content),style:h?.content,children:[l(`div`,{className:i.timelineHeader,children:[c(`div`,{className:o(i.timelineTitle,m?.title),style:h?.title,children:t.title}),t.timestamp!=null&&c(`div`,{className:o(i.timelineTimestamp,m?.timestamp),style:h?.timestamp,children:t.timestamp})]}),t.description!=null&&c(`div`,{className:o(i.timelineDescription,m?.description),style:h?.description,children:t.description}),t.content]})]}),x=o(i.timelineItem,{[i.timelineItemRight]:_},{[i.timelineItemClickable]:v},{[i.timelineItemDisabled]:t.disabled},m?.item);return v?c(r,{className:x,style:h?.item,onClick:t.onClick,children:b},p):c(`div`,{className:x,style:h?.item,"aria-disabled":t.disabled||void 0,children:b},p)})})}export{u as default};
2
2
  //# sourceMappingURL=timeline.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"timeline.mjs","names":[],"sources":["../../../../package/common/timeline/timeline.tsx"],"sourcesContent":["import React from 'react';\nimport cx from 'classnames';\nimport InteractableDiv from '../interactableDiv';\nimport styles from './timeline.module.pcss';\nimport { TimelineAlignment, TimelineItemStatus, type TimelineProps, type TimelineItem } from './timeline.types';\nimport { renderIcon } from '../utils/renderIcon';\n\n// TimelineItemStatus.Default is intentionally absent: it uses .timeline-dot's own\n// background-color, so no modifier class is needed for it.\nconst STATUS_CLASS: Partial<Record<TimelineItemStatus, string>> = {\n [TimelineItemStatus.Primary]: styles.timelineDotPrimary,\n [TimelineItemStatus.Success]: styles.timelineDotSuccess,\n [TimelineItemStatus.Warn]: styles.timelineDotWarn,\n [TimelineItemStatus.Error]: styles.timelineDotError,\n};\n\nexport default function Timeline({\n items = [],\n alignment = TimelineAlignment.Left,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: TimelineProps) {\n // An icon dot is bigger than a plain one, and the marker is only as wide as the dot\n // inside it — so mixing the two put every row's spine and content column at a different\n // x. Widening the marker for the whole timeline fixes the alignment; doing it only when\n // an icon is actually present leaves an icon-less timeline exactly where it was.\n const hasIcons = items.some((item: TimelineItem) => !!item.icon);\n\n return (\n <div\n {...rest}\n className={cx(\n styles.timeline,\n {\n [styles.timelineRight]: alignment === TimelineAlignment.Right,\n [styles.timelineAlternate]: alignment === TimelineAlignment.Alternate,\n [styles.timelineWithIcons]: hasIcons,\n },\n classNames?.root,\n className,\n )}\n style={{ ...slotStyles?.root, ...style }}\n >\n {items.map((item: TimelineItem, index: number) => {\n const key = item.id ?? index;\n const isLast = index === items.length - 1;\n const isAlternateRight = alignment === TimelineAlignment.Alternate && index % 2 === 1;\n const isClickable = !!item.onClick && !item.disabled;\n\n const itemContent = (\n <>\n <div className={cx(styles.timelineMarker, classNames?.marker)} style={slotStyles?.marker}>\n <div\n className={cx(\n styles.timelineDot,\n { [styles.timelineDotWithIcon]: !!item.icon },\n STATUS_CLASS[item.status ?? TimelineItemStatus.Default],\n classNames?.dot,\n )}\n style={slotStyles?.dot}\n >\n {item.icon ? renderIcon(item.icon) : null}\n </div>\n {!isLast && (\n <div className={cx(styles.timelineConnector, classNames?.connector)} style={slotStyles?.connector} />\n )}\n </div>\n <div className={cx(styles.timelineContent, classNames?.content)} style={slotStyles?.content}>\n <div className={styles.timelineHeader}>\n <div className={cx(styles.timelineTitle, classNames?.title)} style={slotStyles?.title}>\n {item.title}\n </div>\n {item.timestamp != null && (\n <div className={cx(styles.timelineTimestamp, classNames?.timestamp)} style={slotStyles?.timestamp}>\n {item.timestamp}\n </div>\n )}\n </div>\n {item.description != null && (\n <div\n className={cx(styles.timelineDescription, classNames?.description)}\n style={slotStyles?.description}\n >\n {item.description}\n </div>\n )}\n {item.content}\n </div>\n </>\n );\n\n const itemClassName = cx(\n styles.timelineItem,\n { [styles.timelineItemRight]: isAlternateRight },\n { [styles.timelineItemClickable]: isClickable },\n { [styles.timelineItemDisabled]: item.disabled },\n classNames?.item,\n );\n\n if (isClickable) {\n return (\n <InteractableDiv key={key} className={itemClassName} style={slotStyles?.item} onClick={item.onClick}>\n {itemContent}\n </InteractableDiv>\n );\n }\n\n return (\n <div key={key} className={itemClassName} style={slotStyles?.item} aria-disabled={item.disabled || undefined}>\n {itemContent}\n </div>\n );\n })}\n </div>\n );\n}\n"],"mappings":"4UASA,IAAM,EAA4D,EAC/D,EAAmB,SAAU,EAAO,oBACpC,EAAmB,SAAU,EAAO,oBACpC,EAAmB,MAAO,EAAO,iBACjC,EAAmB,OAAQ,EAAO,gBACrC,EAEA,SAAwB,EAAS,CAC/B,QAAQ,CAAC,EACT,YAAY,EAAkB,KAC9B,YACA,QACA,aACA,OAAQ,EACR,GAAG,GACa,CAKhB,IAAM,EAAW,EAAM,KAAM,GAAuB,CAAC,CAAC,EAAK,IAAI,EAE/D,OACE,EAAC,MAAD,CACE,GAAI,EACJ,UAAW,EACT,EAAO,SACP,EACG,EAAO,eAAgB,IAAc,EAAkB,OACvD,EAAO,mBAAoB,IAAc,EAAkB,WAC3D,EAAO,mBAAoB,CAC9B,EACA,GAAY,KACZ,CACF,EACA,MAAO,CAAE,GAAG,GAAY,KAAM,GAAG,CAAM,EAEtC,SAAA,EAAM,KAAK,EAAoB,IAAkB,CAChD,IAAM,EAAM,EAAK,IAAM,EACjB,EAAS,IAAU,EAAM,OAAS,EAClC,EAAmB,IAAc,EAAkB,WAAa,EAAQ,GAAM,EAC9E,EAAc,CAAC,CAAC,EAAK,SAAW,CAAC,EAAK,SAEtC,EACJ,EAAA,EAAA,CAAA,SAAA,CACE,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,eAAgB,GAAY,MAAM,EAAG,MAAO,GAAY,OAAlF,SAAA,CACE,EAAC,MAAD,CACE,UAAW,EACT,EAAO,YACP,EAAG,EAAO,qBAAsB,CAAC,CAAC,EAAK,IAAK,EAC5C,EAAa,EAAK,QAAU,EAAmB,SAC/C,GAAY,GACd,EACA,MAAO,GAAY,IAElB,SAAA,EAAK,KAAO,EAAW,EAAK,IAAI,EAAI,IAClC,CAAA,EACJ,CAAC,GACA,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,kBAAmB,GAAY,SAAS,EAAG,MAAO,GAAY,SAAY,CAAA,CAEnG,CACL,CAAA,EAAA,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,gBAAiB,GAAY,OAAO,EAAG,MAAO,GAAY,QAApF,SAAA,CACE,EAAC,MAAD,CAAK,UAAW,EAAO,eAAvB,SAAA,CACE,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,cAAe,GAAY,KAAK,EAAG,MAAO,GAAY,MAC7E,SAAA,EAAK,KACH,CAAA,EACJ,EAAK,WAAa,MACjB,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,kBAAmB,GAAY,SAAS,EAAG,MAAO,GAAY,UACrF,SAAA,EAAK,SACH,CAAA,CAEJ,IACJ,EAAK,aAAe,MACnB,EAAC,MAAD,CACE,UAAW,EAAG,EAAO,oBAAqB,GAAY,WAAW,EACjE,MAAO,GAAY,YAElB,SAAA,EAAK,WACH,CAAA,EAEN,EAAK,OACH,CACL,CAAA,CAAA,CAAA,CAAA,EAGE,EAAgB,EACpB,EAAO,aACP,EAAG,EAAO,mBAAoB,CAAiB,EAC/C,EAAG,EAAO,uBAAwB,CAAY,EAC9C,EAAG,EAAO,sBAAuB,EAAK,QAAS,EAC/C,GAAY,IACd,EAUA,OARI,EAEA,EAAC,EAAD,CAA2B,UAAW,EAAe,MAAO,GAAY,KAAM,QAAS,EAAK,QACzF,SAAA,CACc,EAFK,CAEL,EAKnB,EAAC,MAAD,CAAe,UAAW,EAAe,MAAO,GAAY,KAAM,gBAAe,EAAK,UAAY,IAAA,GAC/F,SAAA,CACE,EAFK,CAEL,CAET,CAAC,CACE,CAAA,CAET"}
1
+ {"version":3,"file":"timeline.mjs","names":[],"sources":["../../../../package/common/timeline/timeline.tsx"],"sourcesContent":["import React from 'react';\nimport cx from 'classnames';\nimport InteractableDiv from '../interactableDiv';\nimport styles from './timeline.module.pcss';\nimport { TimelineAlignment, type TimelineProps, type TimelineItem } from './timeline.types';\nimport { renderIcon } from '../utils/renderIcon';\nimport { toneProps, useToneCheck } from '../styles/tone';\n\nexport default function Timeline({\n items = [],\n alignment = TimelineAlignment.Left,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: TimelineProps) {\n // An icon dot is bigger than a plain one, and the marker is only as wide as the dot\n // inside it — so mixing the two put every row's spine and content column at a different\n // x. Widening the marker for the whole timeline fixes the alignment; doing it only when\n // an icon is actually present leaves an icon-less timeline exactly where it was.\n const hasIcons = items.some((item: TimelineItem) => !!item.icon);\n useToneCheck(\n 'Timeline',\n items.map((item) => item.color),\n );\n\n return (\n <div\n {...rest}\n className={cx(\n styles.timeline,\n {\n [styles.timelineRight]: alignment === TimelineAlignment.Right,\n [styles.timelineAlternate]: alignment === TimelineAlignment.Alternate,\n [styles.timelineWithIcons]: hasIcons,\n },\n classNames?.root,\n className,\n )}\n style={{ ...slotStyles?.root, ...style }}\n >\n {items.map((item: TimelineItem, index: number) => {\n const key = item.id ?? index;\n const isLast = index === items.length - 1;\n const isAlternateRight = alignment === TimelineAlignment.Alternate && index % 2 === 1;\n const isClickable = !!item.onClick && !item.disabled;\n const tone = item.color ? toneProps(item.color) : undefined;\n\n const itemContent = (\n <>\n <div className={cx(styles.timelineMarker, classNames?.marker)} style={slotStyles?.marker}>\n <div\n className={cx(\n styles.timelineDot,\n { [styles.timelineDotWithIcon]: !!item.icon },\n tone && [tone.className, styles.timelineDotToned],\n classNames?.dot,\n )}\n style={{ ...tone?.style, ...slotStyles?.dot }}\n >\n {item.icon ? renderIcon(item.icon) : null}\n </div>\n {!isLast && (\n <div className={cx(styles.timelineConnector, classNames?.connector)} style={slotStyles?.connector} />\n )}\n </div>\n <div className={cx(styles.timelineContent, classNames?.content)} style={slotStyles?.content}>\n <div className={styles.timelineHeader}>\n <div className={cx(styles.timelineTitle, classNames?.title)} style={slotStyles?.title}>\n {item.title}\n </div>\n {item.timestamp != null && (\n <div className={cx(styles.timelineTimestamp, classNames?.timestamp)} style={slotStyles?.timestamp}>\n {item.timestamp}\n </div>\n )}\n </div>\n {item.description != null && (\n <div\n className={cx(styles.timelineDescription, classNames?.description)}\n style={slotStyles?.description}\n >\n {item.description}\n </div>\n )}\n {item.content}\n </div>\n </>\n );\n\n const itemClassName = cx(\n styles.timelineItem,\n { [styles.timelineItemRight]: isAlternateRight },\n { [styles.timelineItemClickable]: isClickable },\n { [styles.timelineItemDisabled]: item.disabled },\n classNames?.item,\n );\n\n if (isClickable) {\n return (\n <InteractableDiv key={key} className={itemClassName} style={slotStyles?.item} onClick={item.onClick}>\n {itemContent}\n </InteractableDiv>\n );\n }\n\n return (\n <div key={key} className={itemClassName} style={slotStyles?.item} aria-disabled={item.disabled || undefined}>\n {itemContent}\n </div>\n );\n })}\n </div>\n );\n}\n"],"mappings":"qXAQA,SAAwB,EAAS,CAC/B,QAAQ,CAAC,EACT,YAAY,EAAkB,KAC9B,YACA,QACA,aACA,OAAQ,EACR,GAAG,GACa,CAKhB,IAAM,EAAW,EAAM,KAAM,GAAuB,CAAC,CAAC,EAAK,IAAI,EAM/D,OALA,EACE,WACA,EAAM,IAAK,GAAS,EAAK,KAAK,CAChC,EAGE,EAAC,MAAD,CACE,GAAI,EACJ,UAAW,EACT,EAAO,SACP,EACG,EAAO,eAAgB,IAAc,EAAkB,OACvD,EAAO,mBAAoB,IAAc,EAAkB,WAC3D,EAAO,mBAAoB,CAC9B,EACA,GAAY,KACZ,CACF,EACA,MAAO,CAAE,GAAG,GAAY,KAAM,GAAG,CAAM,EAEtC,SAAA,EAAM,KAAK,EAAoB,IAAkB,CAChD,IAAM,EAAM,EAAK,IAAM,EACjB,EAAS,IAAU,EAAM,OAAS,EAClC,EAAmB,IAAc,EAAkB,WAAa,EAAQ,GAAM,EAC9E,EAAc,CAAC,CAAC,EAAK,SAAW,CAAC,EAAK,SACtC,EAAO,EAAK,MAAQ,EAAU,EAAK,KAAK,EAAI,IAAA,GAE5C,EACJ,EAAA,EAAA,CAAA,SAAA,CACE,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,eAAgB,GAAY,MAAM,EAAG,MAAO,GAAY,OAAlF,SAAA,CACE,EAAC,MAAD,CACE,UAAW,EACT,EAAO,YACP,EAAG,EAAO,qBAAsB,CAAC,CAAC,EAAK,IAAK,EAC5C,GAAQ,CAAC,EAAK,UAAW,EAAO,gBAAgB,EAChD,GAAY,GACd,EACA,MAAO,CAAE,GAAG,GAAM,MAAO,GAAG,GAAY,GAAI,EAE3C,SAAA,EAAK,KAAO,EAAW,EAAK,IAAI,EAAI,IAClC,CAAA,EACJ,CAAC,GACA,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,kBAAmB,GAAY,SAAS,EAAG,MAAO,GAAY,SAAY,CAAA,CAEnG,CACL,CAAA,EAAA,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,gBAAiB,GAAY,OAAO,EAAG,MAAO,GAAY,QAApF,SAAA,CACE,EAAC,MAAD,CAAK,UAAW,EAAO,eAAvB,SAAA,CACE,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,cAAe,GAAY,KAAK,EAAG,MAAO,GAAY,MAC7E,SAAA,EAAK,KACH,CAAA,EACJ,EAAK,WAAa,MACjB,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,kBAAmB,GAAY,SAAS,EAAG,MAAO,GAAY,UACrF,SAAA,EAAK,SACH,CAAA,CAEJ,IACJ,EAAK,aAAe,MACnB,EAAC,MAAD,CACE,UAAW,EAAG,EAAO,oBAAqB,GAAY,WAAW,EACjE,MAAO,GAAY,YAElB,SAAA,EAAK,WACH,CAAA,EAEN,EAAK,OACH,CACL,CAAA,CAAA,CAAA,CAAA,EAGE,EAAgB,EACpB,EAAO,aACP,EAAG,EAAO,mBAAoB,CAAiB,EAC/C,EAAG,EAAO,uBAAwB,CAAY,EAC9C,EAAG,EAAO,sBAAuB,EAAK,QAAS,EAC/C,GAAY,IACd,EAUA,OARI,EAEA,EAAC,EAAD,CAA2B,UAAW,EAAe,MAAO,GAAY,KAAM,QAAS,EAAK,QACzF,SAAA,CACc,EAFK,CAEL,EAKnB,EAAC,MAAD,CAAe,UAAW,EAAe,MAAO,GAAY,KAAM,gBAAe,EAAK,UAAY,IAAA,GAC/F,SAAA,CACE,EAFK,CAEL,CAET,CAAC,CACE,CAAA,CAET"}
@@ -1,2 +1,2 @@
1
- "use client";var e=`timeline_VtQdt`,t=`timeline-item_s8-U2`,n=`timeline-item-connector_06FQ0`,r=`timeline-item-clickable_0w8zK`,i=`timeline-item-disabled_EkWVA`,a=`timeline-marker_u6jDA`,o=`timeline-dot_l-s7C`,s=`timeline-dot-with-icon_6JK7D`,c=`timeline-dot-primary_5Uk-e`,l=`timeline-dot-success_iEoLv`,u=`timeline-dot-warn_-6G8K`,d=`timeline-dot-error_-10M7`,f=`timeline-with-icons_ylDAw`,p=`timeline-connector_VuXnH`,m=`timeline-content_K4Ztg`,h=`timeline-header_xr4Tw`,g=`timeline-title_MZ26k`,_=`timeline-timestamp_-0w-N`,v=`timeline-description_WcWIu`,y=`timeline-right_fZEKn`,b=`timeline-alternate_Kv9LY`,x=`timeline-item-right_s5ELB`,S={timeline:e,"timeline-item":`timeline-item_s8-U2`,timelineItem:t,"timeline-item-connector":`timeline-item-connector_06FQ0`,timelineItemConnector:n,"timeline-item-clickable":`timeline-item-clickable_0w8zK`,timelineItemClickable:r,"timeline-item-disabled":`timeline-item-disabled_EkWVA`,timelineItemDisabled:i,"timeline-marker":`timeline-marker_u6jDA`,timelineMarker:a,"timeline-dot":`timeline-dot_l-s7C`,timelineDot:o,"timeline-dot-with-icon":`timeline-dot-with-icon_6JK7D`,timelineDotWithIcon:s,"timeline-dot-primary":`timeline-dot-primary_5Uk-e`,timelineDotPrimary:c,"timeline-dot-success":`timeline-dot-success_iEoLv`,timelineDotSuccess:l,"timeline-dot-warn":`timeline-dot-warn_-6G8K`,timelineDotWarn:u,"timeline-dot-error":`timeline-dot-error_-10M7`,timelineDotError:d,"timeline-with-icons":`timeline-with-icons_ylDAw`,timelineWithIcons:f,"timeline-connector":`timeline-connector_VuXnH`,timelineConnector:p,"timeline-content":`timeline-content_K4Ztg`,timelineContent:m,"timeline-header":`timeline-header_xr4Tw`,timelineHeader:h,"timeline-title":`timeline-title_MZ26k`,timelineTitle:g,"timeline-timestamp":`timeline-timestamp_-0w-N`,timelineTimestamp:_,"timeline-description":`timeline-description_WcWIu`,timelineDescription:v,"timeline-right":`timeline-right_fZEKn`,timelineRight:y,"timeline-alternate":`timeline-alternate_Kv9LY`,timelineAlternate:b,"timeline-item-right":`timeline-item-right_s5ELB`,timelineItemRight:x};export{S as default,e as timeline,b as timelineAlternate,p as timelineConnector,m as timelineContent,v as timelineDescription,o as timelineDot,d as timelineDotError,c as timelineDotPrimary,l as timelineDotSuccess,u as timelineDotWarn,s as timelineDotWithIcon,h as timelineHeader,t as timelineItem,r as timelineItemClickable,n as timelineItemConnector,i as timelineItemDisabled,x as timelineItemRight,a as timelineMarker,y as timelineRight,_ as timelineTimestamp,g as timelineTitle,f as timelineWithIcons};
1
+ "use client";var e=`timeline_VtQdt`,t=`timeline-item_s8-U2`,n=`timeline-item-connector_06FQ0`,r=`timeline-item-clickable_0w8zK`,i=`timeline-item-disabled_EkWVA`,a=`timeline-marker_u6jDA`,o=`timeline-dot_l-s7C`,s=`timeline-dot-with-icon_6JK7D`,c=`timeline-dot-toned_h1Cso`,l=`timeline-with-icons_ylDAw`,u=`timeline-connector_VuXnH`,d=`timeline-content_K4Ztg`,f=`timeline-header_xr4Tw`,p=`timeline-title_MZ26k`,m=`timeline-timestamp_-0w-N`,h=`timeline-description_WcWIu`,g=`timeline-right_fZEKn`,_=`timeline-alternate_Kv9LY`,v=`timeline-item-right_s5ELB`,y={timeline:e,"timeline-item":`timeline-item_s8-U2`,timelineItem:t,"timeline-item-connector":`timeline-item-connector_06FQ0`,timelineItemConnector:n,"timeline-item-clickable":`timeline-item-clickable_0w8zK`,timelineItemClickable:r,"timeline-item-disabled":`timeline-item-disabled_EkWVA`,timelineItemDisabled:i,"timeline-marker":`timeline-marker_u6jDA`,timelineMarker:a,"timeline-dot":`timeline-dot_l-s7C`,timelineDot:o,"timeline-dot-with-icon":`timeline-dot-with-icon_6JK7D`,timelineDotWithIcon:s,"timeline-dot-toned":`timeline-dot-toned_h1Cso`,timelineDotToned:c,"timeline-with-icons":`timeline-with-icons_ylDAw`,timelineWithIcons:l,"timeline-connector":`timeline-connector_VuXnH`,timelineConnector:u,"timeline-content":`timeline-content_K4Ztg`,timelineContent:d,"timeline-header":`timeline-header_xr4Tw`,timelineHeader:f,"timeline-title":`timeline-title_MZ26k`,timelineTitle:p,"timeline-timestamp":`timeline-timestamp_-0w-N`,timelineTimestamp:m,"timeline-description":`timeline-description_WcWIu`,timelineDescription:h,"timeline-right":`timeline-right_fZEKn`,timelineRight:g,"timeline-alternate":`timeline-alternate_Kv9LY`,timelineAlternate:_,"timeline-item-right":`timeline-item-right_s5ELB`,timelineItemRight:v};export{y as default,e as timeline,_ as timelineAlternate,u as timelineConnector,d as timelineContent,h as timelineDescription,o as timelineDot,c as timelineDotToned,s as timelineDotWithIcon,f as timelineHeader,t as timelineItem,r as timelineItemClickable,n as timelineItemConnector,i as timelineItemDisabled,v as timelineItemRight,a as timelineMarker,g as timelineRight,m as timelineTimestamp,p as timelineTitle,l as timelineWithIcons};
2
2
  //# sourceMappingURL=timeline.module.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"timeline.module.mjs","names":[],"sources":["../../../../package/common/timeline/timeline.module.pcss"],"sourcesContent":[".timeline {\n /* Theme tokens resolved once, each with a built-in fallback. Set any of the\n public `--timeline-*` variables via ThemeProvider (theme-wide) or `style`\n (per instance) to override; unset ones fall back to the values below. */\n --custom-timeline-dot-size: var(--timeline-dot-size, 14px);\n --custom-timeline-dot-color: var(--timeline-dot-color, var(--primary-color));\n --custom-timeline-dot-border: var(--timeline-dot-border, var(--background));\n --custom-timeline-line-color: var(--timeline-line-color, var(--border-color));\n --custom-timeline-line-thickness: var(--timeline-line-thickness, 2px);\n --custom-timeline-gap: var(--timeline-gap, 16px);\n --custom-timeline-item-gap: var(--timeline-item-gap, 20px);\n --custom-timeline-icon-dot-size: var(--timeline-icon-dot-size, 28px);\n\n display: flex;\n flex-direction: column;\n color: var(--text-color);\n\n &-item {\n display: flex;\n gap: var(--custom-timeline-gap);\n border-radius: var(--default-border-radius);\n\n &:last-child &-connector {\n display: none;\n }\n }\n\n &-item-clickable {\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n transition: background-color 0.15s ease;\n margin: 0 -10px;\n padding: 0 10px;\n\n &:hover {\n background-color: var(--background-accent-light);\n }\n\n &:focus-visible {\n outline: 2px solid var(--focus-border-color, var(--primary-color));\n outline-offset: -2px;\n }\n }\n\n &-item-disabled {\n opacity: 0.5;\n }\n\n &-marker {\n display: flex;\n flex-direction: column;\n align-items: center;\n flex-shrink: 0;\n }\n\n &-dot {\n width: var(--custom-timeline-dot-size);\n height: var(--custom-timeline-dot-size);\n border-radius: 50%;\n background-color: var(--custom-timeline-dot-color);\n box-shadow: 0 0 0 3px var(--custom-timeline-dot-border);\n flex-shrink: 0;\n }\n\n /* Set by the component whenever the item has an icon — not inferred from the\n rendered markup (`:has(svg)`), which would miss a custom icon element that\n isn't an <svg>, e.g. an <img>. */\n &-dot-with-icon {\n width: var(--custom-timeline-icon-dot-size);\n height: var(--custom-timeline-icon-dot-size);\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--text-on-primary);\n font-size: calc(var(--custom-timeline-icon-dot-size) * 0.5);\n }\n\n &-dot-primary {\n background-color: var(--primary-color);\n }\n\n &-dot-success {\n background-color: var(--success-color);\n }\n\n &-dot-warn {\n background-color: var(--warn-color);\n }\n\n &-dot-error {\n background-color: var(--error-color);\n }\n\n /* Set by the component when ANY item has an icon. Every marker is then as wide as the\n widest dot it could hold, so the connectors line up into one vertical spine and every\n content column starts at the same x. max(), because a consumer is free to set the icon\n dot smaller than the plain one. */\n &-with-icons &-marker {\n width: max(var(--custom-timeline-dot-size), var(--custom-timeline-icon-dot-size));\n }\n\n &-connector {\n flex: 1 1 auto;\n width: var(--custom-timeline-line-thickness);\n min-height: 12px;\n background-color: var(--custom-timeline-line-color);\n margin: 4px 0;\n }\n\n &-content {\n flex: 1 1 auto;\n min-width: 0;\n padding-bottom: var(--custom-timeline-item-gap);\n }\n\n &-header {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: 8px;\n }\n\n &-title {\n font-weight: 600;\n color: var(--text-color);\n }\n\n &-timestamp {\n flex-shrink: 0;\n color: var(--text-dark);\n font-size: var(--text-small-font-size, 0.85em);\n white-space: nowrap;\n }\n\n &-description {\n color: var(--text-dark);\n margin-top: 2px;\n }\n\n /* Right: markers + line on the right, content on the left */\n &-right &-item {\n flex-direction: row-reverse;\n text-align: right;\n }\n\n &-right &-header {\n flex-direction: row-reverse;\n }\n\n /* Alternate: two-column layout, entries alternating left/right of a centered line */\n &-alternate &-item {\n display: grid;\n grid-template-columns: 1fr auto 1fr;\n align-items: start;\n gap: var(--custom-timeline-gap);\n }\n\n &-alternate &-marker {\n grid-column: 2;\n grid-row: 1;\n }\n\n &-alternate &-content {\n grid-column: 1;\n grid-row: 1;\n text-align: right;\n }\n\n &-alternate &-header {\n flex-direction: row-reverse;\n }\n\n &-alternate &-item-right &-content {\n grid-column: 3;\n text-align: left;\n }\n\n &-alternate &-item-right &-header {\n flex-direction: row;\n }\n}\n"],"mappings":""}
1
+ {"version":3,"file":"timeline.module.mjs","names":[],"sources":["../../../../package/common/timeline/timeline.module.pcss"],"sourcesContent":[".timeline {\n /* Theme tokens resolved once, each with a built-in fallback. Set any of the\n public `--timeline-*` variables via ThemeProvider (theme-wide) or `style`\n (per instance) to override; unset ones fall back to the values below. */\n --custom-timeline-dot-size: var(--timeline-dot-size, 14px);\n --custom-timeline-dot-color: var(--timeline-dot-color, var(--primary-color));\n --custom-timeline-dot-border: var(--timeline-dot-border, var(--background));\n --custom-timeline-line-color: var(--timeline-line-color, var(--border-color));\n --custom-timeline-line-thickness: var(--timeline-line-thickness, 2px);\n --custom-timeline-gap: var(--timeline-gap, 16px);\n --custom-timeline-item-gap: var(--timeline-item-gap, 20px);\n --custom-timeline-icon-dot-size: var(--timeline-icon-dot-size, 28px);\n\n display: flex;\n flex-direction: column;\n color: var(--text-color);\n\n &-item {\n display: flex;\n gap: var(--custom-timeline-gap);\n border-radius: var(--default-border-radius);\n\n &:last-child &-connector {\n display: none;\n }\n }\n\n &-item-clickable {\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n transition: background-color 0.15s ease;\n margin: 0 -10px;\n padding: 0 10px;\n\n &:hover {\n background-color: var(--background-accent-light);\n }\n\n &:focus-visible {\n outline: 2px solid var(--focus-border-color, var(--primary-color));\n outline-offset: -2px;\n }\n }\n\n &-item-disabled {\n opacity: 0.5;\n }\n\n &-marker {\n display: flex;\n flex-direction: column;\n align-items: center;\n flex-shrink: 0;\n }\n\n &-dot {\n width: var(--custom-timeline-dot-size);\n height: var(--custom-timeline-dot-size);\n border-radius: 50%;\n background-color: var(--custom-timeline-dot-color);\n box-shadow: 0 0 0 3px var(--custom-timeline-dot-border);\n flex-shrink: 0;\n }\n\n /* Set by the component whenever the item has an icon — not inferred from the\n rendered markup (`:has(svg)`), which would miss a custom icon element that\n isn't an <svg>, e.g. an <img>. */\n &-dot-with-icon {\n width: var(--custom-timeline-icon-dot-size);\n height: var(--custom-timeline-icon-dot-size);\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--text-on-primary);\n font-size: calc(var(--custom-timeline-icon-dot-size) * 0.5);\n }\n\n /* After -dot-with-icon, which it ties on specificity: a coloured dot's icon reads on its colour. */\n &-dot-toned {\n background-color: var(--tone);\n color: var(--tone-contrast);\n }\n\n /* Neutral's --tone is its contrast colour too, so an icon needs the see-through fill behind it. */\n &-dot-toned&-dot-with-icon {\n background-color: var(--tone-fill);\n }\n\n /* Set by the component when ANY item has an icon. Every marker is then as wide as the\n widest dot it could hold, so the connectors line up into one vertical spine and every\n content column starts at the same x. max(), because a consumer is free to set the icon\n dot smaller than the plain one. */\n &-with-icons &-marker {\n width: max(var(--custom-timeline-dot-size), var(--custom-timeline-icon-dot-size));\n }\n\n &-connector {\n flex: 1 1 auto;\n width: var(--custom-timeline-line-thickness);\n min-height: 12px;\n background-color: var(--custom-timeline-line-color);\n margin: 4px 0;\n }\n\n &-content {\n flex: 1 1 auto;\n min-width: 0;\n padding-bottom: var(--custom-timeline-item-gap);\n }\n\n &-header {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: 8px;\n }\n\n &-title {\n font-weight: 600;\n color: var(--text-color);\n }\n\n &-timestamp {\n flex-shrink: 0;\n color: var(--text-dark);\n font-size: var(--text-small-font-size, 0.85em);\n white-space: nowrap;\n }\n\n &-description {\n color: var(--text-dark);\n margin-top: 2px;\n }\n\n /* Right: markers + line on the right, content on the left */\n &-right &-item {\n flex-direction: row-reverse;\n text-align: right;\n }\n\n &-right &-header {\n flex-direction: row-reverse;\n }\n\n /* Alternate: two-column layout, entries alternating left/right of a centered line */\n &-alternate &-item {\n display: grid;\n grid-template-columns: 1fr auto 1fr;\n align-items: start;\n gap: var(--custom-timeline-gap);\n }\n\n &-alternate &-marker {\n grid-column: 2;\n grid-row: 1;\n }\n\n &-alternate &-content {\n grid-column: 1;\n grid-row: 1;\n text-align: right;\n }\n\n &-alternate &-header {\n flex-direction: row-reverse;\n }\n\n &-alternate &-item-right &-content {\n grid-column: 3;\n text-align: left;\n }\n\n &-alternate &-item-right &-header {\n flex-direction: row;\n }\n}\n"],"mappings":""}
@@ -1,2 +1,2 @@
1
- "use client";var e=function(e){return e.Left=`left`,e.Right=`right`,e.Alternate=`alternate`,e}({}),t=function(e){return e.Default=`default`,e.Primary=`primary`,e.Success=`success`,e.Warn=`warn`,e.Error=`error`,e}({});export{e as TimelineAlignment,t as TimelineItemStatus};
1
+ "use client";var e=function(e){return e.Left=`left`,e.Right=`right`,e.Alternate=`alternate`,e}({});export{e as TimelineAlignment};
2
2
  //# sourceMappingURL=timeline.types.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"timeline.types.mjs","names":[],"sources":["../../../../package/common/timeline/timeline.types.ts"],"sourcesContent":["import type React from 'react';\nimport type { IconContent } from '../types/icon.types';\nimport type { SlotClassNames, SlotStyles, HtmlProps } from '../types/slots.types';\n\n/** Layout of entries relative to the connecting line. */\nexport enum TimelineAlignment {\n /** Line and markers on the left, content to the right (the default). */\n Left = 'left',\n /** Line and markers on the right, content to the left. */\n Right = 'right',\n /** Line down the center, entries alternating left/right. */\n Alternate = 'alternate',\n}\n\n/** Semantic colour for an entry's marker, matching the theme's status colours. */\nexport enum TimelineItemStatus {\n Default = 'default',\n Primary = 'primary',\n Success = 'success',\n Warn = 'warn',\n Error = 'error',\n}\n\nexport type TimelineSlots =\n | 'root'\n | 'item'\n | 'marker'\n | 'dot'\n | 'connector'\n | 'content'\n | 'title'\n | 'description'\n | 'timestamp';\n\nexport interface TimelineItem {\n /** Stable identity for the entry, used as its React key. Falls back to its array index when omitted; pass one whenever `items` can be reordered or have entries prepended (e.g. a live \"newest first\" audit log), so React doesn't misattribute row state across the shift. */\n id?: string | number;\n /** Primary label for the entry. */\n title: React.ReactNode;\n /** Secondary line under the title. */\n description?: React.ReactNode;\n /** Rendered next to the title, e.g. a date or relative time (\"2 hours ago\"). */\n timestamp?: React.ReactNode;\n /** Icon shown in the marker instead of a plain dot — a FontAwesome icon or any node. */\n icon?: IconContent;\n /** Semantic marker colour (default `Default`). */\n status?: TimelineItemStatus;\n /** Extra content rendered under the description, e.g. a diff, an attachment, an actor avatar. */\n content?: React.ReactNode;\n /** Makes the whole entry clickable (e.g. to open the full record), rendering it as an accessible button. */\n onClick?: (event: React.MouseEvent<HTMLDivElement>) => void;\n /** Disables the entry: never clickable, dimmed. Only relevant alongside `onClick`. */\n disabled?: boolean;\n}\n\nexport interface TimelineProps extends HtmlProps {\n /** The entries to render, in display order (typically newest first for an audit log). */\n items?: TimelineItem[];\n /** Layout of entries relative to the connecting line (default `Left`). */\n alignment?: TimelineAlignment;\n className?: string;\n style?: React.CSSProperties;\n classNames?: SlotClassNames<TimelineSlots>;\n styles?: SlotStyles<TimelineSlots>;\n}\n"],"mappings":"aAKA,IAAY,EAAL,SAAA,EAAA,OAEL,GAAA,KAAA,OAEA,EAAA,MAAA,QAEA,EAAA,UAAA,aACF,EAAA,CAAA,CAAA,EAGY,EAAL,SAAA,EAAA,OACL,GAAA,QAAA,UACA,EAAA,QAAA,UACA,EAAA,QAAA,UACA,EAAA,KAAA,OACA,EAAA,MAAA,SACF,EAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"timeline.types.mjs","names":[],"sources":["../../../../package/common/timeline/timeline.types.ts"],"sourcesContent":["import type React from 'react';\nimport type { IconContent } from '../types/icon.types';\nimport type { SlotClassNames, SlotStyles, HtmlProps } from '../types/slots.types';\nimport type { ColorValue } from '../themeProvider/color.types';\n\n/** Layout of entries relative to the connecting line. */\nexport enum TimelineAlignment {\n /** Line and markers on the left, content to the right (the default). */\n Left = 'left',\n /** Line and markers on the right, content to the left. */\n Right = 'right',\n /** Line down the center, entries alternating left/right. */\n Alternate = 'alternate',\n}\n\nexport type TimelineSlots =\n | 'root'\n | 'item'\n | 'marker'\n | 'dot'\n | 'connector'\n | 'content'\n | 'title'\n | 'description'\n | 'timestamp';\n\nexport interface TimelineItem {\n /** Stable identity for the entry, used as its React key. Falls back to its array index when omitted; pass one whenever `items` can be reordered or have entries prepended (e.g. a live \"newest first\" audit log), so React doesn't misattribute row state across the shift. */\n id?: string | number;\n /** Primary label for the entry. */\n title: React.ReactNode;\n /** Secondary line under the title. */\n description?: React.ReactNode;\n /** Rendered next to the title, e.g. a date or relative time (\"2 hours ago\"). */\n timestamp?: React.ReactNode;\n /** Icon shown in the marker instead of a plain dot — a FontAwesome icon or any node. */\n icon?: IconContent;\n /** The marker's colour: a `ThemeColor` or any CSS colour. Unset, it is `--timeline-dot-color`. */\n color?: ColorValue;\n /** Extra content rendered under the description, e.g. a diff, an attachment, an actor avatar. */\n content?: React.ReactNode;\n /** Makes the whole entry clickable (e.g. to open the full record), rendering it as an accessible button. */\n onClick?: (event: React.MouseEvent<HTMLDivElement>) => void;\n /** Disables the entry: never clickable, dimmed. Only relevant alongside `onClick`. */\n disabled?: boolean;\n}\n\nexport interface TimelineProps extends HtmlProps {\n /** The entries to render, in display order (typically newest first for an audit log). */\n items?: TimelineItem[];\n /** Layout of entries relative to the connecting line (default `Left`). */\n alignment?: TimelineAlignment;\n className?: string;\n style?: React.CSSProperties;\n classNames?: SlotClassNames<TimelineSlots>;\n styles?: SlotStyles<TimelineSlots>;\n}\n"],"mappings":"aAMA,IAAY,EAAL,SAAA,EAAA,OAEL,GAAA,KAAA,OAEA,EAAA,MAAA,QAEA,EAAA,UAAA,aACF,EAAA,CAAA,CAAA"}
@@ -1,2 +1,2 @@
1
- "use client";import{useComponentDefaults as e}from"../configProvider/useComponentDefaults.mjs";import{useLabels as t}from"../configProvider/useLabels.mjs";import{ButtonSize as n}from"../button/button.types.mjs";import r from"../button/button.mjs";import i from"../actionIcon/actionIcon.mjs";import"./timer.chime.mjs";import a from"./timer.module.mjs";import{useEffect as o,useImperativeHandle as ee,useMemo as te,useRef as s,useState as c}from"react";import l from"classnames";import{faMinus as ne,faPause as re,faPlay as ie,faPlus as ae,faXmark as oe}from"@fortawesome/free-solid-svg-icons";import{jsx as u,jsxs as d}from"react/jsx-runtime";var se=200,ce=1e3,le={cancel:`Cancel timer`};function ue(){return typeof window<`u`&&window.matchMedia?.(`(prefers-reduced-motion: reduce)`).matches===!0}function de(e){let t=Math.ceil(e/1e3),n=Math.floor(t/3600),r=Math.floor(t%3600/60),i=t%60,a=String(r).padStart(2,`0`),o=String(i).padStart(2,`0`);return n>0?`${n}:${a}:${o}`:`${a}:${o}`}function f(f){let{ref:fe,durationSeconds:p,autoStart:m=!0,resetOnDurationChange:pe=!0,onTick:h,onComplete:me,onStart:he,onPause:ge,onResume:_e,onCancel:ve,onAddTime:g,onRemoveTime:ye,showControls:_=!0,hideAddButton:be=!1,hideRemoveButton:xe=!1,hidePauseButton:Se=!1,hideCancelButton:Ce=!1,adjustSeconds:v=30,maxSeconds:y,label:b,formatTime:we=de,size:x,strokeWidth:S=10,counterClockwise:Te=!1,urgentThreshold:Ee=.1,urgentMinSeconds:De=3,pulseOnUrgent:Oe=!0,showRunningRipples:C=!1,playSoundOnComplete:w=!1,soundUrl:T,soundVolume:ke=.5,notifyOnComplete:E=!1,notificationTitle:Ae,notificationBody:je,className:Me,style:Ne,classNames:D,styles:O,labels:Pe,...Fe}=e(`Timer`,f),Ie=t(`Timer`,Pe,le),k=p*1e3,[A,Le]=c(m?`running`:`idle`),[j,Re]=c(k),[ze,Be]=c(0),[M,N]=c([]),P=s(j),F=s(A),I=s(k),L=s(!1),R=s(!1),z=s(!1),Ve=s(0);function B(e){P.current=e,Re(e)}function V(e){F.current=e,Le(e)}function H(){Be(e=>e+1)}o(()=>{if(A!==`running`)return;let e=Date.now(),t=P.current,n=setInterval(()=>{let n=Math.max(0,t-(Date.now()-e));B(n),h?.(n),n<=0&&V(`completed`)},se);return()=>clearInterval(n)},[A,ze]),o(()=>{if(A===`completed`&&!L.current){if(L.current=!0,me?.(),w)try{let e=new Audio(T||`data:audio/wav;base64,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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANACUAKwAKAMr/kv+R/9n/TwCxALwAVwCs/xb/8/5p/0YAFgFfAeYA3f/N/lP+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`);e.volume=ke,e.play()?.catch(()=>{})}catch{}if(E&&typeof Notification<`u`&&Notification.permission===`granted`)try{new Notification(Ae??`Timer done`,{body:je??(typeof b==`string`?b:void 0)})}catch{}}A!==`completed`&&(L.current=!1)},[A]),o(()=>{if(!z.current){z.current=!0;return}let e=p*1e3;I.current=e,B(e),L.current=!1,H(),pe&&V(m?`running`:`idle`)},[p]),o(()=>{if(!C||A!==`running`||ue())return;function e(){let e=++Ve.current;N(t=>[...t,e])}let t=setTimeout(e,0),n=setInterval(e,ce);return()=>{clearTimeout(t),clearInterval(n)}},[C,A]);function He(e){N(t=>t.filter(t=>t!==e))}function Ue(){E&&!R.current&&typeof Notification<`u`&&Notification.permission==="default"&&(R.current=!0,Notification.requestPermission().catch(()=>{}))}function U(){Ue(),(F.current===`completed`||F.current===`cancelled`)&&(B(I.current),L.current=!1),H(),V(`running`),he?.()}function W(){F.current===`running`&&(V(`paused`),ge?.())}function G(){F.current===`paused`&&(H(),V(`running`),_e?.())}function K(e){let t=y==null?1/0:y*1e3,n=Math.min(P.current+e*1e3,t);B(n),H(),g?.(e,Math.round(n/1e3)),F.current===`completed`&&n>0&&(L.current=!1,V(`running`))}function q(e){let t=Math.max(0,P.current-e*1e3);B(t),H(),ye?.(e,Math.round(t/1e3)),t<=0&&F.current===`running`&&V(`completed`)}function J(){B(I.current),V(`cancelled`),ve?.()}function We(){B(I.current),L.current=!1,V(`idle`)}ee(fe,()=>({start:U,pause:W,resume:G,addTime:K,removeTime:q,cancel:J,reset:We,getStatus:()=>F.current,getRemainingMs:()=>P.current}));let Y=50-S/2,X=te(()=>2*Math.PI*Y,[Y]),Ge=X*(1-(I.current>0?Math.min(1,j/I.current):0)),Z=Math.max(I.current*Ee,De*1e3),Q=A===`running`&&j<=Z,Ke=Q&&j<=Math.min(5e3,Z),$=A===`paused`,qe=_&&!be,Je=_&&!xe,Ye=_&&!Se,Xe=A===`running`?re:ie,Ze=A===`running`?`Pause`:$?`Resume`:A===`idle`?`Start`:`Restart`,Qe=A===`running`?W:$?G:U,$e=_&&!Ce;return d(`div`,{...Fe,className:l(a.timer,Oe&&Q&&a.timerPulsing,Ke&&a.timerCritical,Me,D?.root),style:{...x?{"--timer-size":x}:null,"--timer-stroke-width":`${S}px`,...Ne,...O?.root},children:[d(`div`,{className:l(a.timerRingWrapper,D?.ringWrapper),style:O?.ringWrapper,children:[M.length>0&&u(`div`,{className:l(a.timerRipples,D?.ripples),style:O?.ripples,children:M.map(e=>u(`span`,{className:l(a.timerRipple,D?.ripple),style:O?.ripple,onAnimationEnd:()=>He(e)},e))}),d(`svg`,{className:l(a.timerRingSvg,D?.ringSvg),viewBox:`0 0 100 100`,style:O?.ringSvg,children:[u(`circle`,{className:l(a.timerRingTrack,D?.ringTrack),cx:`50`,cy:`50`,r:Y,style:O?.ringTrack}),u(`circle`,{className:l(a.timerRingProgress,Q&&a.timerRingProgressUrgent,D?.ringProgress),cx:`50`,cy:`50`,r:Y,strokeDasharray:X,strokeDashoffset:Ge,style:{transition:$?`none`:void 0,transform:Te?`rotate(-90deg)`:void 0,...O?.ringProgress}})]}),d(`div`,{className:l(a.timerDisplay,D?.display),style:O?.display,children:[u(`span`,{className:l(a.timerTime,D?.time),style:O?.time,children:we(j)}),b&&u(`span`,{className:l(a.timerLabel,D?.label),style:O?.label,children:b})]})]}),_&&d(`div`,{className:l(a.timerControls,D?.controls),style:O?.controls,children:[d(`div`,{className:a.timerControlsRow,children:[Je&&u(i,{icon:ne,title:`Remove ${v}s`,onClick:()=>q(v),className:l(a.timerAdjustButton,D?.removeButton),style:O?.removeButton}),Ye&&u(r,{size:n.Small,icon:Xe,title:Ze,onClick:Qe,className:D?.pauseButton,style:O?.pauseButton}),qe&&u(i,{icon:ae,title:`Add ${v}s`,onClick:()=>K(v),className:l(a.timerAdjustButton,D?.addButton),style:O?.addButton})]}),$e&&u(i,{icon:oe,title:Ie.cancel,onClick:J,className:l(a.timerCancelButton,D?.cancelButton),style:O?.cancelButton})]})]})}export{f as default};
1
+ "use client";import{useComponentDefaults as e}from"../configProvider/useComponentDefaults.mjs";import{useLabels as t}from"../configProvider/useLabels.mjs";import{ButtonSize as n}from"../button/button.types.mjs";import r from"../button/button.mjs";import i from"../actionIcon/actionIcon.mjs";import"./timer.chime.mjs";import a from"./timer.module.mjs";import{useEffect as o,useImperativeHandle as ee,useMemo as te,useRef as s,useState as c}from"react";import l from"classnames";import{faMinus as ne,faPause as re,faPlay as ie,faPlus as ae,faXmark as oe}from"@fortawesome/free-solid-svg-icons";import{jsx as u,jsxs as d}from"react/jsx-runtime";var se=200,ce=1e3,le={cancel:`Cancel timer`};function ue(){return typeof window<`u`&&window.matchMedia?.(`(prefers-reduced-motion: reduce)`).matches===!0}function de(e){let t=Math.ceil(e/1e3),n=Math.floor(t/3600),r=Math.floor(t%3600/60),i=t%60,a=String(r).padStart(2,`0`),o=String(i).padStart(2,`0`);return n>0?`${n}:${a}:${o}`:`${a}:${o}`}function f(f){let{ref:fe,durationSeconds:p,autoStart:m=!0,resetOnDurationChange:pe=!0,onTick:h,onComplete:me,onStart:he,onPause:ge,onResume:_e,onCancel:ve,onAddTime:g,onRemoveTime:ye,showControls:_=!0,hideAddButton:be=!1,hideRemoveButton:xe=!1,hidePauseButton:Se=!1,hideCancelButton:Ce=!1,adjustSeconds:v=30,maxSeconds:y,label:b,formatTime:we=de,size:x,strokeWidth:S=10,counterClockwise:Te=!1,urgentThreshold:Ee=.1,urgentMinSeconds:De=3,pulseOnUrgent:Oe=!0,showRunningRipples:C=!1,playSoundOnComplete:w=!1,soundUrl:T,soundVolume:ke=.5,notifyOnComplete:E=!1,notificationTitle:Ae,notificationBody:je,className:Me,style:Ne,classNames:D,styles:O,labels:Pe,...Fe}=e(`Timer`,f),Ie=t(`Timer`,Pe,le),k=p*1e3,[A,Le]=c(m?`running`:`idle`),[j,Re]=c(k),[ze,Be]=c(0),[M,N]=c([]),P=s(j),F=s(A),I=s(k),L=s(!1),R=s(!1),z=s(!1),Ve=s(0);function B(e){P.current=e,Re(e)}function V(e){F.current=e,Le(e)}function H(){Be(e=>e+1)}o(()=>{if(A!==`running`)return;let e=Date.now(),t=P.current,n=setInterval(()=>{let n=Math.max(0,t-(Date.now()-e));B(n),h?.(n),n<=0&&V(`completed`)},se);return()=>clearInterval(n)},[A,ze]),o(()=>{if(A===`completed`&&!L.current){if(L.current=!0,me?.(),w)try{let e=new Audio(T||`data:audio/wav;base64,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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANACUAKwAKAMr/kv+R/9n/TwCxALwAVwCs/xb/8/5p/0YAFgFfAeYA3f/N/lP+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`);e.volume=ke,e.play()?.catch(()=>{})}catch{}if(E&&typeof Notification<`u`&&Notification.permission===`granted`)try{new Notification(Ae??`Timer done`,{body:je??(typeof b==`string`?b:void 0)})}catch{}}A!==`completed`&&(L.current=!1)},[A]),o(()=>{if(!z.current){z.current=!0;return}let e=p*1e3;I.current=e,B(e),L.current=!1,H(),pe&&V(m?`running`:`idle`)},[p]),o(()=>{if(!C||A!==`running`||ue())return;function e(){let e=++Ve.current;N(t=>[...t,e])}let t=setTimeout(e,0),n=setInterval(e,ce);return()=>{clearTimeout(t),clearInterval(n)}},[C,A]);function He(e){N(t=>t.filter(t=>t!==e))}function Ue(){E&&!R.current&&typeof Notification<`u`&&Notification.permission==="default"&&(R.current=!0,Notification.requestPermission().catch(()=>{}))}function U(){Ue(),(F.current===`completed`||F.current===`cancelled`)&&(B(I.current),L.current=!1),H(),V(`running`),he?.()}function W(){F.current===`running`&&(V(`paused`),ge?.())}function G(){F.current===`paused`&&(H(),V(`running`),_e?.())}function K(e){let t=y==null?1/0:y*1e3,n=Math.min(P.current+e*1e3,t);B(n),H(),g?.(e,Math.round(n/1e3)),F.current===`completed`&&n>0&&(L.current=!1,V(`running`))}function q(e){let t=Math.max(0,P.current-e*1e3);B(t),H(),ye?.(e,Math.round(t/1e3)),t<=0&&F.current===`running`&&V(`completed`)}function J(){B(I.current),V(`cancelled`),ve?.()}function We(){B(I.current),L.current=!1,V(`idle`)}ee(fe,()=>({start:U,pause:W,resume:G,addTime:K,removeTime:q,cancel:J,reset:We,getStatus:()=>F.current,getRemainingMs:()=>P.current}));let Y=50-S/2,X=te(()=>2*Math.PI*Y,[Y]),Ge=X*(1-(I.current>0?Math.min(1,j/I.current):0)),Z=Math.max(I.current*Ee,De*1e3),Q=A===`running`&&j<=Z,Ke=Q&&j<=Math.min(5e3,Z),$=A===`paused`,qe=_&&!be,Je=_&&!xe,Ye=_&&!Se,Xe=A===`running`?re:ie,Ze=A===`running`?`Pause`:$?`Resume`:A===`idle`?`Start`:`Restart`,Qe=A===`running`?W:$?G:U,$e=_&&!Ce;return d(`div`,{...Fe,className:l(a.timer,Oe&&Q&&a.timerPulsing,Ke&&a.timerCritical,Me,D?.root),style:{...x?{"--timer-size":x}:null,"--timer-stroke-width":`${S}px`,...Ne,...O?.root},children:[d(`div`,{className:l(a.timerRingWrapper,D?.ringWrapper),style:O?.ringWrapper,children:[M.length>0&&u(`div`,{className:l(a.timerRipples,D?.ripples),style:O?.ripples,children:M.map(e=>u(`span`,{className:l(a.timerRipple,D?.ripple),style:O?.ripple,onAnimationEnd:()=>He(e)},e))}),d(`svg`,{className:l(a.timerRingSvg,D?.ringSvg),viewBox:`0 0 100 100`,style:O?.ringSvg,children:[u(`circle`,{className:l(a.timerRingTrack,D?.ringTrack),cx:`50`,cy:`50`,r:Y,style:O?.ringTrack}),u(`circle`,{className:l(a.timerRingProgress,Q&&a.timerRingProgressUrgent,D?.ringProgress),cx:`50`,cy:`50`,r:Y,strokeDasharray:X,strokeDashoffset:Ge,style:{transition:$?`none`:void 0,transform:Te?`rotate(-90deg)`:void 0,...O?.ringProgress}})]}),d(`div`,{className:l(a.timerDisplay,D?.display),style:O?.display,children:[u(`span`,{className:l(a.timerTime,D?.time),style:O?.time,children:we(j)}),b&&u(`span`,{className:l(a.timerLabel,D?.label),style:O?.label,children:b})]})]}),_&&d(`div`,{className:l(a.timerControls,D?.controls),style:O?.controls,children:[d(`div`,{className:a.timerControlsRow,children:[Je&&u(i,{icon:ne,title:`Remove ${v}s`,onClick:()=>q(v),className:D?.removeButton,style:O?.removeButton}),Ye&&u(r,{size:n.Small,icon:Xe,title:Ze,onClick:Qe,className:D?.pauseButton,style:O?.pauseButton}),qe&&u(i,{icon:ae,title:`Add ${v}s`,onClick:()=>K(v),className:D?.addButton,style:O?.addButton})]}),$e&&u(i,{icon:oe,title:Ie.cancel,onClick:J,className:l(a.timerCancelButton,D?.cancelButton),style:O?.cancelButton})]})]})}export{f as default};
2
2
  //# sourceMappingURL=timer.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"timer.mjs","names":[],"sources":["../../../../package/common/timer/timer.tsx"],"sourcesContent":["import { useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';\nimport cx from 'classnames';\nimport { faPlus, faMinus, faPause, faPlay, faXmark } from '@fortawesome/free-solid-svg-icons';\n\nimport ActionIcon from '../actionIcon';\nimport Button from '../button';\nimport { ButtonSize } from '../button/button.types';\nimport { useComponentDefaults, useLabels } from '../configProvider';\nimport { DEFAULT_CHIME_DATA_URI } from './timer.chime';\nimport type { TimerLabels, TimerProps, TimerStatus } from './timer.types';\nimport styles from './timer.module.pcss';\n\nconst TICK_MS = 200;\nconst RIPPLE_SPAWN_INTERVAL_MS = 1000;\n\nconst DEFAULT_LABELS: Required<TimerLabels> = {\n cancel: 'Cancel timer',\n};\n\nfunction prefersReducedMotion(): boolean {\n return typeof window !== 'undefined' && window.matchMedia?.('(prefers-reduced-motion: reduce)').matches === true;\n}\n\nfunction formatTimeDefault(remainingMs: number) {\n const totalSeconds = Math.ceil(remainingMs / 1000);\n const hours = Math.floor(totalSeconds / 3600);\n const minutes = Math.floor((totalSeconds % 3600) / 60);\n const seconds = totalSeconds % 60;\n const mm = String(minutes).padStart(2, '0');\n const ss = String(seconds).padStart(2, '0');\n return hours > 0 ? `${hours}:${mm}:${ss}` : `${mm}:${ss}`;\n}\n\nfunction Timer(props: TimerProps) {\n const {\n ref,\n durationSeconds,\n autoStart = true,\n resetOnDurationChange = true,\n\n onTick,\n onComplete,\n onStart,\n onPause,\n onResume,\n onCancel,\n onAddTime,\n onRemoveTime,\n\n showControls = true,\n hideAddButton = false,\n hideRemoveButton = false,\n hidePauseButton = false,\n hideCancelButton = false,\n adjustSeconds = 30,\n maxSeconds,\n\n label,\n formatTime = formatTimeDefault,\n size,\n strokeWidth = 10,\n counterClockwise = false,\n\n urgentThreshold = 0.1,\n urgentMinSeconds = 3,\n pulseOnUrgent = true,\n showRunningRipples = false,\n\n playSoundOnComplete = false,\n soundUrl,\n soundVolume = 0.5,\n notifyOnComplete = false,\n notificationTitle,\n notificationBody,\n\n className,\n style,\n classNames,\n styles: slotStyles,\n labels,\n ...rest\n } = useComponentDefaults('Timer', props);\n const text = useLabels('Timer', labels, DEFAULT_LABELS);\n\n const initialMs = durationSeconds * 1000;\n const [status, setStatusState] = useState<TimerStatus>(autoStart ? 'running' : 'idle');\n const [remainingMs, setRemainingMsState] = useState(initialMs);\n const [epoch, setEpoch] = useState(0);\n const [ripples, setRipples] = useState<number[]>([]);\n\n const remainingRef = useRef(remainingMs);\n const statusRef = useRef(status);\n const totalMsRef = useRef(initialMs);\n const completedFiredRef = useRef(false);\n const notifyPermissionRequestedRef = useRef(false);\n const mountedRef = useRef(false);\n const rippleIdRef = useRef(0);\n\n function setRemaining(next: number) {\n remainingRef.current = next;\n setRemainingMsState(next);\n }\n\n function setStatus(next: TimerStatus) {\n statusRef.current = next;\n setStatusState(next);\n }\n\n function bumpEpoch() {\n setEpoch((e) => e + 1);\n }\n\n // Ticking effect. Re-derives the remaining time from Date.now() every tick (rather than\n // accumulating setInterval's own drift), so it stays accurate over long countdowns. Any\n // external mutation of remainingRef (addTime/removeTime while already running, or a resume)\n // must bump `epoch` so this effect re-arms and re-captures a fresh start/startRemaining —\n // without that, a stale `startRemaining` captured before the mutation would silently\n // overwrite it on the next tick.\n useEffect(() => {\n if (status !== 'running') return undefined;\n const start = Date.now();\n const startRemaining = remainingRef.current;\n const id = setInterval(() => {\n const next = Math.max(0, startRemaining - (Date.now() - start));\n setRemaining(next);\n onTick?.(next);\n if (next <= 0) setStatus('completed');\n }, TICK_MS);\n return () => clearInterval(id);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [status, epoch]);\n\n // Fires onComplete exactly once per completion, plus the opt-in sound/notification.\n useEffect(() => {\n if (status === 'completed' && !completedFiredRef.current) {\n completedFiredRef.current = true;\n onComplete?.();\n if (playSoundOnComplete) {\n try {\n const audio = new Audio(soundUrl || DEFAULT_CHIME_DATA_URI);\n audio.volume = soundVolume;\n // play() can reject (autoplay policy) or, in some environments, return undefined\n // instead of a Promise — never let a blocked/unsupported playback surface as an error.\n audio.play()?.catch(() => {});\n } catch {\n // Audio unavailable/unsupported — fail silently.\n }\n }\n if (notifyOnComplete && typeof Notification !== 'undefined' && Notification.permission === 'granted') {\n try {\n new Notification(notificationTitle ?? 'Timer done', {\n body: notificationBody ?? (typeof label === 'string' ? label : undefined),\n });\n } catch {\n // Some browsers (e.g. certain mobile Safari versions) throw constructing\n // Notification outside specific contexts — fail silently, as documented.\n }\n }\n }\n if (status !== 'completed') completedFiredRef.current = false;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [status]);\n\n // durationSeconds prop change: reset (and optionally restart) at the new duration. Skips\n // the initial mount, since autoStart/initial state already cover that.\n useEffect(() => {\n if (!mountedRef.current) {\n mountedRef.current = true;\n return;\n }\n const nextMs = durationSeconds * 1000;\n totalMsRef.current = nextMs;\n setRemaining(nextMs);\n completedFiredRef.current = false;\n bumpEpoch();\n if (resetOnDurationChange) {\n setStatus(autoStart ? 'running' : 'idle');\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [durationSeconds]);\n\n // Running-ripple spawner: spawns a new ripple roughly every RIPPLE_SPAWN_INTERVAL_MS while\n // running, each animating once (via CSS, `forwards`) and removing itself on `onAnimationEnd`.\n // Pausing (or otherwise leaving `running`) only stops new spawns here — it doesn't touch\n // `ripples` — so whichever ripples are already mid-flight keep animating to completion\n // instead of vanishing mid-cycle.\n useEffect(() => {\n if (!showRunningRipples || status !== 'running' || prefersReducedMotion()) return undefined;\n function spawnRipple() {\n // Read now, not in the updater: two spawns before a render would both see the later id.\n const rippleId = ++rippleIdRef.current;\n setRipples((prev) => [...prev, rippleId]);\n }\n // A timer, so the cleanup cancels it too: StrictMode's second mount stacked a second ripple.\n const first = setTimeout(spawnRipple, 0);\n const id = setInterval(spawnRipple, RIPPLE_SPAWN_INTERVAL_MS);\n return () => {\n clearTimeout(first);\n clearInterval(id);\n };\n }, [showRunningRipples, status]);\n\n function handleRippleAnimationEnd(id: number) {\n setRipples((prev) => prev.filter((existingId) => existingId !== id));\n }\n\n function requestNotificationPermissionIfNeeded() {\n if (!notifyOnComplete || notifyPermissionRequestedRef.current) return;\n if (typeof Notification === 'undefined' || Notification.permission !== 'default') return;\n notifyPermissionRequestedRef.current = true;\n Notification.requestPermission().catch(() => {});\n }\n\n function start() {\n requestNotificationPermissionIfNeeded();\n if (statusRef.current === 'completed' || statusRef.current === 'cancelled') {\n setRemaining(totalMsRef.current);\n completedFiredRef.current = false;\n }\n bumpEpoch();\n setStatus('running');\n onStart?.();\n }\n\n function pause() {\n if (statusRef.current !== 'running') return;\n setStatus('paused');\n onPause?.();\n }\n\n function resume() {\n if (statusRef.current !== 'paused') return;\n bumpEpoch();\n setStatus('running');\n onResume?.();\n }\n\n function addTime(seconds: number) {\n const capped = maxSeconds != null ? maxSeconds * 1000 : Infinity;\n const next = Math.min(remainingRef.current + seconds * 1000, capped);\n setRemaining(next);\n bumpEpoch();\n onAddTime?.(seconds, Math.round(next / 1000));\n if (statusRef.current === 'completed' && next > 0) {\n completedFiredRef.current = false;\n setStatus('running');\n }\n }\n\n function removeTime(seconds: number) {\n const next = Math.max(0, remainingRef.current - seconds * 1000);\n setRemaining(next);\n bumpEpoch();\n onRemoveTime?.(seconds, Math.round(next / 1000));\n if (next <= 0 && statusRef.current === 'running') setStatus('completed');\n }\n\n function cancel() {\n setRemaining(totalMsRef.current);\n setStatus('cancelled');\n onCancel?.();\n }\n\n function reset() {\n setRemaining(totalMsRef.current);\n completedFiredRef.current = false;\n setStatus('idle');\n }\n\n useImperativeHandle(ref, () => ({\n start,\n pause,\n resume,\n addTime,\n removeTime,\n cancel,\n reset,\n getStatus: () => statusRef.current,\n getRemainingMs: () => remainingRef.current,\n }));\n\n const radius = 50 - strokeWidth / 2;\n const circumference = useMemo(() => 2 * Math.PI * radius, [radius]);\n const clampedFraction = totalMsRef.current > 0 ? Math.min(1, remainingMs / totalMsRef.current) : 0;\n const dashOffset = circumference * (1 - clampedFraction);\n const urgentMs = Math.max(totalMsRef.current * urgentThreshold, urgentMinSeconds * 1000);\n const isUrgent = status === 'running' && remainingMs <= urgentMs;\n const isCritical = isUrgent && remainingMs <= Math.min(5000, urgentMs);\n const isPaused = status === 'paused';\n\n // The pause button doubles as a play/restart button whenever there's nothing to pause —\n // idle (autoStart={false}), completed, or cancelled — rather than hiding itself, so there's\n // always a way to (re)start the countdown from the built-in controls alone.\n const showAddButton = showControls && !hideAddButton;\n const showRemoveButton = showControls && !hideRemoveButton;\n const showPauseButton = showControls && !hidePauseButton;\n const pauseButtonIcon = status === 'running' ? faPause : faPlay;\n const pauseButtonTitle =\n status === 'running' ? 'Pause' : isPaused ? 'Resume' : status === 'idle' ? 'Start' : 'Restart';\n const handlePauseButtonClick = status === 'running' ? pause : isPaused ? resume : start;\n const showCancelButton = showControls && !hideCancelButton;\n\n return (\n <div\n {...rest}\n className={cx(\n styles.timer,\n pulseOnUrgent && isUrgent && styles.timerPulsing,\n isCritical && styles.timerCritical,\n className,\n classNames?.root,\n )}\n style={\n {\n ...(size ? { '--timer-size': size } : null),\n '--timer-stroke-width': `${strokeWidth}px`,\n ...style,\n ...slotStyles?.root,\n } as React.CSSProperties\n }\n >\n <div className={cx(styles.timerRingWrapper, classNames?.ringWrapper)} style={slotStyles?.ringWrapper}>\n {ripples.length > 0 && (\n <div className={cx(styles.timerRipples, classNames?.ripples)} style={slotStyles?.ripples}>\n {ripples.map((id) => (\n <span\n key={id}\n className={cx(styles.timerRipple, classNames?.ripple)}\n style={slotStyles?.ripple}\n onAnimationEnd={() => handleRippleAnimationEnd(id)}\n />\n ))}\n </div>\n )}\n <svg className={cx(styles.timerRingSvg, classNames?.ringSvg)} viewBox='0 0 100 100' style={slotStyles?.ringSvg}>\n <circle\n className={cx(styles.timerRingTrack, classNames?.ringTrack)}\n cx='50'\n cy='50'\n r={radius}\n style={slotStyles?.ringTrack}\n />\n <circle\n className={cx(\n styles.timerRingProgress,\n isUrgent && styles.timerRingProgressUrgent,\n classNames?.ringProgress,\n )}\n cx='50'\n cy='50'\n r={radius}\n strokeDasharray={circumference}\n strokeDashoffset={dashOffset}\n style={{\n transition: isPaused ? 'none' : undefined,\n transform: counterClockwise ? 'rotate(-90deg)' : undefined,\n ...slotStyles?.ringProgress,\n }}\n />\n </svg>\n <div className={cx(styles.timerDisplay, classNames?.display)} style={slotStyles?.display}>\n <span className={cx(styles.timerTime, classNames?.time)} style={slotStyles?.time}>\n {formatTime(remainingMs)}\n </span>\n {label && (\n <span className={cx(styles.timerLabel, classNames?.label)} style={slotStyles?.label}>\n {label}\n </span>\n )}\n </div>\n </div>\n\n {showControls && (\n <div className={cx(styles.timerControls, classNames?.controls)} style={slotStyles?.controls}>\n <div className={styles.timerControlsRow}>\n {showRemoveButton && (\n <ActionIcon\n icon={faMinus}\n title={`Remove ${adjustSeconds}s`}\n onClick={() => removeTime(adjustSeconds)}\n className={cx(styles.timerAdjustButton, classNames?.removeButton)}\n style={slotStyles?.removeButton}\n />\n )}\n {showPauseButton && (\n <Button\n size={ButtonSize.Small}\n icon={pauseButtonIcon}\n title={pauseButtonTitle}\n onClick={handlePauseButtonClick}\n className={classNames?.pauseButton}\n style={slotStyles?.pauseButton}\n />\n )}\n {showAddButton && (\n <ActionIcon\n icon={faPlus}\n title={`Add ${adjustSeconds}s`}\n onClick={() => addTime(adjustSeconds)}\n className={cx(styles.timerAdjustButton, classNames?.addButton)}\n style={slotStyles?.addButton}\n />\n )}\n </div>\n {showCancelButton && (\n <ActionIcon\n icon={faXmark}\n title={text.cancel}\n onClick={cancel}\n className={cx(styles.timerCancelButton, classNames?.cancelButton)}\n style={slotStyles?.cancelButton}\n />\n )}\n </div>\n )}\n </div>\n );\n}\n\nexport default Timer;\n"],"mappings":"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"}
1
+ {"version":3,"file":"timer.mjs","names":[],"sources":["../../../../package/common/timer/timer.tsx"],"sourcesContent":["import { useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';\nimport cx from 'classnames';\nimport { faPlus, faMinus, faPause, faPlay, faXmark } from '@fortawesome/free-solid-svg-icons';\n\nimport ActionIcon from '../actionIcon';\nimport Button from '../button';\nimport { ButtonSize } from '../button/button.types';\nimport { useComponentDefaults, useLabels } from '../configProvider';\nimport { DEFAULT_CHIME_DATA_URI } from './timer.chime';\nimport type { TimerLabels, TimerProps, TimerStatus } from './timer.types';\nimport styles from './timer.module.pcss';\n\nconst TICK_MS = 200;\nconst RIPPLE_SPAWN_INTERVAL_MS = 1000;\n\nconst DEFAULT_LABELS: Required<TimerLabels> = {\n cancel: 'Cancel timer',\n};\n\nfunction prefersReducedMotion(): boolean {\n return typeof window !== 'undefined' && window.matchMedia?.('(prefers-reduced-motion: reduce)').matches === true;\n}\n\nfunction formatTimeDefault(remainingMs: number) {\n const totalSeconds = Math.ceil(remainingMs / 1000);\n const hours = Math.floor(totalSeconds / 3600);\n const minutes = Math.floor((totalSeconds % 3600) / 60);\n const seconds = totalSeconds % 60;\n const mm = String(minutes).padStart(2, '0');\n const ss = String(seconds).padStart(2, '0');\n return hours > 0 ? `${hours}:${mm}:${ss}` : `${mm}:${ss}`;\n}\n\nfunction Timer(props: TimerProps) {\n const {\n ref,\n durationSeconds,\n autoStart = true,\n resetOnDurationChange = true,\n\n onTick,\n onComplete,\n onStart,\n onPause,\n onResume,\n onCancel,\n onAddTime,\n onRemoveTime,\n\n showControls = true,\n hideAddButton = false,\n hideRemoveButton = false,\n hidePauseButton = false,\n hideCancelButton = false,\n adjustSeconds = 30,\n maxSeconds,\n\n label,\n formatTime = formatTimeDefault,\n size,\n strokeWidth = 10,\n counterClockwise = false,\n\n urgentThreshold = 0.1,\n urgentMinSeconds = 3,\n pulseOnUrgent = true,\n showRunningRipples = false,\n\n playSoundOnComplete = false,\n soundUrl,\n soundVolume = 0.5,\n notifyOnComplete = false,\n notificationTitle,\n notificationBody,\n\n className,\n style,\n classNames,\n styles: slotStyles,\n labels,\n ...rest\n } = useComponentDefaults('Timer', props);\n const text = useLabels('Timer', labels, DEFAULT_LABELS);\n\n const initialMs = durationSeconds * 1000;\n const [status, setStatusState] = useState<TimerStatus>(autoStart ? 'running' : 'idle');\n const [remainingMs, setRemainingMsState] = useState(initialMs);\n const [epoch, setEpoch] = useState(0);\n const [ripples, setRipples] = useState<number[]>([]);\n\n const remainingRef = useRef(remainingMs);\n const statusRef = useRef(status);\n const totalMsRef = useRef(initialMs);\n const completedFiredRef = useRef(false);\n const notifyPermissionRequestedRef = useRef(false);\n const mountedRef = useRef(false);\n const rippleIdRef = useRef(0);\n\n function setRemaining(next: number) {\n remainingRef.current = next;\n setRemainingMsState(next);\n }\n\n function setStatus(next: TimerStatus) {\n statusRef.current = next;\n setStatusState(next);\n }\n\n function bumpEpoch() {\n setEpoch((e) => e + 1);\n }\n\n // Ticking effect. Re-derives the remaining time from Date.now() every tick (rather than\n // accumulating setInterval's own drift), so it stays accurate over long countdowns. Any\n // external mutation of remainingRef (addTime/removeTime while already running, or a resume)\n // must bump `epoch` so this effect re-arms and re-captures a fresh start/startRemaining —\n // without that, a stale `startRemaining` captured before the mutation would silently\n // overwrite it on the next tick.\n useEffect(() => {\n if (status !== 'running') return undefined;\n const start = Date.now();\n const startRemaining = remainingRef.current;\n const id = setInterval(() => {\n const next = Math.max(0, startRemaining - (Date.now() - start));\n setRemaining(next);\n onTick?.(next);\n if (next <= 0) setStatus('completed');\n }, TICK_MS);\n return () => clearInterval(id);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [status, epoch]);\n\n // Fires onComplete exactly once per completion, plus the opt-in sound/notification.\n useEffect(() => {\n if (status === 'completed' && !completedFiredRef.current) {\n completedFiredRef.current = true;\n onComplete?.();\n if (playSoundOnComplete) {\n try {\n const audio = new Audio(soundUrl || DEFAULT_CHIME_DATA_URI);\n audio.volume = soundVolume;\n // play() can reject (autoplay policy) or, in some environments, return undefined\n // instead of a Promise — never let a blocked/unsupported playback surface as an error.\n audio.play()?.catch(() => {});\n } catch {\n // Audio unavailable/unsupported — fail silently.\n }\n }\n if (notifyOnComplete && typeof Notification !== 'undefined' && Notification.permission === 'granted') {\n try {\n new Notification(notificationTitle ?? 'Timer done', {\n body: notificationBody ?? (typeof label === 'string' ? label : undefined),\n });\n } catch {\n // Some browsers (e.g. certain mobile Safari versions) throw constructing\n // Notification outside specific contexts — fail silently, as documented.\n }\n }\n }\n if (status !== 'completed') completedFiredRef.current = false;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [status]);\n\n // durationSeconds prop change: reset (and optionally restart) at the new duration. Skips\n // the initial mount, since autoStart/initial state already cover that.\n useEffect(() => {\n if (!mountedRef.current) {\n mountedRef.current = true;\n return;\n }\n const nextMs = durationSeconds * 1000;\n totalMsRef.current = nextMs;\n setRemaining(nextMs);\n completedFiredRef.current = false;\n bumpEpoch();\n if (resetOnDurationChange) {\n setStatus(autoStart ? 'running' : 'idle');\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [durationSeconds]);\n\n // Running-ripple spawner: spawns a new ripple roughly every RIPPLE_SPAWN_INTERVAL_MS while\n // running, each animating once (via CSS, `forwards`) and removing itself on `onAnimationEnd`.\n // Pausing (or otherwise leaving `running`) only stops new spawns here — it doesn't touch\n // `ripples` — so whichever ripples are already mid-flight keep animating to completion\n // instead of vanishing mid-cycle.\n useEffect(() => {\n if (!showRunningRipples || status !== 'running' || prefersReducedMotion()) return undefined;\n function spawnRipple() {\n // Read now, not in the updater: two spawns before a render would both see the later id.\n const rippleId = ++rippleIdRef.current;\n setRipples((prev) => [...prev, rippleId]);\n }\n // A timer, so the cleanup cancels it too: StrictMode's second mount stacked a second ripple.\n const first = setTimeout(spawnRipple, 0);\n const id = setInterval(spawnRipple, RIPPLE_SPAWN_INTERVAL_MS);\n return () => {\n clearTimeout(first);\n clearInterval(id);\n };\n }, [showRunningRipples, status]);\n\n function handleRippleAnimationEnd(id: number) {\n setRipples((prev) => prev.filter((existingId) => existingId !== id));\n }\n\n function requestNotificationPermissionIfNeeded() {\n if (!notifyOnComplete || notifyPermissionRequestedRef.current) return;\n if (typeof Notification === 'undefined' || Notification.permission !== 'default') return;\n notifyPermissionRequestedRef.current = true;\n Notification.requestPermission().catch(() => {});\n }\n\n function start() {\n requestNotificationPermissionIfNeeded();\n if (statusRef.current === 'completed' || statusRef.current === 'cancelled') {\n setRemaining(totalMsRef.current);\n completedFiredRef.current = false;\n }\n bumpEpoch();\n setStatus('running');\n onStart?.();\n }\n\n function pause() {\n if (statusRef.current !== 'running') return;\n setStatus('paused');\n onPause?.();\n }\n\n function resume() {\n if (statusRef.current !== 'paused') return;\n bumpEpoch();\n setStatus('running');\n onResume?.();\n }\n\n function addTime(seconds: number) {\n const capped = maxSeconds != null ? maxSeconds * 1000 : Infinity;\n const next = Math.min(remainingRef.current + seconds * 1000, capped);\n setRemaining(next);\n bumpEpoch();\n onAddTime?.(seconds, Math.round(next / 1000));\n if (statusRef.current === 'completed' && next > 0) {\n completedFiredRef.current = false;\n setStatus('running');\n }\n }\n\n function removeTime(seconds: number) {\n const next = Math.max(0, remainingRef.current - seconds * 1000);\n setRemaining(next);\n bumpEpoch();\n onRemoveTime?.(seconds, Math.round(next / 1000));\n if (next <= 0 && statusRef.current === 'running') setStatus('completed');\n }\n\n function cancel() {\n setRemaining(totalMsRef.current);\n setStatus('cancelled');\n onCancel?.();\n }\n\n function reset() {\n setRemaining(totalMsRef.current);\n completedFiredRef.current = false;\n setStatus('idle');\n }\n\n useImperativeHandle(ref, () => ({\n start,\n pause,\n resume,\n addTime,\n removeTime,\n cancel,\n reset,\n getStatus: () => statusRef.current,\n getRemainingMs: () => remainingRef.current,\n }));\n\n const radius = 50 - strokeWidth / 2;\n const circumference = useMemo(() => 2 * Math.PI * radius, [radius]);\n const clampedFraction = totalMsRef.current > 0 ? Math.min(1, remainingMs / totalMsRef.current) : 0;\n const dashOffset = circumference * (1 - clampedFraction);\n const urgentMs = Math.max(totalMsRef.current * urgentThreshold, urgentMinSeconds * 1000);\n const isUrgent = status === 'running' && remainingMs <= urgentMs;\n const isCritical = isUrgent && remainingMs <= Math.min(5000, urgentMs);\n const isPaused = status === 'paused';\n\n // The pause button doubles as a play/restart button whenever there's nothing to pause —\n // idle (autoStart={false}), completed, or cancelled — rather than hiding itself, so there's\n // always a way to (re)start the countdown from the built-in controls alone.\n const showAddButton = showControls && !hideAddButton;\n const showRemoveButton = showControls && !hideRemoveButton;\n const showPauseButton = showControls && !hidePauseButton;\n const pauseButtonIcon = status === 'running' ? faPause : faPlay;\n const pauseButtonTitle =\n status === 'running' ? 'Pause' : isPaused ? 'Resume' : status === 'idle' ? 'Start' : 'Restart';\n const handlePauseButtonClick = status === 'running' ? pause : isPaused ? resume : start;\n const showCancelButton = showControls && !hideCancelButton;\n\n return (\n <div\n {...rest}\n className={cx(\n styles.timer,\n pulseOnUrgent && isUrgent && styles.timerPulsing,\n isCritical && styles.timerCritical,\n className,\n classNames?.root,\n )}\n style={\n {\n ...(size ? { '--timer-size': size } : null),\n '--timer-stroke-width': `${strokeWidth}px`,\n ...style,\n ...slotStyles?.root,\n } as React.CSSProperties\n }\n >\n <div className={cx(styles.timerRingWrapper, classNames?.ringWrapper)} style={slotStyles?.ringWrapper}>\n {ripples.length > 0 && (\n <div className={cx(styles.timerRipples, classNames?.ripples)} style={slotStyles?.ripples}>\n {ripples.map((id) => (\n <span\n key={id}\n className={cx(styles.timerRipple, classNames?.ripple)}\n style={slotStyles?.ripple}\n onAnimationEnd={() => handleRippleAnimationEnd(id)}\n />\n ))}\n </div>\n )}\n <svg className={cx(styles.timerRingSvg, classNames?.ringSvg)} viewBox='0 0 100 100' style={slotStyles?.ringSvg}>\n <circle\n className={cx(styles.timerRingTrack, classNames?.ringTrack)}\n cx='50'\n cy='50'\n r={radius}\n style={slotStyles?.ringTrack}\n />\n <circle\n className={cx(\n styles.timerRingProgress,\n isUrgent && styles.timerRingProgressUrgent,\n classNames?.ringProgress,\n )}\n cx='50'\n cy='50'\n r={radius}\n strokeDasharray={circumference}\n strokeDashoffset={dashOffset}\n style={{\n transition: isPaused ? 'none' : undefined,\n transform: counterClockwise ? 'rotate(-90deg)' : undefined,\n ...slotStyles?.ringProgress,\n }}\n />\n </svg>\n <div className={cx(styles.timerDisplay, classNames?.display)} style={slotStyles?.display}>\n <span className={cx(styles.timerTime, classNames?.time)} style={slotStyles?.time}>\n {formatTime(remainingMs)}\n </span>\n {label && (\n <span className={cx(styles.timerLabel, classNames?.label)} style={slotStyles?.label}>\n {label}\n </span>\n )}\n </div>\n </div>\n\n {showControls && (\n <div className={cx(styles.timerControls, classNames?.controls)} style={slotStyles?.controls}>\n <div className={styles.timerControlsRow}>\n {showRemoveButton && (\n <ActionIcon\n icon={faMinus}\n title={`Remove ${adjustSeconds}s`}\n onClick={() => removeTime(adjustSeconds)}\n className={classNames?.removeButton}\n style={slotStyles?.removeButton}\n />\n )}\n {showPauseButton && (\n <Button\n size={ButtonSize.Small}\n icon={pauseButtonIcon}\n title={pauseButtonTitle}\n onClick={handlePauseButtonClick}\n className={classNames?.pauseButton}\n style={slotStyles?.pauseButton}\n />\n )}\n {showAddButton && (\n <ActionIcon\n icon={faPlus}\n title={`Add ${adjustSeconds}s`}\n onClick={() => addTime(adjustSeconds)}\n className={classNames?.addButton}\n style={slotStyles?.addButton}\n />\n )}\n </div>\n {showCancelButton && (\n <ActionIcon\n icon={faXmark}\n title={text.cancel}\n onClick={cancel}\n className={cx(styles.timerCancelButton, classNames?.cancelButton)}\n style={slotStyles?.cancelButton}\n />\n )}\n </div>\n )}\n </div>\n );\n}\n\nexport default Timer;\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use client";var e=`timer_cqe3R`,t=`timer-ringWrapper_OydlE`,n=`timer-ringSvg_qsV1X`,r=`timer-ripples_2Slkv`,i=`timer-ripple_TLdSx`,a=`timerRippleHalo_oEcXJ`,o=`timer-ringTrack_pGGs1`,s=`timer-ringProgress_LL8uQ`,c=`timer-ringProgress-urgent_MwwU2`,l=`timer-display_es2IX`,u=`timer-time_oMZ5O`,d=`timer-label_GknS-`,f=`timer-controls_LHM4q`,p=`timer-controlsRow_42JyZ`,m=`timer-adjustButton_QMxrI`,h=`timer-cancelButton_ObL4-`,g=`timer-pulsing_795m4`,_=`timerHeartbeat_N40Zt`,v=`timer-critical_q-JzB`,y={timer:e,"timer-ringWrapper":`timer-ringWrapper_OydlE`,timerRingWrapper:t,"timer-ringSvg":`timer-ringSvg_qsV1X`,timerRingSvg:n,"timer-ripples":`timer-ripples_2Slkv`,timerRipples:r,"timer-ripple":`timer-ripple_TLdSx`,timerRipple:i,timerRippleHalo:a,"timer-ringTrack":`timer-ringTrack_pGGs1`,timerRingTrack:o,"timer-ringProgress":`timer-ringProgress_LL8uQ`,timerRingProgress:s,"timer-ringProgress-urgent":`timer-ringProgress-urgent_MwwU2`,timerRingProgressUrgent:c,"timer-display":`timer-display_es2IX`,timerDisplay:l,"timer-time":`timer-time_oMZ5O`,timerTime:u,"timer-label":`timer-label_GknS-`,timerLabel:d,"timer-controls":`timer-controls_LHM4q`,timerControls:f,"timer-controlsRow":`timer-controlsRow_42JyZ`,timerControlsRow:p,"timer-adjustButton":`timer-adjustButton_QMxrI`,timerAdjustButton:m,"timer-cancelButton":`timer-cancelButton_ObL4-`,timerCancelButton:h,"timer-pulsing":`timer-pulsing_795m4`,timerPulsing:g,timerHeartbeat:_,"timer-critical":`timer-critical_q-JzB`,timerCritical:v};export{y as default,e as timer,m as timerAdjustButton,h as timerCancelButton,f as timerControls,p as timerControlsRow,v as timerCritical,l as timerDisplay,_ as timerHeartbeat,d as timerLabel,g as timerPulsing,s as timerRingProgress,c as timerRingProgressUrgent,n as timerRingSvg,o as timerRingTrack,t as timerRingWrapper,i as timerRipple,a as timerRippleHalo,r as timerRipples,u as timerTime};
1
+ "use client";var e=`timer_cqe3R`,t=`timer-ringWrapper_OydlE`,n=`timer-ringSvg_qsV1X`,r=`timer-ripples_2Slkv`,i=`timer-ripple_TLdSx`,a=`timerRippleHalo_oEcXJ`,o=`timer-ringTrack_pGGs1`,s=`timer-ringProgress_LL8uQ`,c=`timer-ringProgress-urgent_MwwU2`,l=`timer-display_es2IX`,u=`timer-time_oMZ5O`,d=`timer-label_GknS-`,f=`timer-controls_LHM4q`,p=`timer-controlsRow_42JyZ`,m=`timer-cancelButton_ObL4-`,h=`timer-pulsing_795m4`,g=`timerHeartbeat_N40Zt`,_=`timer-critical_q-JzB`,v={timer:e,"timer-ringWrapper":`timer-ringWrapper_OydlE`,timerRingWrapper:t,"timer-ringSvg":`timer-ringSvg_qsV1X`,timerRingSvg:n,"timer-ripples":`timer-ripples_2Slkv`,timerRipples:r,"timer-ripple":`timer-ripple_TLdSx`,timerRipple:i,timerRippleHalo:a,"timer-ringTrack":`timer-ringTrack_pGGs1`,timerRingTrack:o,"timer-ringProgress":`timer-ringProgress_LL8uQ`,timerRingProgress:s,"timer-ringProgress-urgent":`timer-ringProgress-urgent_MwwU2`,timerRingProgressUrgent:c,"timer-display":`timer-display_es2IX`,timerDisplay:l,"timer-time":`timer-time_oMZ5O`,timerTime:u,"timer-label":`timer-label_GknS-`,timerLabel:d,"timer-controls":`timer-controls_LHM4q`,timerControls:f,"timer-controlsRow":`timer-controlsRow_42JyZ`,timerControlsRow:p,"timer-cancelButton":`timer-cancelButton_ObL4-`,timerCancelButton:m,"timer-pulsing":`timer-pulsing_795m4`,timerPulsing:h,timerHeartbeat:g,"timer-critical":`timer-critical_q-JzB`,timerCritical:_};export{v as default,e as timer,m as timerCancelButton,f as timerControls,p as timerControlsRow,_ as timerCritical,l as timerDisplay,g as timerHeartbeat,d as timerLabel,h as timerPulsing,s as timerRingProgress,c as timerRingProgressUrgent,n as timerRingSvg,o as timerRingTrack,t as timerRingWrapper,i as timerRipple,a as timerRippleHalo,r as timerRipples,u as timerTime};
2
2
  //# sourceMappingURL=timer.module.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"timer.module.mjs","names":[],"sources":["../../../../package/common/timer/timer.module.pcss"],"sourcesContent":[".timer {\n /* em, because the readout inside the ring is em too: a fixed ring stayed put while its own\n digits grew with the theme until they filled it. */\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 1em;\n width: fit-content;\n\n &-ringWrapper {\n position: relative;\n width: var(--timer-size, 10em);\n height: var(--timer-size, 10em);\n transform-origin: center;\n }\n\n &-ringSvg {\n position: relative;\n width: 100%;\n height: 100%;\n overflow: visible;\n }\n\n &-ripples {\n position: absolute;\n inset: 0;\n pointer-events: none;\n }\n\n &-ripple {\n position: absolute;\n inset: 0;\n border-radius: 50%;\n border: 0.125em solid var(--timer-ripple-color, var(--timer-progress-color, var(--primary-color)));\n opacity: 0;\n transform: scale(0.94);\n\n /* One-shot per spawned instance (see the ripple spawner in timer.tsx), not an infinite\n loop — so pausing simply stops new spawns while already-mid-flight ripples keep\n animating to completion via `forwards` instead of vanishing mid-cycle. */\n animation: timerRippleHalo 3s ease-out forwards;\n }\n\n /* Not em, unlike everything else here: inside the svg this is a viewBox user unit, so it\n already scales with the ring, and it has to stay equal to the `strokeWidth` prop that\n timer.tsx subtracts from the circle's radius. */\n &-ringTrack {\n fill: none;\n stroke: var(--timer-track-color, var(--background-accent-light));\n stroke-width: var(--timer-stroke-width, 10px);\n }\n\n &-ringProgress {\n fill: none;\n stroke: var(--timer-progress-color, var(--primary-color));\n stroke-width: var(--timer-stroke-width, 10px);\n stroke-linecap: round;\n\n /* Single combined transform, not split across an SVG `transform` attribute on this element\n plus a separate CSS transform on an ancestor — that split combination, together with an\n actively-transitioning stroke-dashoffset, is a known trigger for SVG dash-rendering glitches\n in some engines (the visible arc appearing to jump/drift independent of the actual\n dashoffset value). scaleX(-1) mirrors so the depleting boundary sweeps clockwise (matching\n a clock face) instead of the counter-clockwise direction a <circle>'s implicit path winds\n by default; rotate(-90deg) moves the fixed anchor from 3 o'clock to 12 o'clock. Both applied\n around the circle's own center, which coincides with the viewBox center here. `counterClockwise`\n overrides this inline (timer.tsx) by dropping the scaleX(-1), keeping just the rotate — that\n default winding direction is exactly counter-clockwise, so no mirroring is needed for it. */\n transform: scaleX(-1) rotate(-90deg);\n transform-origin: 50% 50%;\n\n /* Matches (slightly exceeds) the JS tick interval (TICK_MS in timer.tsx) so the ring\n tracks the real remaining time closely instead of perpetually chasing a target that's\n always a full second stale — a much longer transition here reads as sluggish since the\n rendered ring never catches up to the true value while ticking continues. */\n transition:\n stroke-dashoffset 220ms linear,\n stroke 0.3s ease;\n\n &-urgent {\n stroke: var(--timer-urgent-color, var(--error-color));\n }\n }\n\n &-display {\n position: absolute;\n inset: 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n text-align: center;\n padding: 0 0.75em;\n }\n\n &-time {\n font-size: 1.4em;\n font-weight: 600;\n font-variant-numeric: tabular-nums;\n color: var(--timer-text-color, var(--text-color));\n }\n\n &-label {\n margin-top: 0.25em;\n font-size: 0.8em;\n color: var(--timer-label-color, var(--text-dark));\n }\n\n &-controls {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 0.5em;\n }\n\n &-controlsRow {\n display: flex;\n align-items: center;\n gap: 0.5em;\n }\n\n &-adjustButton {\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n }\n\n &-cancelButton {\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n opacity: 0.6;\n\n &:hover {\n opacity: 1;\n }\n }\n\n &-pulsing &-ringWrapper {\n animation: timerHeartbeat 1s ease-in-out infinite;\n }\n\n &-critical &-ringWrapper {\n animation-duration: 0.6s;\n }\n}\n\n@keyframes timerHeartbeat {\n 0%,\n 100% {\n transform: scale(1);\n }\n\n 50% {\n transform: scale(1.045);\n }\n}\n\n@keyframes timerRippleHalo {\n 0% {\n transform: scale(0.94);\n opacity: 0.5;\n }\n\n 100% {\n transform: scale(1.35);\n opacity: 0;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .timer-ringProgress {\n transition: stroke 0.3s ease;\n }\n\n .timer-pulsing .timer-ringWrapper {\n animation: none;\n }\n\n .timer-ripple {\n animation: none;\n opacity: 0;\n }\n}\n"],"mappings":""}
1
+ {"version":3,"file":"timer.module.mjs","names":[],"sources":["../../../../package/common/timer/timer.module.pcss"],"sourcesContent":[".timer {\n /* em, because the readout inside the ring is em too: a fixed ring stayed put while its own\n digits grew with the theme until they filled it. */\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 1em;\n width: fit-content;\n\n &-ringWrapper {\n position: relative;\n width: var(--timer-size, 10em);\n height: var(--timer-size, 10em);\n transform-origin: center;\n }\n\n &-ringSvg {\n position: relative;\n width: 100%;\n height: 100%;\n overflow: visible;\n }\n\n &-ripples {\n position: absolute;\n inset: 0;\n pointer-events: none;\n }\n\n &-ripple {\n position: absolute;\n inset: 0;\n border-radius: 50%;\n border: 0.125em solid var(--timer-ripple-color, var(--timer-progress-color, var(--primary-color)));\n opacity: 0;\n transform: scale(0.94);\n\n /* One-shot per spawned instance (see the ripple spawner in timer.tsx), not an infinite\n loop — so pausing simply stops new spawns while already-mid-flight ripples keep\n animating to completion via `forwards` instead of vanishing mid-cycle. */\n animation: timerRippleHalo 3s ease-out forwards;\n }\n\n /* Not em, unlike everything else here: inside the svg this is a viewBox user unit, so it\n already scales with the ring, and it has to stay equal to the `strokeWidth` prop that\n timer.tsx subtracts from the circle's radius. */\n &-ringTrack {\n fill: none;\n stroke: var(--timer-track-color, var(--background-accent-light));\n stroke-width: var(--timer-stroke-width, 10px);\n }\n\n &-ringProgress {\n fill: none;\n stroke: var(--timer-progress-color, var(--primary-color));\n stroke-width: var(--timer-stroke-width, 10px);\n stroke-linecap: round;\n\n /* Single combined transform, not split across an SVG `transform` attribute on this element\n plus a separate CSS transform on an ancestor — that split combination, together with an\n actively-transitioning stroke-dashoffset, is a known trigger for SVG dash-rendering glitches\n in some engines (the visible arc appearing to jump/drift independent of the actual\n dashoffset value). scaleX(-1) mirrors so the depleting boundary sweeps clockwise (matching\n a clock face) instead of the counter-clockwise direction a <circle>'s implicit path winds\n by default; rotate(-90deg) moves the fixed anchor from 3 o'clock to 12 o'clock. Both applied\n around the circle's own center, which coincides with the viewBox center here. `counterClockwise`\n overrides this inline (timer.tsx) by dropping the scaleX(-1), keeping just the rotate — that\n default winding direction is exactly counter-clockwise, so no mirroring is needed for it. */\n transform: scaleX(-1) rotate(-90deg);\n transform-origin: 50% 50%;\n\n /* Matches (slightly exceeds) the JS tick interval (TICK_MS in timer.tsx) so the ring\n tracks the real remaining time closely instead of perpetually chasing a target that's\n always a full second stale — a much longer transition here reads as sluggish since the\n rendered ring never catches up to the true value while ticking continues. */\n transition:\n stroke-dashoffset 220ms linear,\n stroke 0.3s ease;\n\n &-urgent {\n stroke: var(--timer-urgent-color, var(--error-color));\n }\n }\n\n &-display {\n position: absolute;\n inset: 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n text-align: center;\n padding: 0 0.75em;\n }\n\n &-time {\n font-size: 1.4em;\n font-weight: 600;\n font-variant-numeric: tabular-nums;\n color: var(--timer-text-color, var(--text-color));\n }\n\n &-label {\n margin-top: 0.25em;\n font-size: 0.8em;\n color: var(--timer-label-color, var(--text-dark));\n }\n\n &-controls {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 0.5em;\n }\n\n &-controlsRow {\n display: flex;\n align-items: center;\n gap: 0.5em;\n }\n\n &-cancelButton {\n opacity: 0.6;\n\n &:hover {\n opacity: 1;\n }\n }\n\n &-pulsing &-ringWrapper {\n animation: timerHeartbeat 1s ease-in-out infinite;\n }\n\n &-critical &-ringWrapper {\n animation-duration: 0.6s;\n }\n}\n\n@keyframes timerHeartbeat {\n 0%,\n 100% {\n transform: scale(1);\n }\n\n 50% {\n transform: scale(1.045);\n }\n}\n\n@keyframes timerRippleHalo {\n 0% {\n transform: scale(0.94);\n opacity: 0.5;\n }\n\n 100% {\n transform: scale(1.35);\n opacity: 0;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n .timer-ringProgress {\n transition: stroke 0.3s ease;\n }\n\n .timer-pulsing .timer-ringWrapper {\n animation: none;\n }\n\n .timer-ripple {\n animation: none;\n opacity: 0;\n }\n}\n"],"mappings":""}
@@ -1,2 +1,2 @@
1
- "use client";import e from"../actionIcon/actionIcon.mjs";import t from"./toast.module.mjs";import{useSwipeDismiss as n}from"../hooks/useSwipeDismiss.mjs";import{useEffect as r,useRef as i,useState as a}from"react";import o from"classnames";import{FontAwesomeIcon as s}from"@fortawesome/react-fontawesome";import{faBell as c,faCircleCheck as l,faCircleInfo as u,faCircleXmark as d,faTriangleExclamation as f,faXmark as p}from"@fortawesome/free-solid-svg-icons";import{jsx as m,jsxs as h}from"react/jsx-runtime";var g={info:u,success:l,error:d,warn:f,default:c};function _({item:c,isBottom:l,onDismiss:u,labels:d}){let{id:f,content:_,options:v,dismissing:y}=c,{duration:b,showRemainingTime:x,showCloseButton:S,pauseOnHover:C,type:w,classNames:T,styles:E}=v,[D,O]=a(!1),[k,A]=a(!1),[j,M]=a(!1),{ref:N,isDragging:P}=n({onDismiss:()=>{M(!0),u(f)}}),F=C&&(D||k)||P,I=i(b);return r(()=>{if(b===0||F)return;let e=Date.now(),t=setTimeout(()=>u(f),I.current);return()=>{clearTimeout(t),I.current-=Date.now()-e}},[f,b,u,F]),h(`div`,{ref:N,className:o(t.toast,l?t.toastBottom:null,t[`toast-${w}`],y&&!j&&t.toastDismissing,F&&t.toastPaused,T?.root),style:E?.root,onMouseEnter:C?()=>O(!0):void 0,onMouseLeave:C?()=>O(!1):void 0,onFocus:C?()=>A(!0):void 0,onBlur:C?()=>A(!1):void 0,children:[m(s,{icon:g[w],className:o(t.toastIcon,T?.icon),style:E?.icon}),m(`div`,{className:o(t.toastContent,T?.content),style:E?.content,children:_}),S&&m(e,{icon:p,onClick:()=>u(f),className:o(t.toastCloseButton,T?.closeButton),style:E?.closeButton,"aria-label":d.close}),x&&b>0&&m(`div`,{className:o(t.toastProgressBar,T?.progressBar),style:{"--toast-duration":`${b}ms`,...E?.progressBar}})]})}export{_ as default};
1
+ "use client";import{ThemeColor as e}from"../themeProvider/color.types.mjs";import{toneProps as t,useToneCheck as n}from"../styles/tone.mjs";import r from"../actionIcon/actionIcon.mjs";import i from"./toast.module.mjs";import{useSwipeDismiss as a}from"../hooks/useSwipeDismiss.mjs";import{useEffect as o,useRef as s,useState as c}from"react";import l from"classnames";import{FontAwesomeIcon as u}from"@fortawesome/react-fontawesome";import{faBell as d,faCircleCheck as f,faCircleInfo as p,faCircleXmark as m,faTriangleExclamation as h,faXmark as g}from"@fortawesome/free-solid-svg-icons";import{jsx as _,jsxs as v}from"react/jsx-runtime";var y=new Map([[e.Info,p],[e.Success,f],[e.Warn,h],[e.Error,m]]);function b({item:e,isBottom:f,onDismiss:p,labels:m}){let{id:h,content:b,options:x,dismissing:S}=e,{duration:C,showRemainingTime:w,showCloseButton:T,pauseOnHover:E,color:D,classNames:O,styles:k}=x,A=t(D);n(`Toast`,[D]);let[j,M]=c(!1),[N,P]=c(!1),[F,I]=c(!1),{ref:L,isDragging:R}=a({onDismiss:()=>{I(!0),p(h)}}),z=E&&(j||N)||R,B=s(C);return o(()=>{if(C===0||z)return;let e=Date.now(),t=setTimeout(()=>p(h),B.current);return()=>{clearTimeout(t),B.current-=Date.now()-e}},[h,C,p,z]),v(`div`,{ref:L,className:l(i.toast,f?i.toastBottom:null,A.className,S&&!F&&i.toastDismissing,z&&i.toastPaused,O?.root),style:{...A.style,...k?.root},onMouseEnter:E?()=>M(!0):void 0,onMouseLeave:E?()=>M(!1):void 0,onFocus:E?()=>P(!0):void 0,onBlur:E?()=>P(!1):void 0,children:[_(u,{icon:y.get(D)??d,className:l(i.toastIcon,O?.icon),style:k?.icon}),_(`div`,{className:l(i.toastContent,O?.content),style:k?.content,children:b}),T&&_(r,{icon:g,color:`var(--text-dark)`,onClick:()=>p(h),className:l(i.toastCloseButton,O?.closeButton),style:k?.closeButton,"aria-label":m.close}),w&&C>0&&_(`div`,{className:l(i.toastProgressBar,O?.progressBar),style:{"--toast-duration":`${C}ms`,...k?.progressBar}})]})}export{b as default};
2
2
  //# sourceMappingURL=toast.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"toast.mjs","names":[],"sources":["../../../../package/common/toast/toast.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from 'react';\nimport cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport {\n faCircleInfo,\n faCircleCheck,\n faCircleXmark,\n faTriangleExclamation,\n faBell,\n faXmark,\n} from '@fortawesome/free-solid-svg-icons';\n\nimport styles from './toast.module.pcss';\nimport type { ToastItem, ToastLabels } from './toast.types';\nimport ActionIcon from '../actionIcon';\nimport { useSwipeDismiss } from '../hooks/useSwipeDismiss';\n\ninterface ToastProps {\n item: ToastItem;\n isBottom: boolean;\n onDismiss: (id: string) => void;\n /** Already resolved by the provider: defaults, provider, then this toast's own. */\n labels: Required<ToastLabels>;\n}\n\nconst typeIcons = {\n info: faCircleInfo,\n success: faCircleCheck,\n error: faCircleXmark,\n warn: faTriangleExclamation,\n default: faBell,\n};\n\nfunction Toast({ item, isBottom, onDismiss, labels }: ToastProps) {\n const { id, content, options, dismissing } = item;\n const { duration, showRemainingTime, showCloseButton, pauseOnHover, type, classNames, styles: slotStyles } = options;\n\n const [hovered, setHovered] = useState(false);\n const [focused, setFocused] = useState(false);\n\n const [swiped, setSwiped] = useState(false);\n const { ref: swipeRef, isDragging } = useSwipeDismiss<HTMLDivElement>({\n onDismiss: () => {\n setSwiped(true);\n onDismiss(id);\n },\n });\n\n const paused = (pauseOnHover && (hovered || focused)) || isDragging;\n\n // Remaining time is carried across pause/resume cycles so the timer continues\n // where it left off instead of restarting on every hover.\n const remainingRef = useRef(duration);\n\n useEffect(() => {\n if (duration === 0 || paused) return;\n const start = Date.now();\n const timer = setTimeout(() => onDismiss(id), remainingRef.current);\n return () => {\n clearTimeout(timer);\n remainingRef.current -= Date.now() - start;\n };\n }, [id, duration, onDismiss, paused]);\n\n return (\n <div\n ref={swipeRef}\n className={cx(\n styles.toast,\n isBottom ? styles.toastBottom : null,\n styles[`toast-${type}`],\n dismissing && !swiped && styles.toastDismissing,\n paused && styles.toastPaused,\n classNames?.root,\n )}\n style={slotStyles?.root}\n onMouseEnter={pauseOnHover ? () => setHovered(true) : undefined}\n onMouseLeave={pauseOnHover ? () => setHovered(false) : undefined}\n onFocus={pauseOnHover ? () => setFocused(true) : undefined}\n onBlur={pauseOnHover ? () => setFocused(false) : undefined}\n >\n <FontAwesomeIcon\n icon={typeIcons[type]}\n className={cx(styles.toastIcon, classNames?.icon)}\n style={slotStyles?.icon as React.CSSProperties & Record<`--fa-font-${string}`, string>}\n />\n\n <div className={cx(styles.toastContent, classNames?.content)} style={slotStyles?.content}>\n {content}\n </div>\n\n {showCloseButton && (\n <ActionIcon\n icon={faXmark}\n onClick={() => onDismiss(id)}\n className={cx(styles.toastCloseButton, classNames?.closeButton)}\n style={slotStyles?.closeButton}\n aria-label={labels.close}\n />\n )}\n\n {showRemainingTime && duration > 0 && (\n <div\n className={cx(styles.toastProgressBar, classNames?.progressBar)}\n style={{ '--toast-duration': `${duration}ms`, ...slotStyles?.progressBar } as React.CSSProperties}\n />\n )}\n </div>\n );\n}\n\nexport default Toast;\n"],"mappings":"8fAyBA,IAAM,EAAY,CAChB,KAAM,EACN,QAAS,EACT,MAAO,EACP,KAAM,EACN,QAAS,CACX,EAEA,SAAS,EAAM,CAAE,OAAM,WAAU,YAAW,UAAsB,CAChE,GAAM,CAAE,KAAI,UAAS,UAAS,cAAe,EACvC,CAAE,WAAU,oBAAmB,kBAAiB,eAAc,OAAM,aAAY,OAAQ,GAAe,EAEvG,CAAC,EAAS,GAAc,EAAS,EAAK,EACtC,CAAC,EAAS,GAAc,EAAS,EAAK,EAEtC,CAAC,EAAQ,GAAa,EAAS,EAAK,EACpC,CAAE,IAAK,EAAU,cAAe,EAAgC,CACpE,cAAiB,CACf,EAAU,EAAI,EACd,EAAU,CAAE,CACd,CACF,CAAC,EAEK,EAAU,IAAiB,GAAW,IAAa,EAInD,EAAe,EAAO,CAAQ,EAYpC,OAVA,MAAgB,CACd,GAAI,IAAa,GAAK,EAAQ,OAC9B,IAAM,EAAQ,KAAK,IAAI,EACjB,EAAQ,eAAiB,EAAU,CAAE,EAAG,EAAa,OAAO,EAClE,UAAa,CACX,aAAa,CAAK,EAClB,EAAa,SAAW,KAAK,IAAI,EAAI,CACvC,CACF,EAAG,CAAC,EAAI,EAAU,EAAW,CAAM,CAAC,EAGlC,EAAC,MAAD,CACE,IAAK,EACL,UAAW,EACT,EAAO,MACP,EAAW,EAAO,YAAc,KAChC,EAAO,SAAS,KAChB,GAAc,CAAC,GAAU,EAAO,gBAChC,GAAU,EAAO,YACjB,GAAY,IACd,EACA,MAAO,GAAY,KACnB,aAAc,MAAqB,EAAW,EAAI,EAAI,IAAA,GACtD,aAAc,MAAqB,EAAW,EAAK,EAAI,IAAA,GACvD,QAAS,MAAqB,EAAW,EAAI,EAAI,IAAA,GACjD,OAAQ,MAAqB,EAAW,EAAK,EAAI,IAAA,GAdnD,SAAA,CAgBE,EAAC,EAAD,CACE,KAAM,EAAU,GAChB,UAAW,EAAG,EAAO,UAAW,GAAY,IAAI,EAChD,MAAO,GAAY,IACpB,CAAA,EAED,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,aAAc,GAAY,OAAO,EAAG,MAAO,GAAY,QAC9E,SAAA,CACE,CAAA,EAEJ,GACC,EAAC,EAAD,CACE,KAAM,EACN,YAAe,EAAU,CAAE,EAC3B,UAAW,EAAG,EAAO,iBAAkB,GAAY,WAAW,EAC9D,MAAO,GAAY,YACnB,aAAY,EAAO,KACpB,CAAA,EAGF,GAAqB,EAAW,GAC/B,EAAC,MAAD,CACE,UAAW,EAAG,EAAO,iBAAkB,GAAY,WAAW,EAC9D,MAAO,CAAE,mBAAoB,GAAG,EAAS,IAAK,GAAG,GAAY,WAAY,CAC1E,CAAA,CAEA,GAET"}
1
+ {"version":3,"file":"toast.mjs","names":[],"sources":["../../../../package/common/toast/toast.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from 'react';\nimport cx from 'classnames';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport {\n faCircleInfo,\n faCircleCheck,\n faCircleXmark,\n faTriangleExclamation,\n faBell,\n faXmark,\n} from '@fortawesome/free-solid-svg-icons';\n\nimport styles from './toast.module.pcss';\nimport type { ToastItem, ToastLabels } from './toast.types';\nimport ActionIcon from '../actionIcon';\nimport { useSwipeDismiss } from '../hooks/useSwipeDismiss';\nimport { ThemeColor } from '../themeProvider/color.types';\nimport { toneProps, useToneCheck } from '../styles/tone';\n\ninterface ToastProps {\n item: ToastItem;\n isBottom: boolean;\n onDismiss: (id: string) => void;\n /** Already resolved by the provider: defaults, provider, then this toast's own. */\n labels: Required<ToastLabels>;\n}\n\n// A Map, so a CSS colour can never hit an Object.prototype key.\nconst ICON_BY_COLOR = new Map<string, typeof faBell>([\n [ThemeColor.Info, faCircleInfo],\n [ThemeColor.Success, faCircleCheck],\n [ThemeColor.Warn, faTriangleExclamation],\n [ThemeColor.Error, faCircleXmark],\n]);\n\nfunction Toast({ item, isBottom, onDismiss, labels }: ToastProps) {\n const { id, content, options, dismissing } = item;\n const { duration, showRemainingTime, showCloseButton, pauseOnHover, color, classNames, styles: slotStyles } = options;\n const tone = toneProps(color);\n useToneCheck('Toast', [color]);\n\n const [hovered, setHovered] = useState(false);\n const [focused, setFocused] = useState(false);\n\n const [swiped, setSwiped] = useState(false);\n const { ref: swipeRef, isDragging } = useSwipeDismiss<HTMLDivElement>({\n onDismiss: () => {\n setSwiped(true);\n onDismiss(id);\n },\n });\n\n const paused = (pauseOnHover && (hovered || focused)) || isDragging;\n\n // Remaining time is carried across pause/resume cycles so the timer continues\n // where it left off instead of restarting on every hover.\n const remainingRef = useRef(duration);\n\n useEffect(() => {\n if (duration === 0 || paused) return;\n const start = Date.now();\n const timer = setTimeout(() => onDismiss(id), remainingRef.current);\n return () => {\n clearTimeout(timer);\n remainingRef.current -= Date.now() - start;\n };\n }, [id, duration, onDismiss, paused]);\n\n return (\n <div\n ref={swipeRef}\n className={cx(\n styles.toast,\n isBottom ? styles.toastBottom : null,\n tone.className,\n dismissing && !swiped && styles.toastDismissing,\n paused && styles.toastPaused,\n classNames?.root,\n )}\n style={{ ...tone.style, ...slotStyles?.root }}\n onMouseEnter={pauseOnHover ? () => setHovered(true) : undefined}\n onMouseLeave={pauseOnHover ? () => setHovered(false) : undefined}\n onFocus={pauseOnHover ? () => setFocused(true) : undefined}\n onBlur={pauseOnHover ? () => setFocused(false) : undefined}\n >\n <FontAwesomeIcon\n icon={ICON_BY_COLOR.get(color) ?? faBell}\n className={cx(styles.toastIcon, classNames?.icon)}\n style={slotStyles?.icon as React.CSSProperties & Record<`--fa-font-${string}`, string>}\n />\n\n <div className={cx(styles.toastContent, classNames?.content)} style={slotStyles?.content}>\n {content}\n </div>\n\n {showCloseButton && (\n <ActionIcon\n icon={faXmark}\n color='var(--text-dark)'\n onClick={() => onDismiss(id)}\n className={cx(styles.toastCloseButton, classNames?.closeButton)}\n style={slotStyles?.closeButton}\n aria-label={labels.close}\n />\n )}\n\n {showRemainingTime && duration > 0 && (\n <div\n className={cx(styles.toastProgressBar, classNames?.progressBar)}\n style={{ '--toast-duration': `${duration}ms`, ...slotStyles?.progressBar } as React.CSSProperties}\n />\n )}\n </div>\n );\n}\n\nexport default Toast;\n"],"mappings":"6nBA4BA,IAAM,EAAgB,IAAI,IAA2B,CACnD,CAAC,EAAW,KAAM,CAAY,EAC9B,CAAC,EAAW,QAAS,CAAa,EAClC,CAAC,EAAW,KAAM,CAAqB,EACvC,CAAC,EAAW,MAAO,CAAa,CAClC,CAAC,EAED,SAAS,EAAM,CAAE,OAAM,WAAU,YAAW,UAAsB,CAChE,GAAM,CAAE,KAAI,UAAS,UAAS,cAAe,EACvC,CAAE,WAAU,oBAAmB,kBAAiB,eAAc,QAAO,aAAY,OAAQ,GAAe,EACxG,EAAO,EAAU,CAAK,EAC5B,EAAa,QAAS,CAAC,CAAK,CAAC,EAE7B,GAAM,CAAC,EAAS,GAAc,EAAS,EAAK,EACtC,CAAC,EAAS,GAAc,EAAS,EAAK,EAEtC,CAAC,EAAQ,GAAa,EAAS,EAAK,EACpC,CAAE,IAAK,EAAU,cAAe,EAAgC,CACpE,cAAiB,CACf,EAAU,EAAI,EACd,EAAU,CAAE,CACd,CACF,CAAC,EAEK,EAAU,IAAiB,GAAW,IAAa,EAInD,EAAe,EAAO,CAAQ,EAYpC,OAVA,MAAgB,CACd,GAAI,IAAa,GAAK,EAAQ,OAC9B,IAAM,EAAQ,KAAK,IAAI,EACjB,EAAQ,eAAiB,EAAU,CAAE,EAAG,EAAa,OAAO,EAClE,UAAa,CACX,aAAa,CAAK,EAClB,EAAa,SAAW,KAAK,IAAI,EAAI,CACvC,CACF,EAAG,CAAC,EAAI,EAAU,EAAW,CAAM,CAAC,EAGlC,EAAC,MAAD,CACE,IAAK,EACL,UAAW,EACT,EAAO,MACP,EAAW,EAAO,YAAc,KAChC,EAAK,UACL,GAAc,CAAC,GAAU,EAAO,gBAChC,GAAU,EAAO,YACjB,GAAY,IACd,EACA,MAAO,CAAE,GAAG,EAAK,MAAO,GAAG,GAAY,IAAK,EAC5C,aAAc,MAAqB,EAAW,EAAI,EAAI,IAAA,GACtD,aAAc,MAAqB,EAAW,EAAK,EAAI,IAAA,GACvD,QAAS,MAAqB,EAAW,EAAI,EAAI,IAAA,GACjD,OAAQ,MAAqB,EAAW,EAAK,EAAI,IAAA,GAdnD,SAAA,CAgBE,EAAC,EAAD,CACE,KAAM,EAAc,IAAI,CAAK,GAAK,EAClC,UAAW,EAAG,EAAO,UAAW,GAAY,IAAI,EAChD,MAAO,GAAY,IACpB,CAAA,EAED,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,aAAc,GAAY,OAAO,EAAG,MAAO,GAAY,QAC9E,SAAA,CACE,CAAA,EAEJ,GACC,EAAC,EAAD,CACE,KAAM,EACN,MAAM,mBACN,YAAe,EAAU,CAAE,EAC3B,UAAW,EAAG,EAAO,iBAAkB,GAAY,WAAW,EAC9D,MAAO,GAAY,YACnB,aAAY,EAAO,KACpB,CAAA,EAGF,GAAqB,EAAW,GAC/B,EAAC,MAAD,CACE,UAAW,EAAG,EAAO,iBAAkB,GAAY,WAAW,EAC9D,MAAO,CAAE,mBAAoB,GAAG,EAAS,IAAK,GAAG,GAAY,WAAY,CAC1E,CAAA,CAEA,GAET"}
@@ -1,2 +1,2 @@
1
- "use client";var e=`container_krdsW`,t=`container-top-left_zfDTO`,n=`container-top-center_CUIGc`,r=`container-top-right_sB0KU`,i=`container-bottom-left_toJdF`,a=`container-bottom-center_Bkf9m`,o=`container-bottom-right_oRSMc`,s=`toast_qBi4o`,c=`toastSlideDown_4lKWq`,l=`toast-bottom_X8ZIe`,u=`toastSlideUp_SGR5X`,d=`toast-dismissing_xKmB-`,f=`toastFadeOut_cvHYp`,p=`toast-paused_NPmT4`,m=`toastProgressBar_6vBs6`,h=`toast-info_RlLli`,g=`toastIcon_xU1nA`,_=`toast-success_I1g1B`,v=`toast-error_MloFO`,y=`toast-warn_pP6HB`,b=`toast-default_RTt2L`,x=`toastContent_gvyIv`,S=`toastCloseButton_n-YST`,C=`toastShrink_h89HS`,w={container:e,"container-top-left":`container-top-left_zfDTO`,containerTopLeft:t,"container-top-center":`container-top-center_CUIGc`,containerTopCenter:n,"container-top-right":`container-top-right_sB0KU`,containerTopRight:r,"container-bottom-left":`container-bottom-left_toJdF`,containerBottomLeft:i,"container-bottom-center":`container-bottom-center_Bkf9m`,containerBottomCenter:a,"container-bottom-right":`container-bottom-right_oRSMc`,containerBottomRight:o,toast:s,toastSlideDown:c,"toast-bottom":`toast-bottom_X8ZIe`,toastBottom:l,toastSlideUp:u,"toast-dismissing":`toast-dismissing_xKmB-`,toastDismissing:d,toastFadeOut:f,"toast-paused":`toast-paused_NPmT4`,toastPaused:p,toastProgressBar:m,"toast-info":`toast-info_RlLli`,toastInfo:h,toastIcon:g,"toast-success":`toast-success_I1g1B`,toastSuccess:_,"toast-error":`toast-error_MloFO`,toastError:v,"toast-warn":`toast-warn_pP6HB`,toastWarn:y,"toast-default":`toast-default_RTt2L`,toastDefault:b,toastContent:x,toastCloseButton:S,toastShrink:C};export{e as container,a as containerBottomCenter,i as containerBottomLeft,o as containerBottomRight,n as containerTopCenter,t as containerTopLeft,r as containerTopRight,w as default,s as toast,l as toastBottom,S as toastCloseButton,x as toastContent,b as toastDefault,d as toastDismissing,v as toastError,f as toastFadeOut,g as toastIcon,h as toastInfo,p as toastPaused,m as toastProgressBar,C as toastShrink,c as toastSlideDown,u as toastSlideUp,_ as toastSuccess,y as toastWarn};
1
+ "use client";var e=`container_krdsW`,t=`container-top-left_zfDTO`,n=`container-top-center_CUIGc`,r=`container-top-right_sB0KU`,i=`container-bottom-left_toJdF`,a=`container-bottom-center_Bkf9m`,o=`container-bottom-right_oRSMc`,s=`toast_qBi4o`,c=`toastSlideDown_4lKWq`,l=`toast-bottom_X8ZIe`,u=`toastSlideUp_SGR5X`,d=`toast-dismissing_xKmB-`,f=`toastFadeOut_cvHYp`,p=`toast-paused_NPmT4`,m=`toastProgressBar_6vBs6`,h=`toastIcon_xU1nA`,g=`toastContent_gvyIv`,_=`toastCloseButton_n-YST`,v=`toastShrink_h89HS`,y={container:e,"container-top-left":`container-top-left_zfDTO`,containerTopLeft:t,"container-top-center":`container-top-center_CUIGc`,containerTopCenter:n,"container-top-right":`container-top-right_sB0KU`,containerTopRight:r,"container-bottom-left":`container-bottom-left_toJdF`,containerBottomLeft:i,"container-bottom-center":`container-bottom-center_Bkf9m`,containerBottomCenter:a,"container-bottom-right":`container-bottom-right_oRSMc`,containerBottomRight:o,toast:s,toastSlideDown:c,"toast-bottom":`toast-bottom_X8ZIe`,toastBottom:l,toastSlideUp:u,"toast-dismissing":`toast-dismissing_xKmB-`,toastDismissing:d,toastFadeOut:f,"toast-paused":`toast-paused_NPmT4`,toastPaused:p,toastProgressBar:m,toastIcon:h,toastContent:g,toastCloseButton:_,toastShrink:v};export{e as container,a as containerBottomCenter,i as containerBottomLeft,o as containerBottomRight,n as containerTopCenter,t as containerTopLeft,r as containerTopRight,y as default,s as toast,l as toastBottom,_ as toastCloseButton,g as toastContent,d as toastDismissing,f as toastFadeOut,h as toastIcon,p as toastPaused,m as toastProgressBar,v as toastShrink,c as toastSlideDown,u as toastSlideUp};
2
2
  //# sourceMappingURL=toast.module.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"toast.module.mjs","names":[],"sources":["../../../../package/common/toast/toast.module.pcss"],"sourcesContent":[".container {\n position: fixed;\n z-index: 9999;\n display: flex;\n flex-direction: column;\n gap: 0.5em;\n pointer-events: none;\n padding: 1em;\n box-sizing: border-box;\n\n &-top-left {\n top: 0;\n left: 0;\n align-items: flex-start;\n }\n\n &-top-center {\n top: 0;\n left: 50%;\n transform: translateX(-50%);\n align-items: center;\n }\n\n &-top-right {\n top: 0;\n right: 0;\n align-items: flex-end;\n }\n\n &-bottom-left {\n bottom: 0;\n left: 0;\n align-items: flex-start;\n flex-direction: column-reverse;\n }\n\n &-bottom-center {\n bottom: 0;\n left: 50%;\n transform: translateX(-50%);\n align-items: center;\n flex-direction: column-reverse;\n }\n\n &-bottom-right {\n bottom: 0;\n right: 0;\n align-items: flex-end;\n flex-direction: column-reverse;\n }\n}\n\n.toast {\n pointer-events: all;\n display: flex;\n align-items: flex-start;\n gap: 0.625em;\n padding: 0.75em 0.875em;\n border-radius: var(--default-border-radius);\n background: var(--background-modal);\n color: var(--text-color);\n font-family: var(--default-font);\n box-shadow: var(--card-shadow);\n\n /* em, so the line length stays a measure rather than a pixel count. The screen\n wins over both: below about 270px the minimum alone was wider than the space\n the container had, and a toast pinned to one edge hung off the other. The 2em\n is the container's own padding, which is in the same em as these. */\n min-width: min(15em, calc(100vw - 2em));\n max-width: min(23.75em, calc(100vw - 2em));\n box-sizing: border-box;\n position: relative;\n\n /* Tells the browser vertical panning is native (so the page can still scroll behind the toast)\n while horizontal movement is left for useSwipeDismiss's own pointer handling to decide. */\n touch-action: pan-y;\n overflow: hidden;\n animation: toastSlideDown 0.25s ease forwards;\n\n &-bottom {\n animation: toastSlideUp 0.25s ease forwards;\n }\n\n &-dismissing {\n animation: toastFadeOut 0.2s ease forwards;\n }\n\n &-paused .toastProgressBar {\n animation-play-state: paused;\n }\n\n &-info {\n border-left: 0.1875em solid var(--info-color, #3b82f6);\n\n .toastIcon {\n color: var(--info-color, #3b82f6);\n }\n }\n\n &-success {\n border-left: 0.1875em solid var(--success-color);\n\n .toastIcon {\n color: var(--success-color);\n }\n }\n\n &-error {\n border-left: 0.1875em solid var(--error-color, #ef4444);\n\n .toastIcon {\n color: var(--error-color, #ef4444);\n }\n }\n\n &-warn {\n border-left: 0.1875em solid var(--warn-color);\n\n .toastIcon {\n color: var(--warn-color);\n }\n }\n\n &-default {\n border-left: 0.1875em solid var(--primary-color);\n\n /* Paints the gradient exactly over border-left, which a background layer only reaches\n because its origin is the border box. The border stays as the no-gradient fallback. */\n background-image: var(--primary-gradient, none);\n background-repeat: no-repeat;\n background-size: 0.1875em 100%;\n background-origin: border-box;\n\n .toastIcon {\n color: var(--primary-color);\n }\n }\n}\n\n.toastIcon {\n flex-shrink: 0;\n margin-top: 0.0667em; /* 1px against this element's own 0.9375em */\n font-size: 0.9375em;\n}\n\n.toastContent {\n flex: 1;\n font-size: 0.875em;\n line-height: 1.4;\n}\n\n.toastCloseButton {\n flex-shrink: 0;\n background: none;\n border: none;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n padding: 0;\n color: var(--text-dark);\n font-size: 0.8125em;\n opacity: 0.6;\n transition: opacity 0.15s;\n margin-top: 0.0769em; /* 1px against this element's own 0.8125em */\n\n &:hover {\n opacity: 1;\n }\n}\n\n.toastProgressBar {\n position: absolute;\n bottom: 0;\n left: 0;\n height: 0.1875em;\n width: 100%;\n background: currentcolor;\n opacity: 0.35;\n transform-origin: left;\n animation: toastShrink var(--toast-duration) linear forwards;\n}\n\n@keyframes toastSlideDown {\n from {\n opacity: 0;\n transform: translateY(-0.75em);\n }\n\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes toastSlideUp {\n from {\n opacity: 0;\n transform: translateY(0.75em);\n }\n\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes toastFadeOut {\n from {\n opacity: 1;\n transform: scale(1);\n }\n\n to {\n opacity: 0;\n transform: scale(0.92);\n }\n}\n\n@keyframes toastShrink {\n from {\n transform: scaleX(1);\n }\n\n to {\n transform: scaleX(0);\n }\n}\n\n/* The entrance and exit slide go. `toastShrink` stays: it is the remaining-time indicator, and a\n progress bar frozen at full width would tell the user the opposite of what is true. Removal is\n driven by a timer in toastProvider, not by these animations, so dropping them cannot strand a\n toast on screen. */\n@media (prefers-reduced-motion: reduce) {\n .toast,\n .toast-bottom,\n .toast-dismissing {\n animation: none;\n }\n}\n"],"mappings":""}
1
+ {"version":3,"file":"toast.module.mjs","names":[],"sources":["../../../../package/common/toast/toast.module.pcss"],"sourcesContent":[".container {\n position: fixed;\n z-index: 9999;\n display: flex;\n flex-direction: column;\n gap: 0.5em;\n pointer-events: none;\n padding: 1em;\n box-sizing: border-box;\n\n &-top-left {\n top: 0;\n left: 0;\n align-items: flex-start;\n }\n\n &-top-center {\n top: 0;\n left: 50%;\n transform: translateX(-50%);\n align-items: center;\n }\n\n &-top-right {\n top: 0;\n right: 0;\n align-items: flex-end;\n }\n\n &-bottom-left {\n bottom: 0;\n left: 0;\n align-items: flex-start;\n flex-direction: column-reverse;\n }\n\n &-bottom-center {\n bottom: 0;\n left: 50%;\n transform: translateX(-50%);\n align-items: center;\n flex-direction: column-reverse;\n }\n\n &-bottom-right {\n bottom: 0;\n right: 0;\n align-items: flex-end;\n flex-direction: column-reverse;\n }\n}\n\n.toast {\n pointer-events: all;\n display: flex;\n align-items: flex-start;\n gap: 0.625em;\n padding: 0.75em 0.875em;\n border-radius: var(--default-border-radius);\n border-left: 0.1875em solid var(--tone);\n background: var(--background-modal);\n\n /* Must follow the shorthand above, which resets it. The gradient reaches over border-left only\n because its origin is the border box; the border is the fallback. */\n background-image: var(--tone-gradient);\n background-repeat: no-repeat;\n background-size: 0.1875em 100%;\n background-origin: border-box;\n color: var(--text-color);\n font-family: var(--default-font);\n box-shadow: var(--card-shadow);\n\n /* em, so the line length stays a measure rather than a pixel count. The screen\n wins over both: below about 270px the minimum alone was wider than the space\n the container had, and a toast pinned to one edge hung off the other. The 2em\n is the container's own padding, which is in the same em as these. */\n min-width: min(15em, calc(100vw - 2em));\n max-width: min(23.75em, calc(100vw - 2em));\n box-sizing: border-box;\n position: relative;\n\n /* Tells the browser vertical panning is native (so the page can still scroll behind the toast)\n while horizontal movement is left for useSwipeDismiss's own pointer handling to decide. */\n touch-action: pan-y;\n overflow: hidden;\n animation: toastSlideDown 0.25s ease forwards;\n\n &-bottom {\n animation: toastSlideUp 0.25s ease forwards;\n }\n\n &-dismissing {\n animation: toastFadeOut 0.2s ease forwards;\n }\n\n &-paused .toastProgressBar {\n animation-play-state: paused;\n }\n}\n\n.toastIcon {\n flex-shrink: 0;\n color: var(--tone);\n margin-top: 0.0667em; /* 1px against this element's own 0.9375em */\n font-size: 0.9375em;\n}\n\n.toastContent {\n flex: 1;\n font-size: 0.875em;\n line-height: 1.4;\n}\n\n/* Two classes, to outrank Button's font-size and ActionIcon's box whichever stylesheet loads\n first. */\n.toast .toastCloseButton {\n flex-shrink: 0;\n width: 1em;\n height: 1em;\n font-size: 0.8125em;\n opacity: 0.6;\n transition: opacity 0.15s;\n margin-top: 0.0769em; /* 1px against this element's own 0.8125em */\n\n &:hover {\n opacity: 1;\n }\n}\n\n.toastProgressBar {\n position: absolute;\n bottom: 0;\n left: 0;\n height: 0.1875em;\n width: 100%;\n background: currentcolor;\n opacity: 0.35;\n transform-origin: left;\n animation: toastShrink var(--toast-duration) linear forwards;\n}\n\n@keyframes toastSlideDown {\n from {\n opacity: 0;\n transform: translateY(-0.75em);\n }\n\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes toastSlideUp {\n from {\n opacity: 0;\n transform: translateY(0.75em);\n }\n\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes toastFadeOut {\n from {\n opacity: 1;\n transform: scale(1);\n }\n\n to {\n opacity: 0;\n transform: scale(0.92);\n }\n}\n\n@keyframes toastShrink {\n from {\n transform: scaleX(1);\n }\n\n to {\n transform: scaleX(0);\n }\n}\n\n/* The entrance and exit slide go. `toastShrink` stays: it is the remaining-time indicator, and a\n progress bar frozen at full width would tell the user the opposite of what is true. Removal is\n driven by a timer in toastProvider, not by these animations, so dropping them cannot strand a\n toast on screen. */\n@media (prefers-reduced-motion: reduce) {\n .toast,\n .toast-bottom,\n .toast-dismissing {\n animation: none;\n }\n}\n"],"mappings":""}
@@ -1,2 +1,2 @@
1
- "use client";import e from"../bodyEnd/bodyEnd.mjs";import t from"./toast.module.mjs";import n from"./toast.mjs";import{_registerToastHandler as r,_unregisterToastHandler as i}from"./toastService.mjs";import{useCallback as a,useInsertionEffect as o,useRef as s,useState as c}from"react";import l from"classnames";import{Fragment as u,jsx as d,jsxs as f}from"react/jsx-runtime";var p={position:`top-right`,duration:4e3,showRemainingTime:!0,showCloseButton:!0,allowStacking:!0,pauseOnHover:!0,labels:{close:`Close`}},m=220;function h(e){return t[`container-${e}`]}function g({children:g,position:_=p.position,duration:v=p.duration,showRemainingTime:y=p.showRemainingTime,showCloseButton:b=p.showCloseButton,allowStacking:x=p.allowStacking,pauseOnHover:S=p.pauseOnHover,labels:C}){let[w,T]=c([]),E=s(0),D=a(e=>{T(t=>t.map(t=>t.id===e?{...t,dismissing:!0}:t)),setTimeout(()=>{T(t=>t.filter(t=>t.id!==e))},m)},[]),O=a((e,t)=>{let n={position:t?.position??_,duration:t?.duration??v,showRemainingTime:t?.showRemainingTime??y,showCloseButton:t?.showCloseButton??b,pauseOnHover:t?.pauseOnHover??S,type:t?.type??`default`,classNames:t?.classNames,styles:t?.styles};E.current+=1;let r={id:`toast-${E.current}`,content:e,options:n,dismissing:!1,labels:t?.labels};T(e=>!x&&e.length>0?(setTimeout(()=>{T([r])},m),e.map(e=>({...e,dismissing:!0}))):[...e,r])},[_,v,y,b,x,S]),k=s(O);o(()=>{k.current=O},[O]),o(()=>{let e=(e,t)=>k.current(e,t);return r(e),()=>i(e)},[]);let A=w.reduce((e,t)=>{let n=t.options.position;return e[n]||(e[n]=[]),e[n].push(t),e},{});return f(u,{children:[g,d(e,{children:Object.entries(A).map(([e,r])=>d(`div`,{className:l(t.container,h(e)),children:r.map(t=>d(n,{item:t,isBottom:e.startsWith(`bottom`),onDismiss:D,labels:{...p.labels,...C,...t.labels}},t.id))},e))})]})}export{g as default};
1
+ "use client";import{ThemeColor as e}from"../themeProvider/color.types.mjs";import t from"../bodyEnd/bodyEnd.mjs";import n from"./toast.module.mjs";import r from"./toast.mjs";import{_registerToastHandler as i,_unregisterToastHandler as a}from"./toastService.mjs";import{useCallback as o,useInsertionEffect as s,useRef as c,useState as l}from"react";import u from"classnames";import{Fragment as d,jsx as f,jsxs as p}from"react/jsx-runtime";var m={position:`top-right`,duration:4e3,showRemainingTime:!0,showCloseButton:!0,allowStacking:!0,pauseOnHover:!0,labels:{close:`Close`}},h=220;function g(e){return n[`container-${e}`]}function _({children:_,position:v=m.position,duration:y=m.duration,showRemainingTime:b=m.showRemainingTime,showCloseButton:x=m.showCloseButton,allowStacking:S=m.allowStacking,pauseOnHover:C=m.pauseOnHover,labels:w}){let[T,E]=l([]),D=c(0),O=o(e=>{E(t=>t.map(t=>t.id===e?{...t,dismissing:!0}:t)),setTimeout(()=>{E(t=>t.filter(t=>t.id!==e))},h)},[]),k=o((t,n)=>{let r={position:n?.position??v,duration:n?.duration??y,showRemainingTime:n?.showRemainingTime??b,showCloseButton:n?.showCloseButton??x,pauseOnHover:n?.pauseOnHover??C,color:n?.color??e.Primary,classNames:n?.classNames,styles:n?.styles};D.current+=1;let i={id:`toast-${D.current}`,content:t,options:r,dismissing:!1,labels:n?.labels};E(e=>!S&&e.length>0?(setTimeout(()=>{E([i])},h),e.map(e=>({...e,dismissing:!0}))):[...e,i])},[v,y,b,x,S,C]),A=c(k);s(()=>{A.current=k},[k]),s(()=>{let e=(e,t)=>A.current(e,t);return i(e),()=>a(e)},[]);let j=T.reduce((e,t)=>{let n=t.options.position;return e[n]||(e[n]=[]),e[n].push(t),e},{});return p(d,{children:[_,f(t,{children:Object.entries(j).map(([e,t])=>f(`div`,{className:u(n.container,g(e)),children:t.map(t=>f(r,{item:t,isBottom:e.startsWith(`bottom`),onDismiss:O,labels:{...m.labels,...w,...t.labels}},t.id))},e))})]})}export{_ as default};
2
2
  //# sourceMappingURL=toastHost.mjs.map