@adia-ai/web-components 0.6.33 → 0.6.35

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 (391) hide show
  1. package/CHANGELOG.md +64 -0
  2. package/color/index.js +1 -1
  3. package/components/accordion/accordion-item.yaml +2 -2
  4. package/components/accordion/accordion.css +2 -2
  5. package/components/accordion/accordion.js +1 -1
  6. package/components/action-list/action-item.yaml +2 -2
  7. package/components/action-list/action-list.css +2 -2
  8. package/components/action-list/action-list.js +1 -1
  9. package/components/agent-artifact/{class.js → agent-artifact.class.js} +1 -1
  10. package/components/agent-artifact/agent-artifact.css +31 -31
  11. package/components/agent-artifact/agent-artifact.js +1 -1
  12. package/components/agent-feedback-bar/agent-feedback-bar.css +10 -10
  13. package/components/agent-feedback-bar/agent-feedback-bar.js +1 -1
  14. package/components/agent-questions/agent-questions.css +57 -57
  15. package/components/agent-questions/agent-questions.js +1 -1
  16. package/components/agent-reasoning/agent-reasoning.css +62 -62
  17. package/components/agent-reasoning/agent-reasoning.js +1 -1
  18. package/components/agent-suggestions/agent-suggestions.css +4 -4
  19. package/components/agent-suggestions/agent-suggestions.js +1 -1
  20. package/components/agent-trace/agent-trace.css +53 -53
  21. package/components/alert/alert.a2ui.json +64 -1
  22. package/components/alert/{class.js → alert.class.js} +189 -2
  23. package/components/alert/alert.css +119 -41
  24. package/components/alert/alert.d.ts +14 -0
  25. package/components/alert/alert.js +1 -1
  26. package/components/alert/alert.test.js +184 -0
  27. package/components/alert/alert.yaml +114 -1
  28. package/components/avatar/avatar-group.yaml +2 -2
  29. package/components/avatar/avatar.css +27 -27
  30. package/components/avatar/avatar.js +1 -1
  31. package/components/badge/badge.css +27 -27
  32. package/components/badge/badge.js +1 -1
  33. package/components/block/block.css +16 -16
  34. package/components/block/block.js +1 -1
  35. package/components/breadcrumb/breadcrumb.css +23 -23
  36. package/components/breadcrumb/breadcrumb.js +1 -1
  37. package/components/button/button.css +101 -91
  38. package/components/button/button.js +1 -1
  39. package/components/calendar-grid/calendar-grid.a2ui.json +146 -0
  40. package/components/calendar-grid/calendar-grid.class.js +326 -0
  41. package/components/calendar-grid/calendar-grid.css +246 -0
  42. package/components/calendar-grid/calendar-grid.d.ts +41 -0
  43. package/components/calendar-grid/calendar-grid.js +17 -0
  44. package/components/calendar-grid/calendar-grid.yaml +136 -0
  45. package/components/calendar-picker/calendar-picker.css +139 -139
  46. package/components/calendar-picker/calendar-picker.js +1 -1
  47. package/components/canvas/canvas.css +12 -12
  48. package/components/card/card.css +83 -83
  49. package/components/card/card.js +1 -1
  50. package/components/chart/chart.css +224 -224
  51. package/components/chart/chart.js +1 -1
  52. package/components/chart-legend/chart-legend.css +26 -26
  53. package/components/chart-legend/chart-legend.js +1 -1
  54. package/components/chat-thread/chat-input.a2ui.json +1 -1
  55. package/components/chat-thread/chat-input.js +6 -1
  56. package/components/chat-thread/chat-input.yaml +4 -1
  57. package/components/chat-thread/chat-thread.js +1 -1
  58. package/components/check/check.css +40 -40
  59. package/components/check/check.js +1 -1
  60. package/components/code/code.css +125 -125
  61. package/components/code/code.js +1 -1
  62. package/components/col/col.css +15 -15
  63. package/components/col/col.js +1 -1
  64. package/components/color-input/color-input.js +1 -1
  65. package/components/color-picker/color-picker.css +55 -55
  66. package/components/color-picker/color-picker.js +1 -1
  67. package/components/combobox/combobox.a2ui.json +363 -0
  68. package/components/combobox/combobox.class.js +861 -0
  69. package/components/combobox/combobox.css +244 -0
  70. package/components/combobox/combobox.d.ts +113 -0
  71. package/components/combobox/combobox.examples.md +59 -0
  72. package/components/combobox/combobox.js +17 -0
  73. package/components/combobox/combobox.test.js +181 -0
  74. package/components/combobox/combobox.yaml +369 -0
  75. package/components/command/command.css +90 -90
  76. package/components/command/command.js +1 -1
  77. package/components/date-range-picker/date-range-picker.a2ui.json +300 -0
  78. package/components/date-range-picker/date-range-picker.class.js +791 -0
  79. package/components/date-range-picker/date-range-picker.css +224 -0
  80. package/components/date-range-picker/date-range-picker.d.ts +82 -0
  81. package/components/date-range-picker/date-range-picker.examples.md +37 -0
  82. package/components/date-range-picker/date-range-picker.js +17 -0
  83. package/components/date-range-picker/date-range-picker.test.js +387 -0
  84. package/components/date-range-picker/date-range-picker.yaml +285 -0
  85. package/components/datetime-picker/datetime-picker.a2ui.json +334 -0
  86. package/components/datetime-picker/datetime-picker.class.js +706 -0
  87. package/components/datetime-picker/datetime-picker.css +150 -0
  88. package/components/datetime-picker/datetime-picker.d.ts +86 -0
  89. package/components/datetime-picker/datetime-picker.examples.md +46 -0
  90. package/components/datetime-picker/datetime-picker.js +17 -0
  91. package/components/datetime-picker/datetime-picker.test.js +454 -0
  92. package/components/datetime-picker/datetime-picker.yaml +332 -0
  93. package/components/demo-toggle/demo-toggle.css +27 -27
  94. package/components/demo-toggle/demo-toggle.js +1 -1
  95. package/components/description-list/description-list.css +18 -18
  96. package/components/description-list/description-list.js +1 -1
  97. package/components/divider/divider.css +24 -24
  98. package/components/divider/divider.js +1 -1
  99. package/components/drawer/drawer.js +1 -1
  100. package/components/embed/embed.css +6 -6
  101. package/components/embed/embed.js +1 -1
  102. package/components/empty-state/empty-state.css +27 -27
  103. package/components/empty-state/empty-state.js +1 -1
  104. package/components/feed/feed.css +12 -12
  105. package/components/feed/feed.js +1 -1
  106. package/components/field/field.css +28 -28
  107. package/components/field/field.js +1 -1
  108. package/components/field/field.test.js +1 -1
  109. package/components/fields/fields.css +5 -5
  110. package/components/fields/fields.js +1 -1
  111. package/components/grid/grid.css +5 -5
  112. package/components/grid/grid.js +1 -1
  113. package/components/heatmap/heatmap.css +63 -63
  114. package/components/heatmap/heatmap.js +1 -1
  115. package/components/icon/icon.css +12 -12
  116. package/components/icon/icon.js +1 -1
  117. package/components/image/image.css +14 -14
  118. package/components/image/image.js +1 -1
  119. package/components/index.js +11 -0
  120. package/components/inline-message/inline-message.a2ui.json +143 -0
  121. package/components/inline-message/inline-message.class.js +169 -0
  122. package/components/inline-message/inline-message.css +75 -0
  123. package/components/inline-message/inline-message.d.ts +31 -0
  124. package/components/inline-message/inline-message.examples.md +19 -0
  125. package/components/inline-message/inline-message.js +17 -0
  126. package/components/inline-message/inline-message.test.js +203 -0
  127. package/components/inline-message/inline-message.yaml +205 -0
  128. package/components/input/input.css +67 -67
  129. package/components/input/input.js +1 -1
  130. package/components/input/input.yaml +5 -4
  131. package/components/inspector/inspector.css +6 -6
  132. package/components/inspector/inspector.js +1 -1
  133. package/components/integration-card/integration-card.a2ui.json +268 -0
  134. package/components/integration-card/integration-card.class.js +410 -0
  135. package/components/integration-card/integration-card.css +169 -0
  136. package/components/integration-card/integration-card.d.ts +63 -0
  137. package/components/integration-card/integration-card.examples.md +41 -0
  138. package/components/integration-card/integration-card.js +17 -0
  139. package/components/integration-card/integration-card.test.js +306 -0
  140. package/components/integration-card/integration-card.yaml +280 -0
  141. package/components/kbd/kbd.css +32 -32
  142. package/components/kbd/kbd.js +1 -1
  143. package/components/link/link.css +12 -12
  144. package/components/link/link.js +1 -1
  145. package/components/list/list-item.yaml +2 -2
  146. package/components/list/list.css +8 -8
  147. package/components/list/list.js +1 -1
  148. package/components/list-window/list-window.a2ui.json +277 -0
  149. package/components/list-window/list-window.class.js +688 -0
  150. package/components/list-window/list-window.css +124 -0
  151. package/components/list-window/list-window.d.ts +84 -0
  152. package/components/list-window/list-window.examples.md +73 -0
  153. package/components/list-window/list-window.js +17 -0
  154. package/components/list-window/list-window.test.js +303 -0
  155. package/components/list-window/list-window.yaml +270 -0
  156. package/components/loading-overlay/loading-overlay.a2ui.json +176 -0
  157. package/components/loading-overlay/loading-overlay.class.js +203 -0
  158. package/components/loading-overlay/loading-overlay.css +81 -0
  159. package/components/loading-overlay/loading-overlay.d.ts +24 -0
  160. package/components/loading-overlay/loading-overlay.examples.md +50 -0
  161. package/components/loading-overlay/loading-overlay.js +17 -0
  162. package/components/loading-overlay/loading-overlay.test.js +257 -0
  163. package/components/loading-overlay/loading-overlay.yaml +260 -0
  164. package/components/menu/menu-divider.yaml +1 -1
  165. package/components/menu/menu-item.yaml +1 -1
  166. package/components/menu/menu.a2ui.json +3 -0
  167. package/components/menu/menu.css +8 -8
  168. package/components/menu/menu.js +1 -1
  169. package/components/menu/menu.yaml +7 -0
  170. package/components/modal/{class.js → modal.class.js} +12 -1
  171. package/components/modal/modal.css +54 -44
  172. package/components/modal/modal.js +1 -1
  173. package/components/nav/nav.css +40 -40
  174. package/components/nav/nav.js +1 -1
  175. package/components/nav-group/nav-group.css +52 -52
  176. package/components/nav-group/nav-group.js +1 -1
  177. package/components/nav-item/nav-item.css +44 -44
  178. package/components/nav-item/nav-item.js +1 -1
  179. package/components/noodles/noodles.css +31 -31
  180. package/components/noodles/noodles.js +1 -1
  181. package/components/option-card/option-card.css +69 -69
  182. package/components/option-card/option-card.js +1 -1
  183. package/components/otp-input/otp-input.css +30 -30
  184. package/components/otp-input/otp-input.js +1 -1
  185. package/components/page/page.css +18 -18
  186. package/components/page/page.js +1 -1
  187. package/components/pagination/pagination.css +61 -61
  188. package/components/pagination/pagination.js +1 -1
  189. package/components/pane/pane.css +57 -57
  190. package/components/pane/pane.js +1 -1
  191. package/components/pipeline-status/pipeline-status.css +65 -65
  192. package/components/pipeline-status/pipeline-status.js +1 -1
  193. package/components/popover/popover.a2ui.json +8 -1
  194. package/components/popover/popover.css +17 -17
  195. package/components/popover/popover.js +1 -1
  196. package/components/popover/popover.yaml +14 -1
  197. package/components/progress/progress.css +23 -23
  198. package/components/progress/progress.js +1 -1
  199. package/components/progress-row/progress-row.css +17 -17
  200. package/components/progress-row/progress-row.js +1 -1
  201. package/components/radio/radio.css +39 -39
  202. package/components/radio/radio.js +1 -1
  203. package/components/range/range.css +55 -55
  204. package/components/range/range.js +1 -1
  205. package/components/rating/rating.css +28 -28
  206. package/components/rating/rating.js +1 -1
  207. package/components/richtext/richtext.css +133 -133
  208. package/components/richtext/richtext.js +1 -1
  209. package/components/row/row.css +19 -19
  210. package/components/row/row.js +1 -1
  211. package/components/search/search.css +5 -5
  212. package/components/search/search.js +1 -1
  213. package/components/segment/segment.css +24 -24
  214. package/components/segment/segment.js +1 -1
  215. package/components/segmented/segmented.css +25 -25
  216. package/components/segmented/segmented.js +1 -1
  217. package/components/select/select.a2ui.json +58 -4
  218. package/components/select/{class.js → select.class.js} +415 -6
  219. package/components/select/select.css +242 -84
  220. package/components/select/select.d.ts +31 -1
  221. package/components/select/select.js +1 -1
  222. package/components/select/select.test.js +202 -0
  223. package/components/select/select.yaml +126 -5
  224. package/components/skeleton/skeleton.css +14 -14
  225. package/components/skeleton/skeleton.js +1 -1
  226. package/components/slider/slider.css +46 -46
  227. package/components/slider/slider.js +1 -1
  228. package/components/spinner/spinner.a2ui.json +198 -0
  229. package/components/spinner/spinner.class.js +99 -0
  230. package/components/spinner/spinner.css +221 -0
  231. package/components/spinner/spinner.d.ts +26 -0
  232. package/components/spinner/spinner.examples.md +26 -0
  233. package/components/spinner/spinner.js +17 -0
  234. package/components/spinner/spinner.test.js +272 -0
  235. package/components/spinner/spinner.yaml +238 -0
  236. package/components/stack/stack.css +11 -11
  237. package/components/stack/stack.js +1 -1
  238. package/components/stat/stat.css +25 -25
  239. package/components/step-progress/step-progress.css +20 -20
  240. package/components/step-progress/step-progress.js +1 -1
  241. package/components/stepper/stepper-item.yaml +1 -1
  242. package/components/stepper/stepper.css +29 -29
  243. package/components/stepper/stepper.js +1 -1
  244. package/components/stream/stream.css +12 -12
  245. package/components/stream/stream.js +1 -1
  246. package/components/swatch/swatch.css +68 -68
  247. package/components/swatch/swatch.js +1 -1
  248. package/components/swiper/swiper.css +57 -57
  249. package/components/swiper/swiper.js +1 -1
  250. package/components/switch/switch.css +52 -52
  251. package/components/switch/switch.js +1 -1
  252. package/components/table/table.css +163 -163
  253. package/components/table/table.js +1 -1
  254. package/components/table-toolbar/{class.js → table-toolbar.class.js} +1 -1
  255. package/components/table-toolbar/table-toolbar.css +32 -32
  256. package/components/table-toolbar/table-toolbar.js +1 -1
  257. package/components/tabs/tab.yaml +2 -2
  258. package/components/tabs/tabs.css +51 -51
  259. package/components/tabs/tabs.js +1 -1
  260. package/components/tag/tag.css +48 -48
  261. package/components/tag/tag.js +1 -1
  262. package/components/tags-input/tags-input.a2ui.json +337 -0
  263. package/components/tags-input/tags-input.class.js +776 -0
  264. package/components/tags-input/tags-input.css +201 -0
  265. package/components/tags-input/tags-input.d.ts +120 -0
  266. package/components/tags-input/tags-input.examples.md +92 -0
  267. package/components/tags-input/tags-input.js +17 -0
  268. package/components/tags-input/tags-input.test.js +368 -0
  269. package/components/tags-input/tags-input.yaml +367 -0
  270. package/components/text/text.css +44 -44
  271. package/components/text/text.js +1 -1
  272. package/components/textarea/textarea.a2ui.json +1 -1
  273. package/components/textarea/textarea.css +46 -46
  274. package/components/textarea/textarea.js +1 -1
  275. package/components/textarea/textarea.yaml +11 -8
  276. package/components/time-picker/time-picker.a2ui.json +267 -0
  277. package/components/time-picker/time-picker.class.js +693 -0
  278. package/components/time-picker/time-picker.css +122 -0
  279. package/components/time-picker/time-picker.d.ts +75 -0
  280. package/components/time-picker/time-picker.examples.md +35 -0
  281. package/components/time-picker/time-picker.js +17 -0
  282. package/components/time-picker/time-picker.test.js +287 -0
  283. package/components/time-picker/time-picker.yaml +256 -0
  284. package/components/timeline/timeline-item.yaml +2 -2
  285. package/components/timeline/{class.js → timeline.class.js} +1 -1
  286. package/components/timeline/timeline.css +50 -50
  287. package/components/timeline/timeline.js +1 -1
  288. package/components/toast/toast.css +58 -58
  289. package/components/toast/toast.js +1 -1
  290. package/components/toggle-group/toggle-group.css +6 -6
  291. package/components/toggle-group/toggle-group.js +1 -1
  292. package/components/toggle-group/toggle-option.yaml +1 -1
  293. package/components/toggle-scheme/toggle-scheme.css +2 -2
  294. package/components/toggle-scheme/toggle-scheme.js +1 -1
  295. package/components/toolbar/toolbar-group.yaml +1 -1
  296. package/components/toolbar/toolbar.css +17 -17
  297. package/components/toolbar/toolbar.js +1 -1
  298. package/components/tooltip/tooltip.css +2 -2
  299. package/components/tooltip/tooltip.js +1 -1
  300. package/components/tree/tree-item.yaml +1 -1
  301. package/components/tree/tree.css +37 -37
  302. package/components/tree/tree.js +1 -1
  303. package/components/upload/upload.css +49 -49
  304. package/components/upload/upload.js +1 -1
  305. package/dist/web-components.min.css +1 -1
  306. package/dist/web-components.min.js +146 -87
  307. package/package.json +3 -3
  308. package/styles/components.css +11 -0
  309. /package/components/accordion/{class.js → accordion.class.js} +0 -0
  310. /package/components/action-list/{class.js → action-list.class.js} +0 -0
  311. /package/components/agent-feedback-bar/{class.js → agent-feedback-bar.class.js} +0 -0
  312. /package/components/agent-questions/{class.js → agent-questions.class.js} +0 -0
  313. /package/components/agent-reasoning/{class.js → agent-reasoning.class.js} +0 -0
  314. /package/components/agent-suggestions/{class.js → agent-suggestions.class.js} +0 -0
  315. /package/components/avatar/{class.js → avatar.class.js} +0 -0
  316. /package/components/badge/{class.js → badge.class.js} +0 -0
  317. /package/components/block/{class.js → block.class.js} +0 -0
  318. /package/components/breadcrumb/{class.js → breadcrumb.class.js} +0 -0
  319. /package/components/button/{class.js → button.class.js} +0 -0
  320. /package/components/calendar-picker/{class.js → calendar-picker.class.js} +0 -0
  321. /package/components/card/{class.js → card.class.js} +0 -0
  322. /package/components/chart/{class.js → chart.class.js} +0 -0
  323. /package/components/chart-legend/{class.js → chart-legend.class.js} +0 -0
  324. /package/components/chat-thread/{class.js → chat-thread.class.js} +0 -0
  325. /package/components/check/{class.js → check.class.js} +0 -0
  326. /package/components/code/{class.js → code.class.js} +0 -0
  327. /package/components/col/{class.js → col.class.js} +0 -0
  328. /package/components/color-input/{class.js → color-input.class.js} +0 -0
  329. /package/components/color-picker/{class.js → color-picker.class.js} +0 -0
  330. /package/components/command/{class.js → command.class.js} +0 -0
  331. /package/components/demo-toggle/{class.js → demo-toggle.class.js} +0 -0
  332. /package/components/description-list/{class.js → description-list.class.js} +0 -0
  333. /package/components/divider/{class.js → divider.class.js} +0 -0
  334. /package/components/drawer/{class.js → drawer.class.js} +0 -0
  335. /package/components/embed/{class.js → embed.class.js} +0 -0
  336. /package/components/empty-state/{class.js → empty-state.class.js} +0 -0
  337. /package/components/feed/{class.js → feed.class.js} +0 -0
  338. /package/components/field/{class.js → field.class.js} +0 -0
  339. /package/components/fields/{class.js → fields.class.js} +0 -0
  340. /package/components/grid/{class.js → grid.class.js} +0 -0
  341. /package/components/heatmap/{class.js → heatmap.class.js} +0 -0
  342. /package/components/icon/{class.js → icon.class.js} +0 -0
  343. /package/components/image/{class.js → image.class.js} +0 -0
  344. /package/components/input/{class.js → input.class.js} +0 -0
  345. /package/components/inspector/{class.js → inspector.class.js} +0 -0
  346. /package/components/kbd/{class.js → kbd.class.js} +0 -0
  347. /package/components/link/{class.js → link.class.js} +0 -0
  348. /package/components/list/{class.js → list.class.js} +0 -0
  349. /package/components/menu/{class.js → menu.class.js} +0 -0
  350. /package/components/nav/{class.js → nav.class.js} +0 -0
  351. /package/components/nav-group/{class.js → nav-group.class.js} +0 -0
  352. /package/components/nav-item/{class.js → nav-item.class.js} +0 -0
  353. /package/components/noodles/{class.js → noodles.class.js} +0 -0
  354. /package/components/option-card/{class.js → option-card.class.js} +0 -0
  355. /package/components/otp-input/{class.js → otp-input.class.js} +0 -0
  356. /package/components/page/{class.js → page.class.js} +0 -0
  357. /package/components/pagination/{class.js → pagination.class.js} +0 -0
  358. /package/components/pane/{class.js → pane.class.js} +0 -0
  359. /package/components/pipeline-status/{class.js → pipeline-status.class.js} +0 -0
  360. /package/components/popover/{class.js → popover.class.js} +0 -0
  361. /package/components/progress/{class.js → progress.class.js} +0 -0
  362. /package/components/progress-row/{class.js → progress-row.class.js} +0 -0
  363. /package/components/radio/{class.js → radio.class.js} +0 -0
  364. /package/components/range/{class.js → range.class.js} +0 -0
  365. /package/components/rating/{class.js → rating.class.js} +0 -0
  366. /package/components/richtext/{class.js → richtext.class.js} +0 -0
  367. /package/components/row/{class.js → row.class.js} +0 -0
  368. /package/components/search/{class.js → search.class.js} +0 -0
  369. /package/components/segment/{class.js → segment.class.js} +0 -0
  370. /package/components/segmented/{class.js → segmented.class.js} +0 -0
  371. /package/components/skeleton/{class.js → skeleton.class.js} +0 -0
  372. /package/components/slider/{class.js → slider.class.js} +0 -0
  373. /package/components/stack/{class.js → stack.class.js} +0 -0
  374. /package/components/step-progress/{class.js → step-progress.class.js} +0 -0
  375. /package/components/stepper/{class.js → stepper.class.js} +0 -0
  376. /package/components/stream/{class.js → stream.class.js} +0 -0
  377. /package/components/swatch/{class.js → swatch.class.js} +0 -0
  378. /package/components/swiper/{class.js → swiper.class.js} +0 -0
  379. /package/components/switch/{class.js → switch.class.js} +0 -0
  380. /package/components/table/{class.js → table.class.js} +0 -0
  381. /package/components/tabs/{class.js → tabs.class.js} +0 -0
  382. /package/components/tag/{class.js → tag.class.js} +0 -0
  383. /package/components/text/{class.js → text.class.js} +0 -0
  384. /package/components/textarea/{class.js → textarea.class.js} +0 -0
  385. /package/components/toast/{class.js → toast.class.js} +0 -0
  386. /package/components/toggle-group/{class.js → toggle-group.class.js} +0 -0
  387. /package/components/toggle-scheme/{class.js → toggle-scheme.class.js} +0 -0
  388. /package/components/toolbar/{class.js → toolbar.class.js} +0 -0
  389. /package/components/tooltip/{class.js → tooltip.class.js} +0 -0
  390. /package/components/tree/{class.js → tree.class.js} +0 -0
  391. /package/components/upload/{class.js → upload.class.js} +0 -0
@@ -0,0 +1,326 @@
1
+ /**
2
+ * Non-side-effect class export for `<calendar-grid-ui>`.
3
+ *
4
+ * The auto-register path stays at `@adia-ai/web-components/components/calendar-grid`
5
+ * (which imports this file + calls `defineIfFree()`).
6
+ *
7
+ * @see ../../USAGE.md#registration--auto-vs-explicit
8
+ */
9
+
10
+ /**
11
+ * `<calendar-grid-ui>` — Substrate primitive: a single-month calendar grid.
12
+ *
13
+ * Renders ONLY the inline grid (month nav + day-cells + keyboard nav). No
14
+ * trigger, no popover — used as a substrate by <calendar-picker-ui> (trigger
15
+ * + popover wrapper), <date-range-picker-ui> (two side-by-side grids), and
16
+ * <datetime-picker-ui> (one grid + time pane).
17
+ *
18
+ * <calendar-grid-ui value="2026-05-23" min="2026-01-01" max="2026-12-31">
19
+ * </calendar-grid-ui>
20
+ *
21
+ * Properties:
22
+ * value — selected ISO date (YYYY-MM-DD)
23
+ * min — minimum selectable date (ISO)
24
+ * max — maximum selectable date (ISO)
25
+ * focus-date — the date that holds the roving tabindex (ISO, defaults to value or today)
26
+ * disabled / readonly — disables / blocks selection
27
+ *
28
+ * Events:
29
+ * change — { value: "2026-05-23" } when a date is selected
30
+ * input — emitted as the user navigates without committing
31
+ *
32
+ * Keyboard: ArrowUp/Down/Left/Right navigate days; Enter selects;
33
+ * PageUp/Down jump month; Home/End first/last of month.
34
+ */
35
+
36
+ import { UIElement } from '../../core/element.js';
37
+
38
+ const DAYS = ['S', 'M', 'T', 'W', 'T', 'F', 'S'];
39
+ const MONTHS_LONG = [
40
+ 'January', 'February', 'March', 'April', 'May', 'June',
41
+ 'July', 'August', 'September', 'October', 'November', 'December',
42
+ ];
43
+
44
+ function pad(n) { return String(n).padStart(2, '0'); }
45
+ function toISO(y, m, d) { return `${y}-${pad(m + 1)}-${pad(d)}`; }
46
+ function parseISO(str) {
47
+ if (!str) return null;
48
+ const m = /^(\d{4})-(\d{2})-(\d{2})$/.exec(String(str).trim());
49
+ if (!m) return null;
50
+ return new Date(+m[1], +m[2] - 1, +m[3]);
51
+ }
52
+ function sameDay(a, b) {
53
+ return a.getFullYear() === b.getFullYear()
54
+ && a.getMonth() === b.getMonth()
55
+ && a.getDate() === b.getDate();
56
+ }
57
+
58
+ export class UICalendarGrid extends UIElement {
59
+ // §154 Phosphor icons stamped without consumer markup.
60
+ static requiredIcons = ['caret-left', 'caret-right'];
61
+
62
+ static properties = {
63
+ value: { type: String, default: '', reflect: true },
64
+ min: { type: String, default: '', reflect: true },
65
+ max: { type: String, default: '', reflect: true },
66
+ disabled: { type: Boolean, default: false, reflect: true },
67
+ readonly: { type: Boolean, default: false, reflect: true },
68
+ // Range-aware highlighting — when both rangeStart and rangeEnd are
69
+ // set, day cells whose date falls strictly between them get
70
+ // `[data-in-range]` stamped on them (the endpoints themselves get
71
+ // `[data-selected]` via the `value` prop). Consumers like
72
+ // <date-range-picker-ui> push the same from/to onto both panes so
73
+ // each independently lights up its in-range cells.
74
+ rangeStart: { type: String, default: '', reflect: true, attribute: 'range-start' },
75
+ rangeEnd: { type: String, default: '', reflect: true, attribute: 'range-end' },
76
+ };
77
+
78
+ // No html`` template — we render imperatively via #renderCalendar so we can
79
+ // mutate per-day cells without diffing.
80
+ static template = () => null;
81
+
82
+ #viewYear = new Date().getFullYear();
83
+ #viewMonth = new Date().getMonth();
84
+ #focusedDay = null;
85
+ #bound = false;
86
+
87
+ // ── Lifecycle ──────────────────────────────────────────────────────
88
+
89
+ connected() {
90
+ this.setAttribute('role', 'group');
91
+ if (!this.hasAttribute('aria-label')) this.setAttribute('aria-label', 'Calendar');
92
+
93
+ // Initialize view to selected date or today.
94
+ const sel = parseISO(this.value);
95
+ if (sel) {
96
+ this.#viewYear = sel.getFullYear();
97
+ this.#viewMonth = sel.getMonth();
98
+ }
99
+
100
+ if (!this.#bound) {
101
+ this.#bound = true;
102
+ this.addEventListener('click', this.#onClick);
103
+ this.addEventListener('keydown', this.#onKey);
104
+ }
105
+ }
106
+
107
+ disconnected() {
108
+ this.removeEventListener('click', this.#onClick);
109
+ this.removeEventListener('keydown', this.#onKey);
110
+ this.#bound = false;
111
+ }
112
+
113
+ render() {
114
+ // If a selected value changed externally, re-sync the visible month so it
115
+ // contains the selection (without clobbering the user's mid-flight nav).
116
+ const sel = parseISO(this.value);
117
+ if (sel && (sel.getFullYear() !== this.#viewYear || sel.getMonth() !== this.#viewMonth)) {
118
+ this.#viewYear = sel.getFullYear();
119
+ this.#viewMonth = sel.getMonth();
120
+ }
121
+ this.#renderCalendar();
122
+ }
123
+
124
+ // ── Public API ─────────────────────────────────────────────────────
125
+
126
+ /** Move the visible month by ±N months. */
127
+ navigate(delta) {
128
+ this.#viewMonth += delta;
129
+ while (this.#viewMonth > 11) { this.#viewMonth -= 12; this.#viewYear++; }
130
+ while (this.#viewMonth < 0) { this.#viewMonth += 12; this.#viewYear--; }
131
+ this.#focusedDay = null;
132
+ this.#renderCalendar();
133
+ }
134
+
135
+ /** Programmatically focus a day (1-based) inside the visible month. */
136
+ focusDay(day) {
137
+ const daysInMonth = new Date(this.#viewYear, this.#viewMonth + 1, 0).getDate();
138
+ if (day < 1 || day > daysInMonth) return;
139
+ this.#focusedDay = day;
140
+ this.#renderCalendar();
141
+ this.querySelector('[data-cal-day][data-focused]')?.focus?.();
142
+ }
143
+
144
+ // ── Internal — render the grid ────────────────────────────────────
145
+
146
+ #renderCalendar() {
147
+ const year = this.#viewYear;
148
+ const month = this.#viewMonth;
149
+ const today = new Date();
150
+ const selected = parseISO(this.value);
151
+ const minDate = parseISO(this.min);
152
+ const maxDate = parseISO(this.max);
153
+ // Range endpoints — only honor when BOTH are set + valid + ordered.
154
+ const rs = parseISO(this.rangeStart);
155
+ const re = parseISO(this.rangeEnd);
156
+ const rangeFrom = (rs && re && rs <= re) ? rs : null;
157
+ const rangeTo = (rs && re && rs <= re) ? re : null;
158
+
159
+ // Header — Prev / Title / Next
160
+ let h = `<div data-cal-header>
161
+ <button data-cal-prev type="button" aria-label="Previous month" tabindex="-1"><icon-ui name="caret-left"></icon-ui></button>
162
+ <span data-cal-title>${MONTHS_LONG[month]} ${year}</span>
163
+ <button data-cal-next type="button" aria-label="Next month" tabindex="-1"><icon-ui name="caret-right"></icon-ui></button>
164
+ </div>`;
165
+
166
+ // Day-of-week header
167
+ h += `<div data-cal-weekdays>${DAYS.map((d) => `<span>${d}</span>`).join('')}</div>`;
168
+
169
+ // Day grid
170
+ const firstDay = new Date(year, month, 1).getDay();
171
+ const daysInMonth = new Date(year, month + 1, 0).getDate();
172
+ const daysInPrev = new Date(year, month, 0).getDate();
173
+
174
+ h += '<div data-cal-grid>';
175
+
176
+ // Previous-month trailing days (outside, disabled)
177
+ for (let i = firstDay - 1; i >= 0; i--) {
178
+ const day = daysInPrev - i;
179
+ h += `<button type="button" data-cal-day data-outside disabled tabindex="-1">${day}</button>`;
180
+ }
181
+
182
+ // Current-month days
183
+ for (let d = 1; d <= daysInMonth; d++) {
184
+ const date = new Date(year, month, d);
185
+ const iso = toISO(year, month, d);
186
+ const isToday = sameDay(date, today);
187
+ const isSelected = selected && sameDay(date, selected);
188
+ const isDisabled = (minDate && date < minDate) || (maxDate && date > maxDate);
189
+ const isFocused = this.#focusedDay === d;
190
+ // In-range: strictly between rangeStart and rangeEnd (endpoints
191
+ // themselves render as `[data-selected]` via the `value` prop;
192
+ // marking them in-range too would double-up the styling).
193
+ const isInRange = !!(rangeFrom && rangeTo
194
+ && date > rangeFrom && date < rangeTo);
195
+ // Range endpoint flags — let CSS render the start/end cell with
196
+ // half-pill caps so the in-range strip reads as a continuous
197
+ // band when displayed next to the in-range cells.
198
+ const isRangeStart = !!(rangeFrom && sameDay(date, rangeFrom));
199
+ const isRangeEnd = !!(rangeTo && sameDay(date, rangeTo));
200
+
201
+ const attrs = [
202
+ 'type="button"',
203
+ 'data-cal-day',
204
+ `data-date="${iso}"`,
205
+ isToday ? 'data-today' : '',
206
+ isSelected ? 'data-selected' : '',
207
+ isInRange ? 'data-in-range' : '',
208
+ isRangeStart ? 'data-range-start' : '',
209
+ isRangeEnd ? 'data-range-end' : '',
210
+ isDisabled ? 'disabled' : '',
211
+ isFocused ? 'data-focused' : '',
212
+ `tabindex="${isFocused ? '0' : '-1'}"`,
213
+ ].filter(Boolean).join(' ');
214
+
215
+ h += `<button ${attrs}>${d}</button>`;
216
+ }
217
+
218
+ // Next-month leading days
219
+ const totalCells = firstDay + daysInMonth;
220
+ const remaining = (7 - (totalCells % 7)) % 7;
221
+ for (let d = 1; d <= remaining; d++) {
222
+ h += `<button type="button" data-cal-day data-outside disabled tabindex="-1">${d}</button>`;
223
+ }
224
+
225
+ h += '</div>';
226
+
227
+ this.innerHTML = h;
228
+ }
229
+
230
+ // ── Selection ─────────────────────────────────────────────────────
231
+
232
+ #selectDate(iso) {
233
+ if (this.disabled || this.readonly) return;
234
+ this.value = iso;
235
+ // Re-render to reflect new selection.
236
+ this.#renderCalendar();
237
+ this.dispatchEvent(new CustomEvent('change', {
238
+ bubbles: true,
239
+ detail: { value: iso },
240
+ }));
241
+ }
242
+
243
+ // ── Event handlers ────────────────────────────────────────────────
244
+
245
+ #onClick = (e) => {
246
+ if (this.disabled) return;
247
+ const target = e.target instanceof Element ? e.target : null;
248
+ if (!target) return;
249
+ const prev = target.closest('[data-cal-prev]');
250
+ if (prev) { e.stopPropagation(); this.navigate(-1); return; }
251
+ const next = target.closest('[data-cal-next]');
252
+ if (next) { e.stopPropagation(); this.navigate(1); return; }
253
+ const day = target.closest('[data-cal-day][data-date]:not([disabled])');
254
+ if (day) { e.stopPropagation(); this.#selectDate(day.dataset.date); }
255
+ };
256
+
257
+ #onKey = (e) => {
258
+ if (this.disabled) return;
259
+
260
+ if (e.key === 'Enter' || e.key === ' ') {
261
+ if (this.#focusedDay) {
262
+ e.preventDefault();
263
+ const iso = toISO(this.#viewYear, this.#viewMonth, this.#focusedDay);
264
+ const date = new Date(this.#viewYear, this.#viewMonth, this.#focusedDay);
265
+ const minDate = parseISO(this.min);
266
+ const maxDate = parseISO(this.max);
267
+ if ((!minDate || date >= minDate) && (!maxDate || date <= maxDate)) {
268
+ this.#selectDate(iso);
269
+ }
270
+ }
271
+ return;
272
+ }
273
+
274
+ const arrows = { ArrowUp: -7, ArrowDown: 7, ArrowLeft: -1, ArrowRight: 1 };
275
+ if (arrows[e.key] !== undefined) {
276
+ e.preventDefault();
277
+ const daysInMonth = new Date(this.#viewYear, this.#viewMonth + 1, 0).getDate();
278
+ let day = (this.#focusedDay || 1) + arrows[e.key];
279
+
280
+ if (day < 1) {
281
+ this.navigate(-1);
282
+ const prevDays = new Date(this.#viewYear, this.#viewMonth + 1, 0).getDate();
283
+ this.#focusedDay = prevDays + day;
284
+ } else if (day > daysInMonth) {
285
+ this.navigate(1);
286
+ this.#focusedDay = day - daysInMonth;
287
+ } else {
288
+ this.#focusedDay = day;
289
+ }
290
+
291
+ this.#renderCalendar();
292
+ const focused = this.querySelector('[data-cal-day][data-focused]');
293
+ focused?.focus?.();
294
+ this.dispatchEvent(new CustomEvent('input', {
295
+ bubbles: true,
296
+ detail: { focusDate: toISO(this.#viewYear, this.#viewMonth, this.#focusedDay) },
297
+ }));
298
+ return;
299
+ }
300
+
301
+ if (e.key === 'PageUp') {
302
+ e.preventDefault();
303
+ this.navigate(-1);
304
+ return;
305
+ }
306
+ if (e.key === 'PageDown') {
307
+ e.preventDefault();
308
+ this.navigate(1);
309
+ return;
310
+ }
311
+ if (e.key === 'Home') {
312
+ e.preventDefault();
313
+ this.#focusedDay = 1;
314
+ this.#renderCalendar();
315
+ this.querySelector('[data-cal-day][data-focused]')?.focus?.();
316
+ return;
317
+ }
318
+ if (e.key === 'End') {
319
+ e.preventDefault();
320
+ this.#focusedDay = new Date(this.#viewYear, this.#viewMonth + 1, 0).getDate();
321
+ this.#renderCalendar();
322
+ this.querySelector('[data-cal-day][data-focused]')?.focus?.();
323
+ return;
324
+ }
325
+ };
326
+ }
@@ -0,0 +1,246 @@
1
+ /* ============================================================
2
+ <calendar-grid-ui> — Inline single-month calendar grid.
3
+
4
+ Substrate primitive consumed by calendar-picker-ui (popover
5
+ wrapper), date-range-picker-ui (two side-by-side grids), and
6
+ datetime-picker-ui (one grid + time pane).
7
+
8
+ Two-block @scope per docs/specs/component-token-contract.md.
9
+ Tokens mirror calendar-picker-ui's grid tokens (same surface,
10
+ shared visual language) so consumers can override either
11
+ --calendar-grid-* OR --calendar-picker-* and pick up the same
12
+ look-and-feel through cascade.
13
+ ============================================================ */
14
+
15
+ @scope (calendar-grid-ui) {
16
+ /* ── Block 1 — TOKENS ── */
17
+ :where(:scope) {
18
+ /* Layout */
19
+ --calendar-grid-gap-default: var(--a-space-1);
20
+ --calendar-grid-width-default: 16rem;
21
+
22
+ /* Header */
23
+ --calendar-grid-header-gap-default: var(--a-space-1);
24
+ --calendar-grid-header-mb-default: var(--a-space-2);
25
+ --calendar-grid-title-fg-default: var(--a-fg);
26
+ --calendar-grid-title-size-default: var(--a-ui-size);
27
+ --calendar-grid-title-weight-default: var(--a-weight-medium);
28
+
29
+ /* Nav buttons (prev/next) */
30
+ --calendar-grid-nav-size-default: 1.5rem;
31
+ --calendar-grid-nav-radius-default: var(--a-radius-sm);
32
+ --calendar-grid-nav-bg-default: transparent;
33
+ --calendar-grid-nav-bg-hover-default: var(--a-bg-muted);
34
+ --calendar-grid-nav-fg-default: var(--a-fg-muted);
35
+ --calendar-grid-nav-fg-hover-default: var(--a-fg);
36
+ --calendar-grid-nav-icon-size-default: 0.75rem;
37
+
38
+ /* Weekday header */
39
+ --calendar-grid-weekday-fg-default: var(--a-fg-muted);
40
+ --calendar-grid-weekday-size-default: var(--a-ui-sm);
41
+ --calendar-grid-weekday-weight-default: var(--a-weight-medium);
42
+ --calendar-grid-weekday-height-default: 1.5rem;
43
+ --calendar-grid-weekday-mb-default: var(--a-space-1);
44
+
45
+ /* Day cells */
46
+ --calendar-grid-day-size-default: 2rem;
47
+ --calendar-grid-day-radius-default: var(--a-radius);
48
+ --calendar-grid-day-font-size-default: var(--a-ui-sm);
49
+ --calendar-grid-day-bg-default: transparent;
50
+ --calendar-grid-day-fg-default: var(--a-fg-subtle);
51
+ --calendar-grid-day-bg-hover-default: var(--a-bg-hover);
52
+ --calendar-grid-day-fg-hover-default: var(--a-fg);
53
+ --calendar-grid-day-bg-selected-default: var(--a-accent);
54
+ --calendar-grid-day-fg-selected-default: var(--a-accent-fg);
55
+ /* In-range cells (strictly between rangeStart and rangeEnd) — muted
56
+ accent strip so the endpoints (full --a-accent fill) read as the
57
+ primary selection while the in-range band reads as secondary
58
+ context. Stylable independently of `selected`. */
59
+ --calendar-grid-day-bg-in-range-default: var(--a-accent-muted);
60
+ --calendar-grid-day-fg-in-range-default: var(--a-fg);
61
+ --calendar-grid-day-fg-outside-default: var(--a-fg-muted);
62
+ --calendar-grid-day-fg-disabled-default: var(--a-ui-text-disabled);
63
+ --calendar-grid-day-today-color-default: var(--a-accent);
64
+ --calendar-grid-day-today-dot-size-default: var(--a-space-0-5);
65
+ --calendar-grid-day-today-dot-offset-default: var(--a-space-1);
66
+ --calendar-grid-day-grid-gap-default: var(--a-space-px);
67
+ --calendar-grid-day-focus-ring-default: var(--a-focus-ring);
68
+
69
+ /* Transitions */
70
+ --calendar-grid-duration-default: var(--a-duration-fast);
71
+ --calendar-grid-easing-default: var(--a-easing);
72
+
73
+ /* Typography */
74
+ --calendar-grid-selected-weight-default: var(--a-weight-medium);
75
+ --calendar-grid-today-weight-default: var(--a-weight-medium);
76
+ }
77
+
78
+ /* ── Block 2 — BASE ── */
79
+ :scope {
80
+ box-sizing: border-box;
81
+ display: block;
82
+ width: var(--calendar-grid-width, var(--calendar-grid-width-default));
83
+ font-size: var(--calendar-grid-day-font-size, var(--calendar-grid-day-font-size-default));
84
+ }
85
+
86
+ :scope[disabled] {
87
+ pointer-events: none;
88
+ opacity: 0.5;
89
+ }
90
+
91
+ /* Header row */
92
+ [data-cal-header] {
93
+ display: flex;
94
+ align-items: center;
95
+ justify-content: space-between;
96
+ gap: var(--calendar-grid-header-gap, var(--calendar-grid-header-gap-default));
97
+ margin-block-end: var(--calendar-grid-header-mb, var(--calendar-grid-header-mb-default));
98
+ }
99
+
100
+ [data-cal-title] {
101
+ flex: 1;
102
+ text-align: center;
103
+ font-size: var(--calendar-grid-title-size, var(--calendar-grid-title-size-default));
104
+ font-weight: var(--calendar-grid-title-weight, var(--calendar-grid-title-weight-default));
105
+ color: var(--calendar-grid-title-fg, var(--calendar-grid-title-fg-default));
106
+ }
107
+
108
+ [data-cal-prev],
109
+ [data-cal-next] {
110
+ display: inline-flex;
111
+ align-items: center;
112
+ justify-content: center;
113
+ width: var(--calendar-grid-nav-size, var(--calendar-grid-nav-size-default));
114
+ height: var(--calendar-grid-nav-size, var(--calendar-grid-nav-size-default));
115
+ padding: 0;
116
+ border: none;
117
+ border-radius: var(--calendar-grid-nav-radius, var(--calendar-grid-nav-radius-default));
118
+ background: var(--calendar-grid-nav-bg, var(--calendar-grid-nav-bg-default));
119
+ color: var(--calendar-grid-nav-fg, var(--calendar-grid-nav-fg-default));
120
+ cursor: pointer;
121
+ transition:
122
+ background var(--calendar-grid-duration, var(--calendar-grid-duration-default)) var(--calendar-grid-easing, var(--calendar-grid-easing-default)),
123
+ color var(--calendar-grid-duration, var(--calendar-grid-duration-default)) var(--calendar-grid-easing, var(--calendar-grid-easing-default));
124
+ --a-icon-size: var(--calendar-grid-nav-icon-size, var(--calendar-grid-nav-icon-size-default));
125
+ }
126
+ [data-cal-prev]:hover,
127
+ [data-cal-next]:hover {
128
+ background: var(--calendar-grid-nav-bg-hover, var(--calendar-grid-nav-bg-hover-default));
129
+ color: var(--calendar-grid-nav-fg-hover, var(--calendar-grid-nav-fg-hover-default));
130
+ }
131
+
132
+ /* Day-of-week header */
133
+ [data-cal-weekdays] {
134
+ display: grid;
135
+ grid-template-columns: repeat(7, 1fr);
136
+ text-align: center;
137
+ font-size: var(--calendar-grid-weekday-size, var(--calendar-grid-weekday-size-default));
138
+ font-weight: var(--calendar-grid-weekday-weight, var(--calendar-grid-weekday-weight-default));
139
+ color: var(--calendar-grid-weekday-fg, var(--calendar-grid-weekday-fg-default));
140
+ margin-block-end: var(--calendar-grid-weekday-mb, var(--calendar-grid-weekday-mb-default));
141
+ }
142
+
143
+ [data-cal-weekdays] span {
144
+ display: flex;
145
+ align-items: center;
146
+ justify-content: center;
147
+ height: var(--calendar-grid-weekday-height, var(--calendar-grid-weekday-height-default));
148
+ }
149
+
150
+ /* Day grid */
151
+ [data-cal-grid] {
152
+ display: grid;
153
+ grid-template-columns: repeat(7, 1fr);
154
+ gap: var(--calendar-grid-day-grid-gap, var(--calendar-grid-day-grid-gap-default));
155
+ }
156
+
157
+ [data-cal-day] {
158
+ display: flex;
159
+ align-items: center;
160
+ justify-content: center;
161
+ width: var(--calendar-grid-day-size, var(--calendar-grid-day-size-default));
162
+ height: var(--calendar-grid-day-size, var(--calendar-grid-day-size-default));
163
+ margin: 0 auto;
164
+ padding: 0;
165
+ border: 1px solid transparent;
166
+ border-radius: var(--calendar-grid-day-radius, var(--calendar-grid-day-radius-default));
167
+ background: var(--calendar-grid-day-bg, var(--calendar-grid-day-bg-default));
168
+ color: var(--calendar-grid-day-fg, var(--calendar-grid-day-fg-default));
169
+ font: inherit;
170
+ font-size: var(--calendar-grid-day-font-size, var(--calendar-grid-day-font-size-default));
171
+ cursor: pointer;
172
+ transition:
173
+ background var(--calendar-grid-duration, var(--calendar-grid-duration-default)) var(--calendar-grid-easing, var(--calendar-grid-easing-default)),
174
+ color var(--calendar-grid-duration, var(--calendar-grid-duration-default)) var(--calendar-grid-easing, var(--calendar-grid-easing-default)),
175
+ border-color var(--calendar-grid-duration, var(--calendar-grid-duration-default)) var(--calendar-grid-easing, var(--calendar-grid-easing-default));
176
+ }
177
+
178
+ /* ── State: hover ── */
179
+ [data-cal-day]:not([disabled]):not([data-outside]):hover {
180
+ background: var(--calendar-grid-day-bg-hover, var(--calendar-grid-day-bg-hover-default));
181
+ color: var(--calendar-grid-day-fg-hover, var(--calendar-grid-day-fg-hover-default));
182
+ }
183
+
184
+ /* ── State: focus ── */
185
+ [data-cal-day]:not([disabled]):not([data-outside]):focus-visible,
186
+ [data-cal-day][data-focused] {
187
+ outline: none;
188
+ box-shadow: var(--calendar-grid-day-focus-ring, var(--calendar-grid-day-focus-ring-default));
189
+ }
190
+
191
+ /* ── State: selected ── */
192
+ [data-cal-day][data-selected] {
193
+ background: var(--calendar-grid-day-bg-selected, var(--calendar-grid-day-bg-selected-default));
194
+ color: var(--calendar-grid-day-fg-selected, var(--calendar-grid-day-fg-selected-default));
195
+ font-weight: var(--calendar-grid-selected-weight, var(--calendar-grid-selected-weight-default));
196
+ }
197
+ [data-cal-day][data-selected]:not([disabled]):hover {
198
+ background: var(--calendar-grid-day-bg-selected, var(--calendar-grid-day-bg-selected-default));
199
+ color: var(--calendar-grid-day-fg-selected, var(--calendar-grid-day-fg-selected-default));
200
+ }
201
+
202
+ /* ── State: in-range ──
203
+ Cells strictly between rangeStart and rangeEnd get the muted accent
204
+ strip. Endpoints themselves render as `[data-selected]` (full accent
205
+ fill); the in-range middle is visually subordinate. `:not([data-selected])`
206
+ guard prevents the muted fill from overriding the endpoint cells in
207
+ consumer code that sets both `value` AND `range-start`/`range-end`. */
208
+ [data-cal-day][data-in-range]:not([data-selected]) {
209
+ background: var(--calendar-grid-day-bg-in-range, var(--calendar-grid-day-bg-in-range-default));
210
+ color: var(--calendar-grid-day-fg-in-range, var(--calendar-grid-day-fg-in-range-default));
211
+ }
212
+ [data-cal-day][data-in-range]:not([data-selected]):not([disabled]):hover {
213
+ background: var(--calendar-grid-day-bg-in-range, var(--calendar-grid-day-bg-in-range-default));
214
+ }
215
+
216
+ /* ── State: today (unselected) ── */
217
+ [data-cal-day][data-today]:not([data-selected]) {
218
+ position: relative;
219
+ color: var(--calendar-grid-day-today-color, var(--calendar-grid-day-today-color-default));
220
+ font-weight: var(--calendar-grid-today-weight, var(--calendar-grid-today-weight-default));
221
+ }
222
+ [data-cal-day][data-today]:not([data-selected])::after {
223
+ content: "";
224
+ position: absolute;
225
+ left: 50%;
226
+ bottom: var(--calendar-grid-day-today-dot-offset, var(--calendar-grid-day-today-dot-offset-default));
227
+ width: var(--calendar-grid-day-today-dot-size, var(--calendar-grid-day-today-dot-size-default));
228
+ height: var(--calendar-grid-day-today-dot-size, var(--calendar-grid-day-today-dot-size-default));
229
+ border-radius: 50%;
230
+ background: var(--calendar-grid-day-today-color, var(--calendar-grid-day-today-color-default));
231
+ transform: translateX(-50%);
232
+ pointer-events: none;
233
+ }
234
+
235
+ /* ── State: outside month ── */
236
+ [data-cal-day][data-outside] {
237
+ color: var(--calendar-grid-day-fg-outside, var(--calendar-grid-day-fg-outside-default));
238
+ cursor: default;
239
+ }
240
+
241
+ /* ── State: disabled (excluding outside) ── */
242
+ [data-cal-day]:disabled:not([data-outside]) {
243
+ color: var(--calendar-grid-day-fg-disabled, var(--calendar-grid-day-fg-disabled-default));
244
+ cursor: not-allowed;
245
+ }
246
+ }
@@ -0,0 +1,41 @@
1
+ /**
2
+ * `<calendar-grid-ui>` — Substrate primitive — a single-month calendar grid (month nav + day cells + keyboard nav). Renders inline; no trigger, no popover. Used as a substrate by calendar-picker-ui (popover wrapper), date-range-picker-ui (two side-by-side grids), and datetime-picker-ui (one grid + time pane). For a complete date-picker affordance (trigger + popover + form participation), use calendar-picker-ui.
3
+ *
4
+ * @see https://ui-kit.exe.xyz/site/components/calendar-grid
5
+ *
6
+ * Type declarations generated by scripts/build/dts-codegen.mjs from
7
+ * the component's `.a2ui.json` sidecar(s). Edit the source `.yaml`,
8
+ * run `npm run build:components`, then `npm run codegen:dts` to
9
+ * regenerate; or hand-author this file fully if rich event types are
10
+ * needed beyond what the yaml `events:` block can express.
11
+ */
12
+
13
+ import { UIElement } from '../../core/element.js';
14
+
15
+ export type CalendarGridChangeEvent = CustomEvent<unknown>;
16
+ export type CalendarGridInputEvent = CustomEvent<unknown>;
17
+
18
+ export class UICalendarGrid extends UIElement {
19
+ /** Disables all interaction. */
20
+ disabled: boolean;
21
+ /** Maximum selectable date in ISO format (YYYY-MM-DD). */
22
+ max: string;
23
+ /** Minimum selectable date in ISO format (YYYY-MM-DD). */
24
+ min: string;
25
+ /** End of a date range (ISO YYYY-MM-DD). See `rangeStart` for the full contract. */
26
+ rangeEnd: string;
27
+ /** Start of a date range (ISO YYYY-MM-DD). When both rangeStart and rangeEnd are set + ordered, day cells strictly between the endpoints get `[data-in-range]` stamped for visual continuity. Used by `<date-range-picker-ui>` which pushes the same from/to onto both calendar panes. Endpoints themselves render via the `value` prop's `[data-selected]` state. */
28
+ rangeStart: string;
29
+ /** Blocks selection but allows month navigation. */
30
+ readonly: boolean;
31
+ /** Selected date in ISO format (YYYY-MM-DD). */
32
+ value: string;
33
+
34
+ addEventListener<K extends keyof HTMLElementEventMap>(
35
+ type: K,
36
+ listener: (this: UICalendarGrid, ev: HTMLElementEventMap[K]) => unknown,
37
+ options?: boolean | AddEventListenerOptions,
38
+ ): void;
39
+ addEventListener(type: 'change', listener: (ev: CalendarGridChangeEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
40
+ addEventListener(type: 'input', listener: (ev: CalendarGridInputEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
41
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * `<calendar-grid-ui>` — auto-registers the tag on import.
3
+ *
4
+ * For non-side-effect class import (test isolation, tag override), use
5
+ * the `class` subpath:
6
+ *
7
+ * import { UICalendarGrid } from '@adia-ai/web-components/components/calendar-grid/class';
8
+ *
9
+ * @see ../../USAGE.md#registration--auto-vs-explicit
10
+ */
11
+
12
+ import { defineIfFree } from '../../core/register.js';
13
+ import { UICalendarGrid } from './calendar-grid.class.js';
14
+
15
+ defineIfFree('calendar-grid-ui', UICalendarGrid);
16
+
17
+ export { UICalendarGrid };