@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":"dates.mjs","names":[],"sources":["../../../../package/common/calendar/dates.ts"],"sourcesContent":["import { CalendarView, type CalendarRange, type CalendarWeekStart } from './calendar.types';\n\n// All arithmetic goes through the local date fields rather than milliseconds: a day with a\n// daylight-saving change is 23 or 25 hours long, so adding 86 400 000 ms lands on the wrong day.\n\nexport const MINUTES_PER_DAY = 1440;\n\nexport function startOfDay(date: Date): Date {\n return new Date(date.getFullYear(), date.getMonth(), date.getDate());\n}\n\n/** Midnight, `days` calendar days away. */\nexport function addDays(date: Date, days: number): Date {\n return new Date(date.getFullYear(), date.getMonth(), date.getDate() + days);\n}\n\n/** The same wall-clock time, `days` calendar days away. */\nexport function shiftDays(date: Date, days: number): Date {\n return new Date(\n date.getFullYear(),\n date.getMonth(),\n date.getDate() + days,\n date.getHours(),\n date.getMinutes(),\n date.getSeconds(),\n date.getMilliseconds(),\n );\n}\n\nexport function daysInMonth(year: number, month: number): number {\n return new Date(year, month + 1, 0).getDate();\n}\n\n/** Midnight, `months` months away. The day is clamped, so 31 January plus one month is the end of February. */\nexport function addMonths(date: Date, months: number): Date {\n const target = new Date(date.getFullYear(), date.getMonth() + months, 1);\n const day = Math.min(date.getDate(), daysInMonth(target.getFullYear(), target.getMonth()));\n return new Date(target.getFullYear(), target.getMonth(), day);\n}\n\nexport function startOfMonth(date: Date): Date {\n return new Date(date.getFullYear(), date.getMonth(), 1);\n}\n\nexport function startOfWeek(date: Date, weekStartsOn: CalendarWeekStart): Date {\n return addDays(date, -((date.getDay() - weekStartsOn + 7) % 7));\n}\n\n/** Calendar days from `a` to `b`, whatever their times of day. */\nexport function dayDiff(a: Date, b: Date): number {\n const utcA = Date.UTC(a.getFullYear(), a.getMonth(), a.getDate());\n const utcB = Date.UTC(b.getFullYear(), b.getMonth(), b.getDate());\n return Math.round((utcB - utcA) / 86_400_000);\n}\n\nexport function isSameDay(a: Date, b: Date): boolean {\n return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();\n}\n\n// `'2026-09-26'` is also the key for lookups and React keys. Never `getTime()`: where a clock\n// change happens at midnight (America/Santiago), the day's first moment is 01:00, and two paths to\n// the same day disagree.\nexport { dateToDay } from '../utils/day';\n\n/** Wall-clock minutes since midnight. On a 25-hour day the repeated hour maps onto itself. */\nexport function minutesOfDay(date: Date): number {\n return date.getHours() * 60 + date.getMinutes();\n}\n\n/**\n * The wall-clock time `minutes` after the start of `day`; 1440 is the next midnight. A time the\n * clock skips resolves forwards (02:30 becomes 03:30) and a repeated one to its first occurrence.\n */\nexport function atMinutes(day: Date, minutes: number): Date {\n return new Date(day.getFullYear(), day.getMonth(), day.getDate(), 0, minutes);\n}\n\n/**\n * `end`, unless a clock change turned the range around: where one end lands in the hour the\n * clocks skip, a wall-clock end can fall on or before its start. Then `minutes` of real time\n * after the start instead.\n */\nexport function endAfter(start: Date, end: Date, minutes: number): Date {\n return end > start ? end : new Date(start.getTime() + minutes * 60_000);\n}\n\n/** Midnight of the first day of the period `date` is in. */\nexport function periodStart(view: CalendarView, date: Date, weekStartsOn: CalendarWeekStart): Date {\n switch (view) {\n case CalendarView.Week:\n return startOfWeek(date, weekStartsOn);\n case CalendarView.Day:\n return startOfDay(date);\n default:\n return startOfMonth(date);\n }\n}\n\n/** The days a view shows for `date`. The month view is always six full weeks. */\nexport function periodRange(view: CalendarView, date: Date, weekStartsOn: CalendarWeekStart): CalendarRange {\n const start = periodStart(view, date, weekStartsOn);\n switch (view) {\n case CalendarView.Month: {\n const gridStart = startOfWeek(start, weekStartsOn);\n return { start: gridStart, end: addDays(gridStart, 42) };\n }\n case CalendarView.Week:\n return { start, end: addDays(start, 7) };\n case CalendarView.Day:\n return { start, end: addDays(start, 1) };\n default:\n return { start, end: addMonths(start, 1) };\n }\n}\n\nconst NO_DAYS: ReadonlySet<number> = new Set();\n\n/** `hiddenDays` as a lookup. A list that leaves no day of the week hides nothing. */\nexport function hiddenDaySet(hiddenDays: readonly number[] | undefined): ReadonlySet<number> {\n const hidden = new Set(hiddenDays);\n return hidden.size === 0 || [0, 1, 2, 3, 4, 5, 6].every((day) => hidden.has(day)) ? NO_DAYS : hidden;\n}\n\n/** `date`, or the first shown day from it on in `direction`. */\nexport function shownDay(date: Date, hidden: ReadonlySet<number>, direction: 1 | -1 = 1): Date {\n let day = startOfDay(date);\n while (hidden.has(day.getDay())) day = addDays(day, direction);\n return day;\n}\n\n/** `date` moved by `steps` periods, keeping its place in the period where it can. */\nexport function stepDate(view: CalendarView, date: Date, steps: number, hidden: ReadonlySet<number> = NO_DAYS): Date {\n switch (view) {\n case CalendarView.Week:\n return addDays(date, 7 * steps);\n case CalendarView.Day: {\n const direction = steps < 0 ? -1 : 1;\n let day = date;\n for (let i = 0; i < Math.abs(steps); i++) day = shownDay(addDays(day, direction), hidden, direction);\n return day;\n }\n default:\n return addMonths(date, steps);\n }\n}\n\n/** The shown period plus one on either side: what the swipe pager can reveal. */\nexport function rangeWithNeighbours(\n view: CalendarView,\n date: Date,\n weekStartsOn: CalendarWeekStart,\n hidden: ReadonlySet<number> = NO_DAYS,\n): CalendarRange {\n return {\n start: periodRange(view, stepDate(view, date, -1, hidden), weekStartsOn).start,\n end: periodRange(view, stepDate(view, date, 1, hidden), weekStartsOn).end,\n };\n}\n\n/** Midnight of each of `count` days from `start`. */\nexport function daysFrom(start: Date, count: number): Date[] {\n return Array.from({ length: count }, (_, i) => addDays(start, i));\n}\n\n/** The days of `count` from `start` that are not hidden: the columns a row of them draws. */\nexport function shownDays(start: Date, count: number, hidden: ReadonlySet<number> = NO_DAYS): Date[] {\n return daysFrom(start, count).filter((day) => !hidden.has(day.getDay()));\n}\n\nconst KEY_DAYS: Record<string, number> = { ArrowLeft: -1, ArrowRight: 1, ArrowUp: -7, ArrowDown: 7 };\n\nfunction keyTarget(key: string, day: Date, weekStartsOn: CalendarWeekStart): Date | null {\n if (key in KEY_DAYS) return addDays(day, KEY_DAYS[key]);\n if (key === 'Home') return startOfWeek(day, weekStartsOn);\n if (key === 'End') return addDays(startOfWeek(day, weekStartsOn), 6);\n if (key === 'PageUp') return addMonths(day, -1);\n if (key === 'PageDown') return addMonths(day, 1);\n return null;\n}\n\n/**\n * The day a month grid moves to for `key`, or `null` for a key it does not handle. A hidden day\n * gives way to the next shown one in the direction the key points, so the focus stays on a cell.\n */\nexport function gridKeyTarget(\n key: string,\n day: Date,\n weekStartsOn: CalendarWeekStart,\n hidden: ReadonlySet<number> = NO_DAYS,\n): Date | null {\n const target = keyTarget(key, day, weekStartsOn);\n return target && shownDay(target, hidden, key === 'ArrowLeft' || key === 'End' ? -1 : 1);\n}\n"],"mappings":"8GAKA,IAAa,EAAkB,KAE/B,SAAgB,EAAW,EAAkB,CAC3C,OAAO,IAAI,KAAK,EAAK,YAAY,EAAG,EAAK,SAAS,EAAG,EAAK,QAAQ,CAAC,CACrE,CAGA,SAAgB,EAAQ,EAAY,EAAoB,CACtD,OAAO,IAAI,KAAK,EAAK,YAAY,EAAG,EAAK,SAAS,EAAG,EAAK,QAAQ,EAAI,CAAI,CAC5E,CAGA,SAAgB,EAAU,EAAY,EAAoB,CACxD,OAAO,IAAI,KACT,EAAK,YAAY,EACjB,EAAK,SAAS,EACd,EAAK,QAAQ,EAAI,EACjB,EAAK,SAAS,EACd,EAAK,WAAW,EAChB,EAAK,WAAW,EAChB,EAAK,gBAAgB,CACvB,CACF,CAEA,SAAgB,EAAY,EAAc,EAAuB,CAC/D,OAAO,IAAI,KAAK,EAAM,EAAQ,EAAG,CAAC,CAAC,CAAC,QAAQ,CAC9C,CAGA,SAAgB,EAAU,EAAY,EAAsB,CAC1D,IAAM,EAAS,IAAI,KAAK,EAAK,YAAY,EAAG,EAAK,SAAS,EAAI,EAAQ,CAAC,EACjE,EAAM,KAAK,IAAI,EAAK,QAAQ,EAAG,EAAY,EAAO,YAAY,EAAG,EAAO,SAAS,CAAC,CAAC,EACzF,OAAO,IAAI,KAAK,EAAO,YAAY,EAAG,EAAO,SAAS,EAAG,CAAG,CAC9D,CAEA,SAAgB,EAAa,EAAkB,CAC7C,OAAO,IAAI,KAAK,EAAK,YAAY,EAAG,EAAK,SAAS,EAAG,CAAC,CACxD,CAEA,SAAgB,EAAY,EAAY,EAAuC,CAC7E,OAAO,EAAQ,EAAM,GAAG,EAAK,OAAO,EAAI,EAAe,GAAK,EAAE,CAChE,CAGA,SAAgB,EAAQ,EAAS,EAAiB,CAChD,IAAM,EAAO,KAAK,IAAI,EAAE,YAAY,EAAG,EAAE,SAAS,EAAG,EAAE,QAAQ,CAAC,EAC1D,EAAO,KAAK,IAAI,EAAE,YAAY,EAAG,EAAE,SAAS,EAAG,EAAE,QAAQ,CAAC,EAChE,OAAO,KAAK,OAAO,EAAO,GAAQ,KAAU,CAC9C,CAEA,SAAgB,EAAU,EAAS,EAAkB,CACnD,OAAO,EAAE,YAAY,IAAM,EAAE,YAAY,GAAK,EAAE,SAAS,IAAM,EAAE,SAAS,GAAK,EAAE,QAAQ,IAAM,EAAE,QAAQ,CAC3G,CAQA,SAAgB,EAAa,EAAoB,CAC/C,OAAO,EAAK,SAAS,EAAI,GAAK,EAAK,WAAW,CAChD,CAMA,SAAgB,EAAU,EAAW,EAAuB,CAC1D,OAAO,IAAI,KAAK,EAAI,YAAY,EAAG,EAAI,SAAS,EAAG,EAAI,QAAQ,EAAG,EAAG,CAAO,CAC9E,CAOA,SAAgB,EAAS,EAAa,EAAW,EAAuB,CACtE,OAAO,EAAM,EAAQ,EAAM,IAAI,KAAK,EAAM,QAAQ,EAAI,EAAU,GAAM,CACxE,CAGA,SAAgB,EAAY,EAAoB,EAAY,EAAuC,CACjG,OAAQ,EAAR,CACE,KAAK,EAAa,KAChB,OAAO,EAAY,EAAM,CAAY,EACvC,KAAK,EAAa,IAChB,OAAO,EAAW,CAAI,EACxB,QACE,OAAO,EAAa,CAAI,CAC5B,CACF,CAGA,SAAgB,EAAY,EAAoB,EAAY,EAAgD,CAC1G,IAAM,EAAQ,EAAY,EAAM,EAAM,CAAY,EAClD,OAAQ,EAAR,CACE,KAAK,EAAa,MAAO,CACvB,IAAM,EAAY,EAAY,EAAO,CAAY,EACjD,MAAO,CAAE,MAAO,EAAW,IAAK,EAAQ,EAAW,EAAE,CAAE,CACzD,CACA,KAAK,EAAa,KAChB,MAAO,CAAE,QAAO,IAAK,EAAQ,EAAO,CAAC,CAAE,EACzC,KAAK,EAAa,IAChB,MAAO,CAAE,QAAO,IAAK,EAAQ,EAAO,CAAC,CAAE,EACzC,QACE,MAAO,CAAE,QAAO,IAAK,EAAU,EAAO,CAAC,CAAE,CAC7C,CACF,CAEA,IAAM,EAA+B,IAAI,IAGzC,SAAgB,EAAa,EAAgE,CAC3F,IAAM,EAAS,IAAI,IAAI,CAAU,EACjC,OAAO,EAAO,OAAS,GAAK,CAAC,EAAG,EAAG,EAAG,EAAG,EAAG,EAAG,CAAC,CAAC,CAAC,MAAO,GAAQ,EAAO,IAAI,CAAG,CAAC,EAAI,EAAU,CAChG,CAGA,SAAgB,EAAS,EAAY,EAA6B,EAAoB,EAAS,CAC7F,IAAI,EAAM,EAAW,CAAI,EACzB,KAAO,EAAO,IAAI,EAAI,OAAO,CAAC,GAAG,EAAM,EAAQ,EAAK,CAAS,EAC7D,OAAO,CACT,CAGA,SAAgB,EAAS,EAAoB,EAAY,EAAe,EAA8B,EAAe,CACnH,OAAQ,EAAR,CACE,KAAK,EAAa,KAChB,OAAO,EAAQ,EAAM,EAAI,CAAK,EAChC,KAAK,EAAa,IAAK,CACrB,IAAM,EAAY,EAAQ,EAAI,GAAK,EAC/B,EAAM,EACV,IAAK,IAAI,EAAI,EAAG,EAAI,KAAK,IAAI,CAAK,EAAG,IAAK,EAAM,EAAS,EAAQ,EAAK,CAAS,EAAG,EAAQ,CAAS,EACnG,OAAO,CACT,CACA,QACE,OAAO,EAAU,EAAM,CAAK,CAChC,CACF,CAGA,SAAgB,EACd,EACA,EACA,EACA,EAA8B,EACf,CACf,MAAO,CACL,MAAO,EAAY,EAAM,EAAS,EAAM,EAAM,GAAI,CAAM,EAAG,CAAY,CAAC,CAAC,MACzE,IAAK,EAAY,EAAM,EAAS,EAAM,EAAM,EAAG,CAAM,EAAG,CAAY,CAAC,CAAC,GACxE,CACF,CAGA,SAAgB,EAAS,EAAa,EAAuB,CAC3D,OAAO,MAAM,KAAK,CAAE,OAAQ,CAAM,GAAI,EAAG,IAAM,EAAQ,EAAO,CAAC,CAAC,CAClE,CAGA,SAAgB,EAAU,EAAa,EAAe,EAA8B,EAAiB,CACnG,OAAO,EAAS,EAAO,CAAK,CAAC,CAAC,OAAQ,GAAQ,CAAC,EAAO,IAAI,EAAI,OAAO,CAAC,CAAC,CACzE,CAEA,IAAM,EAAmC,CAAE,UAAW,GAAI,WAAY,EAAG,QAAS,GAAI,UAAW,CAAE,EAEnG,SAAS,EAAU,EAAa,EAAW,EAA8C,CAMvF,OALI,KAAO,EAAiB,EAAQ,EAAK,EAAS,EAAI,EAClD,IAAQ,OAAe,EAAY,EAAK,CAAY,EACpD,IAAQ,MAAc,EAAQ,EAAY,EAAK,CAAY,EAAG,CAAC,EAC/D,IAAQ,SAAiB,EAAU,EAAK,EAAE,EAC1C,IAAQ,WAAmB,EAAU,EAAK,CAAC,EACxC,IACT,CAMA,SAAgB,EACd,EACA,EACA,EACA,EAA8B,EACjB,CACb,IAAM,EAAS,EAAU,EAAK,EAAK,CAAY,EAC/C,OAAO,GAAU,EAAS,EAAQ,EAAQ,IAAQ,aAAe,IAAQ,MAAQ,GAAK,CAAC,CACzF"}
1
+ {"version":3,"file":"dates.mjs","names":[],"sources":["../../../../package/common/calendar/dates.ts"],"sourcesContent":["import { CalendarView, type CalendarRange, type CalendarSlot, type CalendarWeekStart } from './calendar.types';\n\n// All arithmetic goes through the local date fields rather than milliseconds: a day with a\n// daylight-saving change is 23 or 25 hours long, so adding 86 400 000 ms lands on the wrong day.\n\nexport const MINUTES_PER_DAY = 1440;\n\nexport function startOfDay(date: Date): Date {\n return new Date(date.getFullYear(), date.getMonth(), date.getDate());\n}\n\n/** Midnight, `days` calendar days away. */\nexport function addDays(date: Date, days: number): Date {\n return new Date(date.getFullYear(), date.getMonth(), date.getDate() + days);\n}\n\n/** The same wall-clock time, `days` calendar days away. */\nexport function shiftDays(date: Date, days: number): Date {\n return new Date(\n date.getFullYear(),\n date.getMonth(),\n date.getDate() + days,\n date.getHours(),\n date.getMinutes(),\n date.getSeconds(),\n date.getMilliseconds(),\n );\n}\n\nexport function daysInMonth(year: number, month: number): number {\n return new Date(year, month + 1, 0).getDate();\n}\n\n/** Midnight, `months` months away. The day is clamped, so 31 January plus one month is the end of February. */\nexport function addMonths(date: Date, months: number): Date {\n const target = new Date(date.getFullYear(), date.getMonth() + months, 1);\n const day = Math.min(date.getDate(), daysInMonth(target.getFullYear(), target.getMonth()));\n return new Date(target.getFullYear(), target.getMonth(), day);\n}\n\nexport function startOfMonth(date: Date): Date {\n return new Date(date.getFullYear(), date.getMonth(), 1);\n}\n\nexport function startOfWeek(date: Date, weekStartsOn: CalendarWeekStart): Date {\n return addDays(date, -((date.getDay() - weekStartsOn + 7) % 7));\n}\n\n/** Calendar days from `a` to `b`, whatever their times of day. */\nexport function dayDiff(a: Date, b: Date): number {\n const utcA = Date.UTC(a.getFullYear(), a.getMonth(), a.getDate());\n const utcB = Date.UTC(b.getFullYear(), b.getMonth(), b.getDate());\n return Math.round((utcB - utcA) / 86_400_000);\n}\n\nexport function isSameDay(a: Date, b: Date): boolean {\n return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();\n}\n\n// `'2026-09-26'` is also the key for lookups and React keys. Never `getTime()`: where a clock\n// change happens at midnight (America/Santiago), the day's first moment is 01:00, and two paths to\n// the same day disagree.\nexport { dateToDay } from '../utils/day';\n\n/** Wall-clock minutes since midnight. On a 25-hour day the repeated hour maps onto itself. */\nexport function minutesOfDay(date: Date): number {\n return date.getHours() * 60 + date.getMinutes();\n}\n\n/**\n * The wall-clock time `minutes` after the start of `day`; 1440 is the next midnight. A time the\n * clock skips resolves forwards (02:30 becomes 03:30) and a repeated one to its first occurrence.\n */\nexport function atMinutes(day: Date, minutes: number): Date {\n return new Date(day.getFullYear(), day.getMonth(), day.getDate(), 0, minutes);\n}\n\n/**\n * `end`, unless a clock change turned the range around: where one end lands in the hour the\n * clocks skip, a wall-clock end can fall on or before its start. Then `minutes` of real time\n * after the start instead.\n */\nexport function endAfter(start: Date, end: Date, minutes: number): Date {\n return end > start ? end : new Date(start.getTime() + minutes * 60_000);\n}\n\nconst NO_DAYS: ReadonlySet<number> = new Set();\n\n/**\n * The Week view of a narrow calendar: three shown days from the selected one, paged by three, where\n * seven columns would leave no room for a title. Not a `CalendarView`: the switcher still says Week.\n */\nexport const NARROW_WEEK = 'narrowWeek';\n\n/** What the period arithmetic is keyed by: a view, or the narrow calendar's Week. */\nexport type CalendarPeriod = CalendarView | typeof NARROW_WEEK;\n\n/** Shown days in a period that runs from the selected day, or 0 for one fixed to a week or month. */\nfunction rollingDays(period: CalendarPeriod): number {\n if (period === CalendarView.Day) return 1;\n return period === NARROW_WEEK ? 3 : 0;\n}\n\n/** Midnight of the first day of the period `date` is in. */\nexport function periodStart(period: CalendarPeriod, date: Date, weekStartsOn: CalendarWeekStart): Date {\n if (rollingDays(period) > 0) return startOfDay(date);\n return period === CalendarView.Week ? startOfWeek(date, weekStartsOn) : startOfMonth(date);\n}\n\n/** The days a view shows for `date`. The month view is always six full weeks. */\nexport function periodRange(\n period: CalendarPeriod,\n date: Date,\n weekStartsOn: CalendarWeekStart,\n hidden: ReadonlySet<number> = NO_DAYS,\n): CalendarRange {\n const start = periodStart(period, date, weekStartsOn);\n const rolling = rollingDays(period);\n if (rolling > 0) return { start, end: addDays(stepShownDays(start, rolling - 1, hidden), 1) };\n switch (period) {\n case CalendarView.Month: {\n const gridStart = startOfWeek(start, weekStartsOn);\n return { start: gridStart, end: addDays(gridStart, 42) };\n }\n case CalendarView.Week:\n return { start, end: addDays(start, 7) };\n default:\n return { start, end: addMonths(start, 1) };\n }\n}\n\n/** `hiddenDays` as a lookup. A list that leaves no day of the week hides nothing. */\nexport function hiddenDaySet(hiddenDays: readonly number[] | undefined): ReadonlySet<number> {\n const hidden = new Set(hiddenDays);\n return hidden.size === 0 || [0, 1, 2, 3, 4, 5, 6].every((day) => hidden.has(day)) ? NO_DAYS : hidden;\n}\n\n/** `date`, or the first shown day from it on in `direction`. */\nexport function shownDay(date: Date, hidden: ReadonlySet<number>, direction: 1 | -1 = 1): Date {\n let day = startOfDay(date);\n while (hidden.has(day.getDay())) day = addDays(day, direction);\n return day;\n}\n\n/** `steps` shown days on from the shown day `date`, or back for a negative count. */\nfunction stepShownDays(date: Date, steps: number, hidden: ReadonlySet<number>): Date {\n const direction = steps < 0 ? -1 : 1;\n let day = date;\n for (let i = 0; i < Math.abs(steps); i++) day = shownDay(addDays(day, direction), hidden, direction);\n return day;\n}\n\n/** `date` moved by `steps` periods, keeping its place in the period where it can. */\nexport function stepDate(\n period: CalendarPeriod,\n date: Date,\n steps: number,\n hidden: ReadonlySet<number> = NO_DAYS,\n): Date {\n const rolling = rollingDays(period);\n if (rolling > 0) return stepShownDays(date, steps * rolling, hidden);\n return period === CalendarView.Week ? addDays(date, 7 * steps) : addMonths(date, steps);\n}\n\n/** The shown period plus one on either side: what the swipe pager can reveal. */\nexport function rangeWithNeighbours(\n period: CalendarPeriod,\n date: Date,\n weekStartsOn: CalendarWeekStart,\n hidden: ReadonlySet<number> = NO_DAYS,\n): CalendarRange {\n return {\n start: periodRange(period, stepDate(period, date, -1, hidden), weekStartsOn, hidden).start,\n end: periodRange(period, stepDate(period, date, 1, hidden), weekStartsOn, hidden).end,\n };\n}\n\n/** Every day from `first` to `last`, in either order: what creating whole days hands out. */\nexport function allDaySlot(first: Date, last: Date = first): CalendarSlot {\n const [from, to] = last < first ? [last, first] : [first, last];\n return { start: startOfDay(from), end: addDays(to, 1), allDay: true };\n}\n\n/**\n * What the header's New event button creates on `day`: in the week and day views the hour from\n * the next full hour of the clock, as calendar apps do, and elsewhere the whole day.\n */\nexport function newEventSlot(period: CalendarPeriod, day: Date, now: Date, slotMinutes: number): CalendarSlot {\n if (period === CalendarView.Month || period === CalendarView.Agenda) return allDaySlot(day);\n // 23:00 at the latest, even after 23:00 today: the slot stays on the selected day.\n const start = atMinutes(day, Math.min(now.getHours() + 1, 23) * 60);\n // Real time, as a click on empty time makes it: across a clock change an hour on the clock is none or two.\n const end = new Date(start.getTime() + Math.max(60, slotMinutes) * 60_000);\n const midnight = addDays(day, 1);\n return { start, end: end < midnight ? end : midnight, allDay: false };\n}\n\n/** The ISO 8601 week `date` falls in: weeks run Monday to Sunday, and week 1 holds 4 January. */\nexport function weekNumber(date: Date): number {\n const monday = startOfWeek(date, 1);\n // A week across New Year belongs to the year of its Thursday.\n const year = addDays(monday, 3).getFullYear();\n return dayDiff(startOfWeek(new Date(year, 0, 4), 1), monday) / 7 + 1;\n}\n\n/** Midnight of each of `count` days from `start`. */\nexport function daysFrom(start: Date, count: number): Date[] {\n return Array.from({ length: count }, (_, i) => addDays(start, i));\n}\n\n/** The days of `count` from `start` that are not hidden: the columns a row of them draws. */\nexport function shownDays(start: Date, count: number, hidden: ReadonlySet<number> = NO_DAYS): Date[] {\n return daysFrom(start, count).filter((day) => !hidden.has(day.getDay()));\n}\n\nconst KEY_DAYS: Record<string, number> = { ArrowLeft: -1, ArrowRight: 1, ArrowUp: -7, ArrowDown: 7 };\n\nfunction keyTarget(key: string, day: Date, weekStartsOn: CalendarWeekStart): Date | null {\n if (key in KEY_DAYS) return addDays(day, KEY_DAYS[key]);\n if (key === 'Home') return startOfWeek(day, weekStartsOn);\n if (key === 'End') return addDays(startOfWeek(day, weekStartsOn), 6);\n if (key === 'PageUp') return addMonths(day, -1);\n if (key === 'PageDown') return addMonths(day, 1);\n return null;\n}\n\n/**\n * The day a month grid moves to for `key`, or `null` for a key it does not handle. A hidden day\n * gives way to the next shown one in the direction the key points, so the focus stays on a cell.\n */\nexport function gridKeyTarget(\n key: string,\n day: Date,\n weekStartsOn: CalendarWeekStart,\n hidden: ReadonlySet<number> = NO_DAYS,\n): Date | null {\n const target = keyTarget(key, day, weekStartsOn);\n return target && shownDay(target, hidden, key === 'ArrowLeft' || key === 'End' ? -1 : 1);\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use client";import{CalendarView as e}from"./calendar.types.mjs";import{addDays as t}from"./dates.mjs";var n=new Map,r;function i(){return r===void 0&&(r=new Intl.DateTimeFormat().resolvedOptions().timeZone,queueMicrotask(()=>{r=void 0})),r}function a(e,t){let r=`${i()}|${e??``}|${JSON.stringify(t)}`,a=n.get(r);return a||(a=new Intl.DateTimeFormat(e,t),n.set(r,a)),a}function o(e,t,n){return e.formatRange(t,n)}var s=new Map;function c(e){let t=e??``,n=s.get(t);if(n!==void 0)return n;let r=1;try{let t=e??new Intl.DateTimeFormat().resolvedOptions().locale,n=new Intl.Locale(t),i=n.getWeekInfo?.()??n.weekInfo;i&&(r=i.firstDay%7)}catch{}return s.set(t,r),r}function l(e){let t=a(e,{hour:`numeric`}).resolvedOptions().hourCycle;return t===`h11`||t===`h12`}function u(e,t){return a(t,{hour:`numeric`,minute:`2-digit`}).format(e)}function d(e,t,n){return o(a(n,{hour:`numeric`,minute:`2-digit`}),e,t)}function f(e,t,n){let r=new Date(2e3,0,1,e.getHours(),e.getMinutes()),i=new Date(2e3,0,1,t.getHours(),t.getMinutes());try{return o(a(n,{hour:`numeric`,minute:`2-digit`}),r,i)}catch{return u(e,n)}}function p(e,t){let n=new Date(2e3,0,1,e);return l(t)?a(t,{hour:`numeric`}).format(n):a(t,{hour:`2-digit`,minute:`2-digit`}).format(n)}function m(e,t,n){return a(t,{weekday:n}).format(e)}function h(e,t){return a(t,{day:`numeric`}).format(e)}function g(e,t){return a(t,{weekday:`long`,day:`numeric`,month:`long`,year:`numeric`}).format(e)}function _(e,t){return a(t,{month:`long`,year:`numeric`}).format(e)}function v(n,r,i,s){switch(n){case e.Week:return o(a(s,{day:`numeric`,month:`short`,year:`numeric`}),i.start,t(i.end,-1));case e.Day:return g(r,s);default:return _(r,s)}}export{f as formatClockRange,h as formatDayNumber,p as formatHour,g as formatLongDate,_ as formatMonthTitle,v as formatPeriodTitle,u as formatTime,d as formatTimeRange,m as formatWeekday,a as formatter,c as localeWeekStart};
1
+ "use client";import{CalendarView as e}from"./calendar.types.mjs";import{NARROW_WEEK as t,addDays as n}from"./dates.mjs";var r=new Map,i;function a(){return i===void 0&&(i=new Intl.DateTimeFormat().resolvedOptions().timeZone,queueMicrotask(()=>{i=void 0})),i}function o(e,t){let n=`${a()}|${e??``}|${JSON.stringify(t)}`,i=r.get(n);return i||(i=new Intl.DateTimeFormat(e,t),r.set(n,i)),i}function s(e,t,n){return e.formatRange(t,n)}var c=new Map;function l(e){let t=e??``,n=c.get(t);if(n!==void 0)return n;let r=1;try{let t=e??new Intl.DateTimeFormat().resolvedOptions().locale,n=new Intl.Locale(t),i=n.getWeekInfo?.()??n.weekInfo;i&&(r=i.firstDay%7)}catch{}return c.set(t,r),r}function u(e){let t=o(e,{hour:`numeric`}).resolvedOptions().hourCycle;return t===`h11`||t===`h12`}function d(e,t){return o(t,{hour:`numeric`,minute:`2-digit`}).format(e)}function f(e,t,n){return s(o(n,{hour:`numeric`,minute:`2-digit`}),e,t)}function p(e,t,n){let r=new Date(2e3,0,1,e.getHours(),e.getMinutes()),i=new Date(2e3,0,1,t.getHours(),t.getMinutes());try{return s(o(n,{hour:`numeric`,minute:`2-digit`}),r,i)}catch{return d(e,n)}}function m(e,t){let n=new Date(2e3,0,1,e);return u(t)?o(t,{hour:`numeric`}).format(n):o(t,{hour:`2-digit`,minute:`2-digit`}).format(n)}function h(e,t,n){return o(t,{weekday:n}).format(e)}function g(e,t){return o(t,{day:`numeric`}).format(e)}function _(e,t){return o(t,{weekday:`long`,day:`numeric`,month:`long`,year:`numeric`}).format(e)}function v(e,t){return o(t,{month:`long`,year:`numeric`}).format(e)}function y(r,i,a,c){switch(r){case e.Week:case t:return s(o(c,{day:`numeric`,month:`short`,year:`numeric`}),a.start,n(a.end,-1));case e.Day:return _(i,c);default:return v(i,c)}}export{p as formatClockRange,g as formatDayNumber,m as formatHour,_ as formatLongDate,v as formatMonthTitle,y as formatPeriodTitle,d as formatTime,f as formatTimeRange,h as formatWeekday,o as formatter,l as localeWeekStart};
2
2
  //# sourceMappingURL=format.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"format.mjs","names":[],"sources":["../../../../package/common/calendar/format.ts"],"sourcesContent":["import { CalendarView, type CalendarRange, type CalendarWeekStart } from './calendar.types';\nimport { addDays } from './dates';\n\n// `locale` is passed to Intl as given, and `undefined` means the browser's locale. Not\n// `getLocale()` from services/localization: it narrows to a few supported locales and maps\n// en-GB to en-US, which would give British users 12-hour times.\n\nconst formatters = new Map<string, Intl.DateTimeFormat>();\nlet zone: string | undefined;\n\n/**\n * Read once per task: reading the zone costs as much as building a formatter. Its name, not its\n * offsets, because Casablanca and Brazzaville share January's and July's but not March's.\n */\nfunction currentZone(): string {\n if (zone === undefined) {\n zone = new Intl.DateTimeFormat().resolvedOptions().timeZone;\n queueMicrotask(() => {\n zone = undefined;\n });\n }\n return zone;\n}\n\n/**\n * Cached, since building one costs about fifty times more than using it. A formatter keeps the\n * time zone it was built in while `Date` follows the current one, so the key carries the zone: a\n * zone change (the device's, or `process.env.TZ` between tests) then builds a new formatter\n * instead of labelling days in the old zone.\n */\nexport function formatter(locale: string | undefined, options: Intl.DateTimeFormatOptions): Intl.DateTimeFormat {\n const key = `${currentZone()}|${locale ?? ''}|${JSON.stringify(options)}`;\n let cached = formatters.get(key);\n if (!cached) {\n cached = new Intl.DateTimeFormat(locale, options);\n formatters.set(key, cached);\n }\n return cached;\n}\n\n// ES2020's lib predates `formatRange`, which every supported browser has had since 2021.\nfunction formatRange(format: Intl.DateTimeFormat, start: Date, end: Date): string {\n return (format as Intl.DateTimeFormat & { formatRange(a: Date, b: Date): string }).formatRange(start, end);\n}\n\ntype WeekInfoLocale = Intl.Locale & {\n getWeekInfo?: () => { firstDay: number };\n /** The accessor form Chrome 99 to 129 and Safari 15.4 to 16 shipped before the method. */\n weekInfo?: { firstDay: number };\n};\n\nconst weekStarts = new Map<string, CalendarWeekStart>();\n\n/**\n * The locale's first day of the week, falling back to Monday where `getWeekInfo` is missing:\n * it is Baseline only since July 2026 (Chrome 130, Firefox 153, Safari 17).\n */\nexport function localeWeekStart(locale: string | undefined): CalendarWeekStart {\n const key = locale ?? '';\n const cached = weekStarts.get(key);\n if (cached !== undefined) return cached;\n\n let result: CalendarWeekStart = 1;\n try {\n const tag = locale ?? new Intl.DateTimeFormat().resolvedOptions().locale;\n const info = new Intl.Locale(tag) as WeekInfoLocale;\n const weekInfo = info.getWeekInfo?.() ?? info.weekInfo;\n // `firstDay` counts 1 (Monday) to 7 (Sunday); `getDay()` counts 0 (Sunday) to 6.\n if (weekInfo) result = (weekInfo.firstDay % 7) as CalendarWeekStart;\n } catch {\n // An invalid tag: Intl.DateTimeFormat would have thrown for it too, so keep the fallback.\n }\n weekStarts.set(key, result);\n return result;\n}\n\nfunction uses12Hour(locale: string | undefined): boolean {\n // `hourCycle` is missing from ES2020's lib typings, not from any supported browser.\n const options = formatter(locale, { hour: 'numeric' }).resolvedOptions() as { hourCycle?: string };\n const cycle = options.hourCycle;\n return cycle === 'h11' || cycle === 'h12';\n}\n\nexport function formatTime(date: Date, locale: string | undefined): string {\n return formatter(locale, { hour: 'numeric', minute: '2-digit' }).format(date);\n}\n\n/** A time span, with the dates added by Intl where the two ends fall on different days. */\nexport function formatTimeRange(start: Date, end: Date, locale: string | undefined): string {\n return formatRange(formatter(locale, { hour: 'numeric', minute: '2-digit' }), start, end);\n}\n\n/**\n * The clock times alone, `10:00 PM to 2:00 AM` as the locale writes it, where `formatTimeRange` would add both dates for\n * an event that crosses midnight. Both ends are moved onto one day for it. The first spec of\n * `formatRange` threw a RangeError for an end earlier than the start; an engine still doing that\n * gets the start time alone.\n */\nexport function formatClockRange(start: Date, end: Date, locale: string | undefined): string {\n const from = new Date(2000, 0, 1, start.getHours(), start.getMinutes());\n const to = new Date(2000, 0, 1, end.getHours(), end.getMinutes());\n try {\n return formatRange(formatter(locale, { hour: 'numeric', minute: '2-digit' }), from, to);\n } catch {\n return formatTime(start, locale);\n }\n}\n\n/** `9 AM` where the locale counts to twelve, `09:00` where it counts to 24. */\nexport function formatHour(hour: number, locale: string | undefined): string {\n const date = new Date(2000, 0, 1, hour);\n return uses12Hour(locale)\n ? formatter(locale, { hour: 'numeric' }).format(date)\n : formatter(locale, { hour: '2-digit', minute: '2-digit' }).format(date);\n}\n\nexport function formatWeekday(date: Date, locale: string | undefined, width: 'long' | 'short' | 'narrow'): string {\n return formatter(locale, { weekday: width }).format(date);\n}\n\n/** The day of the month in the locale's own digits. */\nexport function formatDayNumber(date: Date, locale: string | undefined): string {\n return formatter(locale, { day: 'numeric' }).format(date);\n}\n\nexport function formatLongDate(date: Date, locale: string | undefined): string {\n return formatter(locale, { weekday: 'long', day: 'numeric', month: 'long', year: 'numeric' }).format(date);\n}\n\nexport function formatShortDate(date: Date, locale: string | undefined): string {\n return formatter(locale, { weekday: 'short', day: 'numeric', month: 'short' }).format(date);\n}\n\nexport function formatMonthTitle(date: Date, locale: string | undefined): string {\n return formatter(locale, { month: 'long', year: 'numeric' }).format(date);\n}\n\nexport function formatPeriodTitle(\n view: CalendarView,\n date: Date,\n range: CalendarRange,\n locale: string | undefined,\n): string {\n switch (view) {\n case CalendarView.Week:\n return formatRange(\n formatter(locale, { day: 'numeric', month: 'short', year: 'numeric' }),\n range.start,\n addDays(range.end, -1),\n );\n case CalendarView.Day:\n return formatLongDate(date, locale);\n default:\n return formatMonthTitle(date, locale);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"format.mjs","names":[],"sources":["../../../../package/common/calendar/format.ts"],"sourcesContent":["import { CalendarView, type CalendarRange, type CalendarWeekStart } from './calendar.types';\nimport { addDays, NARROW_WEEK, type CalendarPeriod } from './dates';\n\n// `locale` is passed to Intl as given, and `undefined` means the browser's locale. Not\n// `getLocale()` from services/localization: it narrows to a few supported locales and maps\n// en-GB to en-US, which would give British users 12-hour times.\n\nconst formatters = new Map<string, Intl.DateTimeFormat>();\nlet zone: string | undefined;\n\n/**\n * Read once per task: reading the zone costs as much as building a formatter. Its name, not its\n * offsets, because Casablanca and Brazzaville share January's and July's but not March's.\n */\nfunction currentZone(): string {\n if (zone === undefined) {\n zone = new Intl.DateTimeFormat().resolvedOptions().timeZone;\n queueMicrotask(() => {\n zone = undefined;\n });\n }\n return zone;\n}\n\n/**\n * Cached, since building one costs about fifty times more than using it. A formatter keeps the\n * time zone it was built in while `Date` follows the current one, so the key carries the zone: a\n * zone change (the device's, or `process.env.TZ` between tests) then builds a new formatter\n * instead of labelling days in the old zone.\n */\nexport function formatter(locale: string | undefined, options: Intl.DateTimeFormatOptions): Intl.DateTimeFormat {\n const key = `${currentZone()}|${locale ?? ''}|${JSON.stringify(options)}`;\n let cached = formatters.get(key);\n if (!cached) {\n cached = new Intl.DateTimeFormat(locale, options);\n formatters.set(key, cached);\n }\n return cached;\n}\n\n// ES2020's lib predates `formatRange`, which every supported browser has had since 2021.\nfunction formatRange(format: Intl.DateTimeFormat, start: Date, end: Date): string {\n return (format as Intl.DateTimeFormat & { formatRange(a: Date, b: Date): string }).formatRange(start, end);\n}\n\ntype WeekInfoLocale = Intl.Locale & {\n getWeekInfo?: () => { firstDay: number };\n /** The accessor form Chrome 99 to 129 and Safari 15.4 to 16 shipped before the method. */\n weekInfo?: { firstDay: number };\n};\n\nconst weekStarts = new Map<string, CalendarWeekStart>();\n\n/**\n * The locale's first day of the week, falling back to Monday where `getWeekInfo` is missing:\n * it is Baseline only since July 2026 (Chrome 130, Firefox 153, Safari 17).\n */\nexport function localeWeekStart(locale: string | undefined): CalendarWeekStart {\n const key = locale ?? '';\n const cached = weekStarts.get(key);\n if (cached !== undefined) return cached;\n\n let result: CalendarWeekStart = 1;\n try {\n const tag = locale ?? new Intl.DateTimeFormat().resolvedOptions().locale;\n const info = new Intl.Locale(tag) as WeekInfoLocale;\n const weekInfo = info.getWeekInfo?.() ?? info.weekInfo;\n // `firstDay` counts 1 (Monday) to 7 (Sunday); `getDay()` counts 0 (Sunday) to 6.\n if (weekInfo) result = (weekInfo.firstDay % 7) as CalendarWeekStart;\n } catch {\n // An invalid tag: Intl.DateTimeFormat would have thrown for it too, so keep the fallback.\n }\n weekStarts.set(key, result);\n return result;\n}\n\nfunction uses12Hour(locale: string | undefined): boolean {\n // `hourCycle` is missing from ES2020's lib typings, not from any supported browser.\n const options = formatter(locale, { hour: 'numeric' }).resolvedOptions() as { hourCycle?: string };\n const cycle = options.hourCycle;\n return cycle === 'h11' || cycle === 'h12';\n}\n\nexport function formatTime(date: Date, locale: string | undefined): string {\n return formatter(locale, { hour: 'numeric', minute: '2-digit' }).format(date);\n}\n\n/** A time span, with the dates added by Intl where the two ends fall on different days. */\nexport function formatTimeRange(start: Date, end: Date, locale: string | undefined): string {\n return formatRange(formatter(locale, { hour: 'numeric', minute: '2-digit' }), start, end);\n}\n\n/**\n * The clock times alone, `10:00 PM to 2:00 AM` as the locale writes it, where `formatTimeRange` would add both dates for\n * an event that crosses midnight. Both ends are moved onto one day for it. The first spec of\n * `formatRange` threw a RangeError for an end earlier than the start; an engine still doing that\n * gets the start time alone.\n */\nexport function formatClockRange(start: Date, end: Date, locale: string | undefined): string {\n const from = new Date(2000, 0, 1, start.getHours(), start.getMinutes());\n const to = new Date(2000, 0, 1, end.getHours(), end.getMinutes());\n try {\n return formatRange(formatter(locale, { hour: 'numeric', minute: '2-digit' }), from, to);\n } catch {\n return formatTime(start, locale);\n }\n}\n\n/** `9 AM` where the locale counts to twelve, `09:00` where it counts to 24. */\nexport function formatHour(hour: number, locale: string | undefined): string {\n const date = new Date(2000, 0, 1, hour);\n return uses12Hour(locale)\n ? formatter(locale, { hour: 'numeric' }).format(date)\n : formatter(locale, { hour: '2-digit', minute: '2-digit' }).format(date);\n}\n\nexport function formatWeekday(date: Date, locale: string | undefined, width: 'long' | 'short' | 'narrow'): string {\n return formatter(locale, { weekday: width }).format(date);\n}\n\n/** The day of the month in the locale's own digits. */\nexport function formatDayNumber(date: Date, locale: string | undefined): string {\n return formatter(locale, { day: 'numeric' }).format(date);\n}\n\nexport function formatLongDate(date: Date, locale: string | undefined): string {\n return formatter(locale, { weekday: 'long', day: 'numeric', month: 'long', year: 'numeric' }).format(date);\n}\n\nexport function formatShortDate(date: Date, locale: string | undefined): string {\n return formatter(locale, { weekday: 'short', day: 'numeric', month: 'short' }).format(date);\n}\n\nexport function formatMonthTitle(date: Date, locale: string | undefined): string {\n return formatter(locale, { month: 'long', year: 'numeric' }).format(date);\n}\n\nexport function formatPeriodTitle(\n period: CalendarPeriod,\n date: Date,\n range: CalendarRange,\n locale: string | undefined,\n): string {\n switch (period) {\n case CalendarView.Week:\n case NARROW_WEEK:\n return formatRange(\n formatter(locale, { day: 'numeric', month: 'short', year: 'numeric' }),\n range.start,\n addDays(range.end, -1),\n );\n case CalendarView.Day:\n return formatLongDate(date, locale);\n default:\n return formatMonthTitle(date, locale);\n }\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use client";import{MINUTES_PER_DAY as e,addDays as t,dayDiff as n,minutesOfDay as r,startOfDay as i}from"./dates.mjs";var a=864e5,o=20;function s(e){return e.end<e.start?e.start:e.end}function c(e){return!!e.allDay||s(e).getTime()-e.start.getTime()>=a}function l(e){let r=i(e.start),a=s(e);if(e.allDay){let e=i(a);return{first:r,last:n(r,e)>=1?t(e,-1):r}}return{first:r,last:a>e.start?i(new Date(a.getTime()-1)):r}}function u(e,t){let n=Number(c(t))-Number(c(e));if(n!==0)return n;let r=e.start.getTime()-t.start.getTime();if(r!==0)return r;let i=s(t).getTime()-s(e).getTime();return i===0?e.title.localeCompare(t.title):i}function d(e,t){let r=t.map(()=>[]);for(let i of e){let{first:e,last:a}=l(i);t.forEach((t,o)=>{n(e,t)>=0&&n(t,a)>=0&&r[o].push(i)})}for(let e of r)e.sort(u);return r}function f(n,a){let l=i(a),u=t(l,1),d=[];for(let t of n){if(c(t))continue;let{start:n}=t,i=s(t);if(n>=u||i<=l&&n<l)continue;let a=n<l,f=i>u,p=a?0:r(n),m=Math.max(i>=u?e:r(i),p),h=m-p<15?Math.min(m+o,e):m;d.push({event:t,top:p,bottom:m,reach:h,column:0,columns:1,span:1,continuesBefore:a,continuesAfter:f})}d.sort((e,t)=>e.top-t.top||t.reach-e.reach);let f=[],m=-1;for(let e of d)f.length>0&&e.top>=m&&(p(f),f=[]),f.push(e),m=Math.max(m,e.reach);return f.length>0&&p(f),d}function p(e){let t=[];for(let n of e){let e=t.findIndex(e=>e<=n.top);e===-1&&(e=t.push(0)-1),n.column=e,t[e]=n.reach}let n=t.length;for(let t of e){t.columns=n;let r=1;for(let i=t.column+1;i<n&&!e.some(e=>e.column===i&&e.top<t.reach&&e.reach>t.top);i++)r++;t.span=r}}function m(e,t,r=()=>!0){let i=[];for(let a of e){if(!r(a))continue;let{first:e,last:o}=l(a),s=t.findIndex(t=>n(e,t)>=0&&n(t,o)>=0);if(s===-1)continue;let c=s;for(;c+1<t.length&&n(t[c+1],o)>=0;)c++;i.push({event:a,start:s,span:c-s+1,lane:0,continuesBefore:n(e,t[s])>0,continuesAfter:n(t[c],o)>0})}i.sort((e,t)=>e.start-t.start||t.span-e.span||u(e.event,t.event));let a=[];for(let e of i){let t=a.findIndex(t=>t<=e.start);t===-1&&(t=a.push(0)-1),e.lane=t,a[t]=e.start+e.span}return i}function h(e,t,n){let r=Math.max(n-1,0),i=Array.from({length:t},()=>0);for(let t of e)for(let e=t.start;e<t.start+t.span;e++)i[e]=Math.max(i[e],t.lane+1);let a=Array.from({length:t},()=>0),o=[];for(let t of e){let e=t.lane<r;if(!e&&t.lane===r){e=!0;for(let r=t.start;r<t.start+t.span;r++)i[r]>n&&(e=!1)}if(e){o.push(t);continue}for(let e=t.start;e<t.start+t.span;e++)a[e]++}return{visible:o,moreLane:r,hidden:a}}export{u as compareEvents,l as eventDays,s as eventEnd,d as eventsByDay,c as isAllDayLike,h as limitLanes,f as packDay,m as packLanes};
1
+ "use client";import{MINUTES_PER_DAY as e,addDays as t,dayDiff as n,endAfter as r,minutesOfDay as i,shiftDays as a,startOfDay as o}from"./dates.mjs";var s=864e5,c=20;function l(e){return e.end<e.start?e.start:e.end}function u(e,t){let n=a(e.start,t),i=(l(e).getTime()-e.start.getTime())/6e4;return{start:n,end:r(n,a(l(e),t),i)}}function d(e){return!!e.allDay||l(e).getTime()-e.start.getTime()>=s}function f(e){let r=o(e.start),i=l(e);if(e.allDay){let e=o(i);return{first:r,last:n(r,e)>=1?t(e,-1):r}}return{first:r,last:i>e.start?o(new Date(i.getTime()-1)):r}}function p(e,t){let n=Number(d(t))-Number(d(e));if(n!==0)return n;let r=e.start.getTime()-t.start.getTime();if(r!==0)return r;let i=l(t).getTime()-l(e).getTime();return i===0?e.title.localeCompare(t.title):i}function m(e,t){let r=t.map(()=>[]);for(let i of e){let{first:e,last:a}=f(i);t.forEach((t,o)=>{n(e,t)>=0&&n(t,a)>=0&&r[o].push(i)})}for(let e of r)e.sort(p);return r}function h(n,r){let a=o(r),s=t(a,1),u=[];for(let t of n){if(d(t))continue;let{start:n}=t,r=l(t);if(n>=s||r<=a&&n<a)continue;let o=n<a,f=r>s,p=o?0:i(n),m=Math.max(r>=s?e:i(r),p),h=m-p<15?Math.min(m+c,e):m;u.push({event:t,top:p,bottom:m,reach:h,column:0,columns:1,span:1,continuesBefore:o,continuesAfter:f})}u.sort((e,t)=>e.top-t.top||t.reach-e.reach);let f=[],p=-1;for(let e of u)f.length>0&&e.top>=p&&(g(f),f=[]),f.push(e),p=Math.max(p,e.reach);return f.length>0&&g(f),u}function g(e){let t=[];for(let n of e){let e=t.findIndex(e=>e<=n.top);e===-1&&(e=t.push(0)-1),n.column=e,t[e]=n.reach}let n=t.length;for(let t of e){t.columns=n;let r=1;for(let i=t.column+1;i<n&&!e.some(e=>e.column===i&&e.top<t.reach&&e.reach>t.top);i++)r++;t.span=r}}function _(e,t,r=()=>!0){let i=[];for(let a of e){if(!r(a))continue;let{first:e,last:o}=f(a),s=t.findIndex(t=>n(e,t)>=0&&n(t,o)>=0);if(s===-1)continue;let c=s;for(;c+1<t.length&&n(t[c+1],o)>=0;)c++;i.push({event:a,start:s,span:c-s+1,lane:0,continuesBefore:n(e,t[s])>0,continuesAfter:n(t[c],o)>0})}i.sort((e,t)=>e.start-t.start||t.span-e.span||p(e.event,t.event));let a=[];for(let e of i){let t=a.findIndex(t=>t<=e.start);t===-1&&(t=a.push(0)-1),e.lane=t,a[t]=e.start+e.span}return i}function v(e,t,n){let r=Math.max(n-1,0),i=Array.from({length:t},()=>0);for(let t of e)for(let e=t.start;e<t.start+t.span;e++)i[e]=Math.max(i[e],t.lane+1);let a=Array.from({length:t},()=>0),o=[];for(let t of e){let e=t.lane<r;if(!e&&t.lane===r){e=!0;for(let r=t.start;r<t.start+t.span;r++)i[r]>n&&(e=!1)}if(e){o.push(t);continue}for(let e=t.start;e<t.start+t.span;e++)a[e]++}return{visible:o,moreLane:r,hidden:a}}export{p as compareEvents,f as eventDays,l as eventEnd,m as eventsByDay,d as isAllDayLike,v as limitLanes,u as moveByDays,h as packDay,_ as packLanes};
2
2
  //# sourceMappingURL=layout.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"layout.mjs","names":[],"sources":["../../../../package/common/calendar/layout.ts"],"sourcesContent":["import type { CalendarEvent } from './calendar.types';\nimport { addDays, dayDiff, MINUTES_PER_DAY, minutesOfDay, startOfDay } from './dates';\n\nconst DAY_MS = 86_400_000;\n\n/**\n * Below this an event has no room for a line of text at the default hour height. It is drawn as a\n * bar of its real length with its label beneath, and packed with room for that label.\n */\nexport const BRIEF_EVENT_MINUTES = 15;\n/** The label's line (`--label` in timeGrid.module.pcss) at the default 48px hour: 15px. */\nconst BRIEF_LABEL_MINUTES = 20;\n\n/** `end`, clamped so an event that ends before it starts is treated as having no length. */\nexport function eventEnd(event: CalendarEvent): Date {\n return event.end < event.start ? event.start : event.end;\n}\n\n/** Drawn in the all-day row rather than the time grid. */\nexport function isAllDayLike(event: CalendarEvent): boolean {\n return Boolean(event.allDay) || eventEnd(event).getTime() - event.start.getTime() >= DAY_MS;\n}\n\n/** First and last day (both midnight, both inclusive) the event appears on. */\nexport function eventDays(event: CalendarEvent): { first: Date; last: Date } {\n const first = startOfDay(event.start);\n const end = eventEnd(event);\n if (event.allDay) {\n // `end` is exclusive, but an all-day event ending on its own start day still takes that day.\n const endDay = startOfDay(end);\n return { first, last: dayDiff(first, endDay) >= 1 ? addDays(endDay, -1) : first };\n }\n // One millisecond back, so a timed event ending at midnight does not appear on the next day.\n const last = end > event.start ? startOfDay(new Date(end.getTime() - 1)) : first;\n return { first, last };\n}\n\n/** All-day events first, then by start, then the longer first, so a day reads the same everywhere. */\nexport function compareEvents(a: CalendarEvent, b: CalendarEvent): number {\n const allDay = Number(isAllDayLike(b)) - Number(isAllDayLike(a));\n if (allDay !== 0) return allDay;\n const start = a.start.getTime() - b.start.getTime();\n if (start !== 0) return start;\n const length = eventEnd(b).getTime() - eventEnd(a).getTime();\n if (length !== 0) return length;\n return a.title.localeCompare(b.title);\n}\n\n/** The events on each of `dates`, sorted with `compareEvents`. */\nexport function eventsByDay<E extends CalendarEvent>(events: readonly E[], dates: readonly Date[]): E[][] {\n const result: E[][] = dates.map(() => []);\n for (const event of events) {\n const { first, last } = eventDays(event);\n dates.forEach((day, i) => {\n if (dayDiff(first, day) >= 0 && dayDiff(day, last) >= 0) result[i].push(event);\n });\n }\n for (const day of result) day.sort(compareEvents);\n return result;\n}\n\nexport interface TimedBox<E extends CalendarEvent = CalendarEvent> {\n event: E;\n /** Wall-clock minutes from the column's midnight. */\n top: number;\n bottom: number;\n /** Where the next event in its column may start: below the label of a brief event. */\n reach: number;\n /** Left edge, as a column of `columns`. */\n column: number;\n columns: number;\n /** Columns it can widen into to its right without covering another event. */\n span: number;\n continuesBefore: boolean;\n continuesAfter: boolean;\n}\n\n/**\n * Lays out one day column of the time grid: events that overlap share the width in columns, and\n * each one widens right into columns that are free for its whole height.\n *\n * Positions are wall-clock minutes, never milliseconds from midnight. Drawing and packing have\n * to agree on that: on a 25-hour day two events in the repeated hour occupy the same rows, and\n * packing them by real time would put them in one column, drawn over each other.\n */\nexport function packDay<E extends CalendarEvent>(events: readonly E[], day: Date): TimedBox<E>[] {\n const dayStart = startOfDay(day);\n const next = addDays(dayStart, 1);\n\n const boxes: TimedBox<E>[] = [];\n for (const event of events) {\n if (isAllDayLike(event)) continue;\n const { start } = event;\n const end = eventEnd(event);\n if (start >= next) continue;\n // A zero-length event at midnight belongs to the day it starts on.\n if (end <= dayStart && start < dayStart) continue;\n\n const continuesBefore = start < dayStart;\n const continuesAfter = end > next;\n const top = continuesBefore ? 0 : minutesOfDay(start);\n // Never upside down: on the day the clocks go back, an event can end on an earlier clock time.\n const bottom = Math.max(end >= next ? MINUTES_PER_DAY : minutesOfDay(end), top);\n const reach = bottom - top < BRIEF_EVENT_MINUTES ? Math.min(bottom + BRIEF_LABEL_MINUTES, MINUTES_PER_DAY) : bottom;\n boxes.push({ event, top, bottom, reach, column: 0, columns: 1, span: 1, continuesBefore, continuesAfter });\n }\n\n boxes.sort((a, b) => a.top - b.top || b.reach - a.reach);\n\n let cluster: TimedBox<E>[] = [];\n let clusterEnd = -1;\n for (const box of boxes) {\n if (cluster.length > 0 && box.top >= clusterEnd) {\n packCluster(cluster);\n cluster = [];\n }\n cluster.push(box);\n clusterEnd = Math.max(clusterEnd, box.reach);\n }\n if (cluster.length > 0) packCluster(cluster);\n\n return boxes;\n}\n\nfunction packCluster(cluster: TimedBox[]): void {\n const columnBottoms: number[] = [];\n for (const box of cluster) {\n let column = columnBottoms.findIndex((bottom) => bottom <= box.top);\n if (column === -1) column = columnBottoms.push(0) - 1;\n box.column = column;\n columnBottoms[column] = box.reach;\n }\n const columns = columnBottoms.length;\n for (const box of cluster) {\n box.columns = columns;\n let span = 1;\n for (let column = box.column + 1; column < columns; column++) {\n const blocked = cluster.some(\n (other) => other.column === column && other.top < box.reach && other.reach > box.top,\n );\n if (blocked) break;\n span++;\n }\n box.span = span;\n }\n}\n\nexport interface LaneBar<E extends CalendarEvent = CalendarEvent> {\n event: E;\n /** First column of the row it covers, 0-based. */\n start: number;\n /** Columns it covers within the row. */\n span: number;\n lane: number;\n /** It starts before its first column: in an earlier row, or on a hidden day. */\n continuesBefore: boolean;\n continuesAfter: boolean;\n}\n\n/**\n * Stacks the events of one row of days into lanes, as the month view and the all-day row draw\n * them: longer bars first, so a multi-day event keeps one lane across the week. `dates` are the\n * row's columns, so a hidden day between two of them is simply not drawn.\n */\nexport function packLanes<E extends CalendarEvent>(\n events: readonly E[],\n dates: readonly Date[],\n include: (event: E) => boolean = () => true,\n): LaneBar<E>[] {\n const bars: LaneBar<E>[] = [];\n for (const event of events) {\n if (!include(event)) continue;\n const { first, last } = eventDays(event);\n const start = dates.findIndex((day) => dayDiff(first, day) >= 0 && dayDiff(day, last) >= 0);\n if (start === -1) continue;\n let end = start;\n while (end + 1 < dates.length && dayDiff(dates[end + 1], last) >= 0) end++;\n bars.push({\n event,\n start,\n span: end - start + 1,\n lane: 0,\n continuesBefore: dayDiff(first, dates[start]) > 0,\n continuesAfter: dayDiff(dates[end], last) > 0,\n });\n }\n\n bars.sort((a, b) => a.start - b.start || b.span - a.span || compareEvents(a.event, b.event));\n\n const laneEnds: number[] = [];\n for (const bar of bars) {\n let lane = laneEnds.findIndex((end) => end <= bar.start);\n if (lane === -1) lane = laneEnds.push(0) - 1;\n bar.lane = lane;\n laneEnds[lane] = bar.start + bar.span;\n }\n return bars;\n}\n\nexport interface LimitedLanes<E extends CalendarEvent = CalendarEvent> {\n visible: LaneBar<E>[];\n /** Lane the `+N` buttons go in, on the days that have one. */\n moreLane: number;\n /** Events hidden on each day of the row. */\n hidden: number[];\n}\n\n/**\n * Fits the bars into `capacity` lanes. A day that needs more gives its last lane to a `+N`\n * button; a day that does not keeps every bar. Decided per day, so one crowded day does not\n * hide events on the quiet days next to it. A bar crossing into a crowded day's `+N` lane is\n * hidden along its whole length and counted on each day it covers.\n */\nexport function limitLanes<E extends CalendarEvent>(\n bars: LaneBar<E>[],\n days: number,\n capacity: number,\n): LimitedLanes<E> {\n const moreLane = Math.max(capacity - 1, 0);\n const lanesPerDay = Array.from({ length: days }, () => 0);\n for (const bar of bars) {\n for (let day = bar.start; day < bar.start + bar.span; day++) {\n lanesPerDay[day] = Math.max(lanesPerDay[day], bar.lane + 1);\n }\n }\n\n const hidden = Array.from({ length: days }, () => 0);\n const visible: LaneBar<E>[] = [];\n for (const bar of bars) {\n let fits = bar.lane < moreLane;\n if (!fits && bar.lane === moreLane) {\n fits = true;\n for (let day = bar.start; day < bar.start + bar.span; day++) {\n if (lanesPerDay[day] > capacity) fits = false;\n }\n }\n if (fits) {\n visible.push(bar);\n continue;\n }\n for (let day = bar.start; day < bar.start + bar.span; day++) hidden[day]++;\n }\n return { visible, moreLane, hidden };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"layout.mjs","names":[],"sources":["../../../../package/common/calendar/layout.ts"],"sourcesContent":["import type { CalendarEvent } from './calendar.types';\nimport { addDays, dayDiff, endAfter, MINUTES_PER_DAY, minutesOfDay, shiftDays, startOfDay } from './dates';\n\nconst DAY_MS = 86_400_000;\n\n/**\n * Below this an event has no room for a line of text at the default hour height. It is drawn as a\n * bar of its real length with its label beneath, and packed with room for that label.\n */\nexport const BRIEF_EVENT_MINUTES = 15;\n/** The label's line (`--label` in timeGrid.module.pcss) at the default 48px hour: 15px. */\nconst BRIEF_LABEL_MINUTES = 20;\n\n/** `end`, clamped so an event that ends before it starts is treated as having no length. */\nexport function eventEnd(event: CalendarEvent): Date {\n return event.end < event.start ? event.start : event.end;\n}\n\n/** `event` moved by `days` calendar days, keeping its clock times and its real length. */\nexport function moveByDays(event: CalendarEvent, days: number): { start: Date; end: Date } {\n const start = shiftDays(event.start, days);\n const length = (eventEnd(event).getTime() - event.start.getTime()) / 60_000;\n return { start, end: endAfter(start, shiftDays(eventEnd(event), days), length) };\n}\n\n/** Drawn in the all-day row rather than the time grid. */\nexport function isAllDayLike(event: CalendarEvent): boolean {\n return Boolean(event.allDay) || eventEnd(event).getTime() - event.start.getTime() >= DAY_MS;\n}\n\n/** First and last day (both midnight, both inclusive) the event appears on. */\nexport function eventDays(event: CalendarEvent): { first: Date; last: Date } {\n const first = startOfDay(event.start);\n const end = eventEnd(event);\n if (event.allDay) {\n // `end` is exclusive, but an all-day event ending on its own start day still takes that day.\n const endDay = startOfDay(end);\n return { first, last: dayDiff(first, endDay) >= 1 ? addDays(endDay, -1) : first };\n }\n // One millisecond back, so a timed event ending at midnight does not appear on the next day.\n const last = end > event.start ? startOfDay(new Date(end.getTime() - 1)) : first;\n return { first, last };\n}\n\n/** All-day events first, then by start, then the longer first, so a day reads the same everywhere. */\nexport function compareEvents(a: CalendarEvent, b: CalendarEvent): number {\n const allDay = Number(isAllDayLike(b)) - Number(isAllDayLike(a));\n if (allDay !== 0) return allDay;\n const start = a.start.getTime() - b.start.getTime();\n if (start !== 0) return start;\n const length = eventEnd(b).getTime() - eventEnd(a).getTime();\n if (length !== 0) return length;\n return a.title.localeCompare(b.title);\n}\n\n/** The events on each of `dates`, sorted with `compareEvents`. */\nexport function eventsByDay<E extends CalendarEvent>(events: readonly E[], dates: readonly Date[]): E[][] {\n const result: E[][] = dates.map(() => []);\n for (const event of events) {\n const { first, last } = eventDays(event);\n dates.forEach((day, i) => {\n if (dayDiff(first, day) >= 0 && dayDiff(day, last) >= 0) result[i].push(event);\n });\n }\n for (const day of result) day.sort(compareEvents);\n return result;\n}\n\nexport interface TimedBox<E extends CalendarEvent = CalendarEvent> {\n event: E;\n /** Wall-clock minutes from the column's midnight. */\n top: number;\n bottom: number;\n /** Where the next event in its column may start: below the label of a brief event. */\n reach: number;\n /** Left edge, as a column of `columns`. */\n column: number;\n columns: number;\n /** Columns it can widen into to its right without covering another event. */\n span: number;\n continuesBefore: boolean;\n continuesAfter: boolean;\n}\n\n/**\n * Lays out one day column of the time grid: events that overlap share the width in columns, and\n * each one widens right into columns that are free for its whole height.\n *\n * Positions are wall-clock minutes, never milliseconds from midnight. Drawing and packing have\n * to agree on that: on a 25-hour day two events in the repeated hour occupy the same rows, and\n * packing them by real time would put them in one column, drawn over each other.\n */\nexport function packDay<E extends CalendarEvent>(events: readonly E[], day: Date): TimedBox<E>[] {\n const dayStart = startOfDay(day);\n const next = addDays(dayStart, 1);\n\n const boxes: TimedBox<E>[] = [];\n for (const event of events) {\n if (isAllDayLike(event)) continue;\n const { start } = event;\n const end = eventEnd(event);\n if (start >= next) continue;\n // A zero-length event at midnight belongs to the day it starts on.\n if (end <= dayStart && start < dayStart) continue;\n\n const continuesBefore = start < dayStart;\n const continuesAfter = end > next;\n const top = continuesBefore ? 0 : minutesOfDay(start);\n // Never upside down: on the day the clocks go back, an event can end on an earlier clock time.\n const bottom = Math.max(end >= next ? MINUTES_PER_DAY : minutesOfDay(end), top);\n const reach = bottom - top < BRIEF_EVENT_MINUTES ? Math.min(bottom + BRIEF_LABEL_MINUTES, MINUTES_PER_DAY) : bottom;\n boxes.push({ event, top, bottom, reach, column: 0, columns: 1, span: 1, continuesBefore, continuesAfter });\n }\n\n boxes.sort((a, b) => a.top - b.top || b.reach - a.reach);\n\n let cluster: TimedBox<E>[] = [];\n let clusterEnd = -1;\n for (const box of boxes) {\n if (cluster.length > 0 && box.top >= clusterEnd) {\n packCluster(cluster);\n cluster = [];\n }\n cluster.push(box);\n clusterEnd = Math.max(clusterEnd, box.reach);\n }\n if (cluster.length > 0) packCluster(cluster);\n\n return boxes;\n}\n\nfunction packCluster(cluster: TimedBox[]): void {\n const columnBottoms: number[] = [];\n for (const box of cluster) {\n let column = columnBottoms.findIndex((bottom) => bottom <= box.top);\n if (column === -1) column = columnBottoms.push(0) - 1;\n box.column = column;\n columnBottoms[column] = box.reach;\n }\n const columns = columnBottoms.length;\n for (const box of cluster) {\n box.columns = columns;\n let span = 1;\n for (let column = box.column + 1; column < columns; column++) {\n const blocked = cluster.some(\n (other) => other.column === column && other.top < box.reach && other.reach > box.top,\n );\n if (blocked) break;\n span++;\n }\n box.span = span;\n }\n}\n\nexport interface LaneBar<E extends CalendarEvent = CalendarEvent> {\n event: E;\n /** First column of the row it covers, 0-based. */\n start: number;\n /** Columns it covers within the row. */\n span: number;\n lane: number;\n /** It starts before its first column: in an earlier row, or on a hidden day. */\n continuesBefore: boolean;\n continuesAfter: boolean;\n}\n\n/**\n * Stacks the events of one row of days into lanes, as the month view and the all-day row draw\n * them: longer bars first, so a multi-day event keeps one lane across the week. `dates` are the\n * row's columns, so a hidden day between two of them is simply not drawn.\n */\nexport function packLanes<E extends CalendarEvent>(\n events: readonly E[],\n dates: readonly Date[],\n include: (event: E) => boolean = () => true,\n): LaneBar<E>[] {\n const bars: LaneBar<E>[] = [];\n for (const event of events) {\n if (!include(event)) continue;\n const { first, last } = eventDays(event);\n const start = dates.findIndex((day) => dayDiff(first, day) >= 0 && dayDiff(day, last) >= 0);\n if (start === -1) continue;\n let end = start;\n while (end + 1 < dates.length && dayDiff(dates[end + 1], last) >= 0) end++;\n bars.push({\n event,\n start,\n span: end - start + 1,\n lane: 0,\n continuesBefore: dayDiff(first, dates[start]) > 0,\n continuesAfter: dayDiff(dates[end], last) > 0,\n });\n }\n\n bars.sort((a, b) => a.start - b.start || b.span - a.span || compareEvents(a.event, b.event));\n\n const laneEnds: number[] = [];\n for (const bar of bars) {\n let lane = laneEnds.findIndex((end) => end <= bar.start);\n if (lane === -1) lane = laneEnds.push(0) - 1;\n bar.lane = lane;\n laneEnds[lane] = bar.start + bar.span;\n }\n return bars;\n}\n\nexport interface LimitedLanes<E extends CalendarEvent = CalendarEvent> {\n visible: LaneBar<E>[];\n /** Lane the `+N` buttons go in, on the days that have one. */\n moreLane: number;\n /** Events hidden on each day of the row. */\n hidden: number[];\n}\n\n/**\n * Fits the bars into `capacity` lanes. A day that needs more gives its last lane to a `+N`\n * button; a day that does not keeps every bar. Decided per day, so one crowded day does not\n * hide events on the quiet days next to it. A bar crossing into a crowded day's `+N` lane is\n * hidden along its whole length and counted on each day it covers.\n */\nexport function limitLanes<E extends CalendarEvent>(\n bars: LaneBar<E>[],\n days: number,\n capacity: number,\n): LimitedLanes<E> {\n const moreLane = Math.max(capacity - 1, 0);\n const lanesPerDay = Array.from({ length: days }, () => 0);\n for (const bar of bars) {\n for (let day = bar.start; day < bar.start + bar.span; day++) {\n lanesPerDay[day] = Math.max(lanesPerDay[day], bar.lane + 1);\n }\n }\n\n const hidden = Array.from({ length: days }, () => 0);\n const visible: LaneBar<E>[] = [];\n for (const bar of bars) {\n let fits = bar.lane < moreLane;\n if (!fits && bar.lane === moreLane) {\n fits = true;\n for (let day = bar.start; day < bar.start + bar.span; day++) {\n if (lanesPerDay[day] > capacity) fits = false;\n }\n }\n if (fits) {\n visible.push(bar);\n continue;\n }\n for (let day = bar.start; day < bar.start + bar.span; day++) hidden[day]++;\n }\n return { visible, moreLane, hidden };\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ "use client";import{isSameDay as e,startOfDay as t}from"./dates.mjs";import{useEffect as n,useState as r}from"react";function i(e){return e?t(new Date):new Date}function a(t){let[a,o]=r(()=>i(t));return n(()=>{let n;function r(){n=setTimeout(()=>{let n=i(t);o(r=>t&&e(r,n)?r:n),r()},6e4-Date.now()%6e4)}return r(),()=>clearTimeout(n)},[t]),a}function o(){return a(!1)}function s(){return a(!0)}export{o as useNow,s as useToday};
2
+ //# sourceMappingURL=useNow.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useNow.mjs","names":[],"sources":["../../../../package/common/calendar/useNow.ts"],"sourcesContent":["import { useEffect, useState } from 'react';\n\nimport { isSameDay, startOfDay } from './dates';\n\nfunction read(day: boolean): Date {\n return day ? startOfDay(new Date()) : new Date();\n}\n\n/**\n * Checked on each minute boundary rather than once at midnight: a long timer is paused while the\n * device sleeps, and would mark the old day for hours after waking.\n */\nfunction useClock(day: boolean): Date {\n const [now, setNow] = useState(() => read(day));\n useEffect(() => {\n let timer: ReturnType<typeof setTimeout>;\n function schedule() {\n timer = setTimeout(\n () => {\n const next = read(day);\n // The same object while the day lasts, so nothing re-renders for it.\n setNow((previous) => (day && isSameDay(previous, next) ? previous : next));\n schedule();\n },\n 60_000 - (Date.now() % 60_000),\n );\n }\n schedule();\n return () => clearTimeout(timer);\n }, [day]);\n return now;\n}\n\n/** The current time, updated on each minute boundary: it carries the now-line through the day. */\nexport function useNow(): Date {\n return useClock(false);\n}\n\n/** Midnight of today, updated when the day changes: today's mark, for a calendar left open overnight. */\nexport function useToday(): Date {\n return useClock(true);\n}\n"],"mappings":"qHAIA,SAAS,EAAK,EAAoB,CAChC,OAAO,EAAM,EAAW,IAAI,IAAM,EAAI,IAAI,IAC5C,CAMA,SAAS,EAAS,EAAoB,CACpC,GAAM,CAAC,EAAK,GAAU,MAAe,EAAK,CAAG,CAAC,EAiB9C,OAhBA,MAAgB,CACd,IAAI,EACJ,SAAS,GAAW,CAClB,EAAQ,eACA,CACJ,IAAM,EAAO,EAAK,CAAG,EAErB,EAAQ,GAAc,GAAO,EAAU,EAAU,CAAI,EAAI,EAAW,CAAK,EACzE,EAAS,CACX,EACA,IAAU,KAAK,IAAI,EAAI,GACzB,CACF,CAEA,OADA,EAAS,MACI,aAAa,CAAK,CACjC,EAAG,CAAC,CAAG,CAAC,EACD,CACT,CAGA,SAAgB,GAAe,CAC7B,OAAO,EAAS,EAAK,CACvB,CAGA,SAAgB,GAAiB,CAC/B,OAAO,EAAS,EAAI,CACtB"}
@@ -1,2 +1,2 @@
1
- "use client";import{useComponentDefaults as e}from"../configProvider/useComponentDefaults.mjs";import{isSelfActivation as t}from"../utils/activationKey.mjs";import n from"../ripple/ripple.mjs";import r from"../interactableDiv/index.mjs";import{CardStyleType as i}from"./card.types.mjs";import a from"./card.module.mjs";import{useRef as o}from"react";import s from"classnames";import{jsx as c}from"react/jsx-runtime";var l={elevated:a.cardStyleElevated,outlined:a.cardStyleOutlined,filled:a.cardStyleFilled};function u(u){let{className:d=void 0,children:f=null,styleType:p=i.Elevated,onClick:m=void 0,tabIndex:h=null,hoverEffect:g=void 0,style:_=void 0,autoGap:v=!0,clip:y=!1,onKeyDown:b,classNames:x,styles:S,...C}=e(`Card`,u),w=!!m,T=o(null);function E(e){w&&t(e)&&T.current?.addRipple(),b?.(e)}return c(r,{...C,className:s(a.card,l[p],y&&a.cardClip,w&&a.cardInteractable,(w&&g!==!1||g)&&a.cardHover,d,x?.root),onClick:m,onKeyDown:E,tabIndex:h??(w?0:null),style:{..._,...S?.root},children:c(n,{ref:T,disabled:!w,className:s(a.cardPadding,v&&a.cardGaps,x?.content),style:{borderRadius:`inherit`,...S?.content},children:f})})}export{u as default};
1
+ "use client";import{useComponentDefaults as e}from"../configProvider/useComponentDefaults.mjs";import{isSelfActivation as t}from"../utils/activationKey.mjs";import{ThemeColor as n}from"../themeProvider/color.types.mjs";import{toneProps as r,useToneCheck as i}from"../styles/tone.mjs";import a from"../ripple/ripple.mjs";import o from"../interactableDiv/index.mjs";import{CardStyleType as s}from"./card.types.mjs";import c from"./card.module.mjs";import{useRef as l}from"react";import u from"classnames";import{jsx as d}from"react/jsx-runtime";var f={elevated:c.cardStyleElevated,outlined:c.cardStyleOutlined,light:c.cardStyleLight};function p(p){let{className:m=void 0,children:h=null,styleType:g=s.Elevated,color:_=n.Neutral,onClick:v=void 0,tabIndex:y=null,hoverEffect:b=void 0,style:x=void 0,autoGap:S=!0,clip:C=!1,onKeyDown:w,classNames:T,styles:E,...D}=e(`Card`,p),O=!!v,k=r(_);i(`Card`,[_]);let A=l(null);function j(e){O&&t(e)&&A.current?.addRipple(),w?.(e)}return d(o,{...D,className:u(c.card,k.className,_===n.Neutral&&c.cardNeutral,f[g],C&&c.cardClip,O&&c.cardInteractable,(O&&b!==!1||b)&&c.cardHover,m,T?.root),onClick:v,onKeyDown:j,tabIndex:y??(O?0:null),style:{...k.style,...x,...E?.root},children:d(a,{ref:A,disabled:!O,className:u(c.cardPadding,S&&c.cardGaps,T?.content),style:{borderRadius:`inherit`,...E?.content},children:h})})}export{p as default};
2
2
  //# sourceMappingURL=Card.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"Card.mjs","names":[],"sources":["../../../../package/common/card/Card.tsx"],"sourcesContent":["import cx from 'classnames';\nimport React, { useRef } from 'react';\n\nimport { CardStyleType, type CardProps } from './card.types';\nimport styles from './card.module.pcss';\nimport InteractableDiv from '../interactableDiv';\nimport Ripple from '../ripple';\nimport type { RippleHandle } from '../ripple';\nimport { useComponentDefaults } from '../configProvider';\nimport { isSelfActivation } from '../utils/activationKey';\n\nconst CLASS_BY_STYLE: Record<CardStyleType, string> = {\n elevated: styles.cardStyleElevated,\n outlined: styles.cardStyleOutlined,\n filled: styles.cardStyleFilled,\n};\n\nfunction Card(props: CardProps) {\n const {\n className = undefined,\n children = null,\n styleType = CardStyleType.Elevated,\n onClick = undefined,\n tabIndex = null,\n hoverEffect = undefined,\n style = undefined,\n autoGap = true,\n clip = false,\n onKeyDown: onKeyDownProp,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('Card', props);\n const isInteractable = !!onClick;\n\n const rippleRef = useRef<RippleHandle>(null);\n\n // Keyboard activation calls onClick directly without dispatching a DOM click, so Ripple's own\n // listener never sees it.\n function handleKeyDown(event: React.KeyboardEvent<HTMLDivElement>) {\n if (isInteractable && isSelfActivation(event)) rippleRef.current?.addRipple();\n onKeyDownProp?.(event);\n }\n\n return (\n <InteractableDiv\n {...rest}\n className={cx(\n styles.card,\n CLASS_BY_STYLE[styleType],\n clip && styles.cardClip,\n isInteractable && styles.cardInteractable,\n ((isInteractable && hoverEffect !== false) || hoverEffect) && styles.cardHover,\n className,\n classNames?.root,\n )}\n onClick={onClick}\n onKeyDown={handleKeyDown}\n tabIndex={tabIndex ?? (isInteractable ? 0 : null)}\n style={{ ...style, ...slotStyles?.root }}\n >\n <Ripple\n ref={rippleRef}\n disabled={!isInteractable}\n className={cx(styles.cardPadding, autoGap && styles.cardGaps, classNames?.content)}\n style={{ borderRadius: 'inherit', ...slotStyles?.content }}\n >\n {children}\n </Ripple>\n </InteractableDiv>\n );\n}\n\nexport default Card;\n"],"mappings":"gaAWA,IAAM,EAAgD,CACpD,SAAU,EAAO,kBACjB,SAAU,EAAO,kBACjB,OAAQ,EAAO,eACjB,EAEA,SAAS,EAAK,EAAkB,CAC9B,GAAM,CACJ,YAAY,IAAA,GACZ,WAAW,KACX,YAAY,EAAc,SAC1B,UAAU,IAAA,GACV,WAAW,KACX,cAAc,IAAA,GACd,QAAQ,IAAA,GACR,UAAU,GACV,OAAO,GACP,UAAW,EACX,aACA,OAAQ,EACR,GAAG,GACD,EAAqB,OAAQ,CAAK,EAChC,EAAiB,CAAC,CAAC,EAEnB,EAAY,EAAqB,IAAI,EAI3C,SAAS,EAAc,EAA4C,CAC7D,GAAkB,EAAiB,CAAK,GAAG,EAAU,SAAS,UAAU,EAC5E,IAAgB,CAAK,CACvB,CAEA,OACE,EAAC,EAAD,CACE,GAAI,EACJ,UAAW,EACT,EAAO,KACP,EAAe,GACf,GAAQ,EAAO,SACf,GAAkB,EAAO,kBACvB,GAAkB,IAAgB,IAAU,IAAgB,EAAO,UACrE,EACA,GAAY,IACd,EACS,UACT,UAAW,EACX,SAAU,IAAa,EAAiB,EAAI,MAC5C,MAAO,CAAE,GAAG,EAAO,GAAG,GAAY,IAAK,EAEvC,SAAA,EAAC,EAAD,CACE,IAAK,EACL,SAAU,CAAC,EACX,UAAW,EAAG,EAAO,YAAa,GAAW,EAAO,SAAU,GAAY,OAAO,EACjF,MAAO,CAAE,aAAc,UAAW,GAAG,GAAY,OAAQ,EAExD,UACK,CAAA,CACO,CAAA,CAErB"}
1
+ {"version":3,"file":"Card.mjs","names":[],"sources":["../../../../package/common/card/Card.tsx"],"sourcesContent":["import cx from 'classnames';\nimport React, { useRef } from 'react';\n\nimport { CardStyleType, type CardProps } from './card.types';\nimport styles from './card.module.pcss';\nimport InteractableDiv from '../interactableDiv';\nimport Ripple from '../ripple';\nimport type { RippleHandle } from '../ripple';\nimport { useComponentDefaults } from '../configProvider';\nimport { isSelfActivation } from '../utils/activationKey';\nimport { ThemeColor } from '../themeProvider/color.types';\nimport { toneProps, useToneCheck } from '../styles/tone';\n\nconst CLASS_BY_STYLE: Record<CardStyleType, string> = {\n elevated: styles.cardStyleElevated,\n outlined: styles.cardStyleOutlined,\n light: styles.cardStyleLight,\n};\n\nfunction Card(props: CardProps) {\n const {\n className = undefined,\n children = null,\n styleType = CardStyleType.Elevated,\n color = ThemeColor.Neutral,\n onClick = undefined,\n tabIndex = null,\n hoverEffect = undefined,\n style = undefined,\n autoGap = true,\n clip = false,\n onKeyDown: onKeyDownProp,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('Card', props);\n const isInteractable = !!onClick;\n const tone = toneProps(color);\n useToneCheck('Card', [color]);\n\n const rippleRef = useRef<RippleHandle>(null);\n\n // Keyboard activation calls onClick directly without dispatching a DOM click, so Ripple's own\n // listener never sees it.\n function handleKeyDown(event: React.KeyboardEvent<HTMLDivElement>) {\n if (isInteractable && isSelfActivation(event)) rippleRef.current?.addRipple();\n onKeyDownProp?.(event);\n }\n\n return (\n <InteractableDiv\n {...rest}\n className={cx(\n styles.card,\n tone.className,\n color === ThemeColor.Neutral && styles.cardNeutral,\n CLASS_BY_STYLE[styleType],\n clip && styles.cardClip,\n isInteractable && styles.cardInteractable,\n ((isInteractable && hoverEffect !== false) || hoverEffect) && styles.cardHover,\n className,\n classNames?.root,\n )}\n onClick={onClick}\n onKeyDown={handleKeyDown}\n tabIndex={tabIndex ?? (isInteractable ? 0 : null)}\n style={{ ...tone.style, ...style, ...slotStyles?.root }}\n >\n <Ripple\n ref={rippleRef}\n disabled={!isInteractable}\n className={cx(styles.cardPadding, autoGap && styles.cardGaps, classNames?.content)}\n style={{ borderRadius: 'inherit', ...slotStyles?.content }}\n >\n {children}\n </Ripple>\n </InteractableDiv>\n );\n}\n\nexport default Card;\n"],"mappings":"+hBAaA,IAAM,EAAgD,CACpD,SAAU,EAAO,kBACjB,SAAU,EAAO,kBACjB,MAAO,EAAO,cAChB,EAEA,SAAS,EAAK,EAAkB,CAC9B,GAAM,CACJ,YAAY,IAAA,GACZ,WAAW,KACX,YAAY,EAAc,SAC1B,QAAQ,EAAW,QACnB,UAAU,IAAA,GACV,WAAW,KACX,cAAc,IAAA,GACd,QAAQ,IAAA,GACR,UAAU,GACV,OAAO,GACP,UAAW,EACX,aACA,OAAQ,EACR,GAAG,GACD,EAAqB,OAAQ,CAAK,EAChC,EAAiB,CAAC,CAAC,EACnB,EAAO,EAAU,CAAK,EAC5B,EAAa,OAAQ,CAAC,CAAK,CAAC,EAE5B,IAAM,EAAY,EAAqB,IAAI,EAI3C,SAAS,EAAc,EAA4C,CAC7D,GAAkB,EAAiB,CAAK,GAAG,EAAU,SAAS,UAAU,EAC5E,IAAgB,CAAK,CACvB,CAEA,OACE,EAAC,EAAD,CACE,GAAI,EACJ,UAAW,EACT,EAAO,KACP,EAAK,UACL,IAAU,EAAW,SAAW,EAAO,YACvC,EAAe,GACf,GAAQ,EAAO,SACf,GAAkB,EAAO,kBACvB,GAAkB,IAAgB,IAAU,IAAgB,EAAO,UACrE,EACA,GAAY,IACd,EACS,UACT,UAAW,EACX,SAAU,IAAa,EAAiB,EAAI,MAC5C,MAAO,CAAE,GAAG,EAAK,MAAO,GAAG,EAAO,GAAG,GAAY,IAAK,EAEtD,SAAA,EAAC,EAAD,CACE,IAAK,EACL,SAAU,CAAC,EACX,UAAW,EAAG,EAAO,YAAa,GAAW,EAAO,SAAU,GAAY,OAAO,EACjF,MAAO,CAAE,aAAc,UAAW,GAAG,GAAY,OAAQ,EAExD,UACK,CAAA,CACO,CAAA,CAErB"}
@@ -1,2 +1,2 @@
1
- "use client";import{ButtonStyleType as e}from"../button/button.types.mjs";import t from"../button/button.mjs";import n from"./card.module.mjs";import"react";import r from"classnames";import{jsx as i,jsxs as a}from"react/jsx-runtime";function o({className:o=``,actions:s=[],children:c=null}){return a(`div`,{className:r(n.cardActions,o),children:[s.map(({id:n,onClick:r,label:a,styleType:o=e.Default})=>i(`div`,{children:i(t,{onClick:r,styleType:o,children:a})},n??a)),c]})}export{o as default};
1
+ "use client";import e from"../button/button.mjs";import t from"./card.module.mjs";import"react";import n from"classnames";import{jsx as r,jsxs as i}from"react/jsx-runtime";function a({className:a=``,actions:o=[],children:s=null}){return i(`div`,{className:n(t.cardActions,a),children:[o.map(({id:t,onClick:n,label:i,styleType:a,color:o})=>r(`div`,{children:r(e,{onClick:n,styleType:a,color:o,children:i})},t??i)),s]})}export{a as default};
2
2
  //# sourceMappingURL=CardActions.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"CardActions.mjs","names":[],"sources":["../../../../package/common/card/CardActions.tsx"],"sourcesContent":["import React from 'react';\nimport cx from 'classnames';\nimport Button from '../button';\nimport { ButtonStyleType } from '../button/button.types';\n\nimport type { CardActionsProps } from './card.types';\nimport styles from './card.module.pcss';\n\nfunction CardActions({ className = '', actions = [], children = null }: CardActionsProps) {\n return (\n <div className={cx(styles.cardActions, className)}>\n {actions.map(({ id, onClick, label, styleType = ButtonStyleType.Default }) => (\n <div key={id ?? label}>\n <Button onClick={onClick} styleType={styleType}>\n {label}\n </Button>\n </div>\n ))}\n {children}\n </div>\n );\n}\n\nexport default CardActions;\n"],"mappings":"yOAQA,SAAS,EAAY,CAAE,YAAY,GAAI,UAAU,CAAC,EAAG,WAAW,MAA0B,CACxF,OACE,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,YAAa,CAAS,EAAhD,SAAA,CACG,EAAQ,KAAK,CAAE,KAAI,UAAS,QAAO,YAAY,EAAgB,WAC9D,EAAC,MAAD,CAAA,SACE,EAAC,EAAD,CAAiB,UAAoB,YAClC,SAAA,CACK,CAAA,CACL,EAJK,GAAM,CAIX,CACN,EACA,CACE,GAET"}
1
+ {"version":3,"file":"CardActions.mjs","names":[],"sources":["../../../../package/common/card/CardActions.tsx"],"sourcesContent":["import React from 'react';\nimport cx from 'classnames';\nimport Button from '../button';\n\nimport type { CardActionsProps } from './card.types';\nimport styles from './card.module.pcss';\n\nfunction CardActions({ className = '', actions = [], children = null }: CardActionsProps) {\n return (\n <div className={cx(styles.cardActions, className)}>\n {actions.map(({ id, onClick, label, styleType, color }) => (\n <div key={id ?? label}>\n <Button onClick={onClick} styleType={styleType} color={color}>\n {label}\n </Button>\n </div>\n ))}\n {children}\n </div>\n );\n}\n\nexport default CardActions;\n"],"mappings":"4KAOA,SAAS,EAAY,CAAE,YAAY,GAAI,UAAU,CAAC,EAAG,WAAW,MAA0B,CACxF,OACE,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,YAAa,CAAS,EAAhD,SAAA,CACG,EAAQ,KAAK,CAAE,KAAI,UAAS,QAAO,YAAW,WAC7C,EAAC,MAAD,CAAA,SACE,EAAC,EAAD,CAAiB,UAAoB,YAAkB,QACpD,SAAA,CACK,CAAA,CACL,EAJK,GAAM,CAIX,CACN,EACA,CACE,GAET"}
@@ -1 +1 @@
1
- {"version":3,"file":"CardHeader.mjs","names":[],"sources":["../../../../package/common/card/CardHeader.tsx"],"sourcesContent":["import React from 'react';\nimport cx from 'classnames';\n\nimport type { CardHeaderProps } from './card.types';\nimport styles from './card.module.pcss';\nimport ActionIcon from '../actionIcon';\n\nfunction CardHeader({\n className = '',\n title = '',\n subTitle = '',\n thumbnail = '',\n actions = undefined,\n}: CardHeaderProps) {\n const thumbnailUrl = typeof thumbnail === 'string' && thumbnail.startsWith('http') ? thumbnail : undefined;\n\n return (\n <div className={cx(styles.cardHeader, className)}>\n {thumbnail && (\n <div\n className={styles.cardHeaderThumbnail}\n style={thumbnailUrl ? { backgroundImage: `url(${thumbnailUrl})` } : {}}\n >\n {!thumbnailUrl && thumbnail}\n </div>\n )}\n <div className={styles.cardHeaderTitles}>\n <div className={styles.cardHeaderTitlesMainContainer}>\n <div className={styles.cardHeaderTitlesMain}>{title}</div>\n <div className={styles.cardHeaderActions}>\n {Array.isArray(actions)\n ? actions.map((action, index) => (\n <ActionIcon\n key={index}\n title={action.title}\n onClick={\n action.onClick\n ? (e: React.MouseEvent<HTMLDivElement>) => {\n e.stopPropagation();\n action.onClick?.(e);\n }\n : undefined\n }\n icon={action.icon}\n />\n ))\n : actions}\n </div>\n </div>\n <div className={styles.cardHeaderTitlesSub}>{subTitle}</div>\n </div>\n </div>\n );\n}\n\nexport default CardHeader;\n"],"mappings":"oLAOA,SAAS,EAAW,CAClB,YAAY,GACZ,QAAQ,GACR,WAAW,GACX,YAAY,GACZ,UAAU,IAAA,IACQ,CAClB,IAAM,EAAe,OAAO,GAAc,UAAY,EAAU,WAAW,MAAM,EAAI,EAAY,IAAA,GAEjG,OACE,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,WAAY,CAAS,EAA/C,SAAA,CACG,GACC,EAAC,MAAD,CACE,UAAW,EAAO,oBAClB,MAAO,EAAe,CAAE,gBAAiB,OAAO,EAAa,EAAG,EAAI,CAAC,EAEpE,SAAA,CAAC,GAAgB,CACf,CAAA,EAEP,EAAC,MAAD,CAAK,UAAW,EAAO,iBAAvB,SAAA,CACE,EAAC,MAAD,CAAK,UAAW,EAAO,8BAAvB,SAAA,CACE,EAAC,MAAD,CAAK,UAAW,EAAO,qBAAuB,SAAA,CAAW,CAAA,EACzD,EAAC,MAAD,CAAK,UAAW,EAAO,kBACpB,SAAA,MAAM,QAAQ,CAAO,EAClB,EAAQ,KAAK,EAAQ,IACnB,EAAC,EAAD,CAEE,MAAO,EAAO,MACd,QACE,EAAO,QACF,GAAwC,CACvC,EAAE,gBAAgB,EAClB,EAAO,UAAU,CAAC,CACpB,EACA,IAAA,GAEN,KAAM,EAAO,IACd,EAXM,CAWN,CACF,EACD,CACD,CAAA,CACF,CACL,CAAA,EAAA,EAAC,MAAD,CAAK,UAAW,EAAO,oBAAsB,SAAA,CAAc,CAAA,CACxD,CACF,CAAA,CAAA,GAET"}
1
+ {"version":3,"file":"CardHeader.mjs","names":[],"sources":["../../../../package/common/card/CardHeader.tsx"],"sourcesContent":["import React from 'react';\nimport cx from 'classnames';\n\nimport type { CardHeaderProps } from './card.types';\nimport styles from './card.module.pcss';\nimport ActionIcon from '../actionIcon';\n\nfunction CardHeader({\n className = '',\n title = '',\n subTitle = '',\n thumbnail = '',\n actions = undefined,\n}: CardHeaderProps) {\n const thumbnailUrl = typeof thumbnail === 'string' && thumbnail.startsWith('http') ? thumbnail : undefined;\n\n return (\n <div className={cx(styles.cardHeader, className)}>\n {thumbnail && (\n <div\n className={styles.cardHeaderThumbnail}\n style={thumbnailUrl ? { backgroundImage: `url(${thumbnailUrl})` } : {}}\n >\n {!thumbnailUrl && thumbnail}\n </div>\n )}\n <div className={styles.cardHeaderTitles}>\n <div className={styles.cardHeaderTitlesMainContainer}>\n <div className={styles.cardHeaderTitlesMain}>{title}</div>\n <div className={styles.cardHeaderActions}>\n {Array.isArray(actions)\n ? actions.map((action, index) => (\n <ActionIcon\n key={index}\n title={action.title}\n onClick={\n action.onClick\n ? (e: React.MouseEvent<HTMLButtonElement>) => {\n e.stopPropagation();\n action.onClick?.(e);\n }\n : undefined\n }\n icon={action.icon}\n />\n ))\n : actions}\n </div>\n </div>\n <div className={styles.cardHeaderTitlesSub}>{subTitle}</div>\n </div>\n </div>\n );\n}\n\nexport default CardHeader;\n"],"mappings":"oLAOA,SAAS,EAAW,CAClB,YAAY,GACZ,QAAQ,GACR,WAAW,GACX,YAAY,GACZ,UAAU,IAAA,IACQ,CAClB,IAAM,EAAe,OAAO,GAAc,UAAY,EAAU,WAAW,MAAM,EAAI,EAAY,IAAA,GAEjG,OACE,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,WAAY,CAAS,EAA/C,SAAA,CACG,GACC,EAAC,MAAD,CACE,UAAW,EAAO,oBAClB,MAAO,EAAe,CAAE,gBAAiB,OAAO,EAAa,EAAG,EAAI,CAAC,EAEpE,SAAA,CAAC,GAAgB,CACf,CAAA,EAEP,EAAC,MAAD,CAAK,UAAW,EAAO,iBAAvB,SAAA,CACE,EAAC,MAAD,CAAK,UAAW,EAAO,8BAAvB,SAAA,CACE,EAAC,MAAD,CAAK,UAAW,EAAO,qBAAuB,SAAA,CAAW,CAAA,EACzD,EAAC,MAAD,CAAK,UAAW,EAAO,kBACpB,SAAA,MAAM,QAAQ,CAAO,EAClB,EAAQ,KAAK,EAAQ,IACnB,EAAC,EAAD,CAEE,MAAO,EAAO,MACd,QACE,EAAO,QACF,GAA2C,CAC1C,EAAE,gBAAgB,EAClB,EAAO,UAAU,CAAC,CACpB,EACA,IAAA,GAEN,KAAM,EAAO,IACd,EAXM,CAWN,CACF,EACD,CACD,CAAA,CACF,CACL,CAAA,EAAA,EAAC,MAAD,CAAK,UAAW,EAAO,oBAAsB,SAAA,CAAc,CAAA,CACxD,CACF,CAAA,CAAA,GAET"}
@@ -1,2 +1,2 @@
1
- "use client";var e=`card_w-6Ki`,t=`card-clip_eZ8-1`,n=`card-padding_X2-q-`,r=`card-gaps_jhYkx`,i=`card-style-elevated_exvMB`,a=`card-style-outlined_PxZZA`,o=`card-style-filled_2nhAY`,s=`card-interactable_az2lE`,c=`card-hover_fdS-X`,l=`cardHeader_HfIlm`,u=`cardHeader-thumbnail_rFw-N`,d=`cardHeader-actions_awD46`,f=`cardHeader-titles_CAUU3`,p=`cardHeader-titles-main_Z834V`,m=`cardHeader-titles-main-container_1j-od`,h=`cardHeader-titles-sub_2X08b`,g=`cardMedia_GZJQF`,_=`cardActions_uYu-0`,v={card:e,"card-clip":`card-clip_eZ8-1`,cardClip:t,"card-padding":`card-padding_X2-q-`,cardPadding:n,"card-gaps":`card-gaps_jhYkx`,cardGaps:r,"card-style-elevated":`card-style-elevated_exvMB`,cardStyleElevated:i,"card-style-outlined":`card-style-outlined_PxZZA`,cardStyleOutlined:a,"card-style-filled":`card-style-filled_2nhAY`,cardStyleFilled:o,"card-interactable":`card-interactable_az2lE`,cardInteractable:s,"card-hover":`card-hover_fdS-X`,cardHover:c,cardHeader:l,"cardHeader-thumbnail":`cardHeader-thumbnail_rFw-N`,cardHeaderThumbnail:u,"cardHeader-actions":`cardHeader-actions_awD46`,cardHeaderActions:d,"cardHeader-titles":`cardHeader-titles_CAUU3`,cardHeaderTitles:f,"cardHeader-titles-main":`cardHeader-titles-main_Z834V`,cardHeaderTitlesMain:p,"cardHeader-titles-main-container":`cardHeader-titles-main-container_1j-od`,cardHeaderTitlesMainContainer:m,"cardHeader-titles-sub":`cardHeader-titles-sub_2X08b`,cardHeaderTitlesSub:h,cardMedia:g,cardActions:_};export{e as card,_ as cardActions,t as cardClip,r as cardGaps,l as cardHeader,d as cardHeaderActions,u as cardHeaderThumbnail,f as cardHeaderTitles,p as cardHeaderTitlesMain,m as cardHeaderTitlesMainContainer,h as cardHeaderTitlesSub,c as cardHover,s as cardInteractable,g as cardMedia,n as cardPadding,i as cardStyleElevated,o as cardStyleFilled,a as cardStyleOutlined,v as default};
1
+ "use client";var e=`card_w-6Ki`,t=`card-clip_eZ8-1`,n=`card-padding_X2-q-`,r=`card-gaps_jhYkx`,i=`card-style-elevated_exvMB`,a=`card-style-outlined_PxZZA`,o=`card-style-light_J5TME`,s=`card-neutral_AZL-v`,c=`card-interactable_az2lE`,l=`card-hover_fdS-X`,u=`cardHeader_HfIlm`,d=`cardHeader-thumbnail_rFw-N`,f=`cardHeader-actions_awD46`,p=`cardHeader-titles_CAUU3`,m=`cardHeader-titles-main_Z834V`,h=`cardHeader-titles-main-container_1j-od`,g=`cardHeader-titles-sub_2X08b`,_=`cardMedia_GZJQF`,v=`cardActions_uYu-0`,y={card:e,"card-clip":`card-clip_eZ8-1`,cardClip:t,"card-padding":`card-padding_X2-q-`,cardPadding:n,"card-gaps":`card-gaps_jhYkx`,cardGaps:r,"card-style-elevated":`card-style-elevated_exvMB`,cardStyleElevated:i,"card-style-outlined":`card-style-outlined_PxZZA`,cardStyleOutlined:a,"card-style-light":`card-style-light_J5TME`,cardStyleLight:o,"card-neutral":`card-neutral_AZL-v`,cardNeutral:s,"card-interactable":`card-interactable_az2lE`,cardInteractable:c,"card-hover":`card-hover_fdS-X`,cardHover:l,cardHeader:u,"cardHeader-thumbnail":`cardHeader-thumbnail_rFw-N`,cardHeaderThumbnail:d,"cardHeader-actions":`cardHeader-actions_awD46`,cardHeaderActions:f,"cardHeader-titles":`cardHeader-titles_CAUU3`,cardHeaderTitles:p,"cardHeader-titles-main":`cardHeader-titles-main_Z834V`,cardHeaderTitlesMain:m,"cardHeader-titles-main-container":`cardHeader-titles-main-container_1j-od`,cardHeaderTitlesMainContainer:h,"cardHeader-titles-sub":`cardHeader-titles-sub_2X08b`,cardHeaderTitlesSub:g,cardMedia:_,cardActions:v};export{e as card,v as cardActions,t as cardClip,r as cardGaps,u as cardHeader,f as cardHeaderActions,d as cardHeaderThumbnail,p as cardHeaderTitles,m as cardHeaderTitlesMain,h as cardHeaderTitlesMainContainer,g as cardHeaderTitlesSub,l as cardHover,c as cardInteractable,_ as cardMedia,s as cardNeutral,n as cardPadding,i as cardStyleElevated,o as cardStyleLight,a as cardStyleOutlined,y as default};
2
2
  //# sourceMappingURL=card.module.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"card.module.mjs","names":[],"sources":["../../../../package/common/card/card.module.pcss"],"sourcesContent":[".card {\n border-radius: var(--default-border-radius);\n color: var(--text-color);\n border: 1px solid transparent;\n box-sizing: border-box;\n\n &-clip {\n overflow: hidden;\n }\n\n &-padding {\n padding: 1em;\n }\n\n &-gaps {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-s);\n }\n\n &-style {\n &-elevated {\n background: var(--background-card-elevated, var(--background-accent-light));\n box-shadow: var(--card-shadow);\n }\n\n &-outlined {\n background: var(--background-card-outlined, transparent);\n border-color: var(--border-color);\n }\n\n &-filled {\n background: var(--background-card-filled, var(--background-accent));\n }\n }\n\n &-interactable {\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n }\n\n &-hover {\n transition:\n transform 0.15s ease,\n box-shadow 0.15s ease,\n filter 0.3s ease;\n\n &:hover {\n transform: translateY(-2px);\n background: var(--background-accent);\n }\n }\n}\n\n.cardHeader {\n display: flex;\n gap: 1em;\n align-items: center;\n\n &-thumbnail {\n display: flex;\n justify-content: center;\n align-items: center;\n width: 2.5em;\n height: 2.5em;\n background: rgb(0 0 0 / 8%);\n border-radius: 50%;\n overflow: hidden;\n background-size: cover;\n background-position: center;\n flex-shrink: 0;\n }\n\n &-actions {\n display: flex;\n gap: var(--spacing-s);\n flex-wrap: wrap;\n flex-shrink: 1;\n align-items: center;\n justify-content: flex-end;\n }\n\n &-titles {\n display: flex;\n flex-flow: column;\n flex: 1;\n gap: 0.25em;\n overflow: hidden;\n\n &-main {\n font-size: 1.125em;\n font-weight: 600;\n min-width: 3ch;\n flex-shrink: 100000;\n overflow: hidden;\n text-overflow: ellipsis;\n\n &-container {\n display: flex;\n align-items: center;\n gap: var(--spacing-m);\n justify-content: space-between;\n }\n }\n\n &-sub {\n font-weight: 300;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n }\n}\n\n/* Pulled out to the card's own edges, so these must stay twice and once .card-padding above. */\n.cardMedia {\n width: calc(100% + 2em);\n margin: 0 -1em;\n}\n\n.cardActions {\n display: flex;\n flex-wrap: wrap;\n gap: 0.5em;\n}\n\n/* The lift on hover is the only motion here; the shadow and border it transitions alongside stay. */\n@media (prefers-reduced-motion: reduce) {\n .card-hover:hover {\n transform: none;\n }\n}\n"],"mappings":""}
1
+ {"version":3,"file":"card.module.mjs","names":[],"sources":["../../../../package/common/card/card.module.pcss"],"sourcesContent":[".card {\n border-radius: var(--default-border-radius);\n color: var(--text-color);\n border: 1px solid transparent;\n box-sizing: border-box;\n\n &-clip {\n overflow: hidden;\n }\n\n &-padding {\n padding: 1em;\n }\n\n &-gaps {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-s);\n }\n\n &-style {\n &-elevated {\n background: var(--background-card-elevated, var(--background-accent-light));\n box-shadow: var(--card-shadow);\n }\n\n &-outlined {\n background: var(--background-card-outlined, transparent);\n border-color: var(--tone-outline);\n }\n\n &-light {\n background: var(--tone-light);\n }\n }\n\n /* A theme may give the Neutral card a surface of its own; any other colour's tint is the point. */\n &-neutral&-style-light {\n background: var(--background-card-filled, var(--tone-light));\n }\n\n &-interactable {\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n }\n\n &-hover {\n position: relative;\n transition:\n transform 0.15s ease,\n box-shadow 0.15s ease,\n filter 0.3s ease;\n\n /* A layer over the card's own surface, so a coloured card keeps its colour. Opacity, because\n Chromium does not interpolate a currentcolor mix. Paints under the later Ripple wrapper. */\n &::before {\n content: '';\n position: absolute;\n inset: 0;\n border-radius: inherit;\n background: currentcolor;\n opacity: 0;\n transition: opacity 0.15s ease;\n pointer-events: none;\n }\n\n &:hover {\n transform: translateY(-2px);\n\n &::before {\n opacity: 0.05;\n }\n }\n }\n}\n\n.cardHeader {\n display: flex;\n gap: 1em;\n align-items: center;\n\n &-thumbnail {\n display: flex;\n justify-content: center;\n align-items: center;\n width: 2.5em;\n height: 2.5em;\n background: rgb(0 0 0 / 8%);\n border-radius: 50%;\n overflow: hidden;\n background-size: cover;\n background-position: center;\n flex-shrink: 0;\n }\n\n &-actions {\n display: flex;\n gap: var(--spacing-s);\n flex-wrap: wrap;\n flex-shrink: 1;\n align-items: center;\n justify-content: flex-end;\n }\n\n &-titles {\n display: flex;\n flex-flow: column;\n flex: 1;\n gap: 0.25em;\n overflow: hidden;\n\n &-main {\n font-size: 1.125em;\n font-weight: 600;\n min-width: 3ch;\n flex-shrink: 100000;\n overflow: hidden;\n text-overflow: ellipsis;\n\n &-container {\n display: flex;\n align-items: center;\n gap: var(--spacing-m);\n justify-content: space-between;\n }\n }\n\n &-sub {\n font-weight: 300;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n }\n}\n\n/* Pulled out to the card's own edges, so these must stay twice and once .card-padding above. */\n.cardMedia {\n width: calc(100% + 2em);\n margin: 0 -1em;\n}\n\n.cardActions {\n display: flex;\n flex-wrap: wrap;\n gap: 0.5em;\n}\n\n/* The lift on hover is the only motion here; the shadow and border it transitions alongside stay. */\n@media (prefers-reduced-motion: reduce) {\n .card-hover:hover {\n transform: none;\n }\n}\n"],"mappings":""}
@@ -1,2 +1,2 @@
1
- "use client";var e=function(e){return e.Elevated=`elevated`,e.Outlined=`outlined`,e.Filled=`filled`,e}({});export{e as CardStyleType};
1
+ "use client";var e=function(e){return e.Elevated=`elevated`,e.Outlined=`outlined`,e.Light=`light`,e}({});export{e as CardStyleType};
2
2
  //# sourceMappingURL=card.types.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"card.types.mjs","names":[],"sources":["../../../../package/common/card/card.types.ts"],"sourcesContent":["import type React from 'react';\nimport type { ReactNode } from 'react';\nimport type { ButtonStyleType } from '../button/button.types';\nimport type { HtmlProps, SlotClassNames, SlotStyles } from '../types/slots.types';\nimport type { IconAction } from '../types/actions.types';\n\nexport enum CardStyleType {\n Elevated = 'elevated',\n Outlined = 'outlined',\n Filled = 'filled',\n}\n\n// `tabIndex` is omitted only because this component's version also accepts `null`.\nexport type CardSlots = 'root' | 'content';\n\nexport interface CardProps extends Omit<HtmlProps, 'tabIndex'> {\n className?: string | undefined;\n children?: ReactNode;\n styleType?: CardStyleType;\n onClick?: () => void;\n tabIndex?: number | null;\n hoverEffect?: boolean;\n style?: React.CSSProperties;\n autoGap?: boolean;\n clip?: boolean;\n /** Ref to the root element. */\n ref?: React.Ref<HTMLDivElement>;\n /** Classes for the inner elements. See `CardSlots`. */\n classNames?: SlotClassNames<CardSlots>;\n /** Inline styles for the inner elements. See `CardSlots`. */\n styles?: SlotStyles<CardSlots>;\n}\n\nexport type CardHeaderAction = IconAction;\n\nexport interface CardHeaderProps {\n className?: string;\n title?: ReactNode;\n subTitle?: ReactNode;\n /** URL string → rendered as background-image. Any other ReactNode → rendered inside the thumbnail div. */\n thumbnail?: string | ReactNode;\n actions?: CardHeaderAction[] | ReactNode;\n}\n\nexport interface CardMediaProps {\n src?: string;\n alt?: string;\n}\n\nexport interface CardContentProps {\n children?: ReactNode;\n}\n\nexport interface CardAction {\n id?: string;\n label?: string;\n styleType?: ButtonStyleType;\n onClick?: () => void;\n}\n\nexport interface CardActionsProps {\n className?: string;\n /** Renders a Button for each action object. Pass `children` for custom content instead. */\n actions?: CardAction[];\n children?: ReactNode;\n}\n"],"mappings":"aAMA,IAAY,EAAL,SAAA,EAAA,OACL,GAAA,SAAA,WACA,EAAA,SAAA,WACA,EAAA,OAAA,UACF,EAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"card.types.mjs","names":[],"sources":["../../../../package/common/card/card.types.ts"],"sourcesContent":["import type React from 'react';\nimport type { ReactNode } from 'react';\nimport type { ButtonProps, ButtonStyleType } from '../button/button.types';\nimport type { HtmlProps, SlotClassNames, SlotStyles } from '../types/slots.types';\nimport type { IconAction } from '../types/actions.types';\nimport type { ColorValue } from '../themeProvider/color.types';\n\n/**\n * The card's surface. `Outlined` and `Light` mean what they do on Button, Badge and Chip; `Elevated`\n * is a card's own. There is no `Filled`: body text on a solid colour reads badly.\n */\nexport enum CardStyleType {\n /** A raised surface with a shadow, always neutral. The default. */\n Elevated = 'elevated',\n /** A border in the colour, no fill. */\n Outlined = 'outlined',\n /** A flat tint of the colour, no border. */\n Light = 'light',\n}\n\n// `tabIndex` is omitted only because this component's version also accepts `null`.\nexport type CardSlots = 'root' | 'content';\n\nexport interface CardProps extends Omit<HtmlProps, 'tabIndex'> {\n className?: string | undefined;\n children?: ReactNode;\n styleType?: CardStyleType;\n /**\n * The border of an `Outlined` card and the tint of a `Light` one: a `ThemeColor` (default\n * `Neutral`) or any CSS colour. An `Elevated` card stays neutral.\n */\n color?: ColorValue;\n onClick?: () => void;\n tabIndex?: number | null;\n hoverEffect?: boolean;\n style?: React.CSSProperties;\n autoGap?: boolean;\n clip?: boolean;\n /** Ref to the root element. */\n ref?: React.Ref<HTMLDivElement>;\n /** Classes for the inner elements. See `CardSlots`. */\n classNames?: SlotClassNames<CardSlots>;\n /** Inline styles for the inner elements. See `CardSlots`. */\n styles?: SlotStyles<CardSlots>;\n}\n\nexport type CardHeaderAction = IconAction;\n\nexport interface CardHeaderProps {\n className?: string;\n title?: ReactNode;\n subTitle?: ReactNode;\n /** URL string → rendered as background-image. Any other ReactNode → rendered inside the thumbnail div. */\n thumbnail?: string | ReactNode;\n actions?: CardHeaderAction[] | ReactNode;\n}\n\nexport interface CardMediaProps {\n src?: string;\n alt?: string;\n}\n\nexport interface CardContentProps {\n children?: ReactNode;\n}\n\nexport interface CardAction {\n id?: string;\n label?: string;\n styleType?: ButtonStyleType;\n color?: ButtonProps['color'];\n onClick?: () => void;\n}\n\nexport interface CardActionsProps {\n className?: string;\n /** Renders a Button for each action object. Pass `children` for custom content instead. */\n actions?: CardAction[];\n children?: ReactNode;\n}\n"],"mappings":"aAWA,IAAY,EAAL,SAAA,EAAA,OAEL,GAAA,SAAA,WAEA,EAAA,SAAA,WAEA,EAAA,MAAA,SACF,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 n from"../interactableDiv/index.mjs";import r from"../actionIcon/actionIcon.mjs";import i from"./carousel.module.mjs";import a from"../styles/scrollFade.module.mjs";import o,{useEffect as ee,useLayoutEffect as s,useRef as c,useState as l}from"react";import u from"classnames";import{faChevronLeft as te,faChevronRight as ne}from"@fortawesome/free-solid-svg-icons";import{Fragment as re,jsx as d,jsxs as f}from"react/jsx-runtime";var p=10,ie=.2,ae={previous:`Previous slide`,next:`Next slide`,slides:`Slides`,goToSlide:e=>`Go to slide ${e}`};function m(m){let{children:oe,currentIndex:_,defaultIndex:se=0,onChange:ce=()=>{},loop:le=!0,autoPlay:v=!1,autoPlayInterval:y=4e3,pauseOnHover:ue=!0,showArrows:de=!0,showDots:fe=!0,swipeable:pe=!0,lazyRender:me=!1,adaptiveHeight:b=!1,className:he,style:ge,classNames:x,styles:S,labels:_e,...C}=e(`Carousel`,m),w=t(`Carousel`,_e,ae),T=o.useId(),E=o.Children.toArray(oe),D=E.length,O=le&&D>1,k=+!!O,A=O?[E[D-1],...E,E[0]]:E,j=_!==void 0,[ve,ye]=l(()=>g(se,D,O)),M=g(j?_:ve,D,O),[N,P]=l(M+k),[be,F]=l(!0),I=c(M),[xe,L]=l(!1),[Se,R]=l(!1),[Ce,z]=l(!1),B=c(null),V=c(null),H=c(null),U=A.length>0?100/A.length:100;s(()=>{let e=I.current;if(I.current=M,e===M)return;let t=A.length-1,n=N;O&&N===0?n=D:O&&N===t&&(n=1);let r=O&&e===D-1&&M===0,i=O&&e===0&&M===D-1,a;a=r?n+1:i?n-1:M+k;let o=V.current;n!==N&&o&&(o.style.transition=`none`,o.style.transform=h(n,0,U),o.offsetWidth,o.style.transition=``),F(!0),P(a)},[M]);let[W,we]=l(()=>({min:M+k-1,max:M+k+1})),Te=Math.min(W.min,N-1),Ee=Math.max(W.max,N+1),[De,Oe]=l(void 0);s(()=>{if(!b)return;let e=V.current?.children[N];if(!e)return;let t=()=>Oe(e.offsetHeight);t();let n=new ResizeObserver(t);return n.observe(e),()=>n.disconnect()},[b,N,D]),s(()=>{let e=H.current,t=e?.children[M];e&&t&&(e.scrollLeft=t.offsetLeft-(e.clientWidth-t.offsetWidth)/2)},[M,D]);function G(e){let t=g(e,D,O);j||ye(t),ce(t)}function K(){!O&&M>=D-1||G(M+1)}function q(){!O&&M<=0||G(M-1)}function ke(e){e.target===e.currentTarget&&(we({min:N-1,max:N+1}),O&&(N===0?(F(!1),P(D)):N===A.length-1&&(F(!1),P(1))))}let J=v&&ue,Y=xe||Se||Ce;ee(()=>{if(!v||D<=1||Y)return;let e=setInterval(K,y);return()=>clearInterval(e)},[v,y,Y,M,D]);let X=c(null);function Ae(e){!pe||D<=1||(X.current={startX:e.clientX,startY:e.clientY,width:B.current?.getBoundingClientRect().width||1,axisLocked:!1,active:!0,offsetPercent:0})}function je(e){let t=X.current;if(!t||!t.active)return;let n=e.clientX-t.startX,r=e.clientY-t.startY;if(!t.axisLocked){if(Math.abs(n)<p&&Math.abs(r)<p)return;if(Math.abs(r)>Math.abs(n)){t.active=!1;return}t.axisLocked=!0,e.currentTarget.setPointerCapture?.(e.pointerId),z(!0),F(!1)}t.offsetPercent=n/t.width*100,V.current&&(V.current.style.transform=h(N,t.offsetPercent,U))}function Me(){let e=X.current;if(X.current=null,!e||!e.axisLocked){z(!1);return}F(!0),z(!1),V.current&&(V.current.style.transition=``,V.current.style.transform=h(N,0,U)),Math.abs(e.offsetPercent)>=ie*100&&(e.offsetPercent<0?K():q())}function Ne(e){e.defaultPrevented||V.current?.contains(e.target)||(e.key===`ArrowLeft`?(e.preventDefault(),q()):e.key===`ArrowRight`&&(e.preventDefault(),K()))}function Pe(e){let t=null;if(e.key===`ArrowLeft`?t=M-1:e.key===`ArrowRight`?t=M+1:e.key===`Home`?t=0:e.key===`End`&&(t=D-1),t===null)return;e.preventDefault();let n=g(t,D,O);G(n),(H.current?.children[n])?.focus()}let Fe=fe&&D>1,Ie=e=>`${T}-dot-${e}`,Z=e=>`${T}-slide-${e}`,Le=C[`aria-label`]!==void 0||C[`aria-labelledby`]!==void 0;function Re(e){return Fe?{id:Z(e),role:`tabpanel`,"aria-labelledby":Ie(e)}:{id:Z(e),role:`group`,"aria-roledescription":`slide`,"aria-label":`${e+1} of ${D}`}}let Q=!O&&M<=0,$=!O&&M>=D-1,ze=h(N,0,U);return f(`div`,{...C,ref:B,role:Le?`region`:`group`,"aria-roledescription":`carousel`,className:u(i.carousel,b&&i.carouselAdaptive,x?.root,he),style:{height:b?De:void 0,...ge,...S?.root},onMouseEnter:J?()=>L(!0):void 0,onMouseLeave:J?()=>L(!1):void 0,onFocus:J?()=>R(!0):void 0,onBlur:J?()=>R(!1):void 0,onKeyDown:Ne,children:[d(`div`,{ref:V,className:u(i.carouselTrack,b&&i.carouselTrackAdaptive,x?.track),style:{width:`${A.length*100}%`,transform:ze,transition:be?void 0:`none`,...S?.track},"aria-live":v?`off`:`polite`,onTransitionEnd:ke,onPointerDown:Ae,onPointerMove:je,onPointerUp:Me,onPointerCancel:Me,children:A.map((e,t)=>{let n=O&&(t===0||t===A.length-1),r=t-k,a=!n&&r===M,o=!me||t>=Te&&t<=Ee;return d(`div`,{...n?{}:Re(r),className:u(i.carouselSlide,x?.slide),style:{width:`${100/A.length}%`,...S?.slide},inert:!a||void 0,children:o?e:null},`carousel-slide-${t}`)})}),de&&D>1&&f(re,{children:[d(r,{icon:te,title:w.previous,"aria-label":w.previous,"aria-disabled":Q||void 0,onClick:()=>!Q&&q(),className:u(i.carouselPrevButton,Q&&i.carouselButtonDisabled,x?.prevButton),style:S?.prevButton}),d(r,{icon:ne,title:w.next,"aria-label":w.next,"aria-disabled":$||void 0,onClick:()=>!$&&K(),className:u(i.carouselNextButton,$&&i.carouselButtonDisabled,x?.nextButton),style:S?.nextButton})]}),Fe&&d(`div`,{ref:H,role:`tablist`,"aria-label":w.slides,className:u(i.carouselDots,a.scrollFade,a.scrollFadeX,a.scrollFadeFadedStart,a.scrollFadeFadedEnd,x?.dots),style:S?.dots,onKeyDown:Pe,children:E.map((e,t)=>d(n,{id:Ie(t),role:`tab`,"aria-label":w.goToSlide(t+1),"aria-selected":t===M,"aria-controls":Z(t),tabIndex:t===M?0:-1,onClick:()=>G(t),className:u(i.carouselDot,t===M&&i.carouselDotActive,x?.dot),style:S?.dot},`carousel-dot-${t}`))})]})}function h(e,t,n){return`translateX(calc(${-e*n}% + ${n/100*t}%))`}function g(e,t,n){return t===0?0:n?(e%t+t)%t:Math.max(0,Math.min(t-1,e))}export{m as default};
1
+ "use client";import{useComponentDefaults as e}from"../configProvider/useComponentDefaults.mjs";import{useLabels as t}from"../configProvider/useLabels.mjs";import{ButtonStyleType as n}from"../button/button.types.mjs";import r from"../actionIcon/actionIcon.mjs";import i from"../interactableDiv/index.mjs";import a from"./carousel.module.mjs";import o from"../styles/scrollFade.module.mjs";import s,{useEffect as ee,useLayoutEffect as c,useRef as l,useState as u}from"react";import d from"classnames";import{faChevronLeft as te,faChevronRight as ne}from"@fortawesome/free-solid-svg-icons";import{Fragment as re,jsx as f,jsxs as p}from"react/jsx-runtime";var m=`var(--background-accent)`,h=10,ie=.2,ae={previous:`Previous slide`,next:`Next slide`,slides:`Slides`,goToSlide:e=>`Go to slide ${e}`};function g(g){let{children:oe,currentIndex:y,defaultIndex:se=0,onChange:ce=()=>{},loop:le=!0,autoPlay:b=!1,autoPlayInterval:ue=4e3,pauseOnHover:de=!0,showArrows:fe=!0,showDots:pe=!0,swipeable:me=!0,lazyRender:he=!1,adaptiveHeight:x=!1,className:ge,style:_e,classNames:S,styles:C,labels:ve,...w}=e(`Carousel`,g),T=t(`Carousel`,ve,ae),E=s.useId(),D=s.Children.toArray(oe),O=D.length,k=le&&O>1,A=+!!k,j=k?[D[O-1],...D,D[0]]:D,M=y!==void 0,[ye,be]=u(()=>v(se,O,k)),N=v(M?y:ye,O,k),[P,F]=u(N+A),[xe,I]=u(!0),L=l(N),[Se,R]=u(!1),[Ce,z]=u(!1),[we,B]=u(!1),V=l(null),H=l(null),U=l(null),W=j.length>0?100/j.length:100;c(()=>{let e=L.current;if(L.current=N,e===N)return;let t=j.length-1,n=P;k&&P===0?n=O:k&&P===t&&(n=1);let r=k&&e===O-1&&N===0,i=k&&e===0&&N===O-1,a;a=r?n+1:i?n-1:N+A;let o=H.current;n!==P&&o&&(o.style.transition=`none`,o.style.transform=_(n,0,W),o.offsetWidth,o.style.transition=``),I(!0),F(a)},[N]);let[G,Te]=u(()=>({min:N+A-1,max:N+A+1})),Ee=Math.min(G.min,P-1),De=Math.max(G.max,P+1),[Oe,ke]=u(void 0);c(()=>{if(!x)return;let e=H.current?.children[P];if(!e)return;let t=()=>ke(e.offsetHeight);t();let n=new ResizeObserver(t);return n.observe(e),()=>n.disconnect()},[x,P,O]),c(()=>{let e=U.current,t=e?.children[N];e&&t&&(e.scrollLeft=t.offsetLeft-(e.clientWidth-t.offsetWidth)/2)},[N,O]);function K(e){let t=v(e,O,k);M||be(t),ce(t)}function q(){!k&&N>=O-1||K(N+1)}function J(){!k&&N<=0||K(N-1)}function Ae(e){e.target===e.currentTarget&&(Te({min:P-1,max:P+1}),k&&(P===0?(I(!1),F(O)):P===j.length-1&&(I(!1),F(1))))}let Y=b&&de,je=Se||Ce||we;ee(()=>{if(!b||O<=1||je)return;let e=setInterval(q,ue);return()=>clearInterval(e)},[b,ue,je,N,O]);let X=l(null);function Me(e){!me||O<=1||(X.current={startX:e.clientX,startY:e.clientY,width:V.current?.getBoundingClientRect().width||1,axisLocked:!1,active:!0,offsetPercent:0})}function Ne(e){let t=X.current;if(!t||!t.active)return;let n=e.clientX-t.startX,r=e.clientY-t.startY;if(!t.axisLocked){if(Math.abs(n)<h&&Math.abs(r)<h)return;if(Math.abs(r)>Math.abs(n)){t.active=!1;return}t.axisLocked=!0,e.currentTarget.setPointerCapture?.(e.pointerId),B(!0),I(!1)}t.offsetPercent=n/t.width*100,H.current&&(H.current.style.transform=_(P,t.offsetPercent,W))}function Pe(){let e=X.current;if(X.current=null,!e||!e.axisLocked){B(!1);return}I(!0),B(!1),H.current&&(H.current.style.transition=``,H.current.style.transform=_(P,0,W)),Math.abs(e.offsetPercent)>=ie*100&&(e.offsetPercent<0?q():J())}function Fe(e){e.defaultPrevented||H.current?.contains(e.target)||(e.key===`ArrowLeft`?(e.preventDefault(),J()):e.key===`ArrowRight`&&(e.preventDefault(),q()))}function Ie(e){let t=null;if(e.key===`ArrowLeft`?t=N-1:e.key===`ArrowRight`?t=N+1:e.key===`Home`?t=0:e.key===`End`&&(t=O-1),t===null)return;e.preventDefault();let n=v(t,O,k);K(n),(U.current?.children[n])?.focus()}let Le=pe&&O>1,Re=e=>`${E}-dot-${e}`,Z=e=>`${E}-slide-${e}`,ze=w[`aria-label`]!==void 0||w[`aria-labelledby`]!==void 0;function Be(e){return Le?{id:Z(e),role:`tabpanel`,"aria-labelledby":Re(e)}:{id:Z(e),role:`group`,"aria-roledescription":`slide`,"aria-label":`${e+1} of ${O}`}}let Q=!k&&N<=0,$=!k&&N>=O-1,Ve=_(P,0,W);return p(`div`,{...w,ref:V,role:ze?`region`:`group`,"aria-roledescription":`carousel`,className:d(a.carousel,x&&a.carouselAdaptive,S?.root,ge),style:{height:x?Oe:void 0,..._e,...C?.root},onMouseEnter:Y?()=>R(!0):void 0,onMouseLeave:Y?()=>R(!1):void 0,onFocus:Y?()=>z(!0):void 0,onBlur:Y?()=>z(!1):void 0,onKeyDown:Fe,children:[f(`div`,{ref:H,className:d(a.carouselTrack,x&&a.carouselTrackAdaptive,S?.track),style:{width:`${j.length*100}%`,transform:Ve,transition:xe?void 0:`none`,...C?.track},"aria-live":b?`off`:`polite`,onTransitionEnd:Ae,onPointerDown:Me,onPointerMove:Ne,onPointerUp:Pe,onPointerCancel:Pe,children:j.map((e,t)=>{let n=k&&(t===0||t===j.length-1),r=t-A,i=!n&&r===N,o=!he||t>=Ee&&t<=De;return f(`div`,{...n?{}:Be(r),className:d(a.carouselSlide,S?.slide),style:{width:`${100/j.length}%`,...C?.slide},inert:!i||void 0,children:o?e:null},`carousel-slide-${t}`)})}),fe&&O>1&&p(re,{children:[f(r,{styleType:n.Filled,color:m,icon:te,title:T.previous,"aria-label":T.previous,"aria-disabled":Q||void 0,onClick:()=>{Q||J()},className:d(a.carouselPrevButton,Q&&a.carouselButtonDisabled,S?.prevButton),style:C?.prevButton}),f(r,{styleType:n.Filled,color:m,icon:ne,title:T.next,"aria-label":T.next,"aria-disabled":$||void 0,onClick:()=>{$||q()},className:d(a.carouselNextButton,$&&a.carouselButtonDisabled,S?.nextButton),style:C?.nextButton})]}),Le&&f(`div`,{ref:U,role:`tablist`,"aria-label":T.slides,className:d(a.carouselDots,o.scrollFade,o.scrollFadeX,o.scrollFadeFadedStart,o.scrollFadeFadedEnd,S?.dots),style:C?.dots,onKeyDown:Ie,children:D.map((e,t)=>f(i,{id:Re(t),role:`tab`,"aria-label":T.goToSlide(t+1),"aria-selected":t===N,"aria-controls":Z(t),tabIndex:t===N?0:-1,onClick:()=>K(t),className:d(a.carouselDot,t===N&&a.carouselDotActive,S?.dot),style:C?.dot},`carousel-dot-${t}`))})]})}function _(e,t,n){return`translateX(calc(${-e*n}% + ${n/100*t}%))`}function v(e,t,n){return t===0?0:n?(e%t+t)%t:Math.max(0,Math.min(t-1,e))}export{g as default};
2
2
  //# sourceMappingURL=carousel.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"carousel.mjs","names":[],"sources":["../../../../package/common/carousel/carousel.tsx"],"sourcesContent":["import React, { useEffect, useLayoutEffect, useRef, useState } from 'react';\nimport cx from 'classnames';\nimport { faChevronLeft, faChevronRight } from '@fortawesome/free-solid-svg-icons';\n\nimport ActionIcon from '../actionIcon';\nimport InteractableDiv from '../interactableDiv';\nimport { useComponentDefaults, useLabels } from '../configProvider';\nimport type { CarouselLabels, CarouselProps } from './carousel.types';\n\nimport styles from './carousel.module.pcss';\nimport fadeStyles from 'components/common/styles/scrollFade.module.pcss';\n\nconst AXIS_LOCK_THRESHOLD = 10;\nconst DRAG_COMMIT_RATIO = 0.2;\n\nconst DEFAULT_LABELS: Required<CarouselLabels> = {\n previous: 'Previous slide',\n next: 'Next slide',\n slides: 'Slides',\n goToSlide: (slide) => `Go to slide ${slide}`,\n};\n\nfunction Carousel(props: CarouselProps) {\n const {\n children,\n currentIndex,\n defaultIndex = 0,\n onChange = () => {},\n loop = true,\n autoPlay = false,\n autoPlayInterval = 4000,\n pauseOnHover = true,\n showArrows = true,\n showDots = true,\n swipeable = true,\n lazyRender = false,\n adaptiveHeight = false,\n className,\n style,\n classNames,\n styles: slotStyles,\n labels,\n ...rest\n } = useComponentDefaults('Carousel', props);\n const text = useLabels('Carousel', labels, DEFAULT_LABELS);\n\n const instanceId = React.useId();\n const slides = React.Children.toArray(children);\n const count = slides.length;\n const canLoop = loop && count > 1;\n const offset = canLoop ? 1 : 0;\n const extendedSlides = canLoop ? [slides[count - 1], ...slides, slides[0]] : slides;\n\n const isControlled = currentIndex !== undefined;\n const [internalIndex, setInternalIndex] = useState(() => clampIndex(defaultIndex, count, canLoop));\n const realIndex = clampIndex(isControlled ? currentIndex! : internalIndex, count, canLoop);\n\n const [displayIndex, setDisplayIndex] = useState(realIndex + offset);\n const [transitionEnabled, setTransitionEnabled] = useState(true);\n const prevRealIndexRef = useRef(realIndex);\n\n const [hovered, setHovered] = useState(false);\n const [focused, setFocused] = useState(false);\n const [dragging, setDragging] = useState(false);\n\n const containerRef = useRef<HTMLDivElement>(null);\n const trackRef = useRef<HTMLDivElement>(null);\n const dotsRef = useRef<HTMLDivElement>(null);\n\n const slideWidthPercent = extendedSlides.length > 0 ? 100 / extendedSlides.length : 100;\n\n useLayoutEffect(() => {\n const prevReal = prevRealIndexRef.current;\n prevRealIndexRef.current = realIndex;\n if (prevReal === realIndex) return;\n\n // A wrap parks the track on a clone until transitionEnd swaps it back, so a change arriving\n // before that has to animate from the normalised position rather than the clone.\n const lastExtendedIndex = extendedSlides.length - 1;\n let fromIndex = displayIndex;\n if (canLoop && displayIndex === 0) fromIndex = count;\n else if (canLoop && displayIndex === lastExtendedIndex) fromIndex = 1;\n\n const forwardWrap = canLoop && prevReal === count - 1 && realIndex === 0;\n const backwardWrap = canLoop && prevReal === 0 && realIndex === count - 1;\n\n let target: number;\n if (forwardWrap) target = fromIndex + 1;\n else if (backwardWrap) target = fromIndex - 1;\n else target = realIndex + offset;\n\n // Written straight to the node: the normalised position has to reach style recalculation on its\n // own, or it and the animated position collapse into one jump with no transition.\n const track = trackRef.current;\n if (fromIndex !== displayIndex && track) {\n track.style.transition = 'none';\n track.style.transform = buildTrackTransform(fromIndex, 0, slideWidthPercent);\n void track.offsetWidth;\n track.style.transition = '';\n }\n\n setTransitionEnabled(true);\n setDisplayIndex(target);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [realIndex]);\n\n // The window of slides `lazyRender` keeps mounted, as of the last settled position. Slides are\n // rendered for the union of this and the current window, so the ones a multi-step jump slides\n // past stay mounted until the transform transition ends instead of blanking out mid-flight.\n const [settledMountRange, setSettledMountRange] = useState(() => ({\n min: realIndex + offset - 1,\n max: realIndex + offset + 1,\n }));\n const mountMin = Math.min(settledMountRange.min, displayIndex - 1);\n const mountMax = Math.max(settledMountRange.max, displayIndex + 1);\n\n const [contentHeight, setContentHeight] = useState<number | undefined>(undefined);\n\n useLayoutEffect(() => {\n if (!adaptiveHeight) return;\n const slideElement = trackRef.current?.children[displayIndex] as HTMLElement | undefined;\n if (!slideElement) return;\n\n const update = () => setContentHeight(slideElement.offsetHeight);\n update();\n\n const observer = new ResizeObserver(update);\n observer.observe(slideElement);\n return () => observer.disconnect();\n }, [adaptiveHeight, displayIndex, count]);\n\n // Keeps the selected dot in view. Written as `scrollLeft` because `scrollIntoView` is free to\n // scroll the page along with it.\n useLayoutEffect(() => {\n const strip = dotsRef.current;\n const dot = strip?.children[realIndex] as HTMLElement | undefined;\n if (!strip || !dot) return;\n strip.scrollLeft = dot.offsetLeft - (strip.clientWidth - dot.offsetWidth) / 2;\n }, [realIndex, count]);\n\n function goToIndex(nextIndex: number) {\n const clamped = clampIndex(nextIndex, count, canLoop);\n if (!isControlled) setInternalIndex(clamped);\n onChange(clamped);\n }\n\n function goNext() {\n if (!canLoop && realIndex >= count - 1) return;\n goToIndex(realIndex + 1);\n }\n\n function goPrev() {\n if (!canLoop && realIndex <= 0) return;\n goToIndex(realIndex - 1);\n }\n\n function handleTrackTransitionEnd(event: React.TransitionEvent<HTMLDivElement>) {\n if (event.target !== event.currentTarget) return;\n setSettledMountRange({ min: displayIndex - 1, max: displayIndex + 1 });\n\n if (!canLoop) return;\n if (displayIndex === 0) {\n setTransitionEnabled(false);\n setDisplayIndex(count);\n } else if (displayIndex === extendedSlides.length - 1) {\n setTransitionEnabled(false);\n setDisplayIndex(1);\n }\n }\n\n // Hover and focus only ever pause the timer, so without one they are not worth tracking.\n const tracksPointerPause = autoPlay && pauseOnHover;\n const isPaused = hovered || focused || dragging;\n useEffect(() => {\n if (!autoPlay || count <= 1 || isPaused) return;\n const timer = setInterval(goNext, autoPlayInterval);\n return () => clearInterval(timer);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [autoPlay, autoPlayInterval, isPaused, realIndex, count]);\n\n // A drag follows the pointer through the node, not through state: a render per move event would\n // rebuild every slide and dot for something only the track's transform sees.\n const dragRef = useRef<{\n startX: number;\n startY: number;\n width: number;\n axisLocked: boolean;\n active: boolean;\n offsetPercent: number;\n } | null>(null);\n\n function handlePointerDown(event: React.PointerEvent<HTMLDivElement>) {\n if (!swipeable || count <= 1) return;\n dragRef.current = {\n startX: event.clientX,\n startY: event.clientY,\n // Measured once: measuring per move would force a layout between the transform writes.\n width: containerRef.current?.getBoundingClientRect().width || 1,\n axisLocked: false,\n active: true,\n offsetPercent: 0,\n };\n }\n\n function handlePointerMove(event: React.PointerEvent<HTMLDivElement>) {\n const drag = dragRef.current;\n if (!drag || !drag.active) return;\n\n const deltaX = event.clientX - drag.startX;\n const deltaY = event.clientY - drag.startY;\n\n if (!drag.axisLocked) {\n if (Math.abs(deltaX) < AXIS_LOCK_THRESHOLD && Math.abs(deltaY) < AXIS_LOCK_THRESHOLD) return;\n if (Math.abs(deltaY) > Math.abs(deltaX)) {\n drag.active = false;\n return;\n }\n drag.axisLocked = true;\n // Never on pointerdown: a captured pointer sends its `click` to the capture target too, so\n // capturing earlier would swallow every click meant for a button inside a slide.\n event.currentTarget.setPointerCapture?.(event.pointerId);\n setDragging(true);\n setTransitionEnabled(false);\n }\n\n drag.offsetPercent = (deltaX / drag.width) * 100;\n if (trackRef.current) {\n trackRef.current.style.transform = buildTrackTransform(displayIndex, drag.offsetPercent, slideWidthPercent);\n }\n }\n\n function handlePointerUp() {\n const drag = dragRef.current;\n dragRef.current = null;\n if (!drag || !drag.axisLocked) {\n setDragging(false);\n return;\n }\n\n setTransitionEnabled(true);\n setDragging(false);\n\n // React never saw the dragged transform, so it has to be handed back by hand, and always: a\n // drag that changes no index would otherwise strand the track off-screen. One that does change\n // it overwrites this in the same tick, and still animates on from where the pointer left off.\n if (trackRef.current) {\n trackRef.current.style.transition = '';\n trackRef.current.style.transform = buildTrackTransform(displayIndex, 0, slideWidthPercent);\n }\n\n if (Math.abs(drag.offsetPercent) >= DRAG_COMMIT_RATIO * 100) {\n if (drag.offsetPercent < 0) goNext();\n else goPrev();\n }\n }\n\n // Arrow keys belong to the carousel's own controls, never to the slides: a text field or a\n // scrollable region in a slide has to keep its own. `defaultPrevented` leaves the dots to their\n // own handling below.\n function handleKeyDown(event: React.KeyboardEvent<HTMLDivElement>) {\n if (event.defaultPrevented || trackRef.current?.contains(event.target as Node)) return;\n\n if (event.key === 'ArrowLeft') {\n event.preventDefault();\n goPrev();\n } else if (event.key === 'ArrowRight') {\n event.preventDefault();\n goNext();\n }\n }\n\n function handleDotsKeyDown(event: React.KeyboardEvent<HTMLDivElement>) {\n let next: number | null = null;\n if (event.key === 'ArrowLeft') next = realIndex - 1;\n else if (event.key === 'ArrowRight') next = realIndex + 1;\n else if (event.key === 'Home') next = 0;\n else if (event.key === 'End') next = count - 1;\n if (next === null) return;\n\n event.preventDefault();\n const clamped = clampIndex(next, count, canLoop);\n goToIndex(clamped);\n // The selected dot is the one holding the tab stop, so focus has to travel with the selection.\n (dotsRef.current?.children[clamped] as HTMLElement | undefined)?.focus();\n }\n\n // The dots are the APG tablist over the slides. Without them the slides describe themselves as\n // plain slides rather than as panels.\n const hasTabs = showDots && count > 1;\n const dotId = (index: number) => `${instanceId}-dot-${index}`;\n const slideId = (index: number) => `${instanceId}-slide-${index}`;\n\n // An unnamed landmark is worse than none, so the carousel is only a region once it has a name.\n const isNamed = rest['aria-label'] !== undefined || rest['aria-labelledby'] !== undefined;\n\n function slideSemantics(index: number) {\n if (hasTabs) {\n return { id: slideId(index), role: 'tabpanel', 'aria-labelledby': dotId(index) };\n }\n return {\n id: slideId(index),\n role: 'group',\n 'aria-roledescription': 'slide',\n 'aria-label': `${index + 1} of ${count}`,\n };\n }\n\n const isPrevDisabled = !canLoop && realIndex <= 0;\n const isNextDisabled = !canLoop && realIndex >= count - 1;\n\n const trackTransform = buildTrackTransform(displayIndex, 0, slideWidthPercent);\n\n return (\n <div\n {...rest}\n ref={containerRef}\n role={isNamed ? 'region' : 'group'}\n aria-roledescription='carousel'\n className={cx(styles.carousel, adaptiveHeight && styles.carouselAdaptive, classNames?.root, className)}\n style={{ height: adaptiveHeight ? contentHeight : undefined, ...style, ...slotStyles?.root }}\n onMouseEnter={tracksPointerPause ? () => setHovered(true) : undefined}\n onMouseLeave={tracksPointerPause ? () => setHovered(false) : undefined}\n onFocus={tracksPointerPause ? () => setFocused(true) : undefined}\n onBlur={tracksPointerPause ? () => setFocused(false) : undefined}\n onKeyDown={handleKeyDown}\n >\n <div\n ref={trackRef}\n className={cx(styles.carouselTrack, adaptiveHeight && styles.carouselTrackAdaptive, classNames?.track)}\n style={{\n width: `${extendedSlides.length * 100}%`,\n transform: trackTransform,\n transition: transitionEnabled ? undefined : 'none',\n ...slotStyles?.track,\n }}\n aria-live={autoPlay ? 'off' : 'polite'}\n onTransitionEnd={handleTrackTransitionEnd}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n onPointerCancel={handlePointerUp}\n >\n {extendedSlides.map((slide, idx) => {\n const isClonePosition = canLoop && (idx === 0 || idx === extendedSlides.length - 1);\n const logicalIndex = idx - offset;\n const isActive = !isClonePosition && logicalIndex === realIndex;\n const isRendered = !lazyRender || (idx >= mountMin && idx <= mountMax);\n\n return (\n <div\n key={`carousel-slide-${idx}`}\n {...(isClonePosition ? {} : slideSemantics(logicalIndex))}\n className={cx(styles.carouselSlide, classNames?.slide)}\n style={{ width: `${100 / extendedSlides.length}%`, ...slotStyles?.slide }}\n inert={isActive ? undefined : true}\n >\n {isRendered ? slide : null}\n </div>\n );\n })}\n </div>\n\n {showArrows && count > 1 && (\n <>\n <ActionIcon\n icon={faChevronLeft}\n title={text.previous}\n aria-label={text.previous}\n aria-disabled={isPrevDisabled || undefined}\n onClick={() => !isPrevDisabled && goPrev()}\n className={cx(\n styles.carouselPrevButton,\n isPrevDisabled && styles.carouselButtonDisabled,\n classNames?.prevButton,\n )}\n style={slotStyles?.prevButton}\n />\n <ActionIcon\n icon={faChevronRight}\n title={text.next}\n aria-label={text.next}\n aria-disabled={isNextDisabled || undefined}\n onClick={() => !isNextDisabled && goNext()}\n className={cx(\n styles.carouselNextButton,\n isNextDisabled && styles.carouselButtonDisabled,\n classNames?.nextButton,\n )}\n style={slotStyles?.nextButton}\n />\n </>\n )}\n\n {hasTabs && (\n <div\n ref={dotsRef}\n role='tablist'\n aria-label={text.slides}\n className={cx(\n styles.carouselDots,\n // Both ends always: the strip's own padding holds the outer dots clear of the fade\n // until there is something to scroll, so this needs no measuring.\n fadeStyles.scrollFade,\n fadeStyles.scrollFadeX,\n fadeStyles.scrollFadeFadedStart,\n fadeStyles.scrollFadeFadedEnd,\n classNames?.dots,\n )}\n style={slotStyles?.dots}\n onKeyDown={handleDotsKeyDown}\n >\n {slides.map((_, index) => (\n <InteractableDiv\n key={`carousel-dot-${index}`}\n id={dotId(index)}\n role='tab'\n aria-label={text.goToSlide(index + 1)}\n aria-selected={index === realIndex}\n aria-controls={slideId(index)}\n // One tab stop for the whole set, arrow keys inside it.\n tabIndex={index === realIndex ? 0 : -1}\n onClick={() => goToIndex(index)}\n className={cx(styles.carouselDot, index === realIndex && styles.carouselDotActive, classNames?.dot)}\n style={slotStyles?.dot}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n\nfunction buildTrackTransform(position: number, dragPercent: number, slideWidthPercent: number): string {\n return `translateX(calc(${-position * slideWidthPercent}% + ${dragPercent * (slideWidthPercent / 100)}%))`;\n}\n\nfunction clampIndex(index: number, count: number, canLoop: boolean): number {\n if (count === 0) return 0;\n if (canLoop) return ((index % count) + count) % count;\n return Math.max(0, Math.min(count - 1, index));\n}\n\nexport default Carousel;\n"],"mappings":"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"}
1
+ {"version":3,"file":"carousel.mjs","names":[],"sources":["../../../../package/common/carousel/carousel.tsx"],"sourcesContent":["import React, { useEffect, useLayoutEffect, useRef, useState } from 'react';\nimport cx from 'classnames';\nimport { faChevronLeft, faChevronRight } from '@fortawesome/free-solid-svg-icons';\n\nimport ActionIcon from '../actionIcon';\nimport InteractableDiv from '../interactableDiv';\nimport { useComponentDefaults, useLabels } from '../configProvider';\nimport type { CarouselLabels, CarouselProps } from './carousel.types';\n\nimport styles from './carousel.module.pcss';\nimport fadeStyles from 'components/common/styles/scrollFade.module.pcss';\nimport { ButtonStyleType } from '../button/button.types';\n\n// Opaque, because the arrows sit over the slide's own image; Neutral's fill is see-through.\nconst ARROW_COLOR = 'var(--background-accent)';\n\nconst AXIS_LOCK_THRESHOLD = 10;\nconst DRAG_COMMIT_RATIO = 0.2;\n\nconst DEFAULT_LABELS: Required<CarouselLabels> = {\n previous: 'Previous slide',\n next: 'Next slide',\n slides: 'Slides',\n goToSlide: (slide) => `Go to slide ${slide}`,\n};\n\nfunction Carousel(props: CarouselProps) {\n const {\n children,\n currentIndex,\n defaultIndex = 0,\n onChange = () => {},\n loop = true,\n autoPlay = false,\n autoPlayInterval = 4000,\n pauseOnHover = true,\n showArrows = true,\n showDots = true,\n swipeable = true,\n lazyRender = false,\n adaptiveHeight = false,\n className,\n style,\n classNames,\n styles: slotStyles,\n labels,\n ...rest\n } = useComponentDefaults('Carousel', props);\n const text = useLabels('Carousel', labels, DEFAULT_LABELS);\n\n const instanceId = React.useId();\n const slides = React.Children.toArray(children);\n const count = slides.length;\n const canLoop = loop && count > 1;\n const offset = canLoop ? 1 : 0;\n const extendedSlides = canLoop ? [slides[count - 1], ...slides, slides[0]] : slides;\n\n const isControlled = currentIndex !== undefined;\n const [internalIndex, setInternalIndex] = useState(() => clampIndex(defaultIndex, count, canLoop));\n const realIndex = clampIndex(isControlled ? currentIndex! : internalIndex, count, canLoop);\n\n const [displayIndex, setDisplayIndex] = useState(realIndex + offset);\n const [transitionEnabled, setTransitionEnabled] = useState(true);\n const prevRealIndexRef = useRef(realIndex);\n\n const [hovered, setHovered] = useState(false);\n const [focused, setFocused] = useState(false);\n const [dragging, setDragging] = useState(false);\n\n const containerRef = useRef<HTMLDivElement>(null);\n const trackRef = useRef<HTMLDivElement>(null);\n const dotsRef = useRef<HTMLDivElement>(null);\n\n const slideWidthPercent = extendedSlides.length > 0 ? 100 / extendedSlides.length : 100;\n\n useLayoutEffect(() => {\n const prevReal = prevRealIndexRef.current;\n prevRealIndexRef.current = realIndex;\n if (prevReal === realIndex) return;\n\n // A wrap parks the track on a clone until transitionEnd swaps it back, so a change arriving\n // before that has to animate from the normalised position rather than the clone.\n const lastExtendedIndex = extendedSlides.length - 1;\n let fromIndex = displayIndex;\n if (canLoop && displayIndex === 0) fromIndex = count;\n else if (canLoop && displayIndex === lastExtendedIndex) fromIndex = 1;\n\n const forwardWrap = canLoop && prevReal === count - 1 && realIndex === 0;\n const backwardWrap = canLoop && prevReal === 0 && realIndex === count - 1;\n\n let target: number;\n if (forwardWrap) target = fromIndex + 1;\n else if (backwardWrap) target = fromIndex - 1;\n else target = realIndex + offset;\n\n // Written straight to the node: the normalised position has to reach style recalculation on its\n // own, or it and the animated position collapse into one jump with no transition.\n const track = trackRef.current;\n if (fromIndex !== displayIndex && track) {\n track.style.transition = 'none';\n track.style.transform = buildTrackTransform(fromIndex, 0, slideWidthPercent);\n void track.offsetWidth;\n track.style.transition = '';\n }\n\n setTransitionEnabled(true);\n setDisplayIndex(target);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [realIndex]);\n\n // The window of slides `lazyRender` keeps mounted, as of the last settled position. Slides are\n // rendered for the union of this and the current window, so the ones a multi-step jump slides\n // past stay mounted until the transform transition ends instead of blanking out mid-flight.\n const [settledMountRange, setSettledMountRange] = useState(() => ({\n min: realIndex + offset - 1,\n max: realIndex + offset + 1,\n }));\n const mountMin = Math.min(settledMountRange.min, displayIndex - 1);\n const mountMax = Math.max(settledMountRange.max, displayIndex + 1);\n\n const [contentHeight, setContentHeight] = useState<number | undefined>(undefined);\n\n useLayoutEffect(() => {\n if (!adaptiveHeight) return;\n const slideElement = trackRef.current?.children[displayIndex] as HTMLElement | undefined;\n if (!slideElement) return;\n\n const update = () => setContentHeight(slideElement.offsetHeight);\n update();\n\n const observer = new ResizeObserver(update);\n observer.observe(slideElement);\n return () => observer.disconnect();\n }, [adaptiveHeight, displayIndex, count]);\n\n // Keeps the selected dot in view. Written as `scrollLeft` because `scrollIntoView` is free to\n // scroll the page along with it.\n useLayoutEffect(() => {\n const strip = dotsRef.current;\n const dot = strip?.children[realIndex] as HTMLElement | undefined;\n if (!strip || !dot) return;\n strip.scrollLeft = dot.offsetLeft - (strip.clientWidth - dot.offsetWidth) / 2;\n }, [realIndex, count]);\n\n function goToIndex(nextIndex: number) {\n const clamped = clampIndex(nextIndex, count, canLoop);\n if (!isControlled) setInternalIndex(clamped);\n onChange(clamped);\n }\n\n function goNext() {\n if (!canLoop && realIndex >= count - 1) return;\n goToIndex(realIndex + 1);\n }\n\n function goPrev() {\n if (!canLoop && realIndex <= 0) return;\n goToIndex(realIndex - 1);\n }\n\n function handleTrackTransitionEnd(event: React.TransitionEvent<HTMLDivElement>) {\n if (event.target !== event.currentTarget) return;\n setSettledMountRange({ min: displayIndex - 1, max: displayIndex + 1 });\n\n if (!canLoop) return;\n if (displayIndex === 0) {\n setTransitionEnabled(false);\n setDisplayIndex(count);\n } else if (displayIndex === extendedSlides.length - 1) {\n setTransitionEnabled(false);\n setDisplayIndex(1);\n }\n }\n\n // Hover and focus only ever pause the timer, so without one they are not worth tracking.\n const tracksPointerPause = autoPlay && pauseOnHover;\n const isPaused = hovered || focused || dragging;\n useEffect(() => {\n if (!autoPlay || count <= 1 || isPaused) return;\n const timer = setInterval(goNext, autoPlayInterval);\n return () => clearInterval(timer);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [autoPlay, autoPlayInterval, isPaused, realIndex, count]);\n\n // A drag follows the pointer through the node, not through state: a render per move event would\n // rebuild every slide and dot for something only the track's transform sees.\n const dragRef = useRef<{\n startX: number;\n startY: number;\n width: number;\n axisLocked: boolean;\n active: boolean;\n offsetPercent: number;\n } | null>(null);\n\n function handlePointerDown(event: React.PointerEvent<HTMLDivElement>) {\n if (!swipeable || count <= 1) return;\n dragRef.current = {\n startX: event.clientX,\n startY: event.clientY,\n // Measured once: measuring per move would force a layout between the transform writes.\n width: containerRef.current?.getBoundingClientRect().width || 1,\n axisLocked: false,\n active: true,\n offsetPercent: 0,\n };\n }\n\n function handlePointerMove(event: React.PointerEvent<HTMLDivElement>) {\n const drag = dragRef.current;\n if (!drag || !drag.active) return;\n\n const deltaX = event.clientX - drag.startX;\n const deltaY = event.clientY - drag.startY;\n\n if (!drag.axisLocked) {\n if (Math.abs(deltaX) < AXIS_LOCK_THRESHOLD && Math.abs(deltaY) < AXIS_LOCK_THRESHOLD) return;\n if (Math.abs(deltaY) > Math.abs(deltaX)) {\n drag.active = false;\n return;\n }\n drag.axisLocked = true;\n // Never on pointerdown: a captured pointer sends its `click` to the capture target too, so\n // capturing earlier would swallow every click meant for a button inside a slide.\n event.currentTarget.setPointerCapture?.(event.pointerId);\n setDragging(true);\n setTransitionEnabled(false);\n }\n\n drag.offsetPercent = (deltaX / drag.width) * 100;\n if (trackRef.current) {\n trackRef.current.style.transform = buildTrackTransform(displayIndex, drag.offsetPercent, slideWidthPercent);\n }\n }\n\n function handlePointerUp() {\n const drag = dragRef.current;\n dragRef.current = null;\n if (!drag || !drag.axisLocked) {\n setDragging(false);\n return;\n }\n\n setTransitionEnabled(true);\n setDragging(false);\n\n // React never saw the dragged transform, so it has to be handed back by hand, and always: a\n // drag that changes no index would otherwise strand the track off-screen. One that does change\n // it overwrites this in the same tick, and still animates on from where the pointer left off.\n if (trackRef.current) {\n trackRef.current.style.transition = '';\n trackRef.current.style.transform = buildTrackTransform(displayIndex, 0, slideWidthPercent);\n }\n\n if (Math.abs(drag.offsetPercent) >= DRAG_COMMIT_RATIO * 100) {\n if (drag.offsetPercent < 0) goNext();\n else goPrev();\n }\n }\n\n // Arrow keys belong to the carousel's own controls, never to the slides: a text field or a\n // scrollable region in a slide has to keep its own. `defaultPrevented` leaves the dots to their\n // own handling below.\n function handleKeyDown(event: React.KeyboardEvent<HTMLDivElement>) {\n if (event.defaultPrevented || trackRef.current?.contains(event.target as Node)) return;\n\n if (event.key === 'ArrowLeft') {\n event.preventDefault();\n goPrev();\n } else if (event.key === 'ArrowRight') {\n event.preventDefault();\n goNext();\n }\n }\n\n function handleDotsKeyDown(event: React.KeyboardEvent<HTMLDivElement>) {\n let next: number | null = null;\n if (event.key === 'ArrowLeft') next = realIndex - 1;\n else if (event.key === 'ArrowRight') next = realIndex + 1;\n else if (event.key === 'Home') next = 0;\n else if (event.key === 'End') next = count - 1;\n if (next === null) return;\n\n event.preventDefault();\n const clamped = clampIndex(next, count, canLoop);\n goToIndex(clamped);\n // The selected dot is the one holding the tab stop, so focus has to travel with the selection.\n (dotsRef.current?.children[clamped] as HTMLElement | undefined)?.focus();\n }\n\n // The dots are the APG tablist over the slides. Without them the slides describe themselves as\n // plain slides rather than as panels.\n const hasTabs = showDots && count > 1;\n const dotId = (index: number) => `${instanceId}-dot-${index}`;\n const slideId = (index: number) => `${instanceId}-slide-${index}`;\n\n // An unnamed landmark is worse than none, so the carousel is only a region once it has a name.\n const isNamed = rest['aria-label'] !== undefined || rest['aria-labelledby'] !== undefined;\n\n function slideSemantics(index: number) {\n if (hasTabs) {\n return { id: slideId(index), role: 'tabpanel', 'aria-labelledby': dotId(index) };\n }\n return {\n id: slideId(index),\n role: 'group',\n 'aria-roledescription': 'slide',\n 'aria-label': `${index + 1} of ${count}`,\n };\n }\n\n const isPrevDisabled = !canLoop && realIndex <= 0;\n const isNextDisabled = !canLoop && realIndex >= count - 1;\n\n const trackTransform = buildTrackTransform(displayIndex, 0, slideWidthPercent);\n\n return (\n <div\n {...rest}\n ref={containerRef}\n role={isNamed ? 'region' : 'group'}\n aria-roledescription='carousel'\n className={cx(styles.carousel, adaptiveHeight && styles.carouselAdaptive, classNames?.root, className)}\n style={{ height: adaptiveHeight ? contentHeight : undefined, ...style, ...slotStyles?.root }}\n onMouseEnter={tracksPointerPause ? () => setHovered(true) : undefined}\n onMouseLeave={tracksPointerPause ? () => setHovered(false) : undefined}\n onFocus={tracksPointerPause ? () => setFocused(true) : undefined}\n onBlur={tracksPointerPause ? () => setFocused(false) : undefined}\n onKeyDown={handleKeyDown}\n >\n <div\n ref={trackRef}\n className={cx(styles.carouselTrack, adaptiveHeight && styles.carouselTrackAdaptive, classNames?.track)}\n style={{\n width: `${extendedSlides.length * 100}%`,\n transform: trackTransform,\n transition: transitionEnabled ? undefined : 'none',\n ...slotStyles?.track,\n }}\n aria-live={autoPlay ? 'off' : 'polite'}\n onTransitionEnd={handleTrackTransitionEnd}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n onPointerCancel={handlePointerUp}\n >\n {extendedSlides.map((slide, idx) => {\n const isClonePosition = canLoop && (idx === 0 || idx === extendedSlides.length - 1);\n const logicalIndex = idx - offset;\n const isActive = !isClonePosition && logicalIndex === realIndex;\n const isRendered = !lazyRender || (idx >= mountMin && idx <= mountMax);\n\n return (\n <div\n key={`carousel-slide-${idx}`}\n {...(isClonePosition ? {} : slideSemantics(logicalIndex))}\n className={cx(styles.carouselSlide, classNames?.slide)}\n style={{ width: `${100 / extendedSlides.length}%`, ...slotStyles?.slide }}\n inert={isActive ? undefined : true}\n >\n {isRendered ? slide : null}\n </div>\n );\n })}\n </div>\n\n {showArrows && count > 1 && (\n <>\n <ActionIcon\n styleType={ButtonStyleType.Filled}\n color={ARROW_COLOR}\n icon={faChevronLeft}\n title={text.previous}\n aria-label={text.previous}\n aria-disabled={isPrevDisabled || undefined}\n onClick={() => {\n if (!isPrevDisabled) goPrev();\n }}\n className={cx(\n styles.carouselPrevButton,\n isPrevDisabled && styles.carouselButtonDisabled,\n classNames?.prevButton,\n )}\n style={slotStyles?.prevButton}\n />\n <ActionIcon\n styleType={ButtonStyleType.Filled}\n color={ARROW_COLOR}\n icon={faChevronRight}\n title={text.next}\n aria-label={text.next}\n aria-disabled={isNextDisabled || undefined}\n onClick={() => {\n if (!isNextDisabled) goNext();\n }}\n className={cx(\n styles.carouselNextButton,\n isNextDisabled && styles.carouselButtonDisabled,\n classNames?.nextButton,\n )}\n style={slotStyles?.nextButton}\n />\n </>\n )}\n\n {hasTabs && (\n <div\n ref={dotsRef}\n role='tablist'\n aria-label={text.slides}\n className={cx(\n styles.carouselDots,\n // Both ends always: the strip's own padding holds the outer dots clear of the fade\n // until there is something to scroll, so this needs no measuring.\n fadeStyles.scrollFade,\n fadeStyles.scrollFadeX,\n fadeStyles.scrollFadeFadedStart,\n fadeStyles.scrollFadeFadedEnd,\n classNames?.dots,\n )}\n style={slotStyles?.dots}\n onKeyDown={handleDotsKeyDown}\n >\n {slides.map((_, index) => (\n <InteractableDiv\n key={`carousel-dot-${index}`}\n id={dotId(index)}\n role='tab'\n aria-label={text.goToSlide(index + 1)}\n aria-selected={index === realIndex}\n aria-controls={slideId(index)}\n // One tab stop for the whole set, arrow keys inside it.\n tabIndex={index === realIndex ? 0 : -1}\n onClick={() => goToIndex(index)}\n className={cx(styles.carouselDot, index === realIndex && styles.carouselDotActive, classNames?.dot)}\n style={slotStyles?.dot}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n\nfunction buildTrackTransform(position: number, dragPercent: number, slideWidthPercent: number): string {\n return `translateX(calc(${-position * slideWidthPercent}% + ${dragPercent * (slideWidthPercent / 100)}%))`;\n}\n\nfunction clampIndex(index: number, count: number, canLoop: boolean): number {\n if (count === 0) return 0;\n if (canLoop) return ((index % count) + count) % count;\n return Math.max(0, Math.min(count - 1, index));\n}\n\nexport default Carousel;\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"carousel.module.mjs","names":[],"sources":["../../../../package/common/carousel/carousel.module.pcss"],"sourcesContent":[".carousel {\n position: relative;\n overflow: hidden;\n border-radius: var(--default-border-radius);\n\n &-adaptive {\n transition: height 0.4s ease;\n }\n\n &-track {\n display: flex;\n align-items: stretch;\n transition: transform 0.4s ease;\n touch-action: pan-y;\n user-select: none;\n }\n\n &-trackAdaptive {\n align-items: flex-start;\n }\n\n &-slide {\n flex-shrink: 0;\n box-sizing: border-box;\n }\n\n &-prevButton,\n &-nextButton {\n position: absolute;\n top: 50%;\n transform: translateY(-50%);\n z-index: 1;\n width: 36px;\n height: 36px;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 50%;\n background: var(--background-accent);\n color: var(--text-color);\n box-shadow: var(--card-shadow);\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n transition:\n opacity 0.15s,\n background 0.15s;\n\n &:hover {\n background: var(--background-accent-light);\n }\n\n &:focus-visible {\n outline: none;\n box-shadow:\n var(--card-shadow),\n 0 0 0 2px var(--primary-lighter);\n }\n }\n\n &-buttonDisabled {\n opacity: 0.35;\n pointer-events: none;\n }\n\n &-prevButton {\n left: 12px;\n }\n\n &-nextButton {\n right: 12px;\n }\n\n /* A scroll strip rather than a row that shrinks, so the dots keep their size at any slide count.\n The padding holds the outer dots clear of the fade until the strip has somewhere to scroll. */\n &-dots {\n position: absolute;\n bottom: 4px;\n left: 50%;\n transform: translateX(-50%);\n z-index: 1;\n display: flex;\n box-sizing: border-box;\n width: max-content;\n max-width: 100%;\n padding-inline: 16px;\n overflow-x: auto;\n overscroll-behavior-x: contain;\n scroll-behavior: smooth;\n\n /* Matches the strip's own `padding-inline`, so the first and last dot start out clear of the\n fade. The shared sheet's private length, not `--scroll-fade-length`, which would inherit. */\n --custom-scroll-fade-length: 16px;\n\n scrollbar-width: none;\n\n &::-webkit-scrollbar {\n display: none;\n }\n\n @media (prefers-reduced-motion: reduce) {\n scroll-behavior: auto;\n }\n }\n\n /* The dot stays 8px, its padding carries the hit area out to the 24px minimum. */\n &-dot {\n box-sizing: content-box;\n\n /* The strip is width-capped, and shrinking would pull the content box, the only part\n `background-clip` paints, down to nothing. */\n flex-shrink: 0;\n width: 8px;\n height: 8px;\n padding: 8px;\n border-radius: 2000px;\n background: var(--background-accent);\n background-clip: content-box;\n opacity: 0.6;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n transition:\n opacity 0.15s,\n background 0.15s,\n width 0.15s;\n\n &:hover {\n opacity: 0.85;\n }\n\n &:focus-visible {\n outline: none;\n box-shadow: 0 0 0 2px var(--primary-lighter);\n }\n\n &-active {\n background: var(--primary-color);\n background-clip: content-box;\n opacity: 1;\n width: 20px;\n }\n }\n}\n"],"mappings":""}
1
+ {"version":3,"file":"carousel.module.mjs","names":[],"sources":["../../../../package/common/carousel/carousel.module.pcss"],"sourcesContent":[".carousel {\n position: relative;\n overflow: hidden;\n border-radius: var(--default-border-radius);\n\n &-adaptive {\n transition: height 0.4s ease;\n }\n\n &-track {\n display: flex;\n align-items: stretch;\n transition: transform 0.4s ease;\n touch-action: pan-y;\n user-select: none;\n }\n\n &-trackAdaptive {\n align-items: flex-start;\n }\n\n &-slide {\n flex-shrink: 0;\n box-sizing: border-box;\n }\n\n /* Two classes, to outrank Button's radius and ActionIcon's box whichever stylesheet loads\n first. */\n & &-prevButton,\n & &-nextButton {\n position: absolute;\n top: 50%;\n transform: translateY(-50%);\n z-index: 1;\n width: 36px;\n height: 36px;\n border-radius: 50%;\n box-shadow: var(--card-shadow);\n transition: opacity 0.15s;\n }\n\n &-buttonDisabled {\n opacity: 0.35;\n pointer-events: none;\n }\n\n &-prevButton {\n left: 12px;\n }\n\n &-nextButton {\n right: 12px;\n }\n\n /* A scroll strip rather than a row that shrinks, so the dots keep their size at any slide count.\n The padding holds the outer dots clear of the fade until the strip has somewhere to scroll. */\n &-dots {\n position: absolute;\n bottom: 4px;\n left: 50%;\n transform: translateX(-50%);\n z-index: 1;\n display: flex;\n box-sizing: border-box;\n width: max-content;\n max-width: 100%;\n padding-inline: 16px;\n overflow-x: auto;\n overscroll-behavior-x: contain;\n scroll-behavior: smooth;\n\n /* Matches the strip's own `padding-inline`, so the first and last dot start out clear of the\n fade. The shared sheet's private length, not `--scroll-fade-length`, which would inherit. */\n --custom-scroll-fade-length: 16px;\n\n scrollbar-width: none;\n\n &::-webkit-scrollbar {\n display: none;\n }\n\n @media (prefers-reduced-motion: reduce) {\n scroll-behavior: auto;\n }\n }\n\n /* The dot stays 8px, its padding carries the hit area out to the 24px minimum. */\n &-dot {\n box-sizing: content-box;\n\n /* The strip is width-capped, and shrinking would pull the content box, the only part\n `background-clip` paints, down to nothing. */\n flex-shrink: 0;\n width: 8px;\n height: 8px;\n padding: 8px;\n border-radius: 2000px;\n background: var(--background-accent);\n background-clip: content-box;\n opacity: 0.6;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n transition:\n opacity 0.15s,\n background 0.15s,\n width 0.15s;\n\n &:hover {\n opacity: 0.85;\n }\n\n &:focus-visible {\n outline: none;\n box-shadow: 0 0 0 2px var(--primary-lighter);\n }\n\n &-active {\n background: var(--primary-color);\n background-clip: content-box;\n opacity: 1;\n width: 20px;\n }\n }\n}\n"],"mappings":""}
@@ -1,2 +1,2 @@
1
- "use client";import{useComponentDefaults as e}from"../configProvider/useComponentDefaults.mjs";import{useLabels as t}from"../configProvider/useLabels.mjs";import{isSelfActivation as n}from"../utils/activationKey.mjs";import r from"../ripple/ripple.mjs";import i from"../interactableDiv/index.mjs";import a from"../actionIcon/actionIcon.mjs";import{ChipStyleType as o}from"./chip.types.mjs";import s from"./chip.module.mjs";import{useMemo as c,useRef as l}from"react";import u from"classnames";import{faXmarkCircle as d}from"@fortawesome/free-solid-svg-icons";import{jsx as f,jsxs as p}from"react/jsx-runtime";var m={default:s.chipStyleDefault,primary:s.chipStylePrimary,info:s.chipStyleInfo,warn:s.chipStyleWarn,error:s.chipStyleError},h={remove:`Remove`};function g(g){let{className:_=``,thumbnail:v=``,text:y=``,styleType:b=o.Default,showRemoveIcon:x=!1,labels:S,onClick:C,onRemove:w,style:T,classNames:E,styles:D,...O}=e(`Chip`,g),k=t(`Chip`,S,h),A=l(null);function j(e){C&&n(e)&&A.current?.addRipple()}let M=c(()=>{if(typeof v==`string`&&v.startsWith(`http`))return v},[v]);return f(i,{...O,className:u(s.chip,m[b],C&&s.chipClickable,_,E?.root),style:{...T,...D?.root},onClick:C,onKeyDown:j,children:f(r,{ref:A,disabled:!C,style:{borderRadius:`inherit`},children:p(`div`,{className:u(s.chipInner,E?.inner),style:D?.inner,children:[v&&f(`div`,{className:u(s.chipThumbnail,E?.thumbnail),style:{...M?{backgroundImage:`url(${M})`}:{},...D?.thumbnail},children:!M&&v}),f(`div`,{className:u(s.chipText,E?.text),style:D?.text,children:y}),x&&f(a,{icon:d,className:E?.removeIcon,style:D?.removeIcon,"aria-label":k.remove,onClick:e=>{e.stopPropagation(),w?.()}})]})})})}export{g as default};
1
+ "use client";import{useComponentDefaults as e}from"../configProvider/useComponentDefaults.mjs";import{useLabels as t}from"../configProvider/useLabels.mjs";import{isSelfActivation as n}from"../utils/activationKey.mjs";import{ThemeColor as r}from"../themeProvider/color.types.mjs";import{toneProps as i,useToneCheck as a}from"../styles/tone.mjs";import o from"../ripple/ripple.mjs";import s from"../actionIcon/actionIcon.mjs";import c from"../interactableDiv/index.mjs";import{ChipStyleType as l}from"./chip.types.mjs";import u from"./chip.module.mjs";import{useMemo as d,useRef as f}from"react";import p from"classnames";import{faXmarkCircle as m}from"@fortawesome/free-solid-svg-icons";import{jsx as h,jsxs as g}from"react/jsx-runtime";var _={filled:u.chipStyleFilled,light:u.chipStyleLight,outlined:u.chipStyleOutlined},v={remove:`Remove`};function y(y){let{className:b=``,thumbnail:x=``,text:S=``,styleType:C=l.Light,color:w=r.Neutral,showRemoveIcon:T=!1,labels:E,onClick:D,onRemove:O,style:k,classNames:A,styles:j,...M}=e(`Chip`,y),N=t(`Chip`,E,v),P=f(null),F=i(w);a(`Chip`,[w]);function I(e){D&&n(e)&&P.current?.addRipple()}let L=d(()=>{if(typeof x==`string`&&x.startsWith(`http`))return x},[x]);return h(c,{...M,className:p(u.chip,F.className,_[C],D&&u.chipClickable,b,A?.root),style:{...F.style,...k,...j?.root},onClick:D,onKeyDown:I,children:h(o,{ref:P,disabled:!D,style:{borderRadius:`inherit`},children:g(`div`,{className:p(u.chipInner,A?.inner),style:j?.inner,children:[x&&h(`div`,{className:p(u.chipThumbnail,A?.thumbnail),style:{...L?{backgroundImage:`url(${L})`}:{},...j?.thumbnail},children:!L&&x}),h(`div`,{className:p(u.chipText,A?.text),style:j?.text,children:S}),T&&h(s,{icon:m,className:A?.removeIcon,style:j?.removeIcon,"aria-label":N.remove,onClick:e=>{e.stopPropagation(),O?.()}})]})})})}export{y as default};
2
2
  //# sourceMappingURL=chip.mjs.map