banhaten 0.1.2 → 0.2.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 (365) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/CONTRIBUTING.md +44 -0
  3. package/README.md +145 -328
  4. package/SECURITY.md +15 -0
  5. package/banhaten.config.example.json +1 -3
  6. package/docs/design-system/README.md +20 -0
  7. package/docs/design-system/adoption-quality-remediation.md +87 -0
  8. package/docs/design-system/agent-usage.md +13 -0
  9. package/docs/design-system/appearance-presets.md +189 -0
  10. package/docs/design-system/appearances/default.md +94 -0
  11. package/docs/design-system/appearances/rounded.md +95 -0
  12. package/docs/design-system/appearances/sharp.md +95 -0
  13. package/docs/design-system/component-docs-pattern.md +81 -0
  14. package/docs/design-system/component-showcase-consistency-report.md +217 -0
  15. package/docs/design-system/component-token-consistency-audit.md +173 -0
  16. package/docs/design-system/components/README.md +75 -0
  17. package/docs/design-system/components/accordion.md +67 -0
  18. package/docs/design-system/components/activity-feed.md +106 -0
  19. package/docs/design-system/components/alert-dialog.md +87 -0
  20. package/docs/design-system/components/alert.md +111 -0
  21. package/docs/design-system/components/aspect-ratio.md +59 -0
  22. package/docs/design-system/components/attribute.md +103 -0
  23. package/docs/design-system/components/autocomplete.md +93 -0
  24. package/docs/design-system/components/avatar.md +70 -0
  25. package/docs/design-system/components/badge.md +72 -0
  26. package/docs/design-system/components/banner.md +99 -0
  27. package/docs/design-system/components/breadcrumbs.md +188 -0
  28. package/docs/design-system/components/button-group.md +117 -0
  29. package/docs/design-system/components/button.md +95 -0
  30. package/docs/design-system/components/card.md +95 -0
  31. package/docs/design-system/components/carousel.md +61 -0
  32. package/docs/design-system/components/catalog-components.md +59 -0
  33. package/docs/design-system/components/chart.md +58 -0
  34. package/docs/design-system/components/checkbox.md +68 -0
  35. package/docs/design-system/components/collapsible.md +63 -0
  36. package/docs/design-system/components/command.md +75 -0
  37. package/docs/design-system/components/context-menu.md +59 -0
  38. package/docs/design-system/components/date-picker.md +97 -0
  39. package/docs/design-system/components/divider.md +117 -0
  40. package/docs/design-system/components/empty-state.md +72 -0
  41. package/docs/design-system/components/field.md +86 -0
  42. package/docs/design-system/components/file-upload.md +199 -0
  43. package/docs/design-system/components/hover-card.md +61 -0
  44. package/docs/design-system/components/icons.md +48 -0
  45. package/docs/design-system/components/input-group.md +73 -0
  46. package/docs/design-system/components/input-otp.md +73 -0
  47. package/docs/design-system/components/input.md +84 -0
  48. package/docs/design-system/components/item.md +72 -0
  49. package/docs/design-system/components/kbd.md +62 -0
  50. package/docs/design-system/components/label.md +64 -0
  51. package/docs/design-system/components/menu.md +76 -0
  52. package/docs/design-system/components/menubar.md +60 -0
  53. package/docs/design-system/components/modal.md +119 -0
  54. package/docs/design-system/components/native-select.md +70 -0
  55. package/docs/design-system/components/navigation-menu.md +63 -0
  56. package/docs/design-system/components/onboarding-step-list-item.md +94 -0
  57. package/docs/design-system/components/page-header.md +98 -0
  58. package/docs/design-system/components/pagination.md +71 -0
  59. package/docs/design-system/components/popover.md +77 -0
  60. package/docs/design-system/components/progress-slider.md +66 -0
  61. package/docs/design-system/components/progress.md +92 -0
  62. package/docs/design-system/components/radio-card.md +65 -0
  63. package/docs/design-system/components/radio-group.md +72 -0
  64. package/docs/design-system/components/resizable.md +57 -0
  65. package/docs/design-system/components/scroll-area.md +60 -0
  66. package/docs/design-system/components/segmented-control.md +71 -0
  67. package/docs/design-system/components/select.md +87 -0
  68. package/docs/design-system/components/sheet.md +82 -0
  69. package/docs/design-system/components/sidebar.md +83 -0
  70. package/docs/design-system/components/skeleton.md +91 -0
  71. package/docs/design-system/components/slideout.md +77 -0
  72. package/docs/design-system/components/slider.md +81 -0
  73. package/docs/design-system/components/social-button.md +65 -0
  74. package/docs/design-system/components/spinner.md +77 -0
  75. package/docs/design-system/components/steps.md +77 -0
  76. package/docs/design-system/components/table.md +411 -0
  77. package/docs/design-system/components/tabs.md +69 -0
  78. package/docs/design-system/components/tag.md +95 -0
  79. package/docs/design-system/components/textarea.md +64 -0
  80. package/docs/design-system/components/timeline.md +95 -0
  81. package/docs/design-system/components/toast.md +73 -0
  82. package/docs/design-system/components/toggle.md +96 -0
  83. package/docs/design-system/components/toolbar.md +105 -0
  84. package/docs/design-system/components/tooltip.md +107 -0
  85. package/docs/design-system/components/typography.md +18 -0
  86. package/docs/design-system/density-and-elevation.md +44 -0
  87. package/docs/design-system/design-system-test-missing-items.md +368 -0
  88. package/docs/design-system/direction-and-localization.md +23 -0
  89. package/docs/design-system/form-recipes.md +73 -0
  90. package/docs/design-system/gap-promotion-policy.md +21 -0
  91. package/docs/design-system/gap-promotion-report.md +166 -0
  92. package/docs/design-system/icons.md +69 -0
  93. package/docs/design-system/installation.md +68 -0
  94. package/docs/design-system/launch-comparison-shadcn.md +98 -0
  95. package/docs/design-system/registry-and-cli.md +64 -0
  96. package/docs/design-system/release-policy.md +30 -0
  97. package/docs/design-system/roadmap.md +14 -0
  98. package/docs/design-system/support-matrix.md +23 -0
  99. package/docs/design-system/tabs.md +53 -0
  100. package/docs/design-system/token-governance.md +60 -0
  101. package/package.json +97 -65
  102. package/registry/component-contract.json +40 -0
  103. package/registry/components/alert-dialog.tsx +297 -0
  104. package/registry/components/alert.tsx +86 -65
  105. package/registry/components/aspect-ratio.tsx +30 -0
  106. package/registry/components/autocomplete.tsx +23 -9
  107. package/registry/components/avatar.tsx +7 -7
  108. package/registry/components/badge.tsx +1 -1
  109. package/registry/components/button-group.tsx +321 -4
  110. package/registry/components/button.tsx +38 -17
  111. package/registry/components/card.tsx +68 -59
  112. package/registry/components/carousel.tsx +282 -0
  113. package/registry/components/chart.tsx +203 -0
  114. package/registry/components/checkbox.tsx +3 -3
  115. package/registry/components/collapsible.tsx +69 -0
  116. package/registry/components/command.tsx +174 -0
  117. package/registry/components/context-menu.tsx +236 -0
  118. package/registry/components/date-picker.tsx +246 -105
  119. package/registry/components/expanded/ActivityFeed.tsx +6 -15
  120. package/registry/components/expanded/Banner.tsx +3 -3
  121. package/registry/components/expanded/Breadcrumbs.tsx +5 -5
  122. package/registry/components/expanded/CatalogComponentsShowcase.tsx +13 -13
  123. package/registry/components/expanded/CatalogDivider.tsx +1 -1
  124. package/registry/components/expanded/EmptyState.tsx +1 -1
  125. package/registry/components/expanded/FileUpload.tsx +9 -2
  126. package/registry/components/expanded/OnboardingStepListItem.tsx +2 -4
  127. package/registry/components/expanded/PageHeader.tsx +14 -14
  128. package/registry/components/expanded/Slideout.tsx +15 -415
  129. package/registry/components/expanded/Steps.tsx +4 -4
  130. package/registry/components/expanded/Table.tsx +116 -69
  131. package/registry/components/expanded/Timeline.tsx +3 -3
  132. package/registry/components/expanded/activityFeed.css +1 -1
  133. package/registry/components/expanded/breadcrumbs.css +139 -139
  134. package/registry/components/expanded/catalogComponentsShowcase.css +83 -83
  135. package/registry/components/expanded/divider.css +1 -1
  136. package/registry/components/expanded/emptyState.css +1 -1
  137. package/registry/components/expanded/fileUpload.css +6 -6
  138. package/registry/components/expanded/slideout.css +9 -685
  139. package/registry/components/expanded/steps.css +274 -274
  140. package/registry/components/expanded/table.css +2 -2
  141. package/registry/components/expanded/timeline.css +264 -264
  142. package/registry/components/field.tsx +230 -0
  143. package/registry/components/hover-card.tsx +48 -0
  144. package/registry/components/input-content.ts +1 -0
  145. package/registry/components/input-group.tsx +130 -0
  146. package/registry/components/input-otp.tsx +13 -3
  147. package/registry/components/input.tsx +70 -45
  148. package/registry/components/item.tsx +189 -0
  149. package/registry/components/kbd.tsx +151 -0
  150. package/registry/components/label.tsx +78 -0
  151. package/registry/components/menu.tsx +34 -246
  152. package/registry/components/menubar.tsx +226 -0
  153. package/registry/components/modal.tsx +216 -143
  154. package/registry/components/native-select.tsx +205 -0
  155. package/registry/components/navigation-menu.tsx +171 -0
  156. package/registry/components/pagination.tsx +80 -58
  157. package/registry/components/popover.tsx +162 -664
  158. package/registry/components/radio-card.tsx +116 -87
  159. package/registry/components/radio-group.tsx +1 -1
  160. package/registry/components/resizable.tsx +74 -0
  161. package/registry/components/scroll-area.tsx +67 -0
  162. package/registry/components/segmented-control.tsx +87 -0
  163. package/registry/components/select-content.tsx +2 -2
  164. package/registry/components/select.tsx +54 -20
  165. package/registry/components/sheet.tsx +305 -0
  166. package/registry/components/sidebar.tsx +352 -0
  167. package/registry/components/skeleton.css +0 -3
  168. package/registry/components/social-button.tsx +116 -30
  169. package/registry/components/spinner.tsx +18 -55
  170. package/registry/components/{expanded/tabs.css → tabs.css} +127 -106
  171. package/registry/components/tabs.tsx +246 -0
  172. package/registry/components/tag.tsx +2 -2
  173. package/registry/components/textarea.tsx +4 -4
  174. package/registry/components/toast.tsx +136 -0
  175. package/registry/components/toggle.tsx +2 -2
  176. package/registry/components/toolbar.tsx +89 -17
  177. package/registry/components/tooltip.tsx +1 -1
  178. package/registry/examples/alert-demo.tsx +25 -5
  179. package/registry/examples/alert-dialog-demo.tsx +42 -0
  180. package/registry/examples/aspect-ratio-demo.tsx +11 -0
  181. package/registry/examples/attribute-demo.tsx +1 -1
  182. package/registry/examples/autocomplete-demo.tsx +3 -3
  183. package/registry/examples/avatar-demo.tsx +7 -7
  184. package/registry/examples/badge-demo.tsx +1 -1
  185. package/registry/examples/button-demo.tsx +6 -6
  186. package/registry/examples/button-group-demo.tsx +23 -2
  187. package/registry/examples/card-demo.tsx +46 -8
  188. package/registry/examples/carousel-demo.tsx +43 -0
  189. package/registry/examples/chart-demo.tsx +33 -0
  190. package/registry/examples/checkbox-demo.tsx +5 -5
  191. package/registry/examples/collapsible-demo.tsx +16 -0
  192. package/registry/examples/collection-filter-bar-demo.tsx +135 -0
  193. package/registry/examples/command-demo.tsx +42 -0
  194. package/registry/examples/{expanded/command-bar-demo.tsx → command-palette-demo.tsx} +5 -15
  195. package/registry/examples/context-menu-demo.tsx +29 -0
  196. package/registry/examples/control-density-contract-demo.tsx +61 -0
  197. package/registry/examples/date-picker-demo.tsx +12 -12
  198. package/registry/examples/divider-demo.tsx +3 -3
  199. package/registry/examples/expanded/banner-demo.tsx +1 -1
  200. package/registry/examples/expanded/breadcrumbs-demo.tsx +1 -1
  201. package/registry/examples/expanded/empty-state-demo.tsx +1 -1
  202. package/registry/examples/expanded/file-upload-demo.tsx +1 -1
  203. package/registry/examples/expanded/onboarding-step-demo.tsx +1 -1
  204. package/registry/examples/expanded/slideout-demo.tsx +2 -2
  205. package/registry/examples/expanded/steps-demo.tsx +1 -1
  206. package/registry/examples/expanded/tabs-demo.tsx +2 -2
  207. package/registry/examples/expanded/timeline-demo.tsx +1 -1
  208. package/registry/examples/field-demo.tsx +51 -0
  209. package/registry/examples/hover-card-demo.tsx +23 -0
  210. package/registry/examples/input-demo.tsx +6 -6
  211. package/registry/examples/input-group-demo.tsx +16 -0
  212. package/registry/examples/input-otp-demo.tsx +4 -4
  213. package/registry/examples/item-demo.tsx +46 -0
  214. package/registry/examples/kbd-demo.tsx +11 -0
  215. package/registry/examples/label-demo.tsx +20 -0
  216. package/registry/examples/menu-demo.tsx +1 -1
  217. package/registry/examples/menubar-demo.tsx +34 -0
  218. package/registry/examples/modal-demo.tsx +67 -9
  219. package/registry/examples/native-select-demo.tsx +16 -0
  220. package/registry/examples/navigation-menu-demo.tsx +29 -0
  221. package/registry/examples/pagination-demo.tsx +6 -3
  222. package/registry/examples/popover-demo.tsx +19 -19
  223. package/registry/examples/progress-demo.tsx +1 -1
  224. package/registry/examples/progress-slider-demo.tsx +1 -1
  225. package/registry/examples/radio-card-demo.tsx +4 -4
  226. package/registry/examples/radio-group-demo.tsx +2 -2
  227. package/registry/examples/resizable-demo.tsx +22 -0
  228. package/registry/examples/results-toolbar-demo.tsx +44 -0
  229. package/registry/examples/scroll-area-demo.tsx +15 -0
  230. package/registry/examples/segmented-control-demo.tsx +39 -0
  231. package/registry/examples/select-demo.tsx +1 -1
  232. package/registry/examples/sheet-demo.tsx +47 -0
  233. package/registry/examples/sidebar-demo.tsx +55 -0
  234. package/registry/examples/slider-demo.tsx +3 -3
  235. package/registry/examples/social-button-demo.tsx +18 -8
  236. package/registry/examples/spinner-demo.tsx +13 -13
  237. package/registry/examples/tabs-demo.tsx +13 -0
  238. package/registry/examples/tag-demo.tsx +1 -1
  239. package/registry/examples/textarea-demo.tsx +4 -4
  240. package/registry/examples/toast-demo.tsx +35 -0
  241. package/registry/examples/toggle-demo.tsx +6 -6
  242. package/registry/examples/tooltip-demo.tsx +4 -4
  243. package/registry/guidance/USAGE.md +27 -0
  244. package/registry/hooks/use-direction.ts +193 -13
  245. package/registry/index.json +6010 -432
  246. package/registry/styles/globals.css +3112 -4690
  247. package/registry.json +1582 -0
  248. package/schema/config.schema.json +51 -0
  249. package/schema/registry.schema.json +190 -0
  250. package/schema/tokens.schema.json +163 -0
  251. package/src/cli/command-line.js +194 -0
  252. package/src/cli/config-editors.js +9 -0
  253. package/src/cli/doctor.js +399 -0
  254. package/src/cli/file-transaction.js +295 -0
  255. package/src/cli/global-css.js +153 -0
  256. package/src/cli/index.js +639 -1391
  257. package/src/cli/install-plan.js +592 -0
  258. package/src/cli/install-receipt.js +171 -0
  259. package/src/cli/jsonc.js +203 -0
  260. package/src/cli/package-install-state.js +254 -0
  261. package/src/cli/package-manager.js +238 -0
  262. package/src/cli/package-plan.js +185 -0
  263. package/src/cli/package-version.js +97 -0
  264. package/src/cli/registry-query.js +207 -0
  265. package/src/cli/reporting.js +55 -0
  266. package/src/cli/schema-validation.js +19 -0
  267. package/src/cli/source-scanner.js +686 -0
  268. package/src/cli/vite-config.js +478 -0
  269. package/tokens/banhaten.tokens.json +4313 -310
  270. package/registry/assets/avatars/avatar-02.jpg +0 -0
  271. package/registry/assets/avatars/avatar-03.jpg +0 -0
  272. package/registry/assets/avatars/avatar-04.jpg +0 -0
  273. package/registry/assets/avatars/avatar-05.jpg +0 -0
  274. package/registry/assets/avatars/avatar-06.jpg +0 -0
  275. package/registry/assets/avatars/avatar-07.jpg +0 -0
  276. package/registry/assets/avatars/avatar-08.jpg +0 -0
  277. package/registry/assets/avatars/avatar-09.jpg +0 -0
  278. package/registry/assets/avatars/avatar-10.jpg +0 -0
  279. package/registry/assets/avatars/avatar-11.jpg +0 -0
  280. package/registry/assets/avatars/avatar-12.jpg +0 -0
  281. package/registry/assets/avatars/avatar-13.jpg +0 -0
  282. package/registry/assets/avatars/avatar-14.jpg +0 -0
  283. package/registry/assets/avatars/avatar-15.jpg +0 -0
  284. package/registry/assets/avatars/avatar-16.jpg +0 -0
  285. package/registry/assets/avatars/avatar-17.jpg +0 -0
  286. package/registry/assets/avatars/avatar-18.jpg +0 -0
  287. package/registry/assets/avatars/avatar-19.jpg +0 -0
  288. package/registry/assets/avatars/avatar-20.jpg +0 -0
  289. package/registry/assets/avatars/avatar-21.jpg +0 -0
  290. package/registry/assets/avatars/avatar-22.jpg +0 -0
  291. package/registry/assets/avatars/avatar-23.jpg +0 -0
  292. package/registry/assets/avatars/avatar-24.jpg +0 -0
  293. package/registry/assets/avatars/avatar-25.jpg +0 -0
  294. package/registry/assets/avatars/avatar-26.jpg +0 -0
  295. package/registry/assets/avatars/avatar-27.jpg +0 -0
  296. package/registry/assets/avatars/avatar-28.jpg +0 -0
  297. package/registry/assets/avatars/avatar-29.jpg +0 -0
  298. package/registry/assets/avatars/avatar-30.jpg +0 -0
  299. package/registry/assets/avatars/avatar-31.jpg +0 -0
  300. package/registry/assets/avatars/avatar-32.jpg +0 -0
  301. package/registry/assets/avatars/avatar-33.jpg +0 -0
  302. package/registry/assets/avatars/avatar-34.jpg +0 -0
  303. package/registry/assets/avatars/avatar-35.jpg +0 -0
  304. package/registry/assets/image-assets.json +0 -744
  305. package/registry/assets/images/art-02.jpg +0 -0
  306. package/registry/assets/images/art-03.jpg +0 -0
  307. package/registry/assets/images/art-04.jpg +0 -0
  308. package/registry/assets/images/art-05.jpg +0 -0
  309. package/registry/assets/images/art-06.jpg +0 -0
  310. package/registry/assets/images/art-07.jpg +0 -0
  311. package/registry/assets/images/art-08.jpg +0 -0
  312. package/registry/assets/images/art-09.jpg +0 -0
  313. package/registry/assets/images/art-10.jpg +0 -0
  314. package/registry/assets/images/art-11.jpg +0 -0
  315. package/registry/assets/images/art-12.jpg +0 -0
  316. package/registry/assets/images/art-13.jpg +0 -0
  317. package/registry/assets/images/art-14.jpg +0 -0
  318. package/registry/assets/images/art-15.jpg +0 -0
  319. package/registry/assets/images/art-16.jpg +0 -0
  320. package/registry/assets/images/art-17.jpg +0 -0
  321. package/registry/assets/images/art-18.jpg +0 -0
  322. package/registry/assets/images/art-19.jpg +0 -0
  323. package/registry/assets/images/art-20.jpg +0 -0
  324. package/registry/assets/images/art-21.jpg +0 -0
  325. package/registry/assets/images/art-22.jpg +0 -0
  326. package/registry/assets/images/art-23.jpg +0 -0
  327. package/registry/assets/images/art-24.jpg +0 -0
  328. package/registry/assets/images/art-25.jpg +0 -0
  329. package/registry/assets/images/art-26.jpg +0 -0
  330. package/registry/assets/images/art-27.jpg +0 -0
  331. package/registry/assets/images/nature-01.jpg +0 -0
  332. package/registry/assets/images/nature-02.jpg +0 -0
  333. package/registry/assets/images/nature-03.jpg +0 -0
  334. package/registry/assets/images/nature-04.jpg +0 -0
  335. package/registry/assets/images/nature-05.jpg +0 -0
  336. package/registry/assets/images/nature-06.jpg +0 -0
  337. package/registry/assets/images/nature-07.jpg +0 -0
  338. package/registry/assets/images/nature-08.jpg +0 -0
  339. package/registry/assets/images/nature-09.jpg +0 -0
  340. package/registry/assets/images/nature-10.jpg +0 -0
  341. package/registry/assets/images/nature-11.jpg +0 -0
  342. package/registry/assets/images/nature-12.jpg +0 -0
  343. package/registry/assets/images/nature-13.jpg +0 -0
  344. package/registry/assets/images/nature-14.jpg +0 -0
  345. package/registry/assets/images/nature-15.jpg +0 -0
  346. package/registry/assets/images/nature-16.jpg +0 -0
  347. package/registry/assets/images/nature-17.jpg +0 -0
  348. package/registry/assets/images/nature-18.jpg +0 -0
  349. package/registry/assets/images/nature-19.jpg +0 -0
  350. package/registry/assets/images/nature-20.jpg +0 -0
  351. package/registry/components/expanded/BannerBoard.tsx +0 -225
  352. package/registry/components/expanded/CatalogTag.tsx +0 -85
  353. package/registry/components/expanded/CommandBar.tsx +0 -386
  354. package/registry/components/expanded/IconExplorer.tsx +0 -612
  355. package/registry/components/expanded/Tabs.tsx +0 -86
  356. package/registry/components/expanded/TimelineShowcase.tsx +0 -158
  357. package/registry/components/expanded/commandBar.css +0 -470
  358. package/registry/components/expanded/iconExplorer.css +0 -764
  359. package/registry/components/expanded/iconPacks.ts +0 -866
  360. package/registry/components/expanded/tag.css +0 -148
  361. package/registry/examples/expanded/icons-demo.tsx +0 -5
  362. package/tokens/Color mode.zip +0 -0
  363. package/tokens/Numbers.zip +0 -0
  364. package/tokens/Radius.zip +0 -0
  365. package/tokens/Theme.zip +0 -0
@@ -11,6 +11,7 @@ import {
11
11
  import { cva } from "class-variance-authority"
12
12
 
13
13
  import { cn } from "@/lib/utils"
14
+ import { Popover, PopoverContent, PopoverTrigger } from "./popover"
14
15
  import {
15
16
  addMonths,
16
17
  formatCalendarDate,
@@ -34,6 +35,8 @@ import type {
34
35
  RangeCalendarType,
35
36
  } from "./date-picker-state"
36
37
 
38
+ type ControlDensity = "compact" | "default" | "comfortable"
39
+
37
40
  type CalendarTimeValue = {
38
41
  hours?: string
39
42
  minutes?: string
@@ -45,6 +48,7 @@ type CalendarMonthYearItem = {
45
48
  id?: string
46
49
  month: React.ReactNode
47
50
  year: React.ReactNode
51
+ value?: Date
48
52
  selected?: boolean
49
53
  disabled?: boolean
50
54
  }
@@ -111,6 +115,7 @@ type DatePickerProps = Omit<
111
115
  >
112
116
  defaultOpen?: boolean
113
117
  defaultValue?: Date
118
+ density?: ControlDensity
114
119
  dir?: DatePickerDirection
115
120
  disabled?: boolean
116
121
  icon?: React.ReactNode
@@ -119,6 +124,10 @@ type DatePickerProps = Omit<
119
124
  open?: boolean
120
125
  placeholder?: React.ReactNode
121
126
  triggerClassName?: string
127
+ triggerProps?: Omit<
128
+ DatePickerTriggerProps,
129
+ "density" | "icon" | "open" | "placeholder" | "value"
130
+ >
122
131
  value?: Date
123
132
  }
124
133
 
@@ -132,6 +141,7 @@ type DateRangePickerProps = Omit<
132
141
  >
133
142
  defaultOpen?: boolean
134
143
  defaultValue?: CalendarRange
144
+ density?: ControlDensity
135
145
  dir?: DatePickerDirection
136
146
  disabled?: boolean
137
147
  icon?: React.ReactNode
@@ -140,43 +150,16 @@ type DateRangePickerProps = Omit<
140
150
  open?: boolean
141
151
  placeholder?: React.ReactNode
142
152
  triggerClassName?: string
153
+ triggerProps?: Omit<
154
+ DatePickerTriggerProps,
155
+ "density" | "icon" | "open" | "placeholder" | "value"
156
+ >
143
157
  type?: RangeCalendarType
144
158
  value?: CalendarRange
145
159
  }
146
160
 
147
- const defaultDisplayMonth = new Date(2050, 6, 1)
148
- const defaultSelectedDate = new Date(2050, 6, 18)
149
- const defaultRange: CalendarRange = {
150
- from: new Date(2050, 6, 15),
151
- to: new Date(2050, 7, 23),
152
- }
153
- const defaultTimeValue: Required<CalendarTimeValue> = {
154
- hours: "05",
155
- minutes: "21",
156
- period: "AM",
157
- zone: "GTM-3",
158
- }
161
+ const defaultTimeValue = getCurrentTimeValue()
159
162
  const defaultDayLabels = ["S", "M", "T", "W", "T", "F", "S"]
160
- const defaultMonthYearItems: CalendarMonthYearItem[] = [
161
- { month: "April", year: "2023" },
162
- { month: "May", year: "2022" },
163
- { month: "June", year: "2023" },
164
- { month: "July", year: "2024", selected: true },
165
- { month: "August", year: "2025" },
166
- { month: "September", year: "2026" },
167
- { month: "October", year: "2027" },
168
- ]
169
- const defaultPresets: CalendarPreset[] = [
170
- { label: "Today" },
171
- { label: "Last 7 days" },
172
- { label: "Last 14 days" },
173
- { label: "Last 30 days" },
174
- { label: "Last 3 months" },
175
- { label: "Last 12 months" },
176
- { label: "Quarter to date" },
177
- { label: "Year to date" },
178
- { label: "All time" },
179
- ]
180
163
 
181
164
  const calendarSurface = cva(
182
165
  [
@@ -206,21 +189,33 @@ const calendarSurface = cva(
206
189
 
207
190
  const pickerTrigger = cva(
208
191
  [
209
- "group/date-trigger relative flex h-[var(--bh-date-trigger-height)] w-[var(--bh-date-trigger-width)] max-w-full items-center gap-[var(--bh-space-md-8)] rounded-[var(--bh-radius-lg-8)]",
210
- "bg-[var(--bh-interactive-input-default)] px-[var(--bh-space-lg-10)] text-start outline-none",
192
+ "group/date-trigger relative flex w-[var(--bh-date-trigger-width)] max-w-full items-center gap-[var(--bh-space-md-8)] rounded-[var(--bh-radius-lg-8)]",
193
+ "bg-[var(--bh-interactive-input-default)] text-start outline-none",
211
194
  "[--bh-date-trigger-border:var(--bh-border-input)] [--bh-date-trigger-shadow:inset_0px_0px_0px_var(--bh-border-width-default)_var(--bh-date-trigger-border),var(--shadow-component-default)]",
212
195
  "text-[length:var(--bh-text-body-md-regular-font-size)] font-[var(--bh-text-body-md-regular-font-weight)] leading-[var(--bh-text-body-md-regular-line-height)] tracking-[var(--bh-text-body-md-regular-letter-spacing)]",
213
196
  "text-[var(--bh-content-default)] shadow-[var(--bh-date-trigger-shadow)] transition-[background-color,box-shadow]",
214
197
  "hover:bg-[var(--bh-bg-default-hover)] focus-visible:shadow-[var(--shadow-input-focus-ring)]",
215
198
  "disabled:pointer-events-none disabled:bg-[var(--bh-interactive-input-disabled)] disabled:text-[var(--bh-content-disabled)] disabled:shadow-[inset_0px_0px_0px_var(--bh-border-width-default)_var(--bh-border-disabled)]",
216
- ]
199
+ ],
200
+ {
201
+ variants: {
202
+ density: {
203
+ compact: "h-[var(--bh-button-xs-height)] px-[var(--bh-space-md-8)]",
204
+ default: "h-[var(--bh-button-sm-height)] px-[var(--bh-space-lg-10)]",
205
+ comfortable: "h-[var(--bh-date-trigger-height)] px-[var(--bh-space-xl-12)]",
206
+ },
207
+ },
208
+ defaultVariants: {
209
+ density: "comfortable",
210
+ },
211
+ }
217
212
  )
218
213
 
219
214
  const monthButton = cva(
220
215
  [
221
216
  "flex size-[var(--bh-date-nav-button-size)] shrink-0 items-center justify-center rounded-[var(--bh-control-default)]",
222
217
  "bg-[var(--bh-interactive-soft-default)] text-[var(--bh-content-default)] outline-none transition-[background-color,box-shadow,color]",
223
- "hover:bg-[var(--bh-interactive-soft-hover)] focus-visible:shadow-[var(--shadow-button-focus)] disabled:opacity-0",
218
+ "hover:bg-[var(--bh-interactive-soft-hover)] focus-visible:shadow-[var(--shadow-button-focus)] disabled:opacity-[var(--bh-opacity-0)]",
224
219
  "[&_svg]:size-[var(--bh-date-nav-icon-size)]",
225
220
  ]
226
221
  )
@@ -288,18 +283,18 @@ const dateListItem = cva(
288
283
 
289
284
  function Calendar({
290
285
  className,
291
- defaultValue = defaultSelectedDate,
286
+ defaultValue,
292
287
  dir,
293
288
  displayMonth,
294
289
  events,
295
- monthYearItems = defaultMonthYearItems,
290
+ monthYearItems,
296
291
  nextLabel = "Next month",
297
292
  onDisplayMonthChange,
298
293
  onSelect,
299
294
  onViewChange,
300
295
  previousLabel = "Previous month",
301
296
  selectedDate,
302
- showTime = true,
297
+ showTime = false,
303
298
  surfaceSize = "calendar",
304
299
  timeLabel = "Time",
305
300
  timeValue = defaultTimeValue,
@@ -310,14 +305,16 @@ function Calendar({
310
305
  }: CalendarProps) {
311
306
  const controlledValue = value ?? selectedDate
312
307
  const [internalValue, setInternalValue] = React.useState(defaultValue)
313
- const [internalDisplayMonth, setInternalDisplayMonth] = React.useState(
314
- startOfMonth(displayMonth ?? controlledValue ?? defaultValue)
308
+ const [internalDisplayMonth, setInternalDisplayMonth] = React.useState(() =>
309
+ startOfMonth(displayMonth ?? controlledValue ?? defaultValue ?? new Date())
315
310
  )
316
311
  const [internalView, setInternalView] = React.useState<CalendarView>("days")
317
312
  const selected = controlledValue ?? internalValue
318
313
  const activeDisplayMonth = startOfMonth(displayMonth ?? internalDisplayMonth)
319
314
  const activeView = view ?? internalView
320
- const eventDates = events ?? [new Date(2050, 6, 15)]
315
+ const eventDates = events ?? []
316
+ const resolvedMonthYearItems =
317
+ monthYearItems ?? createMonthYearItems(activeDisplayMonth)
321
318
 
322
319
  function updateDisplayMonth(nextMonth: Date) {
323
320
  const normalized = startOfMonth(nextMonth)
@@ -372,7 +369,14 @@ function Calendar({
372
369
  {activeView === "month-year" ? (
373
370
  <>
374
371
  <div aria-hidden="true" className="h-[var(--bh-date-month-year-spacer-height)] w-full" />
375
- <MonthYearList items={monthYearItems} />
372
+ <MonthYearList
373
+ items={resolvedMonthYearItems}
374
+ onSelect={(item) => {
375
+ if (!item.value) return
376
+ updateDisplayMonth(item.value)
377
+ updateView("days")
378
+ }}
379
+ />
376
380
  </>
377
381
  ) : null}
378
382
  </div>
@@ -381,17 +385,17 @@ function Calendar({
381
385
 
382
386
  function RangeCalendar({
383
387
  className,
384
- defaultValue = defaultRange,
388
+ defaultValue = {},
385
389
  dir,
386
390
  displayMonth,
387
391
  nextLabel = "Next month",
388
392
  onDisplayMonthChange,
389
393
  onPresetSelect,
390
394
  onSelect,
391
- presets = defaultPresets,
395
+ presets,
392
396
  previousLabel = "Previous month",
393
397
  showPresets,
394
- showTime = true,
398
+ showTime = false,
395
399
  timeLabel = "Time",
396
400
  timeValue = defaultTimeValue,
397
401
  type = "double",
@@ -399,13 +403,15 @@ function RangeCalendar({
399
403
  ...props
400
404
  }: RangeCalendarProps) {
401
405
  const [internalRange, setInternalRange] = React.useState(defaultValue)
402
- const [internalDisplayMonth, setInternalDisplayMonth] = React.useState(
403
- startOfMonth(displayMonth ?? defaultValue.from ?? defaultDisplayMonth)
406
+ const [internalDisplayMonth, setInternalDisplayMonth] = React.useState(() =>
407
+ startOfMonth(displayMonth ?? defaultValue.from ?? new Date())
404
408
  )
409
+ const [presetReferenceDate] = React.useState(() => startOfDay(new Date()))
405
410
  const selectedRange = normalizeRange(value ?? internalRange)
406
411
  const activeDisplayMonth = startOfMonth(displayMonth ?? internalDisplayMonth)
407
412
  const monthsToRender = type === "single" ? 1 : 2
408
413
  const shouldShowPresets = showPresets ?? type === "double-with-presets"
414
+ const presetItems = presets ?? createDefaultPresets(presetReferenceDate)
409
415
  const monthNodes = Array.from({ length: monthsToRender }, (_, index) =>
410
416
  addMonths(activeDisplayMonth, index)
411
417
  )
@@ -451,12 +457,17 @@ function RangeCalendar({
451
457
  data-slot="range-calendar-presets"
452
458
  className="grid w-[var(--bh-date-presets-width)] shrink-0 border-e border-[var(--bh-border-subtle)] pe-[var(--bh-space-md-8)]"
453
459
  >
454
- {presets.map((preset, index) => (
460
+ {presetItems.map((preset, index) => {
461
+ const disabled =
462
+ Boolean(preset.disabled) ||
463
+ (!preset.range && onPresetSelect === undefined)
464
+
465
+ return (
455
466
  <button
456
- aria-disabled={preset.disabled || undefined}
467
+ aria-disabled={disabled || undefined}
457
468
  className={dateListItem()}
458
469
  data-slot="range-calendar-preset"
459
- disabled={preset.disabled}
470
+ disabled={disabled}
460
471
  key={preset.id || index}
461
472
  type="button"
462
473
  onClick={() => selectPreset(preset)}
@@ -465,7 +476,8 @@ function RangeCalendar({
465
476
  {preset.label}
466
477
  </span>
467
478
  </button>
468
- ))}
479
+ )
480
+ })}
469
481
  </div>
470
482
  ) : null}
471
483
 
@@ -501,6 +513,7 @@ function DatePicker({
501
513
  className,
502
514
  defaultOpen = false,
503
515
  defaultValue,
516
+ density,
504
517
  dir,
505
518
  disabled,
506
519
  icon,
@@ -509,13 +522,14 @@ function DatePicker({
509
522
  open,
510
523
  placeholder = "Select date",
511
524
  triggerClassName,
525
+ triggerProps,
512
526
  value,
513
527
  ...props
514
528
  }: DatePickerProps) {
515
529
  const [internalOpen, setInternalOpen] = React.useState(defaultOpen)
516
530
  const [internalValue, setInternalValue] = React.useState(defaultValue)
517
531
  const [internalDisplayMonth, setInternalDisplayMonth] = React.useState(() =>
518
- startOfMonth(value ?? defaultValue ?? defaultDisplayMonth)
532
+ startOfMonth(value ?? defaultValue ?? new Date())
519
533
  )
520
534
  const selected = value ?? internalValue
521
535
  const isOpen = open ?? internalOpen
@@ -550,34 +564,41 @@ function DatePicker({
550
564
  }
551
565
 
552
566
  return (
553
- <div
567
+ <Popover
568
+ open={isOpen}
569
+ onOpenChange={updateOpen}
554
570
  data-open={isOpen ? "true" : "false"}
555
571
  data-slot="date-picker"
556
572
  dir={dir}
557
573
  className={cn("relative w-[var(--bh-date-picker-width)] max-w-full", className)}
558
574
  {...props}
559
575
  >
560
- <DatePickerTrigger
561
- disabled={disabled}
562
- icon={icon}
563
- open={isOpen}
564
- placeholder={placeholder}
565
- value={selected ? formatCalendarDate(selected, { month: "long" }) : undefined}
566
- className={triggerClassName}
567
- onClick={() => updateOpen(!isOpen)}
568
- />
576
+ <PopoverTrigger asChild>
577
+ <DatePickerTrigger
578
+ {...triggerProps}
579
+ disabled={disabled ?? triggerProps?.disabled}
580
+ density={density}
581
+ icon={icon}
582
+ open={isOpen}
583
+ placeholder={placeholder}
584
+ value={selected ? formatCalendarDate(selected, { month: "long" }) : undefined}
585
+ className={cn(triggerClassName, triggerProps?.className)}
586
+ />
587
+ </PopoverTrigger>
569
588
 
570
- {isOpen ? (
589
+ <PopoverContent
590
+ align="center"
591
+ showArrow={false}
592
+ size="auto"
593
+ className="w-auto bg-transparent p-0 shadow-none"
594
+ >
571
595
  <Calendar
572
596
  {...calendarProps}
573
- defaultValue={defaultValue ?? defaultSelectedDate}
597
+ defaultValue={defaultValue}
574
598
  displayMonth={calendarProps?.displayMonth ?? internalDisplayMonth}
575
599
  selectedDate={selected}
576
600
  surfaceSize="picker"
577
- className={cn(
578
- "absolute left-1/2 top-[calc(100%+var(--bh-space-md-8))] z-[var(--bh-z-popover)] -translate-x-1/2",
579
- calendarProps?.className
580
- )}
601
+ className={calendarProps?.className}
581
602
  dir={calendarProps?.dir ?? dir}
582
603
  onDisplayMonthChange={updateDisplayMonth}
583
604
  onSelect={(nextDate) => {
@@ -585,8 +606,8 @@ function DatePicker({
585
606
  calendarProps?.onSelect?.(nextDate)
586
607
  }}
587
608
  />
588
- ) : null}
589
- </div>
609
+ </PopoverContent>
610
+ </Popover>
590
611
  )
591
612
  }
592
613
 
@@ -595,6 +616,7 @@ function DateRangePicker({
595
616
  className,
596
617
  defaultOpen = false,
597
618
  defaultValue,
619
+ density,
598
620
  dir,
599
621
  disabled,
600
622
  icon,
@@ -603,6 +625,7 @@ function DateRangePicker({
603
625
  open,
604
626
  placeholder = "Select date range",
605
627
  triggerClassName,
628
+ triggerProps,
606
629
  type = "double",
607
630
  value,
608
631
  ...props
@@ -612,7 +635,7 @@ function DateRangePicker({
612
635
  const selectedRange = normalizeRange(value ?? internalValue ?? {})
613
636
  const isOpen = open ?? internalOpen
614
637
  const [internalDisplayMonth, setInternalDisplayMonth] = React.useState(() =>
615
- startOfMonth(selectedRange.from ?? defaultValue?.from ?? defaultDisplayMonth)
638
+ startOfMonth(selectedRange.from ?? defaultValue?.from ?? new Date())
616
639
  )
617
640
  const selectedRangeFromTime = selectedRange.from?.getTime()
618
641
 
@@ -645,7 +668,9 @@ function DateRangePicker({
645
668
  }
646
669
 
647
670
  return (
648
- <div
671
+ <Popover
672
+ open={isOpen}
673
+ onOpenChange={updateOpen}
649
674
  data-open={isOpen ? "true" : "false"}
650
675
  data-slot="date-range-picker"
651
676
  data-type={type}
@@ -653,27 +678,32 @@ function DateRangePicker({
653
678
  className={cn("relative w-[var(--bh-date-picker-width)] max-w-full", className)}
654
679
  {...props}
655
680
  >
656
- <DatePickerTrigger
657
- disabled={disabled}
658
- icon={icon}
659
- open={isOpen}
660
- placeholder={placeholder}
661
- value={formatCalendarRange(selectedRange)}
662
- className={triggerClassName}
663
- onClick={() => updateOpen(!isOpen)}
664
- />
681
+ <PopoverTrigger asChild>
682
+ <DatePickerTrigger
683
+ {...triggerProps}
684
+ disabled={disabled ?? triggerProps?.disabled}
685
+ density={density}
686
+ icon={icon}
687
+ open={isOpen}
688
+ placeholder={placeholder}
689
+ value={formatCalendarRange(selectedRange)}
690
+ className={cn(triggerClassName, triggerProps?.className)}
691
+ />
692
+ </PopoverTrigger>
665
693
 
666
- {isOpen ? (
694
+ <PopoverContent
695
+ align="center"
696
+ showArrow={false}
697
+ size="auto"
698
+ className="w-auto bg-transparent p-0 shadow-none"
699
+ >
667
700
  <RangeCalendar
668
701
  {...calendarProps}
669
- defaultValue={defaultValue ?? defaultRange}
702
+ defaultValue={defaultValue ?? {}}
670
703
  displayMonth={calendarProps?.displayMonth ?? internalDisplayMonth}
671
704
  type={type}
672
705
  value={selectedRange}
673
- className={cn(
674
- "absolute left-1/2 top-[calc(100%+var(--bh-space-md-8))] z-[var(--bh-z-popover)] -translate-x-1/2",
675
- calendarProps?.className
676
- )}
706
+ className={calendarProps?.className}
677
707
  dir={calendarProps?.dir ?? dir}
678
708
  onDisplayMonthChange={updateDisplayMonth}
679
709
  onSelect={(nextRange) => {
@@ -681,45 +711,54 @@ function DateRangePicker({
681
711
  calendarProps?.onSelect?.(nextRange)
682
712
  }}
683
713
  />
684
- ) : null}
685
- </div>
714
+ </PopoverContent>
715
+ </Popover>
686
716
  )
687
717
  }
688
718
 
719
+ type DatePickerTriggerProps = Omit<
720
+ React.ComponentProps<"button">,
721
+ "children" | "value"
722
+ > & {
723
+ density?: ControlDensity
724
+ icon?: React.ReactNode
725
+ open?: boolean
726
+ placeholder: React.ReactNode
727
+ value?: React.ReactNode
728
+ }
729
+
689
730
  function DatePickerTrigger({
690
731
  className,
732
+ density,
691
733
  disabled,
692
734
  icon,
693
735
  onClick,
694
736
  open,
695
737
  placeholder,
738
+ type = "button",
696
739
  value,
697
- }: {
698
- className?: string
699
- disabled?: boolean
700
- icon?: React.ReactNode
701
- onClick?: React.MouseEventHandler<HTMLButtonElement>
702
- open?: boolean
703
- placeholder: React.ReactNode
704
- value?: React.ReactNode
705
- }) {
740
+ ...props
741
+ }: DatePickerTriggerProps) {
706
742
  const hasValue = hasRenderableContent(value)
707
743
 
708
744
  return (
709
745
  <button
710
746
  aria-expanded={open || undefined}
747
+ data-date-picker-trigger=""
748
+ data-density={density ?? "comfortable"}
711
749
  data-slot="date-picker-trigger"
712
750
  disabled={disabled}
713
- type="button"
714
- className={cn(pickerTrigger(), className)}
751
+ type={type}
752
+ className={cn(pickerTrigger({ density }), className)}
715
753
  onClick={onClick}
754
+ {...props}
716
755
  >
717
756
  <span
718
757
  aria-hidden="true"
719
758
  data-slot="date-picker-trigger-icon"
720
759
  className="flex size-[var(--bh-date-trigger-icon-size)] shrink-0 items-center justify-center text-[var(--bh-content-muted)] group-disabled/date-trigger:text-[var(--bh-content-disabled)] [&_svg:not([class*='size-'])]:size-[var(--bh-date-trigger-icon-size)]"
721
760
  >
722
- {icon ?? <CalendarDaysIcon strokeWidth={1.8} />}
761
+ {icon ?? <CalendarDaysIcon strokeWidth="var(--bh-icon-stroke-180)" />}
723
762
  </span>
724
763
  <span
725
764
  data-slot="date-picker-trigger-value"
@@ -1003,7 +1042,7 @@ function CalendarTime({
1003
1042
  {label}
1004
1043
  </span>
1005
1044
  <span
1006
- data-slot="calendar-time-input"
1045
+ data-slot="calendar-time-value"
1007
1046
  className="flex min-h-[var(--bh-date-time-input-min-height)] min-w-0 flex-1 items-center gap-[var(--bh-space-xs-4)] rounded-[var(--bh-radius-lg-8)] bg-[var(--bh-interactive-input-default)] px-[var(--bh-space-md-8)] py-[var(--bh-space-sm-6)] shadow-[var(--shadow-date-time-input)]"
1008
1047
  >
1009
1048
  <CalendarTimeSegment active>{resolved.hours}</CalendarTimeSegment>
@@ -1039,7 +1078,13 @@ function CalendarTimeSegment({
1039
1078
  )
1040
1079
  }
1041
1080
 
1042
- function MonthYearList({ items }: { items: CalendarMonthYearItem[] }) {
1081
+ function MonthYearList({
1082
+ items,
1083
+ onSelect,
1084
+ }: {
1085
+ items: CalendarMonthYearItem[]
1086
+ onSelect: (item: CalendarMonthYearItem) => void
1087
+ }) {
1043
1088
  return (
1044
1089
  <div
1045
1090
  data-slot="calendar-month-year-list"
@@ -1055,8 +1100,9 @@ function MonthYearList({ items }: { items: CalendarMonthYearItem[] }) {
1055
1100
  )}
1056
1101
  data-selected={item.selected ? "true" : undefined}
1057
1102
  data-slot="calendar-month-year-item"
1058
- disabled={item.disabled}
1103
+ disabled={item.disabled || !item.value}
1059
1104
  key={item.id || index}
1105
+ onClick={() => onSelect(item)}
1060
1106
  type="button"
1061
1107
  >
1062
1108
  <span className="truncate">{item.month}</span>
@@ -1067,6 +1113,99 @@ function MonthYearList({ items }: { items: CalendarMonthYearItem[] }) {
1067
1113
  )
1068
1114
  }
1069
1115
 
1116
+ function startOfDay(date: Date) {
1117
+ return new Date(date.getFullYear(), date.getMonth(), date.getDate())
1118
+ }
1119
+
1120
+ function addDays(date: Date, amount: number) {
1121
+ const next = startOfDay(date)
1122
+ next.setDate(next.getDate() + amount)
1123
+ return next
1124
+ }
1125
+
1126
+ function createDefaultPresets(today: Date): CalendarPreset[] {
1127
+ const quarterStartMonth = Math.floor(today.getMonth() / 3) * 3
1128
+
1129
+ return [
1130
+ { id: "today", label: "Today", range: { from: today, to: today } },
1131
+ {
1132
+ id: "last-7-days",
1133
+ label: "Last 7 days",
1134
+ range: { from: addDays(today, -6), to: today },
1135
+ },
1136
+ {
1137
+ id: "last-14-days",
1138
+ label: "Last 14 days",
1139
+ range: { from: addDays(today, -13), to: today },
1140
+ },
1141
+ {
1142
+ id: "last-30-days",
1143
+ label: "Last 30 days",
1144
+ range: { from: addDays(today, -29), to: today },
1145
+ },
1146
+ {
1147
+ id: "last-3-months",
1148
+ label: "Last 3 months",
1149
+ range: { from: addMonths(today, -3), to: today },
1150
+ },
1151
+ {
1152
+ id: "last-12-months",
1153
+ label: "Last 12 months",
1154
+ range: { from: addMonths(today, -12), to: today },
1155
+ },
1156
+ {
1157
+ id: "quarter-to-date",
1158
+ label: "Quarter to date",
1159
+ range: {
1160
+ from: new Date(today.getFullYear(), quarterStartMonth, 1),
1161
+ to: today,
1162
+ },
1163
+ },
1164
+ {
1165
+ id: "year-to-date",
1166
+ label: "Year to date",
1167
+ range: { from: new Date(today.getFullYear(), 0, 1), to: today },
1168
+ },
1169
+ ]
1170
+ }
1171
+
1172
+ function createMonthYearItems(
1173
+ displayMonth: Date
1174
+ ): CalendarMonthYearItem[] {
1175
+ return Array.from({ length: 7 }, (_, index) => {
1176
+ const value = addMonths(displayMonth, index - 3)
1177
+
1178
+ return {
1179
+ id: `${value.getFullYear()}-${value.getMonth()}`,
1180
+ month: new Intl.DateTimeFormat(undefined, { month: "long" }).format(value),
1181
+ selected: index === 3,
1182
+ value,
1183
+ year: String(value.getFullYear()),
1184
+ }
1185
+ })
1186
+ }
1187
+
1188
+ function getCurrentTimeValue(): Required<CalendarTimeValue> {
1189
+ const now = new Date()
1190
+ const timeParts = new Intl.DateTimeFormat("en-US", {
1191
+ hour: "2-digit",
1192
+ hour12: true,
1193
+ minute: "2-digit",
1194
+ }).formatToParts(now)
1195
+ const zoneParts = new Intl.DateTimeFormat("en-US", {
1196
+ timeZoneName: "short",
1197
+ }).formatToParts(now)
1198
+ const getPart = (parts: Intl.DateTimeFormatPart[], type: string) =>
1199
+ parts.find((part) => part.type === type)?.value ?? ""
1200
+
1201
+ return {
1202
+ hours: getPart(timeParts, "hour"),
1203
+ minutes: getPart(timeParts, "minute"),
1204
+ period: getPart(timeParts, "dayPeriod"),
1205
+ zone: getPart(zoneParts, "timeZoneName") || "UTC",
1206
+ }
1207
+ }
1208
+
1070
1209
  function hasRenderableContent(content: React.ReactNode) {
1071
1210
  return (
1072
1211
  content !== undefined &&
@@ -1094,7 +1233,9 @@ export type {
1094
1233
  CalendarView,
1095
1234
  DatePickerDirection,
1096
1235
  DatePickerProps,
1236
+ DatePickerTriggerProps,
1097
1237
  DateRangePickerProps,
1238
+ ControlDensity,
1098
1239
  RangeCalendarProps,
1099
1240
  RangeCalendarType,
1100
1241
  }