@devalok/shilp-sutra 0.38.0 → 0.40.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (361) hide show
  1. package/AGENTS.md +151 -0
  2. package/MIGRATION.md +255 -0
  3. package/README.md +3 -0
  4. package/dist/_chunks/badge-group.js +76 -75
  5. package/dist/_chunks/badge-group.js.map +1 -1
  6. package/dist/_chunks/chart-container.js +50 -0
  7. package/dist/_chunks/chart-container.js.map +1 -0
  8. package/dist/_chunks/chat.js +236 -228
  9. package/dist/_chunks/chat.js.map +1 -1
  10. package/dist/_chunks/colors.js +30 -0
  11. package/dist/_chunks/colors.js.map +1 -0
  12. package/dist/_chunks/document-preview.js +2 -2
  13. package/dist/_chunks/document-preview.js.map +1 -1
  14. package/dist/_chunks/emoji-data.js +45 -0
  15. package/dist/_chunks/emoji-data.js.map +1 -0
  16. package/dist/_chunks/grid-lines.js +72 -0
  17. package/dist/_chunks/grid-lines.js.map +1 -0
  18. package/dist/_chunks/image-preview.js +2 -2
  19. package/dist/_chunks/image-preview.js.map +1 -1
  20. package/dist/_chunks/mention-suggestion.js +35 -263
  21. package/dist/_chunks/mention-suggestion.js.map +1 -1
  22. package/dist/_chunks/normalize-icon.js +18 -0
  23. package/dist/_chunks/normalize-icon.js.map +1 -0
  24. package/dist/_chunks/oauth-button.js +227 -0
  25. package/dist/_chunks/oauth-button.js.map +1 -0
  26. package/dist/_chunks/popover.js +3 -3
  27. package/dist/_chunks/popover.js.map +1 -1
  28. package/dist/_chunks/primitives.js +107 -107
  29. package/dist/_chunks/primitives.js.map +1 -1
  30. package/dist/_chunks/shared.js +5 -5
  31. package/dist/_chunks/shared.js.map +1 -1
  32. package/dist/_chunks/{text.js → success.js} +26 -63
  33. package/dist/_chunks/success.js.map +1 -0
  34. package/dist/_chunks/tiptap.js +1952 -1949
  35. package/dist/_chunks/tiptap.js.map +1 -1
  36. package/dist/_chunks/tooltip.js +58 -0
  37. package/dist/_chunks/tooltip.js.map +1 -0
  38. package/dist/_chunks/tree-view.js +101 -96
  39. package/dist/_chunks/tree-view.js.map +1 -1
  40. package/dist/_chunks/use-calendar.js +5 -5
  41. package/dist/_chunks/use-calendar.js.map +1 -1
  42. package/dist/ai/ai-command-provider.d.ts +3 -2
  43. package/dist/ai/ai-command-provider.d.ts.map +1 -1
  44. package/dist/ai/ai-command-provider.js.map +1 -1
  45. package/dist/ai/block-renderer.js +11 -9
  46. package/dist/ai/block-renderer.js.map +1 -1
  47. package/dist/ai/blocks/error.js +31 -0
  48. package/dist/ai/blocks/error.js.map +1 -0
  49. package/dist/ai/blocks/index.d.ts +0 -2
  50. package/dist/ai/blocks/index.d.ts.map +1 -1
  51. package/dist/ai/blocks/index.js +2 -2
  52. package/dist/ai/blocks/text.js +19 -0
  53. package/dist/ai/blocks/text.js.map +1 -0
  54. package/dist/ai/command-bar.d.ts.map +1 -1
  55. package/dist/ai/command-bar.js +198 -193
  56. package/dist/ai/command-bar.js.map +1 -1
  57. package/dist/ai/conversation.d.ts +2 -1
  58. package/dist/ai/conversation.d.ts.map +1 -1
  59. package/dist/ai/conversation.js +92 -87
  60. package/dist/ai/conversation.js.map +1 -1
  61. package/dist/ai/index.d.ts +0 -4
  62. package/dist/ai/index.d.ts.map +1 -1
  63. package/dist/ai/index.js +45 -46
  64. package/dist/ai/index.js.map +1 -1
  65. package/dist/composed/activity-feed.d.ts +2 -1
  66. package/dist/composed/activity-feed.d.ts.map +1 -1
  67. package/dist/composed/activity-feed.js +5 -5
  68. package/dist/composed/activity-feed.js.map +1 -1
  69. package/dist/composed/avatar-group.js +4 -4
  70. package/dist/composed/avatar-group.js.map +1 -1
  71. package/dist/composed/bulk-action-bar.d.ts +2 -2
  72. package/dist/composed/bulk-action-bar.d.ts.map +1 -1
  73. package/dist/composed/bulk-action-bar.js +12 -12
  74. package/dist/composed/bulk-action-bar.js.map +1 -1
  75. package/dist/composed/command-palette.d.ts +2 -1
  76. package/dist/composed/command-palette.d.ts.map +1 -1
  77. package/dist/composed/command-palette.js +106 -101
  78. package/dist/composed/command-palette.js.map +1 -1
  79. package/dist/composed/content-card.js +1 -1
  80. package/dist/composed/content-card.js.map +1 -1
  81. package/dist/composed/date-picker/index.js +747 -3
  82. package/dist/composed/date-picker/index.js.map +1 -0
  83. package/dist/composed/emoji-picker.js +4 -4
  84. package/dist/composed/emoji-picker.js.map +1 -1
  85. package/dist/composed/empty-state.d.ts +3 -3
  86. package/dist/composed/empty-state.d.ts.map +1 -1
  87. package/dist/composed/empty-state.js +40 -31
  88. package/dist/composed/empty-state.js.map +1 -1
  89. package/dist/composed/error-boundary.js +3 -3
  90. package/dist/composed/error-boundary.js.map +1 -1
  91. package/dist/composed/extensions/emoji-node.js +81 -0
  92. package/dist/composed/extensions/emoji-node.js.map +1 -0
  93. package/dist/composed/extensions/emoji-suggestion.js +117 -0
  94. package/dist/composed/extensions/emoji-suggestion.js.map +1 -0
  95. package/dist/composed/file-preview.js +498 -2
  96. package/dist/composed/file-preview.js.map +1 -0
  97. package/dist/composed/filter-bar.js +1 -1
  98. package/dist/composed/filter-bar.js.map +1 -1
  99. package/dist/composed/index.d.ts +0 -15
  100. package/dist/composed/index.d.ts.map +1 -1
  101. package/dist/composed/index.js +16 -24
  102. package/dist/composed/inline-edit.js +1 -1
  103. package/dist/composed/inline-edit.js.map +1 -1
  104. package/dist/composed/loading-skeleton.js +9 -9
  105. package/dist/composed/loading-skeleton.js.map +1 -1
  106. package/dist/composed/markdown-viewer.js +3 -3
  107. package/dist/composed/markdown-viewer.js.map +1 -1
  108. package/dist/composed/multi-select-popover.js +1 -1
  109. package/dist/composed/multi-select-popover.js.map +1 -1
  110. package/dist/composed/page-header.js +1 -1
  111. package/dist/composed/page-header.js.map +1 -1
  112. package/dist/composed/page-skeletons.js +15 -15
  113. package/dist/composed/page-skeletons.js.map +1 -1
  114. package/dist/composed/priority-indicator.js +3 -3
  115. package/dist/composed/priority-indicator.js.map +1 -1
  116. package/dist/composed/rich-chat-input.js +2073 -2
  117. package/dist/composed/rich-chat-input.js.map +1 -0
  118. package/dist/composed/rich-text-editor.js +75 -72
  119. package/dist/composed/rich-text-editor.js.map +1 -1
  120. package/dist/composed/schedule-view.js +3 -3
  121. package/dist/composed/schedule-view.js.map +1 -1
  122. package/dist/composed/status-badge.d.ts +3 -2
  123. package/dist/composed/status-badge.d.ts.map +1 -1
  124. package/dist/composed/status-badge.js +58 -53
  125. package/dist/composed/status-badge.js.map +1 -1
  126. package/dist/shell/app-command-palette.d.ts +2 -1
  127. package/dist/shell/app-command-palette.d.ts.map +1 -1
  128. package/dist/shell/app-command-palette.js.map +1 -1
  129. package/dist/shell/bottom-navbar.d.ts +3 -1
  130. package/dist/shell/bottom-navbar.d.ts.map +1 -1
  131. package/dist/shell/bottom-navbar.js +94 -86
  132. package/dist/shell/bottom-navbar.js.map +1 -1
  133. package/dist/shell/command-registry.d.ts +2 -1
  134. package/dist/shell/command-registry.d.ts.map +1 -1
  135. package/dist/shell/command-registry.js.map +1 -1
  136. package/dist/shell/notification-center.js +8 -8
  137. package/dist/shell/notification-center.js.map +1 -1
  138. package/dist/shell/notification-preferences.js +1 -1
  139. package/dist/shell/notification-preferences.js.map +1 -1
  140. package/dist/shell/sidebar.d.ts +7 -4
  141. package/dist/shell/sidebar.d.ts.map +1 -1
  142. package/dist/shell/sidebar.js +148 -134
  143. package/dist/shell/sidebar.js.map +1 -1
  144. package/dist/shell/top-bar.d.ts +4 -3
  145. package/dist/shell/top-bar.d.ts.map +1 -1
  146. package/dist/shell/top-bar.js +116 -108
  147. package/dist/shell/top-bar.js.map +1 -1
  148. package/dist/tokens/semantic.css +82 -9
  149. package/dist/ui/accordion.js +1 -1
  150. package/dist/ui/accordion.js.map +1 -1
  151. package/dist/ui/alert-dialog.js +3 -3
  152. package/dist/ui/alert-dialog.js.map +1 -1
  153. package/dist/ui/alert.js +2 -2
  154. package/dist/ui/alert.js.map +1 -1
  155. package/dist/ui/autocomplete.js +2 -2
  156. package/dist/ui/autocomplete.js.map +1 -1
  157. package/dist/ui/avatar.js +11 -11
  158. package/dist/ui/avatar.js.map +1 -1
  159. package/dist/ui/badge-indicator.js +1 -1
  160. package/dist/ui/badge-indicator.js.map +1 -1
  161. package/dist/ui/badge.d.ts +3 -2
  162. package/dist/ui/badge.d.ts.map +1 -1
  163. package/dist/ui/banner.js +1 -1
  164. package/dist/ui/banner.js.map +1 -1
  165. package/dist/ui/breadcrumb.js +1 -1
  166. package/dist/ui/breadcrumb.js.map +1 -1
  167. package/dist/ui/button.d.ts +5 -4
  168. package/dist/ui/button.d.ts.map +1 -1
  169. package/dist/ui/button.js +66 -65
  170. package/dist/ui/button.js.map +1 -1
  171. package/dist/ui/card.js +5 -5
  172. package/dist/ui/card.js.map +1 -1
  173. package/dist/ui/charts/area-chart.js +177 -0
  174. package/dist/ui/charts/area-chart.js.map +1 -0
  175. package/dist/ui/charts/bar-chart.js +127 -0
  176. package/dist/ui/charts/bar-chart.js.map +1 -0
  177. package/dist/ui/charts/chart-container.js +3 -0
  178. package/dist/ui/charts/gauge-chart.js +72 -0
  179. package/dist/ui/charts/gauge-chart.js.map +1 -0
  180. package/dist/ui/charts/index.js +10 -1035
  181. package/dist/ui/charts/line-chart.js +135 -0
  182. package/dist/ui/charts/line-chart.js.map +1 -0
  183. package/dist/ui/charts/pie-chart.js +111 -0
  184. package/dist/ui/charts/pie-chart.js.map +1 -0
  185. package/dist/ui/charts/radar-chart.js +170 -0
  186. package/dist/ui/charts/radar-chart.js.map +1 -0
  187. package/dist/ui/charts/sparkline.js +119 -0
  188. package/dist/ui/charts/sparkline.js.map +1 -0
  189. package/dist/ui/chat/message.d.ts +3 -3
  190. package/dist/ui/chat/message.d.ts.map +1 -1
  191. package/dist/ui/chat/system-message.d.ts +2 -1
  192. package/dist/ui/chat/system-message.d.ts.map +1 -1
  193. package/dist/ui/checkbox.js +1 -1
  194. package/dist/ui/checkbox.js.map +1 -1
  195. package/dist/ui/code.js +2 -2
  196. package/dist/ui/code.js.map +1 -1
  197. package/dist/ui/color-input.js +10 -10
  198. package/dist/ui/color-input.js.map +1 -1
  199. package/dist/ui/color-swatch.js +3 -3
  200. package/dist/ui/color-swatch.js.map +1 -1
  201. package/dist/ui/combobox.d.ts +2 -1
  202. package/dist/ui/combobox.d.ts.map +1 -1
  203. package/dist/ui/combobox.js +100 -95
  204. package/dist/ui/combobox.js.map +1 -1
  205. package/dist/ui/container.d.ts +6 -1
  206. package/dist/ui/container.d.ts.map +1 -1
  207. package/dist/ui/container.js +2 -1
  208. package/dist/ui/container.js.map +1 -1
  209. package/dist/ui/context-menu.js +6 -6
  210. package/dist/ui/context-menu.js.map +1 -1
  211. package/dist/ui/data-table-body.js +1 -1
  212. package/dist/ui/data-table-body.js.map +1 -1
  213. package/dist/ui/data-table-bulk-actions.js +2 -2
  214. package/dist/ui/data-table-bulk-actions.js.map +1 -1
  215. package/dist/ui/data-table-card.js +2 -2
  216. package/dist/ui/data-table-card.js.map +1 -1
  217. package/dist/ui/data-table-header.js +2 -2
  218. package/dist/ui/data-table-header.js.map +1 -1
  219. package/dist/ui/data-table-pagination.js +3 -3
  220. package/dist/ui/data-table-pagination.js.map +1 -1
  221. package/dist/ui/data-table-toolbar.js +1 -1
  222. package/dist/ui/data-table-toolbar.js.map +1 -1
  223. package/dist/ui/data-table.js +1 -1
  224. package/dist/ui/data-table.js.map +1 -1
  225. package/dist/ui/devalok-grain.d.ts +1 -1
  226. package/dist/ui/devalok-grain.js.map +1 -1
  227. package/dist/ui/dialog.js +2 -2
  228. package/dist/ui/dialog.js.map +1 -1
  229. package/dist/ui/dropdown-menu.js +6 -6
  230. package/dist/ui/dropdown-menu.js.map +1 -1
  231. package/dist/ui/file-upload.js +4 -4
  232. package/dist/ui/file-upload.js.map +1 -1
  233. package/dist/ui/hover-card.js +1 -1
  234. package/dist/ui/hover-card.js.map +1 -1
  235. package/dist/ui/icon-button.d.ts +9 -2
  236. package/dist/ui/icon-button.d.ts.map +1 -1
  237. package/dist/ui/icon-button.js +14 -13
  238. package/dist/ui/icon-button.js.map +1 -1
  239. package/dist/ui/index.d.ts +1 -3
  240. package/dist/ui/index.d.ts.map +1 -1
  241. package/dist/ui/index.js +31 -33
  242. package/dist/ui/index.js.map +1 -1
  243. package/dist/ui/input-otp.js +1 -1
  244. package/dist/ui/input-otp.js.map +1 -1
  245. package/dist/ui/input.js +2 -2
  246. package/dist/ui/input.js.map +1 -1
  247. package/dist/ui/lib/icon-input.d.ts +42 -0
  248. package/dist/ui/lib/icon-input.d.ts.map +1 -0
  249. package/dist/ui/lib/normalize-icon.d.ts +39 -0
  250. package/dist/ui/lib/normalize-icon.d.ts.map +1 -0
  251. package/dist/ui/link.js +1 -1
  252. package/dist/ui/link.js.map +1 -1
  253. package/dist/ui/menubar.js +8 -8
  254. package/dist/ui/menubar.js.map +1 -1
  255. package/dist/ui/navigation-menu.js +3 -3
  256. package/dist/ui/navigation-menu.js.map +1 -1
  257. package/dist/ui/number-input.js +3 -3
  258. package/dist/ui/number-input.js.map +1 -1
  259. package/dist/ui/oauth-button/index.d.ts +3 -0
  260. package/dist/ui/oauth-button/index.d.ts.map +1 -0
  261. package/dist/ui/oauth-button/index.js +3 -0
  262. package/dist/ui/oauth-button/oauth-button.d.ts +208 -0
  263. package/dist/ui/oauth-button/oauth-button.d.ts.map +1 -0
  264. package/dist/ui/pagination.js +1 -1
  265. package/dist/ui/pagination.js.map +1 -1
  266. package/dist/ui/progress.js +2 -2
  267. package/dist/ui/progress.js.map +1 -1
  268. package/dist/ui/radio.js +1 -1
  269. package/dist/ui/radio.js.map +1 -1
  270. package/dist/ui/segmented-control.d.ts +3 -4
  271. package/dist/ui/segmented-control.d.ts.map +1 -1
  272. package/dist/ui/segmented-control.js +53 -45
  273. package/dist/ui/segmented-control.js.map +1 -1
  274. package/dist/ui/select.js +3 -3
  275. package/dist/ui/select.js.map +1 -1
  276. package/dist/ui/sheet.js +2 -2
  277. package/dist/ui/sheet.js.map +1 -1
  278. package/dist/ui/sidebar.js +11 -11
  279. package/dist/ui/sidebar.js.map +1 -1
  280. package/dist/ui/skeleton.js +9 -9
  281. package/dist/ui/skeleton.js.map +1 -1
  282. package/dist/ui/slider.js +2 -2
  283. package/dist/ui/slider.js.map +1 -1
  284. package/dist/ui/split-button.js +7 -7
  285. package/dist/ui/split-button.js.map +1 -1
  286. package/dist/ui/stack.d.ts +6 -1
  287. package/dist/ui/stack.d.ts.map +1 -1
  288. package/dist/ui/stack.js +2 -1
  289. package/dist/ui/stack.js.map +1 -1
  290. package/dist/ui/stat-card.d.ts +2 -3
  291. package/dist/ui/stat-card.d.ts.map +1 -1
  292. package/dist/ui/stat-card.js +118 -116
  293. package/dist/ui/stat-card.js.map +1 -1
  294. package/dist/ui/status-dot.js +2 -2
  295. package/dist/ui/status-dot.js.map +1 -1
  296. package/dist/ui/stepper.d.ts +2 -1
  297. package/dist/ui/stepper.d.ts.map +1 -1
  298. package/dist/ui/stepper.js +74 -69
  299. package/dist/ui/stepper.js.map +1 -1
  300. package/dist/ui/switch.js +2 -2
  301. package/dist/ui/switch.js.map +1 -1
  302. package/dist/ui/tabs.js +3 -3
  303. package/dist/ui/tabs.js.map +1 -1
  304. package/dist/ui/text.d.ts +7 -2
  305. package/dist/ui/text.d.ts.map +1 -1
  306. package/dist/ui/text.js +2 -1
  307. package/dist/ui/text.js.map +1 -1
  308. package/dist/ui/textarea.js +1 -1
  309. package/dist/ui/textarea.js.map +1 -1
  310. package/dist/ui/toast.js +8 -8
  311. package/dist/ui/toast.js.map +1 -1
  312. package/dist/ui/toaster.d.ts +11 -2
  313. package/dist/ui/toaster.d.ts.map +1 -1
  314. package/dist/ui/toaster.js.map +1 -1
  315. package/dist/ui/toggle.js +1 -1
  316. package/dist/ui/toggle.js.map +1 -1
  317. package/dist/ui/tooltip.js +12 -12
  318. package/dist/ui/tooltip.js.map +1 -1
  319. package/dist/ui/tree-view/tree-item.d.ts +3 -2
  320. package/dist/ui/tree-view/tree-item.d.ts.map +1 -1
  321. package/dist/ui/tree-view/use-tree.d.ts +2 -1
  322. package/dist/ui/tree-view/use-tree.d.ts.map +1 -1
  323. package/docs/components/_header.md +90 -1
  324. package/docs/components/ui/oauth-button.md +86 -0
  325. package/docs/recipes/customize-brand.md +100 -4
  326. package/docs/recipes/index.md +5 -1
  327. package/docs/recipes/install-astro.md +15 -0
  328. package/docs/recipes/install-next-app-router.md +21 -5
  329. package/docs/recipes/install-next-pages.md +2 -0
  330. package/docs/recipes/install-remix.md +15 -0
  331. package/docs/recipes/install-tanstack-start.md +15 -0
  332. package/docs/recipes/install-vite.md +15 -0
  333. package/docs/recipes/troubleshoot.md +22 -0
  334. package/llms-full.txt +177 -2
  335. package/llms-quick.txt +247 -0
  336. package/llms.txt +116 -3
  337. package/package.json +80 -2
  338. package/scripts/welcome.mjs +219 -0
  339. package/skill/README.md +99 -0
  340. package/skill/SKILL.md +163 -0
  341. package/skill/install.sh +59 -0
  342. package/skill/references/components-full.md +7083 -0
  343. package/skill/references/components.md +778 -0
  344. package/skill/references/customize-brand.md +314 -0
  345. package/skill/references/server-components.md +211 -0
  346. package/skill/references/setup-astro.md +195 -0
  347. package/skill/references/setup-next-app-router.md +248 -0
  348. package/skill/references/setup-next-pages.md +127 -0
  349. package/skill/references/setup-remix.md +188 -0
  350. package/skill/references/setup-tanstack-start.md +160 -0
  351. package/skill/references/setup-vite.md +187 -0
  352. package/skill/references/troubleshoot.md +241 -0
  353. package/dist/_chunks/date-picker.js +0 -748
  354. package/dist/_chunks/date-picker.js.map +0 -1
  355. package/dist/_chunks/file-preview.js +0 -499
  356. package/dist/_chunks/file-preview.js.map +0 -1
  357. package/dist/_chunks/rich-chat-input.js +0 -2071
  358. package/dist/_chunks/rich-chat-input.js.map +0 -1
  359. package/dist/_chunks/text.js.map +0 -1
  360. package/dist/ui/charts/index.js.map +0 -1
  361. /package/{LICENSE → skill/LICENSE} +0 -0
@@ -0,0 +1,58 @@
1
+ "use client";
2
+ import { cn as e } from "../ui/lib/utils.js";
3
+ import { useCallback as t, useState as n } from "react";
4
+ import { jsx as r, jsxs as i } from "react/jsx-runtime";
5
+ //#region src/ui/charts/_internal/legend.tsx
6
+ function a({ items: t, position: n = "bottom", className: a }) {
7
+ return /* @__PURE__ */ r("div", {
8
+ className: e("flex gap-ds-04 text-ds-sm text-surface-fg-muted", n === "left" || n === "right" ? "flex-col" : "flex-row flex-wrap justify-center", a),
9
+ children: t.map((e) => /* @__PURE__ */ i("div", {
10
+ className: "flex items-center gap-ds-02",
11
+ children: [/* @__PURE__ */ r("span", {
12
+ className: "inline-block h-3 w-3 shrink-0 rounded-control-inner",
13
+ style: { backgroundColor: e.color }
14
+ }), /* @__PURE__ */ r("span", { children: e.label })]
15
+ }, e.label))
16
+ });
17
+ }
18
+ a.displayName = "Legend";
19
+ //#endregion
20
+ //#region src/ui/charts/_internal/tooltip.tsx
21
+ function o({ state: t, className: n }) {
22
+ return t.visible ? /* @__PURE__ */ r("div", {
23
+ className: e("pointer-events-none absolute z-tooltip", "rounded-overlay-sm border border-surface-border-strong", "bg-surface-overlay px-ds-03 py-ds-02", "shadow-raised-hover", "text-ds-sm text-surface-fg", n),
24
+ style: {
25
+ left: t.x + 12,
26
+ top: t.y - 12
27
+ },
28
+ children: t.content
29
+ }) : null;
30
+ }
31
+ o.displayName = "ChartTooltip";
32
+ function s() {
33
+ let [e, r] = n({
34
+ visible: !1,
35
+ x: 0,
36
+ y: 0,
37
+ content: null
38
+ });
39
+ return {
40
+ tooltip: e,
41
+ show: t((e, t, n) => {
42
+ r({
43
+ visible: !0,
44
+ x: e,
45
+ y: t,
46
+ content: n
47
+ });
48
+ }, []),
49
+ hide: t(() => {
50
+ r((e) => ({
51
+ ...e,
52
+ visible: !1
53
+ }));
54
+ }, [])
55
+ };
56
+ }
57
+ //#endregion
58
+ export { s as n, a as r, o as t };
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tooltip.js","names":[],"sources":["../../src/ui/charts/_internal/legend.tsx","../../src/ui/charts/_internal/tooltip.tsx"],"sourcesContent":["import * as React from 'react'\n\nimport { cn } from '../../lib/utils'\n\ninterface LegendItem {\n label: string\n color: string // CSS color value or var() reference\n}\n\ninterface LegendProps {\n items: LegendItem[]\n position?: 'top' | 'bottom' | 'left' | 'right'\n className?: string\n}\n\nexport function Legend({ items, position = 'bottom', className }: LegendProps) {\n const isVertical = position === 'left' || position === 'right'\n\n return (\n <div\n className={cn(\n 'flex gap-ds-04 text-ds-sm text-surface-fg-muted',\n isVertical ? 'flex-col' : 'flex-row flex-wrap justify-center',\n className,\n )}\n >\n {items.map((item) => (\n <div key={item.label} className=\"flex items-center gap-ds-02\">\n <span\n className=\"inline-block h-3 w-3 shrink-0 rounded-control-inner\"\n style={{ backgroundColor: item.color }}\n />\n <span>{item.label}</span>\n </div>\n ))}\n </div>\n )\n}\nLegend.displayName = 'Legend'\n\nexport type { LegendItem, LegendProps }\n","'use client'\n\nimport * as React from 'react'\nimport { useCallback,useState } from 'react'\n\nimport { cn } from '../../lib/utils'\n\ninterface TooltipState {\n visible: boolean\n x: number\n y: number\n content: React.ReactNode\n}\n\ninterface ChartTooltipProps {\n state: TooltipState\n className?: string\n}\n\nexport function ChartTooltip({ state, className }: ChartTooltipProps) {\n if (!state.visible) return null\n\n return (\n <div\n className={cn(\n 'pointer-events-none absolute z-tooltip',\n 'rounded-overlay-sm border border-surface-border-strong',\n 'bg-surface-overlay px-ds-03 py-ds-02',\n 'shadow-raised-hover',\n 'text-ds-sm text-surface-fg',\n className,\n )}\n style={{ left: state.x + 12, top: state.y - 12 }}\n >\n {state.content}\n </div>\n )\n}\nChartTooltip.displayName = 'ChartTooltip'\n\n/** Hook to manage chart tooltip state */\nexport function useChartTooltip() {\n const [tooltip, setTooltip] = useState<TooltipState>({\n visible: false,\n x: 0,\n y: 0,\n content: null,\n })\n\n const show = useCallback((x: number, y: number, content: React.ReactNode) => {\n setTooltip({ visible: true, x, y, content })\n }, [])\n\n const hide = useCallback(() => {\n setTooltip((prev) => ({ ...prev, visible: false }))\n }, [])\n\n return { tooltip, show, hide }\n}\n\nexport type { ChartTooltipProps,TooltipState }\n"],"mappings":";;;;AAeA,SAAgB,EAAO,EAAE,UAAO,cAAW,UAAU,gBAA0B;AAG7E,QACE,kBAAC,OAAD;EACE,WAAW,EACT,mDALa,MAAa,UAAU,MAAa,UAMpC,aAAa,qCAC1B,EACD;YAEA,EAAM,KAAK,MACV,kBAAC,OAAD;GAAsB,WAAU;aAAhC,CACE,kBAAC,QAAD;IACE,WAAU;IACV,OAAO,EAAE,iBAAiB,EAAK,OAAO;IACtC,CAAA,EACF,kBAAC,QAAD,EAAA,UAAO,EAAK,OAAa,CAAA,CACrB;KANI,EAAK,MAMT,CACN;EACE,CAAA;;AAGV,EAAO,cAAc;;;ACnBrB,SAAgB,EAAa,EAAE,UAAO,gBAAgC;AAGpE,QAFK,EAAM,UAGT,kBAAC,OAAD;EACE,WAAW,EACT,0CACA,0DACA,wCACA,uBACA,8BACA,EACD;EACD,OAAO;GAAE,MAAM,EAAM,IAAI;GAAI,KAAK,EAAM,IAAI;GAAI;YAE/C,EAAM;EACH,CAAA,GAfmB;;AAkB7B,EAAa,cAAc;AAG3B,SAAgB,IAAkB;CAChC,IAAM,CAAC,GAAS,KAAc,EAAuB;EACnD,SAAS;EACT,GAAG;EACH,GAAG;EACH,SAAS;EACV,CAAC;AAUF,QAAO;EAAE;EAAS,MARL,GAAa,GAAW,GAAW,MAA6B;AAC3E,KAAW;IAAE,SAAS;IAAM;IAAG;IAAG;IAAS,CAAC;KAC3C,EAAE,CAAC;EAMkB,MAJX,QAAkB;AAC7B,MAAY,OAAU;IAAE,GAAG;IAAM,SAAS;IAAO,EAAE;KAClD,EAAE,CAAC;EAEwB"}
@@ -1,29 +1,31 @@
1
1
  "use client";
2
- import { cn as e } from "../ui/lib/utils.js";
3
- import { Icon as t } from "../ui/icon.js";
4
- import { Checkbox as n } from "../ui/checkbox.js";
5
- import * as r from "react";
6
- import { useCallback as i, useState as a } from "react";
7
- import { jsx as o, jsxs as s } from "react/jsx-runtime";
8
- import { IconChevronRight as c } from "@tabler/icons-react";
2
+ import { IconProvider as e } from "../ui/icon-context.js";
3
+ import { cn as t } from "../ui/lib/utils.js";
4
+ import { Icon as n } from "../ui/icon.js";
5
+ import { t as r } from "./normalize-icon.js";
6
+ import { Checkbox as i } from "../ui/checkbox.js";
7
+ import * as a from "react";
8
+ import { useCallback as o, useState as s } from "react";
9
+ import { jsx as c, jsxs as l } from "react/jsx-runtime";
10
+ import { IconChevronRight as u } from "@tabler/icons-react";
9
11
  //#region src/ui/tree-view/use-tree.ts
10
- function l(e = {}) {
11
- let { defaultExpanded: t, defaultSelected: n, multiSelect: r, onSelect: o, onExpand: s } = e, [c, l] = a(new Set(t ?? [])), [u, d] = a(new Set(n ?? []));
12
+ function d(e = {}) {
13
+ let { defaultExpanded: t, defaultSelected: n, multiSelect: r, onSelect: i, onExpand: a } = e, [c, l] = s(new Set(t ?? [])), [u, d] = s(new Set(n ?? []));
12
14
  return {
13
15
  expanded: c,
14
16
  selected: u,
15
- toggle: i((e) => {
17
+ toggle: o((e) => {
16
18
  l((t) => {
17
19
  let n = new Set(t);
18
- return n.has(e) ? n.delete(e) : n.add(e), s?.(Array.from(n)), n;
20
+ return n.has(e) ? n.delete(e) : n.add(e), a?.(Array.from(n)), n;
19
21
  });
20
- }, [s]),
21
- select: i((e, t) => {
22
+ }, [a]),
23
+ select: o((e, t) => {
22
24
  d((n) => {
23
- let i;
24
- return r && t?.ctrlKey ? (i = new Set(n), i.has(e) ? i.delete(e) : i.add(e)) : i = new Set([e]), o?.(Array.from(i)), i;
25
+ let a;
26
+ return r && t?.ctrlKey ? (a = new Set(n), a.has(e) ? a.delete(e) : a.add(e)) : a = new Set([e]), i?.(Array.from(a)), a;
25
27
  });
26
- }, [r, o]),
28
+ }, [r, i]),
27
29
  isExpanded: (e) => c.has(e),
28
30
  isSelected: (e) => u.has(e),
29
31
  expandAll: (e) => l(new Set(e)),
@@ -32,23 +34,23 @@ function l(e = {}) {
32
34
  }
33
35
  //#endregion
34
36
  //#region src/ui/tree-view/tree-view.tsx
35
- var u = r.createContext(null);
36
- function d() {
37
- let e = r.useContext(u);
37
+ var f = a.createContext(null);
38
+ function p() {
39
+ let e = a.useContext(f);
38
40
  if (!e) throw Error("TreeItem must be used within a <TreeView>");
39
41
  return e;
40
42
  }
41
- function f(e, t = 0) {
42
- return e.map((e) => /* @__PURE__ */ o(h, {
43
+ function m(e, t = 0) {
44
+ return e.map((e) => /* @__PURE__ */ c(_, {
43
45
  itemId: e.id,
44
46
  label: e.label,
45
47
  icon: e.icon,
46
48
  disabled: e.disabled,
47
49
  depth: t,
48
- children: e.children && e.children.length > 0 ? f(e.children, t + 1) : void 0
50
+ children: e.children && e.children.length > 0 ? m(e.children, t + 1) : void 0
49
51
  }, e.id));
50
52
  }
51
- function p(e) {
53
+ function h(e) {
52
54
  return Array.from(e.querySelectorAll("[data-tree-item]")).filter((t) => {
53
55
  let n = t.parentElement;
54
56
  for (; n && n !== e;) {
@@ -61,17 +63,17 @@ function p(e) {
61
63
  return !0;
62
64
  });
63
65
  }
64
- var m = r.forwardRef(({ items: t, defaultExpanded: n, defaultSelected: i, multiSelect: a = !1, checkboxes: s = !1, onSelect: c, onExpand: d, className: m, children: h, ...g }, _) => {
65
- let v = l({
66
+ var g = a.forwardRef(({ items: e, defaultExpanded: n, defaultSelected: r, multiSelect: i = !1, checkboxes: o = !1, onSelect: s, onExpand: l, className: u, children: p, ...g }, _) => {
67
+ let v = d({
66
68
  defaultExpanded: n,
67
- defaultSelected: i,
68
- multiSelect: a,
69
- onSelect: c,
70
- onExpand: d
71
- }), y = r.useRef(null), b = _ ?? y, x = (e) => {
69
+ defaultSelected: r,
70
+ multiSelect: i,
71
+ onSelect: s,
72
+ onExpand: l
73
+ }), y = a.useRef(null), b = _ ?? y, x = (e) => {
72
74
  let t = b.current;
73
75
  if (!t) return;
74
- let n = p(t), r = n.findIndex((e) => e === document.activeElement);
76
+ let n = h(t), r = n.findIndex((e) => e === document.activeElement);
75
77
  switch (e.key) {
76
78
  case "ArrowDown":
77
79
  e.preventDefault(), n[r + 1]?.focus();
@@ -102,46 +104,46 @@ var m = r.forwardRef(({ items: t, defaultExpanded: n, defaultSelected: i, multiS
102
104
  e.preventDefault(), n[n.length - 1]?.focus();
103
105
  break;
104
106
  }
105
- }, S = r.useMemo(() => ({
107
+ }, S = a.useMemo(() => ({
106
108
  tree: v,
107
- checkboxes: s
108
- }), [v, s]), C = t ? f(t) : h;
109
- return /* @__PURE__ */ o(u.Provider, {
109
+ checkboxes: o
110
+ }), [v, o]), C = e ? m(e) : p;
111
+ return /* @__PURE__ */ c(f.Provider, {
110
112
  value: S,
111
- children: /* @__PURE__ */ o("ul", {
113
+ children: /* @__PURE__ */ c("ul", {
112
114
  ref: b,
113
115
  role: "tree",
114
- "aria-multiselectable": a || void 0,
116
+ "aria-multiselectable": i || void 0,
115
117
  onKeyDown: x,
116
- className: e("m-0 list-none p-0", m),
118
+ className: t("m-0 list-none p-0", u),
117
119
  ...g,
118
120
  children: C
119
121
  })
120
122
  });
121
123
  });
122
- m.displayName = "TreeView";
124
+ g.displayName = "TreeView";
123
125
  //#endregion
124
126
  //#region src/ui/tree-view/tree-item.tsx
125
- var h = r.forwardRef(({ itemId: i, label: a, icon: l, secondaryLabel: u, actions: f, disabled: p = !1, children: m, depth: h = 0, className: g }, _) => {
126
- let v = d(), y = r.Children.count(m) > 0, b = v.tree.isExpanded(i), x = v.tree.isSelected(i), S = (e) => {
127
- p || v.tree.select(i, e);
128
- }, C = (e) => {
129
- e.stopPropagation(), !p && v.tree.toggle(i);
130
- }, w = (e) => {
131
- p || ((e.key === "Enter" || e.key === " ") && (e.preventDefault(), v.tree.select(i)), e.key === "ArrowRight" && y && !b && (e.preventDefault(), e.stopPropagation(), v.tree.toggle(i)), e.key === "ArrowLeft" && y && b && (e.preventDefault(), e.stopPropagation(), v.tree.toggle(i)));
132
- }, T = r.useMemo(() => {
133
- if (!v.checkboxes || !y) return {
134
- checked: x,
127
+ var _ = a.forwardRef(({ itemId: o, label: s, icon: d, secondaryLabel: f, actions: m, disabled: h = !1, children: g, depth: _ = 0, className: v }, y) => {
128
+ let b = p(), x = a.Children.count(g) > 0, S = b.tree.isExpanded(o), C = b.tree.isSelected(o), w = (e) => {
129
+ h || b.tree.select(o, e);
130
+ }, T = (e) => {
131
+ e.stopPropagation(), !h && b.tree.toggle(o);
132
+ }, E = (e) => {
133
+ h || ((e.key === "Enter" || e.key === " ") && (e.preventDefault(), b.tree.select(o)), e.key === "ArrowRight" && x && !S && (e.preventDefault(), e.stopPropagation(), b.tree.toggle(o)), e.key === "ArrowLeft" && x && S && (e.preventDefault(), e.stopPropagation(), b.tree.toggle(o)));
134
+ }, D = a.useMemo(() => {
135
+ if (!b.checkboxes || !x) return {
136
+ checked: C,
135
137
  indeterminate: !1
136
138
  };
137
139
  let e = [], t = (n) => {
138
- r.Children.forEach(n, (n) => {
139
- r.isValidElement(n) && n.props.itemId && (e.push(n.props.itemId), n.props.children && t(n.props.children));
140
+ a.Children.forEach(n, (n) => {
141
+ a.isValidElement(n) && n.props.itemId && (e.push(n.props.itemId), n.props.children && t(n.props.children));
140
142
  });
141
143
  };
142
- t(m);
143
- let n = e.filter((e) => v.tree.isSelected(e)).length;
144
- return n === 0 && !x ? {
144
+ t(g);
145
+ let n = e.filter((e) => b.tree.isSelected(e)).length;
146
+ return n === 0 && !C ? {
145
147
  checked: !1,
146
148
  indeterminate: !1
147
149
  } : n === e.length ? {
@@ -152,85 +154,88 @@ var h = r.forwardRef(({ itemId: i, label: a, icon: l, secondaryLabel: u, actions
152
154
  indeterminate: !0
153
155
  };
154
156
  }, [
155
- v.checkboxes,
156
- y,
157
- m,
157
+ b.checkboxes,
158
158
  x,
159
- v.tree
159
+ g,
160
+ C,
161
+ b.tree
160
162
  ]);
161
- return /* @__PURE__ */ s("li", {
162
- ref: _,
163
+ return /* @__PURE__ */ l("li", {
164
+ ref: y,
163
165
  role: "treeitem",
164
- "aria-expanded": y ? b : void 0,
165
- "aria-selected": x,
166
- "aria-level": h + 1,
167
- "aria-disabled": p || void 0,
166
+ "aria-expanded": x ? S : void 0,
167
+ "aria-selected": C,
168
+ "aria-level": _ + 1,
169
+ "aria-disabled": h || void 0,
168
170
  className: "list-none",
169
- children: [/* @__PURE__ */ s("div", {
171
+ children: [/* @__PURE__ */ l("div", {
170
172
  role: "presentation",
171
- "data-tree-item": i,
172
- tabIndex: p ? -1 : 0,
173
- onClick: S,
174
- onKeyDown: w,
175
- style: { paddingLeft: `calc(${h} * var(--spacing-ds-05b) + var(--spacing-ds-03))` },
176
- className: e("flex items-center gap-ds-02 py-ds-02 px-ds-02 rounded-ds-md cursor-pointer transition-colors duration-fast-01", "hover:bg-surface-raised", "focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9", x && "bg-accent-3 text-accent-11", p && "opacity-action-disabled cursor-not-allowed pointer-events-none", g),
173
+ "data-tree-item": o,
174
+ tabIndex: h ? -1 : 0,
175
+ onClick: w,
176
+ onKeyDown: E,
177
+ style: { paddingLeft: `calc(${_} * var(--spacing-ds-05b) + var(--spacing-ds-03))` },
178
+ className: t("flex items-center gap-ds-02 py-ds-02 px-ds-02 rounded-control cursor-pointer transition-colors duration-fast-01", "hover:bg-surface-raised", "focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9", C && "bg-accent-3 text-accent-11", h && "opacity-action-disabled cursor-not-allowed pointer-events-none", v),
177
179
  children: [
178
- y ? /* @__PURE__ */ o("button", {
180
+ x ? /* @__PURE__ */ c("button", {
179
181
  type: "button",
180
182
  tabIndex: -1,
181
183
  "aria-hidden": "true",
182
- onClick: C,
184
+ onClick: T,
183
185
  className: "flex shrink-0 items-center justify-center p-0 border-0 bg-transparent cursor-pointer",
184
- children: /* @__PURE__ */ o(t, {
185
- icon: c,
186
+ children: /* @__PURE__ */ c(n, {
187
+ icon: u,
186
188
  size: "sm",
187
- className: e("transition-transform duration-moderate-02", b && "rotate-90")
189
+ className: t("transition-transform duration-moderate-02", S && "rotate-90")
188
190
  })
189
- }) : /* @__PURE__ */ o("span", {
191
+ }) : /* @__PURE__ */ c("span", {
190
192
  className: "inline-block w-4 shrink-0",
191
193
  "aria-hidden": "true"
192
194
  }),
193
- v.checkboxes && /* @__PURE__ */ o(n, {
194
- checked: T.checked,
195
- indeterminate: T.indeterminate,
196
- disabled: p,
195
+ b.checkboxes && /* @__PURE__ */ c(i, {
196
+ checked: D.checked,
197
+ indeterminate: D.indeterminate,
198
+ disabled: h,
197
199
  tabIndex: -1,
198
200
  onClick: (e) => e.stopPropagation(),
199
201
  onCheckedChange: () => {
200
- p || v.tree.select(i);
202
+ h || b.tree.select(o);
201
203
  },
202
204
  className: "shrink-0"
203
205
  }),
204
- l && /* @__PURE__ */ o("span", {
206
+ d && /* @__PURE__ */ c("span", {
205
207
  className: "flex shrink-0 items-center text-surface-fg-subtle",
206
- children: l
208
+ children: /* @__PURE__ */ c(e, {
209
+ size: "sm",
210
+ children: r(d)
211
+ })
207
212
  }),
208
- /* @__PURE__ */ o("span", {
213
+ /* @__PURE__ */ c("span", {
209
214
  className: "truncate text-ds-sm",
210
- children: a
215
+ children: s
211
216
  }),
212
- u && /* @__PURE__ */ o("span", {
217
+ f && /* @__PURE__ */ c("span", {
213
218
  className: "ml-auto truncate text-ds-xs text-surface-fg-muted",
214
- children: u
219
+ children: f
215
220
  }),
216
- f && /* @__PURE__ */ o("span", {
221
+ m && /* @__PURE__ */ c("span", {
217
222
  className: "ml-auto flex shrink-0 items-center gap-ds-01",
218
223
  onClick: (e) => e.stopPropagation(),
219
224
  role: "presentation",
220
- children: f
225
+ children: m
221
226
  })
222
227
  ]
223
- }), y && /* @__PURE__ */ o("div", {
228
+ }), x && /* @__PURE__ */ c("div", {
224
229
  role: "group",
225
- className: e("grid transition-[grid-template-rows] duration-moderate-02 ease-productive-standard", b ? "grid-rows-[1fr]" : "grid-rows-[0fr]"),
226
- children: /* @__PURE__ */ o("ul", {
230
+ className: t("grid transition-[grid-template-rows] duration-moderate-02 ease-productive-standard", S ? "grid-rows-[1fr]" : "grid-rows-[0fr]"),
231
+ children: /* @__PURE__ */ c("ul", {
227
232
  role: "group",
228
233
  className: "overflow-hidden m-0 p-0",
229
- children: r.Children.map(m, (e) => r.isValidElement(e) ? r.cloneElement(e, { depth: h + 1 }) : e)
234
+ children: a.Children.map(g, (e) => a.isValidElement(e) ? a.cloneElement(e, { depth: _ + 1 }) : e)
230
235
  })
231
236
  })]
232
237
  });
233
238
  });
234
- h.displayName = "TreeItem";
239
+ _.displayName = "TreeItem";
235
240
  //#endregion
236
- export { m as n, l as r, h as t };
241
+ export { g as n, d as r, _ as t };
@@ -1 +1 @@
1
- {"version":3,"file":"tree-view.js","names":[],"sources":["../../src/ui/tree-view/use-tree.ts","../../src/ui/tree-view/tree-view.tsx","../../src/ui/tree-view/tree-item.tsx"],"sourcesContent":["import { useCallback,useState } from 'react'\n\nexport interface TreeNode {\n id: string\n label: string\n icon?: React.ReactNode\n children?: TreeNode[]\n disabled?: boolean\n}\n\ninterface UseTreeOptions {\n defaultExpanded?: string[]\n defaultSelected?: string[]\n multiSelect?: boolean\n onSelect?: (selectedIds: string[]) => void\n onExpand?: (expandedIds: string[]) => void\n}\n\nexport function useTree(options: UseTreeOptions = {}) {\n const { defaultExpanded, defaultSelected, multiSelect, onSelect, onExpand } = options\n\n const [expanded, setExpanded] = useState<Set<string>>(\n new Set(defaultExpanded ?? []),\n )\n const [selected, setSelected] = useState<Set<string>>(\n new Set(defaultSelected ?? []),\n )\n\n const toggle = useCallback(\n (id: string) => {\n setExpanded((prev) => {\n const next = new Set(prev)\n if (next.has(id)) next.delete(id)\n else next.add(id)\n onExpand?.(Array.from(next))\n return next\n })\n },\n [onExpand],\n )\n\n const select = useCallback(\n (id: string, event?: React.MouseEvent) => {\n setSelected((prev) => {\n let next: Set<string>\n if (multiSelect && event?.ctrlKey) {\n next = new Set(prev)\n if (next.has(id)) next.delete(id)\n else next.add(id)\n } else {\n next = new Set([id])\n }\n onSelect?.(Array.from(next))\n return next\n })\n },\n [multiSelect, onSelect],\n )\n\n return {\n expanded,\n selected,\n toggle,\n select,\n isExpanded: (id: string) => expanded.has(id),\n isSelected: (id: string) => selected.has(id),\n expandAll: (ids: string[]) => setExpanded(new Set(ids)),\n collapseAll: () => setExpanded(new Set()),\n }\n}\n","'use client'\n\nimport * as React from 'react'\n\nimport { cn } from '../lib/utils'\nimport { TreeItem } from './tree-item'\nimport { type TreeNode,useTree } from './use-tree'\n\n// ─── Context ────────────────────────────────────────────────────────\ninterface TreeContextValue {\n tree: ReturnType<typeof useTree>\n checkboxes: boolean\n}\n\nconst TreeContext = React.createContext<TreeContextValue | null>(null)\n\nexport function useTreeContext() {\n const ctx = React.useContext(TreeContext)\n if (!ctx) {\n throw new Error('TreeItem must be used within a <TreeView>')\n }\n return ctx\n}\n\n// ─── Props ──────────────────────────────────────────────────────────\nexport interface TreeViewProps extends Omit<React.HTMLAttributes<HTMLUListElement>, 'onSelect'> {\n /** Data-driven mode: pass items array */\n items?: TreeNode[]\n /** Initially expanded node IDs */\n defaultExpanded?: string[]\n /** Initially selected node IDs */\n defaultSelected?: string[]\n /** Enable multi-select */\n multiSelect?: boolean\n /** Show checkboxes before each item */\n checkboxes?: boolean\n /** Called when selection changes */\n onSelect?: (ids: string[]) => void\n /** Called when expansion changes */\n onExpand?: (ids: string[]) => void\n className?: string\n /** Declarative mode: render TreeItem children directly */\n children?: React.ReactNode\n}\n\n// ─── Render nodes recursively (data-driven mode) ───────────────────\nfunction renderNodes(nodes: TreeNode[], depth: number = 0): React.ReactNode {\n return nodes.map((node) => (\n <TreeItem\n key={node.id}\n itemId={node.id}\n label={node.label}\n icon={node.icon}\n disabled={node.disabled}\n depth={depth}\n >\n {node.children && node.children.length > 0\n ? renderNodes(node.children, depth + 1)\n : undefined}\n </TreeItem>\n ))\n}\n\n// ─── Helper: collect all visible item IDs ───────────────────────────\nfunction getVisibleItemElements(container: HTMLElement): HTMLElement[] {\n return Array.from(\n container.querySelectorAll<HTMLElement>('[data-tree-item]'),\n ).filter((el) => {\n // Items inside collapsed groups should not be focusable\n let parent = el.parentElement\n while (parent && parent !== container) {\n if (parent.getAttribute('role') === 'group') {\n const grid = parent.parentElement\n if (grid && grid.classList.contains('grid-rows-[0fr]')) {\n return false\n }\n }\n parent = parent.parentElement\n }\n return true\n })\n}\n\n// ─── Component ──────────────────────────────────────────────────────\nconst TreeView = React.forwardRef<HTMLUListElement, TreeViewProps>(\n (\n {\n items,\n defaultExpanded,\n defaultSelected,\n multiSelect = false,\n checkboxes = false,\n onSelect,\n onExpand,\n className,\n children,\n ...props\n },\n ref,\n ) => {\n const tree = useTree({\n defaultExpanded,\n defaultSelected,\n multiSelect,\n onSelect,\n onExpand,\n })\n\n const innerRef = React.useRef<HTMLUListElement>(null)\n const containerRef = (ref as React.RefObject<HTMLUListElement>) ?? innerRef\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLUListElement>) => {\n const container = containerRef.current\n if (!container) return\n\n const visibleItems = getVisibleItemElements(container)\n const currentIndex = visibleItems.findIndex(\n (el) => el === document.activeElement,\n )\n\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault()\n const next = visibleItems[currentIndex + 1]\n next?.focus()\n break\n }\n case 'ArrowUp': {\n e.preventDefault()\n const prev = visibleItems[currentIndex - 1]\n prev?.focus()\n break\n }\n case 'ArrowRight': {\n // Handled in TreeItem for expand; if already expanded, move to first child\n const current = visibleItems[currentIndex]\n if (current) {\n const itemId = current.getAttribute('data-tree-item')\n if (itemId && tree.isExpanded(itemId)) {\n e.preventDefault()\n const nextItem = visibleItems[currentIndex + 1]\n nextItem?.focus()\n }\n }\n break\n }\n case 'ArrowLeft': {\n // Handled in TreeItem for collapse; if already collapsed or leaf, move to parent\n const current = visibleItems[currentIndex]\n if (current) {\n const itemId = current.getAttribute('data-tree-item')\n const treeItem = current.closest('[role=\"treeitem\"]')\n const parentGroup = treeItem?.parentElement?.closest(\n '[role=\"treeitem\"]',\n )\n if (itemId && !tree.isExpanded(itemId) && parentGroup) {\n e.preventDefault()\n const parentRow = parentGroup.querySelector<HTMLElement>(\n '[data-tree-item]',\n )\n parentRow?.focus()\n }\n }\n break\n }\n case 'Home': {\n e.preventDefault()\n visibleItems[0]?.focus()\n break\n }\n case 'End': {\n e.preventDefault()\n visibleItems[visibleItems.length - 1]?.focus()\n break\n }\n }\n }\n\n const ctxValue = React.useMemo<TreeContextValue>(\n () => ({ tree, checkboxes }),\n [tree, checkboxes],\n )\n\n const content = items ? renderNodes(items) : children\n\n return (\n <TreeContext.Provider value={ctxValue}>\n <ul\n ref={containerRef}\n role=\"tree\"\n aria-multiselectable={multiSelect || undefined}\n onKeyDown={handleKeyDown}\n className={cn('m-0 list-none p-0', className)}\n {...props}\n >\n {content}\n </ul>\n </TreeContext.Provider>\n )\n },\n)\nTreeView.displayName = 'TreeView'\n\nexport { TreeView }\n","'use client'\n\nimport { IconChevronRight } from '@tabler/icons-react'\nimport * as React from 'react'\n\nimport { Checkbox } from '../checkbox'\nimport { Icon } from '../icon'\nimport { cn } from '../lib/utils'\nimport { useTreeContext } from './tree-view'\n\nexport interface TreeItemProps {\n /** Unique identifier for this tree item */\n itemId: string\n /** Primary label content */\n label: React.ReactNode\n /** Optional icon rendered before the label */\n icon?: React.ReactNode\n /** Secondary label rendered after the primary label */\n secondaryLabel?: React.ReactNode\n /** Action buttons rendered at the end of the row */\n actions?: React.ReactNode\n /** Whether this item is disabled */\n disabled?: boolean\n /** Nested tree items */\n children?: React.ReactNode\n /** Depth level (used internally) */\n depth?: number\n /** Additional CSS class names */\n className?: string\n}\n\nconst TreeItem = React.forwardRef<HTMLLIElement, TreeItemProps>(\n (\n {\n itemId,\n label,\n icon,\n secondaryLabel,\n actions,\n disabled = false,\n children,\n depth = 0,\n className,\n },\n ref,\n ) => {\n const ctx = useTreeContext()\n const hasChildren = React.Children.count(children) > 0\n const isExpanded = ctx.tree.isExpanded(itemId)\n const isSelected = ctx.tree.isSelected(itemId)\n\n const handleRowClick = (e: React.MouseEvent<HTMLDivElement>) => {\n if (disabled) return\n ctx.tree.select(itemId, e)\n }\n\n const handleChevronClick = (e: React.MouseEvent<HTMLButtonElement>) => {\n e.stopPropagation()\n if (disabled) return\n ctx.tree.toggle(itemId)\n }\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {\n if (disabled) return\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n ctx.tree.select(itemId)\n }\n if (e.key === 'ArrowRight' && hasChildren && !isExpanded) {\n e.preventDefault()\n e.stopPropagation()\n ctx.tree.toggle(itemId)\n }\n if (e.key === 'ArrowLeft' && hasChildren && isExpanded) {\n e.preventDefault()\n e.stopPropagation()\n ctx.tree.toggle(itemId)\n }\n }\n\n // Compute indeterminate state for checkbox mode\n const checkboxState = React.useMemo(() => {\n if (!ctx.checkboxes || !hasChildren) {\n return { checked: isSelected, indeterminate: false }\n }\n // Collect all descendant IDs\n const descendants: string[] = []\n const collectIds = (nodes: React.ReactNode) => {\n React.Children.forEach(nodes, (child) => {\n if (React.isValidElement<TreeItemProps>(child) && child.props.itemId) {\n descendants.push(child.props.itemId)\n if (child.props.children) {\n collectIds(child.props.children)\n }\n }\n })\n }\n collectIds(children)\n const selectedCount = descendants.filter((id) =>\n ctx.tree.isSelected(id),\n ).length\n if (selectedCount === 0 && !isSelected) {\n return { checked: false, indeterminate: false }\n }\n if (selectedCount === descendants.length) {\n return { checked: true, indeterminate: false }\n }\n return { checked: false, indeterminate: true }\n }, [ctx.checkboxes, hasChildren, children, isSelected, ctx.tree])\n\n return (\n <li\n ref={ref}\n role=\"treeitem\"\n aria-expanded={hasChildren ? isExpanded : undefined}\n aria-selected={isSelected}\n aria-level={depth + 1}\n aria-disabled={disabled || undefined}\n className=\"list-none\"\n >\n {/* Row */}\n <div\n role=\"presentation\"\n data-tree-item={itemId}\n tabIndex={disabled ? -1 : 0}\n onClick={handleRowClick}\n onKeyDown={handleKeyDown}\n style={{ paddingLeft: `calc(${depth} * var(--spacing-ds-05b) + var(--spacing-ds-03))` }}\n className={cn(\n 'flex items-center gap-ds-02 py-ds-02 px-ds-02 rounded-ds-md cursor-pointer transition-colors duration-fast-01',\n 'hover:bg-surface-raised',\n 'focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9',\n isSelected &&\n 'bg-accent-3 text-accent-11',\n disabled && 'opacity-action-disabled cursor-not-allowed pointer-events-none',\n className,\n )}\n >\n {/* Expand chevron */}\n {hasChildren ? (\n <button\n type=\"button\"\n tabIndex={-1}\n aria-hidden=\"true\"\n onClick={handleChevronClick}\n className=\"flex shrink-0 items-center justify-center p-0 border-0 bg-transparent cursor-pointer\"\n >\n <Icon\n icon={IconChevronRight}\n size=\"sm\"\n className={cn(\n 'transition-transform duration-moderate-02',\n isExpanded && 'rotate-90',\n )}\n />\n </button>\n ) : (\n <span className=\"inline-block w-4 shrink-0\" aria-hidden=\"true\" />\n )}\n\n {/* Checkbox (optional) */}\n {ctx.checkboxes && (\n <Checkbox\n checked={checkboxState.checked}\n indeterminate={checkboxState.indeterminate}\n disabled={disabled}\n tabIndex={-1}\n onClick={(e) => e.stopPropagation()}\n onCheckedChange={() => {\n if (!disabled) ctx.tree.select(itemId)\n }}\n className=\"shrink-0\"\n />\n )}\n\n {/* Icon */}\n {icon && (\n <span className=\"flex shrink-0 items-center text-surface-fg-subtle\">\n {icon}\n </span>\n )}\n\n {/* Label */}\n <span className=\"truncate text-ds-sm\">{label}</span>\n\n {/* Secondary label */}\n {secondaryLabel && (\n <span className=\"ml-auto truncate text-ds-xs text-surface-fg-muted\">\n {secondaryLabel}\n </span>\n )}\n\n {/* Actions */}\n {actions && (\n <span\n className=\"ml-auto flex shrink-0 items-center gap-ds-01\"\n onClick={(e) => e.stopPropagation()}\n role=\"presentation\"\n >\n {actions}\n </span>\n )}\n </div>\n\n {/* Children (collapsible) */}\n {hasChildren && (\n <div\n role=\"group\"\n className={cn(\n 'grid transition-[grid-template-rows] duration-moderate-02 ease-productive-standard',\n isExpanded ? 'grid-rows-[1fr]' : 'grid-rows-[0fr]',\n )}\n >\n <ul role=\"group\" className=\"overflow-hidden m-0 p-0\">\n {React.Children.map(children, (child) => {\n if (React.isValidElement<TreeItemProps>(child)) {\n return React.cloneElement(child, {\n depth: depth + 1,\n })\n }\n return child\n })}\n </ul>\n </div>\n )}\n </li>\n )\n },\n)\nTreeItem.displayName = 'TreeItem'\n\nexport { TreeItem }\n"],"mappings":"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"}
1
+ {"version":3,"file":"tree-view.js","names":[],"sources":["../../src/ui/tree-view/use-tree.ts","../../src/ui/tree-view/tree-view.tsx","../../src/ui/tree-view/tree-item.tsx"],"sourcesContent":["import { useCallback,useState } from 'react'\n\nimport type { IconInput } from '../lib/icon-input'\n\nexport interface TreeNode {\n id: string\n label: string\n icon?: IconInput\n children?: TreeNode[]\n disabled?: boolean\n}\n\ninterface UseTreeOptions {\n defaultExpanded?: string[]\n defaultSelected?: string[]\n multiSelect?: boolean\n onSelect?: (selectedIds: string[]) => void\n onExpand?: (expandedIds: string[]) => void\n}\n\nexport function useTree(options: UseTreeOptions = {}) {\n const { defaultExpanded, defaultSelected, multiSelect, onSelect, onExpand } = options\n\n const [expanded, setExpanded] = useState<Set<string>>(\n new Set(defaultExpanded ?? []),\n )\n const [selected, setSelected] = useState<Set<string>>(\n new Set(defaultSelected ?? []),\n )\n\n const toggle = useCallback(\n (id: string) => {\n setExpanded((prev) => {\n const next = new Set(prev)\n if (next.has(id)) next.delete(id)\n else next.add(id)\n onExpand?.(Array.from(next))\n return next\n })\n },\n [onExpand],\n )\n\n const select = useCallback(\n (id: string, event?: React.MouseEvent) => {\n setSelected((prev) => {\n let next: Set<string>\n if (multiSelect && event?.ctrlKey) {\n next = new Set(prev)\n if (next.has(id)) next.delete(id)\n else next.add(id)\n } else {\n next = new Set([id])\n }\n onSelect?.(Array.from(next))\n return next\n })\n },\n [multiSelect, onSelect],\n )\n\n return {\n expanded,\n selected,\n toggle,\n select,\n isExpanded: (id: string) => expanded.has(id),\n isSelected: (id: string) => selected.has(id),\n expandAll: (ids: string[]) => setExpanded(new Set(ids)),\n collapseAll: () => setExpanded(new Set()),\n }\n}\n","'use client'\n\nimport * as React from 'react'\n\nimport { cn } from '../lib/utils'\nimport { TreeItem } from './tree-item'\nimport { type TreeNode,useTree } from './use-tree'\n\n// ─── Context ────────────────────────────────────────────────────────\ninterface TreeContextValue {\n tree: ReturnType<typeof useTree>\n checkboxes: boolean\n}\n\nconst TreeContext = React.createContext<TreeContextValue | null>(null)\n\nexport function useTreeContext() {\n const ctx = React.useContext(TreeContext)\n if (!ctx) {\n throw new Error('TreeItem must be used within a <TreeView>')\n }\n return ctx\n}\n\n// ─── Props ──────────────────────────────────────────────────────────\nexport interface TreeViewProps extends Omit<React.HTMLAttributes<HTMLUListElement>, 'onSelect'> {\n /** Data-driven mode: pass items array */\n items?: TreeNode[]\n /** Initially expanded node IDs */\n defaultExpanded?: string[]\n /** Initially selected node IDs */\n defaultSelected?: string[]\n /** Enable multi-select */\n multiSelect?: boolean\n /** Show checkboxes before each item */\n checkboxes?: boolean\n /** Called when selection changes */\n onSelect?: (ids: string[]) => void\n /** Called when expansion changes */\n onExpand?: (ids: string[]) => void\n className?: string\n /** Declarative mode: render TreeItem children directly */\n children?: React.ReactNode\n}\n\n// ─── Render nodes recursively (data-driven mode) ───────────────────\nfunction renderNodes(nodes: TreeNode[], depth: number = 0): React.ReactNode {\n return nodes.map((node) => (\n <TreeItem\n key={node.id}\n itemId={node.id}\n label={node.label}\n icon={node.icon}\n disabled={node.disabled}\n depth={depth}\n >\n {node.children && node.children.length > 0\n ? renderNodes(node.children, depth + 1)\n : undefined}\n </TreeItem>\n ))\n}\n\n// ─── Helper: collect all visible item IDs ───────────────────────────\nfunction getVisibleItemElements(container: HTMLElement): HTMLElement[] {\n return Array.from(\n container.querySelectorAll<HTMLElement>('[data-tree-item]'),\n ).filter((el) => {\n // Items inside collapsed groups should not be focusable\n let parent = el.parentElement\n while (parent && parent !== container) {\n if (parent.getAttribute('role') === 'group') {\n const grid = parent.parentElement\n if (grid && grid.classList.contains('grid-rows-[0fr]')) {\n return false\n }\n }\n parent = parent.parentElement\n }\n return true\n })\n}\n\n// ─── Component ──────────────────────────────────────────────────────\nconst TreeView = React.forwardRef<HTMLUListElement, TreeViewProps>(\n (\n {\n items,\n defaultExpanded,\n defaultSelected,\n multiSelect = false,\n checkboxes = false,\n onSelect,\n onExpand,\n className,\n children,\n ...props\n },\n ref,\n ) => {\n const tree = useTree({\n defaultExpanded,\n defaultSelected,\n multiSelect,\n onSelect,\n onExpand,\n })\n\n const innerRef = React.useRef<HTMLUListElement>(null)\n const containerRef = (ref as React.RefObject<HTMLUListElement>) ?? innerRef\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLUListElement>) => {\n const container = containerRef.current\n if (!container) return\n\n const visibleItems = getVisibleItemElements(container)\n const currentIndex = visibleItems.findIndex(\n (el) => el === document.activeElement,\n )\n\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault()\n const next = visibleItems[currentIndex + 1]\n next?.focus()\n break\n }\n case 'ArrowUp': {\n e.preventDefault()\n const prev = visibleItems[currentIndex - 1]\n prev?.focus()\n break\n }\n case 'ArrowRight': {\n // Handled in TreeItem for expand; if already expanded, move to first child\n const current = visibleItems[currentIndex]\n if (current) {\n const itemId = current.getAttribute('data-tree-item')\n if (itemId && tree.isExpanded(itemId)) {\n e.preventDefault()\n const nextItem = visibleItems[currentIndex + 1]\n nextItem?.focus()\n }\n }\n break\n }\n case 'ArrowLeft': {\n // Handled in TreeItem for collapse; if already collapsed or leaf, move to parent\n const current = visibleItems[currentIndex]\n if (current) {\n const itemId = current.getAttribute('data-tree-item')\n const treeItem = current.closest('[role=\"treeitem\"]')\n const parentGroup = treeItem?.parentElement?.closest(\n '[role=\"treeitem\"]',\n )\n if (itemId && !tree.isExpanded(itemId) && parentGroup) {\n e.preventDefault()\n const parentRow = parentGroup.querySelector<HTMLElement>(\n '[data-tree-item]',\n )\n parentRow?.focus()\n }\n }\n break\n }\n case 'Home': {\n e.preventDefault()\n visibleItems[0]?.focus()\n break\n }\n case 'End': {\n e.preventDefault()\n visibleItems[visibleItems.length - 1]?.focus()\n break\n }\n }\n }\n\n const ctxValue = React.useMemo<TreeContextValue>(\n () => ({ tree, checkboxes }),\n [tree, checkboxes],\n )\n\n const content = items ? renderNodes(items) : children\n\n return (\n <TreeContext.Provider value={ctxValue}>\n <ul\n ref={containerRef}\n role=\"tree\"\n aria-multiselectable={multiSelect || undefined}\n onKeyDown={handleKeyDown}\n className={cn('m-0 list-none p-0', className)}\n {...props}\n >\n {content}\n </ul>\n </TreeContext.Provider>\n )\n },\n)\nTreeView.displayName = 'TreeView'\n\nexport { TreeView }\n","'use client'\n\nimport { IconChevronRight } from '@tabler/icons-react'\nimport * as React from 'react'\n\nimport { Checkbox } from '../checkbox'\nimport { Icon } from '../icon'\nimport { IconProvider } from '../icon-context'\nimport type { IconInput } from '../lib/icon-input'\nimport { normalizeIcon } from '../lib/normalize-icon'\nimport { cn } from '../lib/utils'\nimport { useTreeContext } from './tree-view'\n\nexport interface TreeItemProps {\n /** Unique identifier for this tree item */\n itemId: string\n /** Primary label content */\n label: React.ReactNode\n /** Optional icon rendered before the label. Accepts any `IconInput`. */\n icon?: IconInput\n /** Secondary label rendered after the primary label */\n secondaryLabel?: React.ReactNode\n /** Action buttons rendered at the end of the row */\n actions?: React.ReactNode\n /** Whether this item is disabled */\n disabled?: boolean\n /** Nested tree items */\n children?: React.ReactNode\n /** Depth level (used internally) */\n depth?: number\n /** Additional CSS class names */\n className?: string\n}\n\nconst TreeItem = React.forwardRef<HTMLLIElement, TreeItemProps>(\n (\n {\n itemId,\n label,\n icon,\n secondaryLabel,\n actions,\n disabled = false,\n children,\n depth = 0,\n className,\n },\n ref,\n ) => {\n const ctx = useTreeContext()\n const hasChildren = React.Children.count(children) > 0\n const isExpanded = ctx.tree.isExpanded(itemId)\n const isSelected = ctx.tree.isSelected(itemId)\n\n const handleRowClick = (e: React.MouseEvent<HTMLDivElement>) => {\n if (disabled) return\n ctx.tree.select(itemId, e)\n }\n\n const handleChevronClick = (e: React.MouseEvent<HTMLButtonElement>) => {\n e.stopPropagation()\n if (disabled) return\n ctx.tree.toggle(itemId)\n }\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {\n if (disabled) return\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n ctx.tree.select(itemId)\n }\n if (e.key === 'ArrowRight' && hasChildren && !isExpanded) {\n e.preventDefault()\n e.stopPropagation()\n ctx.tree.toggle(itemId)\n }\n if (e.key === 'ArrowLeft' && hasChildren && isExpanded) {\n e.preventDefault()\n e.stopPropagation()\n ctx.tree.toggle(itemId)\n }\n }\n\n // Compute indeterminate state for checkbox mode\n const checkboxState = React.useMemo(() => {\n if (!ctx.checkboxes || !hasChildren) {\n return { checked: isSelected, indeterminate: false }\n }\n // Collect all descendant IDs\n const descendants: string[] = []\n const collectIds = (nodes: React.ReactNode) => {\n React.Children.forEach(nodes, (child) => {\n if (React.isValidElement<TreeItemProps>(child) && child.props.itemId) {\n descendants.push(child.props.itemId)\n if (child.props.children) {\n collectIds(child.props.children)\n }\n }\n })\n }\n collectIds(children)\n const selectedCount = descendants.filter((id) =>\n ctx.tree.isSelected(id),\n ).length\n if (selectedCount === 0 && !isSelected) {\n return { checked: false, indeterminate: false }\n }\n if (selectedCount === descendants.length) {\n return { checked: true, indeterminate: false }\n }\n return { checked: false, indeterminate: true }\n }, [ctx.checkboxes, hasChildren, children, isSelected, ctx.tree])\n\n return (\n <li\n ref={ref}\n role=\"treeitem\"\n aria-expanded={hasChildren ? isExpanded : undefined}\n aria-selected={isSelected}\n aria-level={depth + 1}\n aria-disabled={disabled || undefined}\n className=\"list-none\"\n >\n {/* Row */}\n <div\n role=\"presentation\"\n data-tree-item={itemId}\n tabIndex={disabled ? -1 : 0}\n onClick={handleRowClick}\n onKeyDown={handleKeyDown}\n style={{ paddingLeft: `calc(${depth} * var(--spacing-ds-05b) + var(--spacing-ds-03))` }}\n className={cn(\n 'flex items-center gap-ds-02 py-ds-02 px-ds-02 rounded-control cursor-pointer transition-colors duration-fast-01',\n 'hover:bg-surface-raised',\n 'focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9',\n isSelected &&\n 'bg-accent-3 text-accent-11',\n disabled && 'opacity-action-disabled cursor-not-allowed pointer-events-none',\n className,\n )}\n >\n {/* Expand chevron */}\n {hasChildren ? (\n <button\n type=\"button\"\n tabIndex={-1}\n aria-hidden=\"true\"\n onClick={handleChevronClick}\n className=\"flex shrink-0 items-center justify-center p-0 border-0 bg-transparent cursor-pointer\"\n >\n <Icon\n icon={IconChevronRight}\n size=\"sm\"\n className={cn(\n 'transition-transform duration-moderate-02',\n isExpanded && 'rotate-90',\n )}\n />\n </button>\n ) : (\n <span className=\"inline-block w-4 shrink-0\" aria-hidden=\"true\" />\n )}\n\n {/* Checkbox (optional) */}\n {ctx.checkboxes && (\n <Checkbox\n checked={checkboxState.checked}\n indeterminate={checkboxState.indeterminate}\n disabled={disabled}\n tabIndex={-1}\n onClick={(e) => e.stopPropagation()}\n onCheckedChange={() => {\n if (!disabled) ctx.tree.select(itemId)\n }}\n className=\"shrink-0\"\n />\n )}\n\n {/* Icon */}\n {icon && (\n <span className=\"flex shrink-0 items-center text-surface-fg-subtle\">\n <IconProvider size=\"sm\">{normalizeIcon(icon)}</IconProvider>\n </span>\n )}\n\n {/* Label */}\n <span className=\"truncate text-ds-sm\">{label}</span>\n\n {/* Secondary label */}\n {secondaryLabel && (\n <span className=\"ml-auto truncate text-ds-xs text-surface-fg-muted\">\n {secondaryLabel}\n </span>\n )}\n\n {/* Actions */}\n {actions && (\n <span\n className=\"ml-auto flex shrink-0 items-center gap-ds-01\"\n onClick={(e) => e.stopPropagation()}\n role=\"presentation\"\n >\n {actions}\n </span>\n )}\n </div>\n\n {/* Children (collapsible) */}\n {hasChildren && (\n <div\n role=\"group\"\n className={cn(\n 'grid transition-[grid-template-rows] duration-moderate-02 ease-productive-standard',\n isExpanded ? 'grid-rows-[1fr]' : 'grid-rows-[0fr]',\n )}\n >\n <ul role=\"group\" className=\"overflow-hidden m-0 p-0\">\n {React.Children.map(children, (child) => {\n if (React.isValidElement<TreeItemProps>(child)) {\n return React.cloneElement(child, {\n depth: depth + 1,\n })\n }\n return child\n })}\n </ul>\n </div>\n )}\n </li>\n )\n },\n)\nTreeItem.displayName = 'TreeItem'\n\nexport { TreeItem }\n"],"mappings":"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"}
@@ -77,7 +77,7 @@ var T = [
77
77
  F ? /* @__PURE__ */ i("span", { className: "h-ds-xs-plus w-ds-xs-plus" }) : /* @__PURE__ */ i("button", {
78
78
  type: "button",
79
79
  onClick: () => A(w(r, 1)),
80
- className: "inline-flex h-ds-xs-plus w-ds-xs-plus items-center justify-center rounded-ds-md text-surface-fg-subtle transition-colors duration-fast-01 ease-productive-standard hover:bg-surface-raised-hover hover:text-surface-fg-muted focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9",
80
+ className: "inline-flex h-ds-xs-plus w-ds-xs-plus items-center justify-center rounded-control text-surface-fg-subtle transition-colors duration-fast-01 ease-productive-standard hover:bg-surface-raised-hover hover:text-surface-fg-muted focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9",
81
81
  "aria-label": "Previous month",
82
82
  children: /* @__PURE__ */ i(t, {
83
83
  icon: o,
@@ -88,14 +88,14 @@ var T = [
88
88
  /* @__PURE__ */ i("button", {
89
89
  type: "button",
90
90
  onClick: j,
91
- className: e("text-ds-md font-semibold text-surface-fg", j && "cursor-pointer rounded-ds-md px-ds-02 transition-colors duration-fast-01 ease-productive-standard hover:bg-surface-raised-hover"),
91
+ className: e("text-ds-md font-semibold text-surface-fg", j && "cursor-pointer rounded-control px-ds-02 transition-colors duration-fast-01 ease-productive-standard hover:bg-surface-raised-hover"),
92
92
  "aria-label": "Switch to month/year view",
93
93
  children: f(r, "MMMM yyyy")
94
94
  }),
95
95
  I ? /* @__PURE__ */ i("span", { className: "h-ds-xs-plus w-ds-xs-plus" }) : /* @__PURE__ */ i("button", {
96
96
  type: "button",
97
97
  onClick: () => A(l(r, 1)),
98
- className: "inline-flex h-ds-xs-plus w-ds-xs-plus items-center justify-center rounded-ds-md text-surface-fg-subtle transition-colors duration-fast-01 ease-productive-standard hover:bg-surface-raised-hover hover:text-surface-fg-muted focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9",
98
+ className: "inline-flex h-ds-xs-plus w-ds-xs-plus items-center justify-center rounded-control text-surface-fg-subtle transition-colors duration-fast-01 ease-productive-standard hover:bg-surface-raised-hover hover:text-surface-fg-muted focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9",
99
99
  "aria-label": "Next month",
100
100
  children: /* @__PURE__ */ i(t, {
101
101
  icon: s,
@@ -131,12 +131,12 @@ var T = [
131
131
  "aria-label": f(t, "EEEE, MMMM d, yyyy"),
132
132
  "aria-selected": c || u || void 0,
133
133
  "aria-disabled": !o || s || void 0,
134
- className: e("relative flex h-ds-sm w-ds-sm-plus items-center justify-center rounded-ds-md text-ds-md font-body transition-colors duration-fast-01 ease-productive-standard", !o && "pointer-events-none opacity-0", o && s && "opacity-action-disabled pointer-events-none cursor-not-allowed", o && !s && !c && !u && !l && "text-surface-fg hover:bg-surface-raised-hover", l && !u && "rounded-ds-none bg-surface-raised-hover text-surface-fg", (c || u) && "bg-accent-9 text-accent-fg hover:bg-accent-10", d && !c && !u && !s && "font-semibold text-accent-11"),
134
+ className: e("relative flex h-ds-sm w-ds-sm-plus items-center justify-center rounded-control text-ds-md font-body transition-colors duration-fast-01 ease-productive-standard", !o && "pointer-events-none opacity-0", o && s && "opacity-action-disabled pointer-events-none cursor-not-allowed", o && !s && !c && !u && !l && "text-surface-fg hover:bg-surface-raised-hover", l && !u && "rounded-none bg-surface-raised-hover text-surface-fg", (c || u) && "bg-accent-9 text-accent-fg hover:bg-accent-10", d && !c && !u && !s && "font-semibold text-accent-11"),
135
135
  children: [f(t, "d"), m.length > 0 && /* @__PURE__ */ i("span", {
136
136
  className: "flex gap-px justify-center absolute bottom-[2px] left-0 right-0",
137
137
  children: m.slice(0, 3).map((e, t) => /* @__PURE__ */ i("span", {
138
138
  "data-event-dot": !0,
139
- className: "h-[4px] w-[4px] rounded-ds-full",
139
+ className: "h-[4px] w-[4px] rounded-pill",
140
140
  style: { backgroundColor: e.color ?? "var(--color-accent-9)" }
141
141
  }, t))
142
142
  })]
@@ -1 +1 @@
1
- {"version":3,"file":"use-calendar.js","names":[],"sources":["../../src/composed/date-picker/calendar-grid.tsx","../../src/composed/date-picker/use-calendar.ts"],"sourcesContent":["'use client'\n\nimport { IconChevronLeft, IconChevronRight } from '@tabler/icons-react'\nimport {\n addDays,\n addMonths,\n endOfMonth,\n endOfWeek,\n format,\n isAfter,\n isBefore,\n isSameDay,\n isSameMonth,\n isWithinInterval,\n lastDayOfMonth,\n startOfDay,\n startOfMonth,\n startOfWeek,\n subMonths,\n} from 'date-fns'\nimport * as React from 'react'\n\nimport { Icon } from '../../ui/icon'\nimport { cn } from '../../ui/lib/utils'\n\nconst WEEKDAYS = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa']\n\nexport interface CalendarEvent {\n date: Date\n color?: string\n label?: string\n}\n\nexport interface CalendarGridProps extends Omit<React.ComponentPropsWithoutRef<'div'>, 'onSelect'> {\n currentMonth: Date\n selected?: Date | null\n rangeStart?: Date | null\n rangeEnd?: Date | null\n hoverDate?: Date | null\n onSelect: (date: Date) => void\n onHover?: (date: Date | null) => void\n onMonthChange: (date: Date) => void\n onHeaderClick?: () => void\n disabledDates?: (date: Date) => boolean\n minDate?: Date\n maxDate?: Date\n /** Hide the previous-month navigation arrow */\n hidePrevNav?: boolean\n /** Hide the next-month navigation arrow */\n hideNextNav?: boolean\n /** Events to display as dot indicators on dates */\n events?: CalendarEvent[]\n}\n\nexport const CalendarGrid = React.forwardRef<HTMLDivElement, CalendarGridProps>(\n function CalendarGrid({\n currentMonth,\n selected,\n rangeStart,\n rangeEnd,\n hoverDate,\n onSelect,\n onHover,\n onMonthChange,\n onHeaderClick,\n disabledDates,\n minDate,\n maxDate,\n hidePrevNav,\n hideNextNav,\n events,\n className,\n ...props\n}, forwardedRef) {\n const gridRef = React.useRef<HTMLDivElement>(null)\n\n const eventsByDate = React.useMemo(() => {\n const map = new Map<string, CalendarEvent[]>()\n if (!events) return map\n for (const evt of events) {\n const key = format(evt.date, 'yyyy-MM-dd')\n const arr = map.get(key) ?? []\n arr.push(evt)\n map.set(key, arr)\n }\n return map\n }, [events])\n\n const monthStart = startOfMonth(currentMonth)\n const monthEnd = endOfMonth(currentMonth)\n const calendarStart = startOfWeek(monthStart)\n const calendarEnd = endOfWeek(monthEnd)\n\n const days: Date[] = []\n let day = calendarStart\n while (day <= calendarEnd) {\n days.push(day)\n day = addDays(day, 1)\n }\n\n const isDateDisabled = (date: Date): boolean => {\n if (disabledDates?.(date)) return true\n if (minDate && isBefore(date, startOfDay(minDate))) return true\n if (maxDate && isAfter(date, startOfDay(maxDate))) return true\n return false\n }\n\n const isInRange = (date: Date) => {\n if (rangeStart && rangeEnd) {\n const start = isBefore(rangeStart, rangeEnd) ? rangeStart : rangeEnd\n const end = isAfter(rangeEnd, rangeStart) ? rangeEnd : rangeStart\n return isWithinInterval(date, { start, end })\n }\n if (rangeStart && hoverDate) {\n const start = isBefore(rangeStart, hoverDate) ? rangeStart : hoverDate\n const end = isAfter(hoverDate, rangeStart) ? hoverDate : rangeStart\n return isWithinInterval(date, { start, end })\n }\n return false\n }\n\n const isRangeEdge = (date: Date) => {\n if (rangeStart && isSameDay(date, rangeStart)) return true\n if (rangeEnd && isSameDay(date, rangeEnd)) return true\n return false\n }\n\n const focusDate = (target: Date) => {\n if (!gridRef.current) return\n const dateStr = format(target, 'yyyy-MM-dd')\n const btn = gridRef.current.querySelector<HTMLButtonElement>(\n `[data-date=\"${dateStr}\"]`,\n )\n if (btn) {\n btn.focus()\n } else {\n // Date is in a different month — navigate there and focus after render\n onMonthChange(startOfMonth(target))\n }\n }\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {\n const target = e.target as HTMLElement\n const dateStr = target.getAttribute('data-date')\n if (!dateStr) return\n\n const current = new Date(dateStr + 'T00:00:00')\n let next: Date | null = null\n\n switch (e.key) {\n case 'ArrowLeft':\n next = addDays(current, -1)\n break\n case 'ArrowRight':\n next = addDays(current, 1)\n break\n case 'ArrowUp':\n next = addDays(current, -7)\n break\n case 'ArrowDown':\n next = addDays(current, 7)\n break\n case 'Home':\n next = startOfMonth(current)\n break\n case 'End':\n next = lastDayOfMonth(current)\n break\n case 'Enter':\n case ' ': {\n e.preventDefault()\n if (!isDateDisabled(current) && isSameMonth(current, currentMonth)) {\n onSelect(current)\n }\n return\n }\n default:\n return\n }\n\n if (next) {\n e.preventDefault()\n focusDate(next)\n }\n }\n\n return (\n <div ref={forwardedRef} {...props} className={cn(\"w-[252px]\", className)}>\n <div className=\"flex items-center justify-between px-ds-02 pb-ds-04\">\n {hidePrevNav ? (\n <span className=\"h-ds-xs-plus w-ds-xs-plus\" />\n ) : (\n <button\n type=\"button\"\n onClick={() => onMonthChange(subMonths(currentMonth, 1))}\n className=\"inline-flex h-ds-xs-plus w-ds-xs-plus items-center justify-center rounded-ds-md text-surface-fg-subtle transition-colors duration-fast-01 ease-productive-standard hover:bg-surface-raised-hover hover:text-surface-fg-muted focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9\"\n aria-label=\"Previous month\"\n >\n <Icon icon={IconChevronLeft} size=\"sm\" stroke=\"light\" />\n </button>\n )}\n <button\n type=\"button\"\n onClick={onHeaderClick}\n className={cn(\n 'text-ds-md font-semibold text-surface-fg',\n onHeaderClick &&\n 'cursor-pointer rounded-ds-md px-ds-02 transition-colors duration-fast-01 ease-productive-standard hover:bg-surface-raised-hover',\n )}\n aria-label=\"Switch to month/year view\"\n >\n {format(currentMonth, 'MMMM yyyy')}\n </button>\n {hideNextNav ? (\n <span className=\"h-ds-xs-plus w-ds-xs-plus\" />\n ) : (\n <button\n type=\"button\"\n onClick={() => onMonthChange(addMonths(currentMonth, 1))}\n className=\"inline-flex h-ds-xs-plus w-ds-xs-plus items-center justify-center rounded-ds-md text-surface-fg-subtle transition-colors duration-fast-01 ease-productive-standard hover:bg-surface-raised-hover hover:text-surface-fg-muted focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9\"\n aria-label=\"Next month\"\n >\n <Icon icon={IconChevronRight} size=\"sm\" stroke=\"light\" />\n </button>\n )}\n </div>\n\n <div\n ref={gridRef}\n className=\"grid grid-cols-7 gap-0\"\n role=\"grid\"\n tabIndex={0}\n aria-label=\"Calendar\"\n onKeyDown={handleKeyDown}\n >\n {WEEKDAYS.map((wd) => (\n <div\n key={wd}\n role=\"columnheader\"\n className=\"flex h-ds-sm items-center justify-center text-ds-xs font-semibold uppercase tracking-wider text-surface-fg-subtle\"\n >\n {wd}\n </div>\n ))}\n\n {days.map((d, i) => {\n const inMonth = isSameMonth(d, currentMonth)\n const disabled = isDateDisabled(d)\n const isSelected = selected && isSameDay(d, selected)\n const inRange = isInRange(d)\n const edge = isRangeEdge(d)\n const isToday = isSameDay(d, new Date())\n const dateKey = format(d, 'yyyy-MM-dd')\n const dayEvents = eventsByDate.get(dateKey) ?? []\n\n return (\n <button\n key={i}\n type=\"button\"\n role=\"gridcell\"\n data-date={dateKey}\n tabIndex={inMonth && !disabled ? 0 : -1}\n disabled={!inMonth || disabled}\n onClick={() => {\n if (inMonth && !disabled) onSelect(d)\n }}\n onMouseEnter={() => onHover?.(d)}\n onMouseLeave={() => onHover?.(null)}\n aria-label={format(d, 'EEEE, MMMM d, yyyy')}\n aria-selected={isSelected || edge || undefined}\n aria-disabled={!inMonth || disabled || undefined}\n className={cn(\n 'relative flex h-ds-sm w-ds-sm-plus items-center justify-center rounded-ds-md text-ds-md font-body transition-colors duration-fast-01 ease-productive-standard',\n !inMonth && 'pointer-events-none opacity-0',\n inMonth && disabled && 'opacity-action-disabled pointer-events-none cursor-not-allowed',\n inMonth && !disabled && !isSelected && !edge && !inRange &&\n 'text-surface-fg hover:bg-surface-raised-hover',\n inRange && !edge &&\n 'rounded-ds-none bg-surface-raised-hover text-surface-fg',\n (isSelected || edge) &&\n 'bg-accent-9 text-accent-fg hover:bg-accent-10',\n isToday && !isSelected && !edge && !disabled &&\n 'font-semibold text-accent-11',\n )}\n >\n {format(d, 'd')}\n {dayEvents.length > 0 && (\n <span className=\"flex gap-px justify-center absolute bottom-[2px] left-0 right-0\">\n {dayEvents.slice(0, 3).map((evt, idx) => (\n <span\n key={idx}\n data-event-dot\n className=\"h-[4px] w-[4px] rounded-ds-full\"\n style={{ backgroundColor: evt.color ?? 'var(--color-accent-9)' }}\n />\n ))}\n </span>\n )}\n </button>\n )\n })}\n </div>\n </div>\n )\n},\n)\n\nCalendarGrid.displayName = 'CalendarGrid'\n","'use client'\n\nimport { addMonths, setMonth, setYear,subMonths } from 'date-fns'\nimport { useState } from 'react'\n\nexport function useCalendar(initialMonth?: Date) {\n const [currentMonth, setCurrentMonth] = useState(initialMonth ?? new Date())\n\n const goToPreviousMonth = () => setCurrentMonth((prev) => subMonths(prev, 1))\n const goToNextMonth = () => setCurrentMonth((prev) => addMonths(prev, 1))\n const goToMonth = (month: number) =>\n setCurrentMonth((prev) => setMonth(prev, month))\n const goToYear = (year: number) =>\n setCurrentMonth((prev) => setYear(prev, year))\n\n return {\n currentMonth,\n setCurrentMonth,\n goToPreviousMonth,\n goToNextMonth,\n goToMonth,\n goToYear,\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"use-calendar.js","names":[],"sources":["../../src/composed/date-picker/calendar-grid.tsx","../../src/composed/date-picker/use-calendar.ts"],"sourcesContent":["'use client'\n\nimport { IconChevronLeft, IconChevronRight } from '@tabler/icons-react'\nimport {\n addDays,\n addMonths,\n endOfMonth,\n endOfWeek,\n format,\n isAfter,\n isBefore,\n isSameDay,\n isSameMonth,\n isWithinInterval,\n lastDayOfMonth,\n startOfDay,\n startOfMonth,\n startOfWeek,\n subMonths,\n} from 'date-fns'\nimport * as React from 'react'\n\nimport { Icon } from '../../ui/icon'\nimport { cn } from '../../ui/lib/utils'\n\nconst WEEKDAYS = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa']\n\nexport interface CalendarEvent {\n date: Date\n color?: string\n label?: string\n}\n\nexport interface CalendarGridProps extends Omit<React.ComponentPropsWithoutRef<'div'>, 'onSelect'> {\n currentMonth: Date\n selected?: Date | null\n rangeStart?: Date | null\n rangeEnd?: Date | null\n hoverDate?: Date | null\n onSelect: (date: Date) => void\n onHover?: (date: Date | null) => void\n onMonthChange: (date: Date) => void\n onHeaderClick?: () => void\n disabledDates?: (date: Date) => boolean\n minDate?: Date\n maxDate?: Date\n /** Hide the previous-month navigation arrow */\n hidePrevNav?: boolean\n /** Hide the next-month navigation arrow */\n hideNextNav?: boolean\n /** Events to display as dot indicators on dates */\n events?: CalendarEvent[]\n}\n\nexport const CalendarGrid = React.forwardRef<HTMLDivElement, CalendarGridProps>(\n function CalendarGrid({\n currentMonth,\n selected,\n rangeStart,\n rangeEnd,\n hoverDate,\n onSelect,\n onHover,\n onMonthChange,\n onHeaderClick,\n disabledDates,\n minDate,\n maxDate,\n hidePrevNav,\n hideNextNav,\n events,\n className,\n ...props\n}, forwardedRef) {\n const gridRef = React.useRef<HTMLDivElement>(null)\n\n const eventsByDate = React.useMemo(() => {\n const map = new Map<string, CalendarEvent[]>()\n if (!events) return map\n for (const evt of events) {\n const key = format(evt.date, 'yyyy-MM-dd')\n const arr = map.get(key) ?? []\n arr.push(evt)\n map.set(key, arr)\n }\n return map\n }, [events])\n\n const monthStart = startOfMonth(currentMonth)\n const monthEnd = endOfMonth(currentMonth)\n const calendarStart = startOfWeek(monthStart)\n const calendarEnd = endOfWeek(monthEnd)\n\n const days: Date[] = []\n let day = calendarStart\n while (day <= calendarEnd) {\n days.push(day)\n day = addDays(day, 1)\n }\n\n const isDateDisabled = (date: Date): boolean => {\n if (disabledDates?.(date)) return true\n if (minDate && isBefore(date, startOfDay(minDate))) return true\n if (maxDate && isAfter(date, startOfDay(maxDate))) return true\n return false\n }\n\n const isInRange = (date: Date) => {\n if (rangeStart && rangeEnd) {\n const start = isBefore(rangeStart, rangeEnd) ? rangeStart : rangeEnd\n const end = isAfter(rangeEnd, rangeStart) ? rangeEnd : rangeStart\n return isWithinInterval(date, { start, end })\n }\n if (rangeStart && hoverDate) {\n const start = isBefore(rangeStart, hoverDate) ? rangeStart : hoverDate\n const end = isAfter(hoverDate, rangeStart) ? hoverDate : rangeStart\n return isWithinInterval(date, { start, end })\n }\n return false\n }\n\n const isRangeEdge = (date: Date) => {\n if (rangeStart && isSameDay(date, rangeStart)) return true\n if (rangeEnd && isSameDay(date, rangeEnd)) return true\n return false\n }\n\n const focusDate = (target: Date) => {\n if (!gridRef.current) return\n const dateStr = format(target, 'yyyy-MM-dd')\n const btn = gridRef.current.querySelector<HTMLButtonElement>(\n `[data-date=\"${dateStr}\"]`,\n )\n if (btn) {\n btn.focus()\n } else {\n // Date is in a different month — navigate there and focus after render\n onMonthChange(startOfMonth(target))\n }\n }\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {\n const target = e.target as HTMLElement\n const dateStr = target.getAttribute('data-date')\n if (!dateStr) return\n\n const current = new Date(dateStr + 'T00:00:00')\n let next: Date | null = null\n\n switch (e.key) {\n case 'ArrowLeft':\n next = addDays(current, -1)\n break\n case 'ArrowRight':\n next = addDays(current, 1)\n break\n case 'ArrowUp':\n next = addDays(current, -7)\n break\n case 'ArrowDown':\n next = addDays(current, 7)\n break\n case 'Home':\n next = startOfMonth(current)\n break\n case 'End':\n next = lastDayOfMonth(current)\n break\n case 'Enter':\n case ' ': {\n e.preventDefault()\n if (!isDateDisabled(current) && isSameMonth(current, currentMonth)) {\n onSelect(current)\n }\n return\n }\n default:\n return\n }\n\n if (next) {\n e.preventDefault()\n focusDate(next)\n }\n }\n\n return (\n <div ref={forwardedRef} {...props} className={cn(\"w-[252px]\", className)}>\n <div className=\"flex items-center justify-between px-ds-02 pb-ds-04\">\n {hidePrevNav ? (\n <span className=\"h-ds-xs-plus w-ds-xs-plus\" />\n ) : (\n <button\n type=\"button\"\n onClick={() => onMonthChange(subMonths(currentMonth, 1))}\n className=\"inline-flex h-ds-xs-plus w-ds-xs-plus items-center justify-center rounded-control text-surface-fg-subtle transition-colors duration-fast-01 ease-productive-standard hover:bg-surface-raised-hover hover:text-surface-fg-muted focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9\"\n aria-label=\"Previous month\"\n >\n <Icon icon={IconChevronLeft} size=\"sm\" stroke=\"light\" />\n </button>\n )}\n <button\n type=\"button\"\n onClick={onHeaderClick}\n className={cn(\n 'text-ds-md font-semibold text-surface-fg',\n onHeaderClick &&\n 'cursor-pointer rounded-control px-ds-02 transition-colors duration-fast-01 ease-productive-standard hover:bg-surface-raised-hover',\n )}\n aria-label=\"Switch to month/year view\"\n >\n {format(currentMonth, 'MMMM yyyy')}\n </button>\n {hideNextNav ? (\n <span className=\"h-ds-xs-plus w-ds-xs-plus\" />\n ) : (\n <button\n type=\"button\"\n onClick={() => onMonthChange(addMonths(currentMonth, 1))}\n className=\"inline-flex h-ds-xs-plus w-ds-xs-plus items-center justify-center rounded-control text-surface-fg-subtle transition-colors duration-fast-01 ease-productive-standard hover:bg-surface-raised-hover hover:text-surface-fg-muted focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-accent-9\"\n aria-label=\"Next month\"\n >\n <Icon icon={IconChevronRight} size=\"sm\" stroke=\"light\" />\n </button>\n )}\n </div>\n\n <div\n ref={gridRef}\n className=\"grid grid-cols-7 gap-0\"\n role=\"grid\"\n tabIndex={0}\n aria-label=\"Calendar\"\n onKeyDown={handleKeyDown}\n >\n {WEEKDAYS.map((wd) => (\n <div\n key={wd}\n role=\"columnheader\"\n className=\"flex h-ds-sm items-center justify-center text-ds-xs font-semibold uppercase tracking-wider text-surface-fg-subtle\"\n >\n {wd}\n </div>\n ))}\n\n {days.map((d, i) => {\n const inMonth = isSameMonth(d, currentMonth)\n const disabled = isDateDisabled(d)\n const isSelected = selected && isSameDay(d, selected)\n const inRange = isInRange(d)\n const edge = isRangeEdge(d)\n const isToday = isSameDay(d, new Date())\n const dateKey = format(d, 'yyyy-MM-dd')\n const dayEvents = eventsByDate.get(dateKey) ?? []\n\n return (\n <button\n key={i}\n type=\"button\"\n role=\"gridcell\"\n data-date={dateKey}\n tabIndex={inMonth && !disabled ? 0 : -1}\n disabled={!inMonth || disabled}\n onClick={() => {\n if (inMonth && !disabled) onSelect(d)\n }}\n onMouseEnter={() => onHover?.(d)}\n onMouseLeave={() => onHover?.(null)}\n aria-label={format(d, 'EEEE, MMMM d, yyyy')}\n aria-selected={isSelected || edge || undefined}\n aria-disabled={!inMonth || disabled || undefined}\n className={cn(\n 'relative flex h-ds-sm w-ds-sm-plus items-center justify-center rounded-control text-ds-md font-body transition-colors duration-fast-01 ease-productive-standard',\n !inMonth && 'pointer-events-none opacity-0',\n inMonth && disabled && 'opacity-action-disabled pointer-events-none cursor-not-allowed',\n inMonth && !disabled && !isSelected && !edge && !inRange &&\n 'text-surface-fg hover:bg-surface-raised-hover',\n inRange && !edge &&\n 'rounded-none bg-surface-raised-hover text-surface-fg',\n (isSelected || edge) &&\n 'bg-accent-9 text-accent-fg hover:bg-accent-10',\n isToday && !isSelected && !edge && !disabled &&\n 'font-semibold text-accent-11',\n )}\n >\n {format(d, 'd')}\n {dayEvents.length > 0 && (\n <span className=\"flex gap-px justify-center absolute bottom-[2px] left-0 right-0\">\n {dayEvents.slice(0, 3).map((evt, idx) => (\n <span\n key={idx}\n data-event-dot\n className=\"h-[4px] w-[4px] rounded-pill\"\n style={{ backgroundColor: evt.color ?? 'var(--color-accent-9)' }}\n />\n ))}\n </span>\n )}\n </button>\n )\n })}\n </div>\n </div>\n )\n},\n)\n\nCalendarGrid.displayName = 'CalendarGrid'\n","'use client'\n\nimport { addMonths, setMonth, setYear,subMonths } from 'date-fns'\nimport { useState } from 'react'\n\nexport function useCalendar(initialMonth?: Date) {\n const [currentMonth, setCurrentMonth] = useState(initialMonth ?? new Date())\n\n const goToPreviousMonth = () => setCurrentMonth((prev) => subMonths(prev, 1))\n const goToNextMonth = () => setCurrentMonth((prev) => addMonths(prev, 1))\n const goToMonth = (month: number) =>\n setCurrentMonth((prev) => setMonth(prev, month))\n const goToYear = (year: number) =>\n setCurrentMonth((prev) => setYear(prev, year))\n\n return {\n currentMonth,\n setCurrentMonth,\n goToPreviousMonth,\n goToNextMonth,\n goToMonth,\n goToYear,\n }\n}\n"],"mappings":"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"}