@human-kit/svelte-components 1.0.0-alpha.2 → 1.0.0-alpha.21

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 (407) hide show
  1. package/dist/FOCUS_STATE_CONTRACT.md +63 -0
  2. package/dist/FOCUS_STATE_REVIEW_TEMPLATE.md +70 -0
  3. package/dist/button/README.md +48 -0
  4. package/dist/button/TODO.md +13 -0
  5. package/dist/button/index.d.ts +5 -0
  6. package/dist/button/index.js +4 -0
  7. package/dist/button/index.parts.d.ts +1 -0
  8. package/dist/button/index.parts.js +1 -0
  9. package/dist/button/root/README.md +43 -0
  10. package/dist/button/root/button-root.svelte +393 -0
  11. package/dist/button/root/button-root.svelte.d.ts +21 -0
  12. package/dist/button/root/button-test.svelte +76 -0
  13. package/dist/button/root/button-test.svelte.d.ts +11 -0
  14. package/dist/calendar/README.md +2 -1
  15. package/dist/calendar/TODO.md +21 -107
  16. package/dist/calendar/body-cell/README.md +15 -0
  17. package/dist/calendar/body-cell/calendar-body-cell.svelte +116 -41
  18. package/dist/calendar/grid/README.md +13 -0
  19. package/dist/calendar/grid-body/README.md +13 -0
  20. package/dist/calendar/grid-header/README.md +13 -0
  21. package/dist/calendar/header-cell/README.md +14 -0
  22. package/dist/calendar/heading/README.md +13 -0
  23. package/dist/calendar/index.d.ts +3 -3
  24. package/dist/calendar/index.js +3 -3
  25. package/dist/calendar/root/README.md +24 -0
  26. package/dist/calendar/root/calendar-root-test.svelte +4 -0
  27. package/dist/calendar/root/calendar-root-test.svelte.d.ts +1 -0
  28. package/dist/calendar/root/calendar-root.svelte +3 -0
  29. package/dist/calendar/root/calendar-root.svelte.d.ts +1 -0
  30. package/dist/calendar/root/context.d.ts +4 -0
  31. package/dist/calendar/root/context.js +28 -25
  32. package/dist/calendar/root/date-utils.d.ts +1 -1
  33. package/dist/calendar/root/date-utils.js +16 -26
  34. package/dist/calendar/trigger-next/README.md +14 -0
  35. package/dist/calendar/trigger-next/calendar-trigger-next.svelte +9 -4
  36. package/dist/calendar/trigger-next/calendar-trigger-next.svelte.d.ts +2 -1
  37. package/dist/calendar/trigger-previous/README.md +14 -0
  38. package/dist/calendar/trigger-previous/calendar-trigger-previous.svelte +9 -4
  39. package/dist/calendar/trigger-previous/calendar-trigger-previous.svelte.d.ts +2 -1
  40. package/dist/checkbox/README.md +53 -0
  41. package/dist/checkbox/TODO.md +16 -0
  42. package/dist/checkbox/index.d.ts +6 -0
  43. package/dist/checkbox/index.js +6 -0
  44. package/dist/checkbox/index.parts.d.ts +2 -0
  45. package/dist/checkbox/index.parts.js +2 -0
  46. package/dist/checkbox/indicator/README.md +23 -0
  47. package/dist/checkbox/indicator/checkbox-indicator.svelte +43 -0
  48. package/dist/checkbox/indicator/checkbox-indicator.svelte.d.ts +10 -0
  49. package/dist/checkbox/root/README.md +47 -0
  50. package/dist/checkbox/root/checkbox-label-test.svelte +10 -0
  51. package/dist/checkbox/root/checkbox-label-test.svelte.d.ts +18 -0
  52. package/dist/checkbox/root/checkbox-root.svelte +386 -0
  53. package/dist/checkbox/root/checkbox-root.svelte.d.ts +29 -0
  54. package/dist/checkbox/root/checkbox-test.svelte +59 -0
  55. package/dist/checkbox/root/checkbox-test.svelte.d.ts +18 -0
  56. package/dist/checkbox/root/context.d.ts +21 -0
  57. package/dist/checkbox/root/context.js +15 -0
  58. package/dist/clock/README.md +75 -0
  59. package/dist/clock/axis/README.md +24 -0
  60. package/dist/clock/axis/clock-axis.svelte +37 -0
  61. package/dist/clock/axis/clock-axis.svelte.d.ts +8 -0
  62. package/dist/clock/hooks/use-wheel-scroll.svelte.d.ts +16 -0
  63. package/dist/clock/hooks/use-wheel-scroll.svelte.js +336 -0
  64. package/dist/clock/index.d.ts +10 -0
  65. package/dist/clock/index.js +10 -0
  66. package/dist/clock/index.parts.d.ts +4 -0
  67. package/dist/clock/index.parts.js +4 -0
  68. package/dist/clock/root/README.md +38 -0
  69. package/dist/clock/root/clock-root-test.svelte +62 -0
  70. package/dist/clock/root/clock-root-test.svelte.d.ts +14 -0
  71. package/dist/clock/root/clock-root.svelte +329 -0
  72. package/dist/clock/root/clock-root.svelte.d.ts +25 -0
  73. package/dist/clock/root/context.d.ts +22 -0
  74. package/dist/clock/root/context.js +15 -0
  75. package/dist/clock/root/resolve-visible-columns.d.ts +7 -0
  76. package/dist/clock/root/resolve-visible-columns.js +16 -0
  77. package/dist/clock/root/time-utils.d.ts +48 -0
  78. package/dist/clock/root/time-utils.js +314 -0
  79. package/dist/clock/root/wheel-options.d.ts +17 -0
  80. package/dist/clock/root/wheel-options.js +63 -0
  81. package/dist/clock/wheel-column/README.md +25 -0
  82. package/dist/clock/wheel-column/clock-wheel-column-bindable-test.svelte +16 -0
  83. package/dist/clock/wheel-column/clock-wheel-column-bindable-test.svelte.d.ts +3 -0
  84. package/dist/clock/wheel-column/clock-wheel-column-custom-snippet-test.svelte +29 -0
  85. package/dist/clock/wheel-column/clock-wheel-column-custom-snippet-test.svelte.d.ts +6 -0
  86. package/dist/clock/wheel-column/clock-wheel-column-default-height-test.svelte +11 -0
  87. package/dist/clock/wheel-column/clock-wheel-column-default-height-test.svelte.d.ts +3 -0
  88. package/dist/clock/wheel-column/clock-wheel-column-test.svelte +38 -0
  89. package/dist/clock/wheel-column/clock-wheel-column-test.svelte.d.ts +12 -0
  90. package/dist/clock/wheel-column/clock-wheel-column-tp-test.svelte +38 -0
  91. package/dist/clock/wheel-column/clock-wheel-column-tp-test.svelte.d.ts +12 -0
  92. package/dist/clock/wheel-column/clock-wheel-column-untagged-snippet-test.svelte +29 -0
  93. package/dist/clock/wheel-column/clock-wheel-column-untagged-snippet-test.svelte.d.ts +6 -0
  94. package/dist/clock/wheel-column/clock-wheel-column.svelte +499 -0
  95. package/dist/clock/wheel-column/clock-wheel-column.svelte.d.ts +17 -0
  96. package/dist/clock/wheel-item/README.md +17 -0
  97. package/dist/clock/wheel-item/clock-wheel-item.svelte +49 -0
  98. package/dist/clock/wheel-item/clock-wheel-item.svelte.d.ts +17 -0
  99. package/dist/combobox/README.md +8 -2
  100. package/dist/combobox/TODO.md +28 -175
  101. package/dist/combobox/button/README.md +8 -3
  102. package/dist/combobox/button/combobox-button-test.svelte +27 -0
  103. package/dist/combobox/button/combobox-button-test.svelte.d.ts +6 -0
  104. package/dist/combobox/button/combobox-button.svelte +10 -11
  105. package/dist/combobox/clear/README.md +21 -0
  106. package/dist/combobox/clear/combobox-clear-test.svelte +34 -0
  107. package/dist/combobox/clear/combobox-clear-test.svelte.d.ts +3 -0
  108. package/dist/combobox/clear/combobox-clear.svelte +61 -0
  109. package/dist/combobox/clear/combobox-clear.svelte.d.ts +9 -0
  110. package/dist/combobox/index.d.ts +5 -3
  111. package/dist/combobox/index.js +5 -3
  112. package/dist/combobox/index.parts.d.ts +2 -0
  113. package/dist/combobox/index.parts.js +2 -0
  114. package/dist/combobox/input/combobox-input.svelte +44 -12
  115. package/dist/combobox/item/combobox-item-implicit-text-test.svelte +1 -1
  116. package/dist/combobox/item/combobox-listboxitem.svelte +14 -11
  117. package/dist/combobox/item-indicator/combobox-item-indicator.svelte +4 -15
  118. package/dist/combobox/list/combobox-listbox.svelte +1 -0
  119. package/dist/combobox/list/combobox-listbox.svelte.d.ts +2 -1
  120. package/dist/combobox/popover/README.md +18 -4
  121. package/dist/combobox/popover/combobox-popover-props-test.svelte +38 -0
  122. package/dist/combobox/popover/combobox-popover-props-test.svelte.d.ts +11 -0
  123. package/dist/combobox/popover/combobox-popover.svelte +166 -23
  124. package/dist/combobox/popover/combobox-popover.svelte.d.ts +3 -3
  125. package/dist/combobox/popover/combobox-scrollable-list-test.svelte +23 -0
  126. package/dist/combobox/popover/combobox-scrollable-list-test.svelte.d.ts +18 -0
  127. package/dist/combobox/root/README.md +1 -0
  128. package/dist/combobox/root/combobox-multiselect-test.svelte +5 -3
  129. package/dist/combobox/root/combobox-multiselect-test.svelte.d.ts +1 -0
  130. package/dist/combobox/root/combobox-numeric-string-id-test.svelte +1 -1
  131. package/dist/combobox/root/combobox-test.svelte +23 -4
  132. package/dist/combobox/root/combobox-test.svelte.d.ts +2 -0
  133. package/dist/combobox/root/combobox.svelte +119 -13
  134. package/dist/combobox/root/combobox.svelte.d.ts +1 -0
  135. package/dist/combobox/root/context.d.ts +19 -1
  136. package/dist/combobox/tag-remove/combobox-tag-remove.svelte +3 -2
  137. package/dist/combobox/trigger/README.md +21 -0
  138. package/dist/combobox/trigger/combobox-trigger.svelte +56 -0
  139. package/dist/combobox/trigger/combobox-trigger.svelte.d.ts +9 -0
  140. package/dist/datepicker/README.md +100 -0
  141. package/dist/datepicker/TODO.md +28 -0
  142. package/dist/datepicker/calendar/README.md +19 -0
  143. package/dist/datepicker/calendar/date-picker-calendar-unsafe-props-test.svelte +60 -0
  144. package/dist/datepicker/calendar/date-picker-calendar-unsafe-props-test.svelte.d.ts +3 -0
  145. package/dist/datepicker/calendar/date-picker-calendar.svelte +65 -0
  146. package/dist/datepicker/calendar/date-picker-calendar.svelte.d.ts +10 -0
  147. package/dist/datepicker/index.d.ts +18 -0
  148. package/dist/datepicker/index.js +18 -0
  149. package/dist/datepicker/index.parts.d.ts +14 -0
  150. package/dist/datepicker/index.parts.js +14 -0
  151. package/dist/datepicker/input/README.md +15 -0
  152. package/dist/datepicker/input/date-picker-input.svelte +108 -0
  153. package/dist/datepicker/input/date-picker-input.svelte.d.ts +11 -0
  154. package/dist/datepicker/internal/strict-props.d.ts +2 -0
  155. package/dist/datepicker/internal/strict-props.js +28 -0
  156. package/dist/datepicker/popover/README.md +20 -0
  157. package/dist/datepicker/popover/date-picker-popover-handler-test.svelte +57 -0
  158. package/dist/datepicker/popover/date-picker-popover-handler-test.svelte.d.ts +3 -0
  159. package/dist/datepicker/popover/date-picker-popover-unsafe-props-test.svelte +45 -0
  160. package/dist/datepicker/popover/date-picker-popover-unsafe-props-test.svelte.d.ts +18 -0
  161. package/dist/datepicker/popover/date-picker-popover.svelte +87 -0
  162. package/dist/datepicker/popover/date-picker-popover.svelte.d.ts +7 -0
  163. package/dist/datepicker/root/README.md +38 -0
  164. package/dist/datepicker/root/context.d.ts +43 -0
  165. package/dist/datepicker/root/context.js +15 -0
  166. package/dist/datepicker/root/date-picker-bindable-empty-test.svelte +24 -0
  167. package/dist/datepicker/root/date-picker-bindable-empty-test.svelte.d.ts +3 -0
  168. package/dist/datepicker/root/date-picker-bindable-test.svelte +41 -0
  169. package/dist/datepicker/root/date-picker-bindable-test.svelte.d.ts +3 -0
  170. package/dist/datepicker/root/date-picker-empty-test.svelte +47 -0
  171. package/dist/datepicker/root/date-picker-empty-test.svelte.d.ts +3 -0
  172. package/dist/datepicker/root/date-picker-locale-typing-test.svelte +47 -0
  173. package/dist/datepicker/root/date-picker-locale-typing-test.svelte.d.ts +3 -0
  174. package/dist/datepicker/root/date-picker-open-cancel-test.svelte +54 -0
  175. package/dist/datepicker/root/date-picker-open-cancel-test.svelte.d.ts +8 -0
  176. package/dist/datepicker/root/date-picker-root.svelte +495 -0
  177. package/dist/datepicker/root/date-picker-root.svelte.d.ts +24 -0
  178. package/dist/datepicker/root/date-picker-test.svelte +86 -0
  179. package/dist/datepicker/root/date-picker-test.svelte.d.ts +13 -0
  180. package/dist/datepicker/root/date-utils.d.ts +17 -0
  181. package/dist/datepicker/root/date-utils.js +138 -0
  182. package/dist/datepicker/root/draft-evaluation.d.ts +13 -0
  183. package/dist/datepicker/root/draft-evaluation.js +56 -0
  184. package/dist/datepicker/root/focus-controller.d.ts +3 -0
  185. package/dist/datepicker/root/focus-controller.js +15 -0
  186. package/dist/datepicker/root/open-change.d.ts +5 -0
  187. package/dist/datepicker/root/open-change.js +13 -0
  188. package/dist/datepicker/root/open-controller.d.ts +7 -0
  189. package/dist/datepicker/root/open-controller.js +15 -0
  190. package/dist/datepicker/root/segment-controller.d.ts +8 -0
  191. package/dist/datepicker/root/segment-controller.js +53 -0
  192. package/dist/datepicker/root/segment-state.d.ts +18 -0
  193. package/dist/datepicker/root/segment-state.js +134 -0
  194. package/dist/datepicker/root/value-commit.d.ts +4 -0
  195. package/dist/datepicker/root/value-commit.js +8 -0
  196. package/dist/datepicker/segment/README.md +14 -0
  197. package/dist/datepicker/segment/date-picker-segment.svelte +319 -0
  198. package/dist/datepicker/segment/date-picker-segment.svelte.d.ts +9 -0
  199. package/dist/datepicker/trigger/README.md +14 -0
  200. package/dist/datepicker/trigger/date-picker-trigger.svelte +110 -0
  201. package/dist/datepicker/trigger/date-picker-trigger.svelte.d.ts +9 -0
  202. package/dist/dialog/content/dialog-content.svelte +6 -6
  203. package/dist/dialog/index.d.ts +3 -3
  204. package/dist/dialog/index.js +2 -2
  205. package/dist/dialog/root/context.d.ts +2 -1
  206. package/dist/dialog/root/dialog-root.svelte +9 -2
  207. package/dist/dialog/trigger/dialog-trigger.svelte +3 -0
  208. package/dist/hooks/use-virtual-focus.svelte.js +3 -1
  209. package/dist/index.d.ts +31 -17
  210. package/dist/index.js +31 -17
  211. package/dist/input/README.md +38 -0
  212. package/dist/input/TODO.md +12 -0
  213. package/dist/input/input-test.svelte +43 -0
  214. package/dist/input/input-test.svelte.d.ts +12 -0
  215. package/dist/input/input.svelte +151 -7
  216. package/dist/input/input.svelte.d.ts +8 -2
  217. package/dist/listbox/index.d.ts +3 -3
  218. package/dist/listbox/index.js +3 -3
  219. package/dist/listbox/item/README.md +2 -1
  220. package/dist/listbox/item/listbox-item.svelte +260 -6
  221. package/dist/listbox/item/listbox-item.svelte.d.ts +6 -0
  222. package/dist/listbox/root/context.d.ts +6 -0
  223. package/dist/listbox/root/context.js +23 -13
  224. package/dist/listbox/root/listbox-test.svelte +14 -2
  225. package/dist/listbox/root/listbox-test.svelte.d.ts +1 -0
  226. package/dist/listbox/root/listbox.svelte +49 -2
  227. package/dist/listbox/root/listbox.svelte.d.ts +4 -2
  228. package/dist/popover/README.md +10 -0
  229. package/dist/popover/content/README.md +11 -0
  230. package/dist/popover/content/popover-content-controlled-close-test.svelte +30 -0
  231. package/dist/popover/content/popover-content-controlled-close-test.svelte.d.ts +3 -0
  232. package/dist/popover/content/popover-content-standalone-test.svelte +28 -0
  233. package/dist/popover/content/popover-content-standalone-test.svelte.d.ts +6 -0
  234. package/dist/popover/content/popover-content-test.svelte +32 -2
  235. package/dist/popover/content/popover-content-test.svelte.d.ts +3 -1
  236. package/dist/popover/content/popover-content.svelte +315 -24
  237. package/dist/popover/content/popover-content.svelte.d.ts +5 -1
  238. package/dist/popover/index.d.ts +3 -3
  239. package/dist/popover/index.js +3 -5
  240. package/dist/popover/root/README.md +10 -15
  241. package/dist/popover/root/context.d.ts +16 -7
  242. package/dist/popover/root/context.js +0 -2
  243. package/dist/popover/root/focus-state.d.ts +4 -0
  244. package/dist/popover/root/focus-state.js +33 -0
  245. package/dist/popover/root/popover-root.svelte +90 -17
  246. package/dist/popover/root/popover-root.svelte.d.ts +2 -1
  247. package/dist/popover/root/popover-test.svelte +2 -1
  248. package/dist/popover/root/popover-test.svelte.d.ts +2 -1
  249. package/dist/popover/trigger/popover-trigger-button-root-test.svelte +17 -0
  250. package/dist/popover/trigger/popover-trigger-button-root-test.svelte.d.ts +18 -0
  251. package/dist/popover/trigger/popover-trigger-button.svelte +9 -7
  252. package/dist/popover/trigger/popover-trigger.svelte +17 -5
  253. package/dist/portal/portal.svelte +3 -1
  254. package/dist/primitives/click-outside.d.ts +1 -1
  255. package/dist/primitives/click-outside.js +1 -1
  256. package/dist/primitives/floating.js +12 -4
  257. package/dist/primitives/focus-trap.d.ts +7 -2
  258. package/dist/primitives/focus-trap.js +50 -17
  259. package/dist/primitives/index.d.ts +1 -0
  260. package/dist/primitives/index.js +1 -0
  261. package/dist/primitives/input-modality.d.ts +7 -0
  262. package/dist/primitives/input-modality.js +125 -0
  263. package/dist/primitives/keyboard-navigation.d.ts +1 -0
  264. package/dist/primitives/keyboard-navigation.js +17 -0
  265. package/dist/table/IMPLEMENTATION_NOTES.md +9 -0
  266. package/dist/table/PLAN-HIDDEN-COLUMNS.md +152 -0
  267. package/dist/table/PLAN.md +1336 -0
  268. package/dist/table/README.md +143 -0
  269. package/dist/table/SELECTION_CHECKBOX_PLAN.md +234 -0
  270. package/dist/table/TODO.md +138 -0
  271. package/dist/table/body/README.md +39 -0
  272. package/dist/table/body/table-body-items-test.svelte +45 -0
  273. package/dist/table/body/table-body-items-test.svelte.d.ts +18 -0
  274. package/dist/table/body/table-body.svelte +171 -0
  275. package/dist/table/body/table-body.svelte.d.ts +45 -0
  276. package/dist/table/cell/README.md +27 -0
  277. package/dist/table/cell/table-cell.svelte +253 -0
  278. package/dist/table/cell/table-cell.svelte.d.ts +4 -0
  279. package/dist/table/checkbox/README.md +40 -0
  280. package/dist/table/checkbox/table-checkbox-test.svelte +170 -0
  281. package/dist/table/checkbox/table-checkbox-test.svelte.d.ts +22 -0
  282. package/dist/table/checkbox/table-checkbox.svelte +235 -0
  283. package/dist/table/checkbox/table-checkbox.svelte.d.ts +4 -0
  284. package/dist/table/checkbox-indicator/README.md +31 -0
  285. package/dist/table/checkbox-indicator/table-checkbox-indicator.svelte +15 -0
  286. package/dist/table/checkbox-indicator/table-checkbox-indicator.svelte.d.ts +4 -0
  287. package/dist/table/column/README.md +36 -0
  288. package/dist/table/column/table-column.svelte +79 -0
  289. package/dist/table/column/table-column.svelte.d.ts +4 -0
  290. package/dist/table/column-header-cell/README.md +30 -0
  291. package/dist/table/column-header-cell/table-column-header-cell.svelte +271 -0
  292. package/dist/table/column-header-cell/table-column-header-cell.svelte.d.ts +4 -0
  293. package/dist/table/column-resizer/README.md +33 -0
  294. package/dist/table/column-resizer/table-column-resizer-fixed-width-test.svelte +57 -0
  295. package/dist/table/column-resizer/table-column-resizer-fixed-width-test.svelte.d.ts +3 -0
  296. package/dist/table/column-resizer/table-column-resizer-freeze-layout-test.svelte +52 -0
  297. package/dist/table/column-resizer/table-column-resizer-freeze-layout-test.svelte.d.ts +3 -0
  298. package/dist/table/column-resizer/table-column-resizer-narrow-min-width-test.svelte +76 -0
  299. package/dist/table/column-resizer/table-column-resizer-narrow-min-width-test.svelte.d.ts +3 -0
  300. package/dist/table/column-resizer/table-column-resizer-overflow-test.svelte +64 -0
  301. package/dist/table/column-resizer/table-column-resizer-overflow-test.svelte.d.ts +3 -0
  302. package/dist/table/column-resizer/table-column-resizer-padded-container-test.svelte +67 -0
  303. package/dist/table/column-resizer/table-column-resizer-padded-container-test.svelte.d.ts +3 -0
  304. package/dist/table/column-resizer/table-column-resizer-sandbox-overflow-test.svelte +87 -0
  305. package/dist/table/column-resizer/table-column-resizer-sandbox-overflow-test.svelte.d.ts +3 -0
  306. package/dist/table/column-resizer/table-column-resizer-selection-column-test.svelte +84 -0
  307. package/dist/table/column-resizer/table-column-resizer-selection-column-test.svelte.d.ts +3 -0
  308. package/dist/table/column-resizer/table-column-resizer-test.svelte +77 -0
  309. package/dist/table/column-resizer/table-column-resizer-test.svelte.d.ts +3 -0
  310. package/dist/table/column-resizer/table-column-resizer-three-column-relative-test.svelte +64 -0
  311. package/dist/table/column-resizer/table-column-resizer-three-column-relative-test.svelte.d.ts +3 -0
  312. package/dist/table/column-resizer/table-column-resizer.svelte +610 -0
  313. package/dist/table/column-resizer/table-column-resizer.svelte.d.ts +4 -0
  314. package/dist/table/empty-state/README.md +27 -0
  315. package/dist/table/empty-state/table-empty-state.svelte +33 -0
  316. package/dist/table/empty-state/table-empty-state.svelte.d.ts +4 -0
  317. package/dist/table/footer/README.md +26 -0
  318. package/dist/table/footer/table-footer.svelte +13 -0
  319. package/dist/table/footer/table-footer.svelte.d.ts +4 -0
  320. package/dist/table/header/README.md +26 -0
  321. package/dist/table/header/table-header.svelte +13 -0
  322. package/dist/table/header/table-header.svelte.d.ts +4 -0
  323. package/dist/table/index.d.ts +18 -0
  324. package/dist/table/index.js +17 -0
  325. package/dist/table/index.parts.d.ts +13 -0
  326. package/dist/table/index.parts.js +13 -0
  327. package/dist/table/root/README.md +66 -0
  328. package/dist/table/root/context.d.ts +233 -0
  329. package/dist/table/root/context.js +2153 -0
  330. package/dist/table/root/table-reorder-test.svelte +64 -0
  331. package/dist/table/root/table-reorder-test.svelte.d.ts +3 -0
  332. package/dist/table/root/table-root.svelte +561 -0
  333. package/dist/table/root/table-root.svelte.d.ts +4 -0
  334. package/dist/table/root/table-ssr-wrapper-column.svelte +48 -0
  335. package/dist/table/root/table-ssr-wrapper-column.svelte.d.ts +4 -0
  336. package/dist/table/root/table-ssr-wrapper-context.d.ts +11 -0
  337. package/dist/table/root/table-ssr-wrapper-context.js +13 -0
  338. package/dist/table/root/table-ssr-wrapper-test.svelte +57 -0
  339. package/dist/table/root/table-ssr-wrapper-test.svelte.d.ts +3 -0
  340. package/dist/table/root/table-test.svelte +206 -0
  341. package/dist/table/root/table-test.svelte.d.ts +29 -0
  342. package/dist/table/row/README.md +29 -0
  343. package/dist/table/row/table-row.svelte +244 -0
  344. package/dist/table/row/table-row.svelte.d.ts +4 -0
  345. package/dist/table/sort-trigger/README.md +45 -0
  346. package/dist/table/sort-trigger/table-sort-trigger.svelte +183 -0
  347. package/dist/table/sort-trigger/table-sort-trigger.svelte.d.ts +4 -0
  348. package/dist/table/types.d.ts +112 -0
  349. package/dist/table/types.js +1 -0
  350. package/dist/table/utils/handle-body-keydown.d.ts +13 -0
  351. package/dist/table/utils/handle-body-keydown.js +67 -0
  352. package/dist/table/utils/visually-hidden-style.d.ts +1 -0
  353. package/dist/table/utils/visually-hidden-style.js +1 -0
  354. package/dist/test-utils/focus-contract.d.ts +3 -0
  355. package/dist/test-utils/focus-contract.js +26 -0
  356. package/dist/timepicker/IMPLEMENTATION_PLAN.md +254 -0
  357. package/dist/timepicker/README.md +97 -0
  358. package/dist/timepicker/TODO.md +86 -0
  359. package/dist/timepicker/clock/README.md +14 -0
  360. package/dist/timepicker/clock/time-picker-clock-test.svelte +45 -0
  361. package/dist/timepicker/clock/time-picker-clock-test.svelte.d.ts +11 -0
  362. package/dist/timepicker/clock/time-picker-clock.svelte +65 -0
  363. package/dist/timepicker/clock/time-picker-clock.svelte.d.ts +10 -0
  364. package/dist/timepicker/index.d.ts +14 -0
  365. package/dist/timepicker/index.js +14 -0
  366. package/dist/timepicker/index.parts.d.ts +8 -0
  367. package/dist/timepicker/index.parts.js +8 -0
  368. package/dist/timepicker/input/README.md +15 -0
  369. package/dist/timepicker/input/time-picker-input-forwarding-test.svelte +40 -0
  370. package/dist/timepicker/input/time-picker-input-forwarding-test.svelte.d.ts +3 -0
  371. package/dist/timepicker/input/time-picker-input.svelte +109 -0
  372. package/dist/timepicker/input/time-picker-input.svelte.d.ts +11 -0
  373. package/dist/timepicker/internal/strict-props.d.ts +4 -0
  374. package/dist/timepicker/internal/strict-props.js +51 -0
  375. package/dist/timepicker/popover/README.md +20 -0
  376. package/dist/timepicker/popover/time-picker-popover-unsafe-props-test.svelte +22 -0
  377. package/dist/timepicker/popover/time-picker-popover-unsafe-props-test.svelte.d.ts +3 -0
  378. package/dist/timepicker/popover/time-picker-popover.svelte +89 -0
  379. package/dist/timepicker/popover/time-picker-popover.svelte.d.ts +7 -0
  380. package/dist/timepicker/root/README.md +42 -0
  381. package/dist/timepicker/root/context.d.ts +51 -0
  382. package/dist/timepicker/root/context.js +15 -0
  383. package/dist/timepicker/root/time-picker-12h-test.svelte +22 -0
  384. package/dist/timepicker/root/time-picker-12h-test.svelte.d.ts +3 -0
  385. package/dist/timepicker/root/time-picker-bindable-test.svelte +25 -0
  386. package/dist/timepicker/root/time-picker-bindable-test.svelte.d.ts +3 -0
  387. package/dist/timepicker/root/time-picker-empty-test.svelte +20 -0
  388. package/dist/timepicker/root/time-picker-empty-test.svelte.d.ts +3 -0
  389. package/dist/timepicker/root/time-picker-root.svelte +625 -0
  390. package/dist/timepicker/root/time-picker-root.svelte.d.ts +28 -0
  391. package/dist/timepicker/root/time-picker-test.svelte +72 -0
  392. package/dist/timepicker/root/time-picker-test.svelte.d.ts +15 -0
  393. package/dist/timepicker/root/time-utils.d.ts +1 -0
  394. package/dist/timepicker/root/time-utils.js +3 -0
  395. package/dist/timepicker/segment/README.md +14 -0
  396. package/dist/timepicker/segment/time-picker-segment.svelte +365 -0
  397. package/dist/timepicker/segment/time-picker-segment.svelte.d.ts +9 -0
  398. package/dist/timepicker/trigger/README.md +14 -0
  399. package/dist/timepicker/trigger/time-picker-trigger-forwarding-test.svelte +35 -0
  400. package/dist/timepicker/trigger/time-picker-trigger-forwarding-test.svelte.d.ts +3 -0
  401. package/dist/timepicker/trigger/time-picker-trigger.svelte +122 -0
  402. package/dist/timepicker/trigger/time-picker-trigger.svelte.d.ts +9 -0
  403. package/dist/utils/date-only.d.ts +11 -0
  404. package/dist/utils/date-only.js +53 -0
  405. package/dist/utils/index.d.ts +1 -0
  406. package/dist/utils/index.js +1 -0
  407. package/package.json +33 -2
@@ -3,11 +3,16 @@
3
3
  import { setComboBoxContext, type ComboBoxContext } from './context';
4
4
  import type { ListBoxContext } from '../../listbox/root/context';
5
5
  import { useVirtualFocus } from '../../hooks/use-virtual-focus.svelte';
6
+ import {
7
+ shouldShowFocusVisible,
8
+ trackInteractionModality
9
+ } from '../../primitives/input-modality';
6
10
 
7
11
  type ComboBoxProps<T> = {
8
12
  /** Stable ID used to generate internal ARIA IDs (recommended for SSR). */
9
13
  id?: string;
10
14
  isDisabled?: boolean;
15
+ isPending?: boolean;
11
16
  isReadOnly?: boolean;
12
17
  /** Selected value(s). Single value for single mode, array for multiple mode. Can be bound with bind:value */
13
18
  value?: string | number | (string | number)[];
@@ -43,6 +48,7 @@
43
48
  let {
44
49
  id: rootId,
45
50
  isDisabled = false,
51
+ isPending = false,
46
52
  isReadOnly = false,
47
53
  value = $bindable(),
48
54
  defaultValue,
@@ -98,6 +104,11 @@
98
104
 
99
105
  // Virtual focus for tag navigation in multiple mode
100
106
  let focusedTagId: string | number | null = $state(null);
107
+ let focusWithin = $state(false);
108
+ let focusVisible = $state(false);
109
+ let popoverPointerDownPending = $state(false);
110
+ let shouldCloseOnEscapeState = $state(true);
111
+ let shouldCloseOnBlurState = $state(true);
101
112
 
102
113
  // Flag to control whether inputValue should be used for filtering
103
114
  // When false, all items are shown regardless of inputValue
@@ -188,6 +199,7 @@
188
199
  // In multiple mode, selections are managed via tags, not input
189
200
  if (selectionMode === 'single' && val.trim() === '' && currentSelection.size > 0) {
190
201
  const emptySelection = new Set<string | number>();
202
+ selectedInternal = emptySelection;
191
203
  if (isSelectionControlled) {
192
204
  onChange?.(toExternalValue(emptySelection));
193
205
  } else {
@@ -199,17 +211,26 @@
199
211
  }
200
212
  }
201
213
 
214
+ function syncInputValue(val: string, options?: { notifyInputChange?: boolean }) {
215
+ inputValueInternal = val;
216
+ inputValue = val;
217
+
218
+ if (options?.notifyInputChange ?? true) {
219
+ onInputChange?.(val);
220
+ }
221
+ }
222
+
202
223
  function selectItem(id: string | number, label: string) {
203
224
  let newSelection: Set<string | number>;
204
225
 
205
226
  if (selectionMode === 'single') {
206
227
  newSelection = new Set([id]);
228
+ shouldFilter = false;
207
229
  // Save the label persistently for restore on blur/escape
208
230
  selectedLabel = label;
209
- // Update input directly without triggering deselection
210
- inputValueInternal = label;
211
- inputValue = label;
212
- onInputChange?.(label);
231
+ // Keep the selected label visible in the input without re-triggering
232
+ // external filtering during the popover close animation.
233
+ syncInputValue(label, { notifyInputChange: false });
213
234
  if (effectiveCloseOnSelect) {
214
235
  closePopover(true); // Close and keep focus on input
215
236
  }
@@ -236,6 +257,7 @@
236
257
  }
237
258
  }
238
259
 
260
+ selectedInternal = newSelection;
239
261
  if (isSelectionControlled) {
240
262
  onChange?.(toExternalValue(newSelection));
241
263
  } else {
@@ -257,6 +279,7 @@
257
279
  // Remove from persistent labels
258
280
  selectedLabels.delete(id);
259
281
 
282
+ selectedInternal = newSelection;
260
283
  if (isSelectionControlled) {
261
284
  onChange?.(toExternalValue(newSelection));
262
285
  } else {
@@ -274,6 +297,7 @@
274
297
  function clearSelection() {
275
298
  const emptySelection = new Set<string | number>();
276
299
 
300
+ selectedInternal = emptySelection;
277
301
  if (isSelectionControlled) {
278
302
  onChange?.(toExternalValue(emptySelection));
279
303
  } else {
@@ -303,6 +327,8 @@
303
327
  onInputChange?.('');
304
328
  }
305
329
  // Otherwise user typed, keep their filter
330
+ } else {
331
+ shouldFilter = true;
306
332
  }
307
333
  setIsOpen(true);
308
334
  // Auto-focus the selected item when opening with a selection
@@ -318,8 +344,6 @@
318
344
  setIsOpen(false);
319
345
  // Reset navigation state
320
346
  navigation.reset();
321
- // Re-enable filtering for next open
322
- shouldFilter = true;
323
347
  // Only refocus input when explicitly requested (e.g., after selection)
324
348
  // Never refocus in focus mode to prevent re-opening
325
349
  if (refocusInput && trigger !== 'focus') {
@@ -335,9 +359,40 @@
335
359
  }
336
360
  }
337
361
 
362
+ function syncFocusWithin() {
363
+ focusWithin =
364
+ !!wrapperRef && !!document.activeElement && wrapperRef.contains(document.activeElement);
365
+ if (!focusWithin) {
366
+ focusVisible = false;
367
+ // Clean up stale data-focused/data-focus-visible that Popover.Root's
368
+ // focus-state module may have set imperatively on the wrapper (the
369
+ // wrapper is briefly used as triggerRef before the input overrides it).
370
+ if (wrapperRef) {
371
+ delete wrapperRef.dataset.focused;
372
+ delete wrapperRef.dataset.focusVisible;
373
+ }
374
+ }
375
+ }
376
+
377
+ function handleFocusIn(event: FocusEvent) {
378
+ focusWithin = true;
379
+ focusVisible = shouldShowFocusVisible(event.target as HTMLElement | null);
380
+ }
381
+
382
+ function handleFocusOut() {
383
+ queueMicrotask(syncFocusWithin);
384
+ }
385
+
386
+ function setFocusVisibleState(visible: boolean) {
387
+ focusVisible = visible && focusWithin;
388
+ }
389
+
338
390
  // Use navigation hook methods for keyboard navigation
339
391
  function selectFocusedItem() {
340
392
  if (navigation.focusedId !== null) {
393
+ if (listboxCtxRef?.isDisabled(navigation.focusedId)) {
394
+ return;
395
+ }
341
396
  const label = navigation.itemLabels.get(navigation.focusedId) ?? String(navigation.focusedId);
342
397
  selectItem(navigation.focusedId, label);
343
398
  }
@@ -346,9 +401,29 @@
346
401
  /**
347
402
  * Handle input blur or escape - restore selection label or clear if no selection
348
403
  */
349
- function handleInputBlur() {
404
+ function consumePopoverPointerDown() {
405
+ if (!popoverPointerDownPending) return false;
406
+ popoverPointerDownPending = false;
407
+ return true;
408
+ }
409
+
410
+ function handleInputBlur(event?: FocusEvent) {
350
411
  // Clear tag virtual focus
351
412
  focusedTagId = null;
413
+
414
+ const nextFocusedElement = event?.relatedTarget;
415
+ const isMovingFocusWithinCombobox =
416
+ nextFocusedElement instanceof Node &&
417
+ ((wrapperRef?.contains(nextFocusedElement) ?? false) ||
418
+ (listboxRef?.contains(nextFocusedElement) ?? false));
419
+
420
+ if (isMovingFocusWithinCombobox || consumePopoverPointerDown()) {
421
+ return;
422
+ }
423
+
424
+ if (!shouldCloseOnBlurState) {
425
+ return;
426
+ }
352
427
  // Close popover first to prevent flash of options when clearing input
353
428
  closePopover();
354
429
 
@@ -376,15 +451,14 @@
376
451
  if (currentSelection.size > 0 && selectedLabel) {
377
452
  if (selectedLabel !== currentInputValue) {
378
453
  // Restore the selected label
379
- inputValueInternal = selectedLabel;
380
- inputValue = selectedLabel;
381
- onInputChange?.(selectedLabel);
454
+ syncInputValue(selectedLabel, { notifyInputChange: false });
382
455
  }
383
456
  }
384
457
  }
385
458
 
386
459
  function handleKeydown(event: KeyboardEvent) {
387
460
  if (isDisabled) return;
461
+ trackInteractionModality(event, event.target as HTMLElement | null);
388
462
 
389
463
  // Handle tag virtual focus navigation in multiple mode
390
464
  if (focusedTagId !== null && selectionMode === 'multiple') {
@@ -552,14 +626,16 @@
552
626
  }
553
627
  break;
554
628
  case 'Escape':
555
- if (currentIsOpen) {
629
+ if (currentIsOpen && shouldCloseOnEscapeState) {
556
630
  closePopover(true); // Keep focus on input after Escape
557
631
  // Stop propagation so parent dialogs don't also close
558
632
  event.stopPropagation();
559
633
  event.stopImmediatePropagation();
634
+ handleInputBlur();
635
+ // Escape is a keyboard-only path, so focus-visible remains enabled for the input.
636
+ focusVisible = true;
637
+ event.preventDefault();
560
638
  }
561
- handleInputBlur();
562
- event.preventDefault();
563
639
  break;
564
640
  case 'Backspace':
565
641
  // In multiple mode, remove last tag when input is empty
@@ -604,6 +680,18 @@
604
680
  get isDisabled() {
605
681
  return isDisabled;
606
682
  },
683
+ get isPending() {
684
+ return isPending;
685
+ },
686
+ get isFocusVisible() {
687
+ return focusVisible;
688
+ },
689
+ get shouldCloseOnEscape() {
690
+ return shouldCloseOnEscapeState;
691
+ },
692
+ get shouldCloseOnBlur() {
693
+ return shouldCloseOnBlurState;
694
+ },
607
695
  get isReadOnly() {
608
696
  return isReadOnly;
609
697
  },
@@ -668,11 +756,22 @@
668
756
  unregisterItem: navigation.unregister,
669
757
  handleKeydown,
670
758
  handleInputBlur,
759
+ setFocusVisible: setFocusVisibleState,
671
760
  get focusedTagId() {
672
761
  return focusedTagId;
673
762
  },
674
763
  setFocusedTagId: (id: string | number | null) => {
675
764
  focusedTagId = id;
765
+ },
766
+ markPopoverPointerDown: () => {
767
+ popoverPointerDownPending = true;
768
+ },
769
+ consumePopoverPointerDown,
770
+ setShouldCloseOnEscape: (value: boolean) => {
771
+ shouldCloseOnEscapeState = value;
772
+ },
773
+ setShouldCloseOnBlur: (value: boolean) => {
774
+ shouldCloseOnBlurState = value;
676
775
  }
677
776
  };
678
777
 
@@ -684,11 +783,18 @@
684
783
  role="group"
685
784
  aria-label={ariaLabel}
686
785
  aria-labelledby={ariaLabelledby}
786
+ aria-busy={isPending ? 'true' : undefined}
687
787
  class={className}
688
788
  data-combobox
789
+ data-focused={focusWithin || undefined}
689
790
  data-disabled={isDisabled || undefined}
791
+ data-pending={isPending || undefined}
690
792
  data-readonly={isReadOnly || undefined}
793
+ data-focus-within={focusWithin || undefined}
794
+ data-focus-visible={focusVisible || undefined}
691
795
  use:setWrapperAsTrigger
796
+ onfocusin={handleFocusIn}
797
+ onfocusout={handleFocusOut}
692
798
  >
693
799
  {#if children}
694
800
  {@render children()}
@@ -3,6 +3,7 @@ type ComboBoxProps<T> = {
3
3
  /** Stable ID used to generate internal ARIA IDs (recommended for SSR). */
4
4
  id?: string;
5
5
  isDisabled?: boolean;
6
+ isPending?: boolean;
6
7
  isReadOnly?: boolean;
7
8
  /** Selected value(s). Single value for single mode, array for multiple mode. Can be bound with bind:value */
8
9
  value?: string | number | (string | number)[];
@@ -20,6 +20,10 @@ export type ComboBoxContext<T extends object = object> = {
20
20
  selectedValue: Set<string | number>;
21
21
  /** Whether the combobox is disabled */
22
22
  isDisabled: boolean;
23
+ /** Whether the combobox is pending async work */
24
+ isPending: boolean;
25
+ /** Whether focus should currently be presented as keyboard-visible */
26
+ isFocusVisible: boolean;
23
27
  /** Whether the combobox is read-only */
24
28
  isReadOnly: boolean;
25
29
  /** Selection mode */
@@ -79,11 +83,25 @@ export type ComboBoxContext<T extends object = object> = {
79
83
  /** Handle keyboard events (arrow navigation, enter, escape) */
80
84
  handleKeydown: (event: KeyboardEvent) => void;
81
85
  /** Handle input blur - restore selection or deselect if empty */
82
- handleInputBlur: () => void;
86
+ handleInputBlur: (event?: FocusEvent) => void;
87
+ /** Update root-level focus-visible state based on current modality. */
88
+ setFocusVisible: (visible: boolean) => void;
83
89
  /** Currently focused tag ID (virtual focus for tag navigation) */
84
90
  focusedTagId: string | number | null;
85
91
  /** Set focused tag ID (virtual focus for tag navigation) */
86
92
  setFocusedTagId: (id: string | number | null) => void;
93
+ /** Mark that the next input blur was caused by pointer interaction inside the popover. */
94
+ markPopoverPointerDown: () => void;
95
+ /** Consume the pending popover-pointer marker. */
96
+ consumePopoverPointerDown: () => boolean;
97
+ /** Whether Escape should close the popover. */
98
+ shouldCloseOnEscape: boolean;
99
+ /** Whether blur should close the popover. */
100
+ shouldCloseOnBlur: boolean;
101
+ /** Update whether Escape should close the popover. */
102
+ setShouldCloseOnEscape: (value: boolean) => void;
103
+ /** Update whether blur should close the popover. */
104
+ setShouldCloseOnBlur: (value: boolean) => void;
87
105
  };
88
106
  export declare function setComboBoxContext<T extends object = object>(ctx: ComboBoxContext<T>): void;
89
107
  export declare function getComboBoxContext<T extends object = object>(): ComboBoxContext<T> | undefined;
@@ -2,6 +2,7 @@
2
2
  import type { Snippet } from 'svelte';
3
3
  import type { HTMLButtonAttributes } from 'svelte/elements';
4
4
  import { getContext } from 'svelte';
5
+ import { ButtonRoot } from '../../button/index.js';
5
6
  import { cn } from '../../utils/cn';
6
7
  import { TAG_CONTEXT_KEY, type TagContext } from '../tag/combobox-tag.svelte';
7
8
 
@@ -27,7 +28,7 @@
27
28
  </script>
28
29
 
29
30
  {#if !tagCtx.disabled}
30
- <button
31
+ <ButtonRoot
31
32
  type="button"
32
33
  onclick={handleClick}
33
34
  aria-label={`Remove ${tagCtx.label}`}
@@ -49,5 +50,5 @@
49
50
  />
50
51
  </svg>
51
52
  {/if}
52
- </button>
53
+ </ButtonRoot>
53
54
  {/if}
@@ -0,0 +1,21 @@
1
+ # ComboBox Trigger
2
+
3
+ ## API reference
4
+
5
+ ### ComboBox.Trigger
6
+
7
+ Name: `ComboBox.Trigger`
8
+ Description: Optional trigger button that toggles the combobox popover without stealing focus from the input.
9
+
10
+ | Prop | Type | Default | Description |
11
+ | -------------- | ---------------------- | ----------- | --------------------------------------------------------------- |
12
+ | `class` | `string` | `undefined` | CSS class names for the trigger element. |
13
+ | `children` | `Snippet` | `undefined` | Custom trigger content. If omitted, a chevron icon is rendered. |
14
+ | `tabindex` | `number` | `-1` | Tab index applied to the trigger button. |
15
+ | `...restProps` | `HTMLButtonAttributes` | `-` | Additional native button attributes. |
16
+
17
+ ## Notes
18
+
19
+ - `ComboBox.Trigger` reflects the root pending state through `data-pending`.
20
+ - While the combobox is disabled, read-only, or pending, the trigger becomes non-interactive.
21
+ - `ComboBox.Button` remains available as a compatibility alias.
@@ -0,0 +1,56 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+ import type { HTMLButtonAttributes } from 'svelte/elements';
4
+ import { ButtonRoot } from '../../button/index.js';
5
+ import { useComboBoxContext } from '../root/context';
6
+
7
+ type ComboBoxTriggerProps = HTMLButtonAttributes & {
8
+ class?: string;
9
+ children?: Snippet;
10
+ };
11
+
12
+ let { class: className, children, tabindex = -1, ...restProps }: ComboBoxTriggerProps = $props();
13
+
14
+ const ctx = useComboBoxContext();
15
+ const isTriggerDisabled = $derived(ctx.isDisabled || ctx.isReadOnly || ctx.isPending);
16
+
17
+ function handleMouseDown(event: MouseEvent) {
18
+ event.preventDefault();
19
+ if (!isTriggerDisabled) {
20
+ ctx.toggle();
21
+ }
22
+ }
23
+ </script>
24
+
25
+ <ButtonRoot
26
+ type="button"
27
+ {tabindex}
28
+ aria-label={ctx.isOpen ? 'Close menu' : 'Open menu'}
29
+ aria-expanded={ctx.isOpen}
30
+ aria-controls={`combobox-listbox-${ctx.instanceId}`}
31
+ isDisabled={ctx.isDisabled || ctx.isReadOnly}
32
+ isPending={ctx.isPending}
33
+ pressed={ctx.isOpen}
34
+ onmousedown={handleMouseDown}
35
+ class={className}
36
+ {...restProps}
37
+ >
38
+ {#if children}
39
+ {@render children()}
40
+ {:else}
41
+ <svg
42
+ xmlns="http://www.w3.org/2000/svg"
43
+ width="16"
44
+ height="16"
45
+ viewBox="0 0 24 24"
46
+ fill="none"
47
+ stroke="currentColor"
48
+ stroke-width="2"
49
+ stroke-linecap="round"
50
+ stroke-linejoin="round"
51
+ class="transition-transform {ctx.isOpen ? 'rotate-180' : ''}"
52
+ >
53
+ <path d="m6 9 6 6 6-6" />
54
+ </svg>
55
+ {/if}
56
+ </ButtonRoot>
@@ -0,0 +1,9 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { HTMLButtonAttributes } from 'svelte/elements';
3
+ type ComboBoxTriggerProps = HTMLButtonAttributes & {
4
+ class?: string;
5
+ children?: Snippet;
6
+ };
7
+ declare const ComboboxTrigger: import("svelte").Component<ComboBoxTriggerProps, {}, "">;
8
+ type ComboboxTrigger = ReturnType<typeof ComboboxTrigger>;
9
+ export default ComboboxTrigger;
@@ -0,0 +1,100 @@
1
+ # DatePicker
2
+
3
+ ## Description
4
+
5
+ `DatePicker` composes a segmented date input with a calendar popover for selecting dates.
6
+
7
+ ## Anatomy
8
+
9
+ - `DatePicker.Root`
10
+ - `DatePicker.Input`
11
+ - `DatePicker.Segment`
12
+ - `DatePicker.Trigger`
13
+ - `DatePicker.Popover`
14
+ - `DatePicker.Calendar`
15
+ - `DatePicker.TriggerPrevious`
16
+ - `DatePicker.Heading`
17
+ - `DatePicker.TriggerNext`
18
+ - `DatePicker.Grid`
19
+ - `DatePicker.GridHeader`
20
+ - `DatePicker.HeaderCell`
21
+ - `DatePicker.GridBody`
22
+ - `DatePicker.BodyCell`
23
+
24
+ ```svelte
25
+ <DatePicker.Root>
26
+ <DatePicker.Input aria-label="Date input">
27
+ {#snippet children(segment)}
28
+ <DatePicker.Segment {segment} />
29
+ {/snippet}
30
+ </DatePicker.Input>
31
+ <DatePicker.Trigger />
32
+
33
+ <DatePicker.Popover>
34
+ <DatePicker.Calendar>
35
+ <div>
36
+ <DatePicker.TriggerPrevious />
37
+ <DatePicker.Heading />
38
+ <DatePicker.TriggerNext />
39
+ </div>
40
+ <DatePicker.Grid>
41
+ <DatePicker.GridHeader />
42
+ <DatePicker.GridBody />
43
+ </DatePicker.Grid>
44
+ </DatePicker.Calendar>
45
+ </DatePicker.Popover>
46
+ </DatePicker.Root>
47
+ ```
48
+
49
+ ## Root API
50
+
51
+ - `value?: string | null` (`YYYY-MM-DD`)
52
+ - `defaultValue?: string | null` (`YYYY-MM-DD`)
53
+ - `onChange?: (value: string | null) => void`
54
+ - `isDisabled?: boolean`
55
+ - `isReadOnly?: boolean`
56
+ - `minValue?: string` (`YYYY-MM-DD`)
57
+ - `maxValue?: string` (`YYYY-MM-DD`)
58
+ - `isDateUnavailable?: (date: string) => boolean`
59
+ - `open?: boolean`
60
+ - `defaultOpen?: boolean`
61
+ - `onOpenChange?: (open: boolean, details: { reason, event?, cancel(), isCanceled }) => void`
62
+ - `closeOnSelect?: boolean`
63
+ - Null-first empty contract: when `value` and `defaultValue` are omitted, the empty state is `null`.
64
+ - `DatePicker.Input` exposes `aria-invalid` and `data-invalid` when the current segment draft is not committeable.
65
+
66
+ ## Popover API
67
+
68
+ - `DatePicker.Popover` forwards `Popover.Content` props (for example `placement`, `offset`, `shouldFlip`, `boundaryElement`, `isNonModal`, and close behavior props).
69
+ - The following are controlled internally by `DatePicker` and are not accepted on `DatePicker.Popover`: `open`, `triggerRef`, `onOpenChange`, `id`.
70
+ - Defaults:
71
+ - `placement` defaults to `bottom-start`.
72
+ - `aria-label` defaults to `Calendar`.
73
+ - `initialFocus` defaults to focusing the current active day cell in the calendar grid.
74
+
75
+ ## Calendar API
76
+
77
+ - `DatePicker.Calendar` forwards `Calendar.Root` props except those controlled by `DatePicker.Root`.
78
+ - The following are controlled internally by `DatePicker` and are not accepted on `DatePicker.Calendar`: `selectionMode`, `value`, `defaultValue`, `onChange`, `isDisabled`, `isReadOnly`, `isDateUnavailable`.
79
+
80
+ ## Notes
81
+
82
+ - Locale is read from `LocaleProvider` when available.
83
+ - Segment accessible names are resolved automatically from the active locale.
84
+ - During segment editing, the committed value is set to `null` when the draft is incomplete, invalid, out-of-range, or unavailable.
85
+ - Current MVP focuses on date-only values.
86
+
87
+ ## UX Decisions
88
+
89
+ - **No Date Auto-Correction:** When users manually type dates out of the configured bounds (`minValue`/`maxValue`) or dates that are unavailable, the DatePicker **does not auto-correct** the typed value. Instead, it exposes `aria-invalid="true"` and `data-invalid` on the input, allowing the user to see what they typed incorrectly. The underlying committed value is kept as `null` until a valid date is completed. Auto-correcting input without explicit user consent is an inaccessible anti-pattern.
90
+ - **Navigable Disabled Dates:** When using the Calendar, disabled dates remain focusable via keyboard navigation. This ensures ARIA Grid spatial navigation parity so that screen readers can consistently announce all calendar cells and report them as "disabled", rather than skipping over them and disorienting the user.
91
+
92
+ ## Focus behavior decisions
93
+
94
+ - DatePicker aligns with the shared modality primitive (`primitives/input-modality.ts`) for `keyboard`, `pointer`, and `virtual` interactions.
95
+ - `data-focus-visible` is modality-driven; `data-focused` and `data-focus-within` continue to represent real DOM focus state.
96
+ - Trigger focus restore after calendar close is modality-aware:
97
+ - keyboard close paths keep visible focus,
98
+ - pointer outside close restores focus without visible focus.
99
+ - The component keeps explicit `trackInteractionModality(...)` calls in local handlers to ensure deterministic modality updates before local focus-state logic runs.
100
+ - Cross-component focus contract and invariants are documented in `FOCUS_STATE_CONTRACT.md`.
@@ -0,0 +1,28 @@
1
+ # DatePicker TODO
2
+
3
+ ## Goal
4
+
5
+ Track DatePicker work with a single mandatory TODO format.
6
+
7
+ ## Backlog
8
+
9
+ - [x] [M][P0][Area: Context][Owner: Unassigned][Target: Done] Complete core context wiring.
10
+ - [x] [M][P0][Area: State][Owner: Unassigned][Target: Done] Implement root state and value handling.
11
+ - [x] [M][P0][Area: Parsing][Owner: Unassigned][Target: Done] Integrate segment parser and formatter.
12
+ - [x] [M][P0][Area: Input][Owner: Unassigned][Target: Done] Deliver baseline segmented input rendering.
13
+ - [x] [M][P0][Area: Composition][Owner: Unassigned][Target: Done] Integrate calendar popover behavior.
14
+ - [x] [M][P0][Area: Accessibility][Owner: Unassigned][Target: Done] Implement keyboard navigation baseline.
15
+ - [x] [M][P0][Area: Validation][Owner: Unassigned][Target: Done] Implement min/max and unavailable date validation baseline.
16
+ - [x] [M][P0][Area: API][Owner: Unassigned][Target: Done] Ship public exports and baseline docs/tests.
17
+ - [x] [M][P0][Area: Forms][Owner: Unassigned][Target: Done] Support rich object values and hidden input synchronization.
18
+ - [x] [M][P0][Area: Focus][Owner: Unassigned][Target: Done] Unify focus-visible behavior with shared modality semantics.
19
+ - [x] [S][P1][Area: Focus][Owner: Unassigned][Target: Done] Remove DatePicker-local modality tracking in favor of shared primitive.
20
+ - [x] [S][P1][Area: Documentation][Owner: Unassigned][Target: Done] Document focus contract updates and DatePicker rationale.
21
+ - [ ] [S][P1][Area: Calendar][Owner: Unassigned][Target: TBD] Add multi-month calendar display.
22
+ - [ ] [S][P1][Area: Accessibility][Owner: Unassigned][Target: TBD] Run deep accessibility audit (SR + keyboard edge cases).
23
+ - [ ] [C][P2][Area: Time][Owner: Unassigned][Target: TBD] Add time selection integration.
24
+ - [ ] [C][P2][Area: API][Owner: Unassigned][Target: TBD] Decide and implement date-range mode strategy.
25
+ - [ ] [C][P2][Area: Input][Owner: Unassigned][Target: TBD] Add input mask helper utilities.
26
+ - [ ] [C][P2][Area: Mobile][Owner: Unassigned][Target: TBD] Add mobile-optimized interaction pass.
27
+ - [ ] [C][P2][Area: UX][Owner: Unassigned][Target: TBD] Add preset shortcuts (today, next week, custom).
28
+ - [ ] [C][P2][Area: Performance][Owner: Unassigned][Target: TBD] Add segment update micro-benchmarks and optimizations.
@@ -0,0 +1,19 @@
1
+ # DatePicker Calendar
2
+
3
+ ## API reference
4
+
5
+ ### DatePicker.Calendar
6
+
7
+ Name: `DatePicker.Calendar`
8
+ Description: Calendar composition part connected to `DatePicker.Root` selected date and navigation state.
9
+
10
+ | Prop | Type | Default | Description |
11
+ | -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- | ------------------------------------------------------ |
12
+ | `children` | `Snippet` | `undefined` | Optional custom calendar content. |
13
+ | `class` | `string` | `''` | CSS class names for the calendar wrapper. |
14
+ | `...restProps` | `Omit<ComponentProps<typeof Calendar.Root>, 'selectionMode' \| 'value' \| 'defaultValue' \| 'onChange' \| 'isDisabled' \| 'isReadOnly' \| 'isDateUnavailable'>` | `-` | Additional calendar root props forwarded by this part. |
15
+
16
+ ### Notes
17
+
18
+ Name: Root-controlled calendar props
19
+ Description: `selectionMode`, `value`, `defaultValue`, `onChange`, `isDisabled`, `isReadOnly`, and `isDateUnavailable` are controlled by `DatePicker.Root` and ignored when passed to this part.
@@ -0,0 +1,60 @@
1
+ <script lang="ts">
2
+ import DatePicker from '../index';
3
+
4
+ let unsafeOnChangeCalls = $state(0);
5
+ let selectedValue = $state<string | null>('');
6
+
7
+ const unsafeCalendarProps: Record<string, unknown> = {
8
+ selectionMode: 'range',
9
+ value: { start: '2026-02-01', end: '2026-02-05' },
10
+ defaultValue: '2026-02-20',
11
+ onChange: () => {
12
+ unsafeOnChangeCalls += 1;
13
+ },
14
+ isDisabled: true,
15
+ isReadOnly: true,
16
+ isDateUnavailable: () => true
17
+ };
18
+ </script>
19
+
20
+ <DatePicker.Root
21
+ defaultValue="2026-02-10"
22
+ defaultOpen={true}
23
+ onChange={(nextValue) => {
24
+ selectedValue = nextValue;
25
+ }}
26
+ >
27
+ <DatePicker.Input class="date-picker-input" aria-label="Date input">
28
+ {#snippet children(segment)}
29
+ <DatePicker.Segment class="date-picker-segment" {segment} />
30
+ {/snippet}
31
+ </DatePicker.Input>
32
+ <DatePicker.Trigger class="date-picker-trigger">Open calendar</DatePicker.Trigger>
33
+
34
+ <DatePicker.Popover class="date-picker-popover">
35
+ <DatePicker.Calendar class="date-picker-calendar" {...unsafeCalendarProps}>
36
+ <div class="flex items-center justify-between gap-2 p-2">
37
+ <DatePicker.TriggerPrevious />
38
+ <DatePicker.Heading />
39
+ <DatePicker.TriggerNext />
40
+ </div>
41
+ <DatePicker.Grid>
42
+ <DatePicker.GridHeader>
43
+ {#snippet children(dayLabel: string)}
44
+ <DatePicker.HeaderCell>
45
+ {dayLabel}
46
+ </DatePicker.HeaderCell>
47
+ {/snippet}
48
+ </DatePicker.GridHeader>
49
+ <DatePicker.GridBody>
50
+ {#snippet children(date: string)}
51
+ <DatePicker.BodyCell {date} />
52
+ {/snippet}
53
+ </DatePicker.GridBody>
54
+ </DatePicker.Grid>
55
+ </DatePicker.Calendar>
56
+ </DatePicker.Popover>
57
+ </DatePicker.Root>
58
+
59
+ <p data-testid="unsafe-on-change-calls">{unsafeOnChangeCalls}</p>
60
+ <p data-testid="selected-value">{selectedValue}</p>
@@ -0,0 +1,3 @@
1
+ declare const DatePickerCalendarUnsafePropsTest: import("svelte").Component<Record<string, never>, {}, "">;
2
+ type DatePickerCalendarUnsafePropsTest = ReturnType<typeof DatePickerCalendarUnsafePropsTest>;
3
+ export default DatePickerCalendarUnsafePropsTest;