@momentumworld/ui-react 0.17.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 (138) hide show
  1. package/dist/chunk-2HQPCV2L.js +895 -0
  2. package/dist/chunk-2HQPCV2L.js.map +1 -0
  3. package/dist/form.d.ts +175 -0
  4. package/dist/form.js +356 -0
  5. package/dist/form.js.map +1 -0
  6. package/dist/index.d.ts +2162 -0
  7. package/dist/index.js +11640 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/input-JCZs61MO.d.ts +24 -0
  10. package/package.json +90 -0
  11. package/src/components/form/checkbox-group-field.tsx +101 -0
  12. package/src/components/form/date-field.tsx +79 -0
  13. package/src/components/form/date-range-field.tsx +106 -0
  14. package/src/components/form/form-context.ts +10 -0
  15. package/src/components/form/form.tsx +54 -0
  16. package/src/components/form/number-field.tsx +69 -0
  17. package/src/components/form/select-field.tsx +76 -0
  18. package/src/components/form/submit-button.tsx +28 -0
  19. package/src/components/form/text-field.tsx +107 -0
  20. package/src/components/layout/dashboard-header.tsx +54 -0
  21. package/src/components/layout/dashboard-panel.tsx +34 -0
  22. package/src/components/layout/dashboard-topbar.tsx +221 -0
  23. package/src/components/theme-provider.tsx +403 -0
  24. package/src/components/ui/accordion.tsx +69 -0
  25. package/src/components/ui/alert-dialog.tsx +169 -0
  26. package/src/components/ui/alert.tsx +80 -0
  27. package/src/components/ui/animated-counter.tsx +109 -0
  28. package/src/components/ui/animated-theme-toggler.tsx +265 -0
  29. package/src/components/ui/app-store-buttons.tsx +182 -0
  30. package/src/components/ui/aspect-ratio.tsx +23 -0
  31. package/src/components/ui/aurora-orb.tsx +163 -0
  32. package/src/components/ui/aurora-text.tsx +76 -0
  33. package/src/components/ui/autocomplete.tsx +296 -0
  34. package/src/components/ui/avatar-group.tsx +150 -0
  35. package/src/components/ui/avatar.tsx +285 -0
  36. package/src/components/ui/badge-group.tsx +160 -0
  37. package/src/components/ui/badge.tsx +172 -0
  38. package/src/components/ui/breadcrumb.tsx +112 -0
  39. package/src/components/ui/button.tsx +77 -0
  40. package/src/components/ui/calendar.tsx +137 -0
  41. package/src/components/ui/card.tsx +244 -0
  42. package/src/components/ui/carousel.tsx +258 -0
  43. package/src/components/ui/chart.tsx +379 -0
  44. package/src/components/ui/chat-divider.tsx +67 -0
  45. package/src/components/ui/chat.tsx +494 -0
  46. package/src/components/ui/checkbox-group.tsx +16 -0
  47. package/src/components/ui/checkbox.tsx +82 -0
  48. package/src/components/ui/collapsible.tsx +45 -0
  49. package/src/components/ui/color-picker.tsx +389 -0
  50. package/src/components/ui/combobox.tsx +411 -0
  51. package/src/components/ui/command.tsx +264 -0
  52. package/src/components/ui/confetti.tsx +196 -0
  53. package/src/components/ui/context-menu.tsx +271 -0
  54. package/src/components/ui/context-meter.tsx +134 -0
  55. package/src/components/ui/credit-card.tsx +214 -0
  56. package/src/components/ui/data-table-paged.tsx +163 -0
  57. package/src/components/ui/date-picker.tsx +154 -0
  58. package/src/components/ui/dialog.tsx +196 -0
  59. package/src/components/ui/drawer.tsx +135 -0
  60. package/src/components/ui/empty.tsx +127 -0
  61. package/src/components/ui/fab.tsx +45 -0
  62. package/src/components/ui/featured-icon.tsx +149 -0
  63. package/src/components/ui/field.tsx +88 -0
  64. package/src/components/ui/fieldset.tsx +29 -0
  65. package/src/components/ui/form.tsx +17 -0
  66. package/src/components/ui/frame.tsx +82 -0
  67. package/src/components/ui/generic-empty.tsx +142 -0
  68. package/src/components/ui/group.tsx +97 -0
  69. package/src/components/ui/help-tip.tsx +94 -0
  70. package/src/components/ui/horizontal-scroll-fader.tsx +228 -0
  71. package/src/components/ui/input-group.tsx +102 -0
  72. package/src/components/ui/input-otp.tsx +96 -0
  73. package/src/components/ui/input.tsx +66 -0
  74. package/src/components/ui/item.tsx +198 -0
  75. package/src/components/ui/kbd.tsx +30 -0
  76. package/src/components/ui/label.tsx +28 -0
  77. package/src/components/ui/markdown.tsx +188 -0
  78. package/src/components/ui/menu.tsx +312 -0
  79. package/src/components/ui/menubar.tsx +93 -0
  80. package/src/components/ui/meter.tsx +67 -0
  81. package/src/components/ui/multi-select.tsx +308 -0
  82. package/src/components/ui/navigation-menu.tsx +143 -0
  83. package/src/components/ui/number-field.tsx +160 -0
  84. package/src/components/ui/pagination-controls.tsx +74 -0
  85. package/src/components/ui/pagination.tsx +149 -0
  86. package/src/components/ui/pipeline.tsx +102 -0
  87. package/src/components/ui/popover.tsx +119 -0
  88. package/src/components/ui/preview-card.tsx +55 -0
  89. package/src/components/ui/progress.tsx +289 -0
  90. package/src/components/ui/qr-code.tsx +150 -0
  91. package/src/components/ui/radio-group.tsx +103 -0
  92. package/src/components/ui/resizable.tsx +56 -0
  93. package/src/components/ui/scroll-area.tsx +90 -0
  94. package/src/components/ui/scroller.tsx +38 -0
  95. package/src/components/ui/section-header.tsx +118 -0
  96. package/src/components/ui/segmented-control.tsx +83 -0
  97. package/src/components/ui/select.tsx +181 -0
  98. package/src/components/ui/separator.tsx +23 -0
  99. package/src/components/ui/sheet.tsx +224 -0
  100. package/src/components/ui/sidebar.tsx +774 -0
  101. package/src/components/ui/skeleton.tsx +16 -0
  102. package/src/components/ui/slider.tsx +108 -0
  103. package/src/components/ui/smooth-scroll.tsx +206 -0
  104. package/src/components/ui/social-button.tsx +247 -0
  105. package/src/components/ui/spinner-on-demand.tsx +32 -0
  106. package/src/components/ui/spinner.tsx +18 -0
  107. package/src/components/ui/stat.tsx +187 -0
  108. package/src/components/ui/stepper.tsx +167 -0
  109. package/src/components/ui/switch.tsx +56 -0
  110. package/src/components/ui/table.tsx +126 -0
  111. package/src/components/ui/tabs.tsx +90 -0
  112. package/src/components/ui/tag.tsx +242 -0
  113. package/src/components/ui/target-countdown.tsx +46 -0
  114. package/src/components/ui/text-editor.tsx +313 -0
  115. package/src/components/ui/textarea.tsx +51 -0
  116. package/src/components/ui/thinking-orb.tsx +6 -0
  117. package/src/components/ui/time-picker.tsx +308 -0
  118. package/src/components/ui/timeline.tsx +116 -0
  119. package/src/components/ui/toast.tsx +268 -0
  120. package/src/components/ui/toggle-group.tsx +101 -0
  121. package/src/components/ui/toggle.tsx +45 -0
  122. package/src/components/ui/toolbar.tsx +89 -0
  123. package/src/components/ui/tooltip.tsx +102 -0
  124. package/src/components/ui/vertical-scroll-fader.tsx +250 -0
  125. package/src/components/ui/video-player.tsx +275 -0
  126. package/src/components/upload/avatar-upload-base.tsx +131 -0
  127. package/src/components/upload/image-upload-base.tsx +112 -0
  128. package/src/form.ts +17 -0
  129. package/src/index.ts +143 -0
  130. package/src/lib/hooks/use-callback-ref.ts +15 -0
  131. package/src/lib/hooks/use-first-render.ts +11 -0
  132. package/src/lib/hooks/use-hover.ts +53 -0
  133. package/src/lib/hooks/use-is-tab-active.ts +17 -0
  134. package/src/lib/hooks/use-media-query.ts +164 -0
  135. package/src/lib/utils/css.ts +6 -0
  136. package/src/styles.css +329 -0
  137. package/src/types/helpers.ts +24 -0
  138. package/src/types/react.d.ts +7 -0
@@ -0,0 +1,112 @@
1
+ "use client";
2
+
3
+ import { mergeProps } from "@base-ui/react/merge-props";
4
+ import { useRender } from "@base-ui/react/use-render";
5
+ import { ChevronRight, MoreHorizontal } from "lucide-react";
6
+ import type * as React from "react";
7
+
8
+ import { cn } from "../../lib/utils/css";
9
+
10
+ function Breadcrumb({ ...props }: React.ComponentProps<"nav">) {
11
+ return <nav aria-label="breadcrumb" data-slot="breadcrumb" {...props} />;
12
+ }
13
+
14
+ function BreadcrumbList({ className, ...props }: React.ComponentProps<"ol">) {
15
+ return (
16
+ <ol
17
+ className={cn(
18
+ "wrap-break-word flex flex-wrap items-center gap-1.5 text-muted-foreground text-sm sm:gap-2.5",
19
+ className,
20
+ )}
21
+ data-slot="breadcrumb-list"
22
+ {...props}
23
+ />
24
+ );
25
+ }
26
+
27
+ function BreadcrumbItem({ className, ...props }: React.ComponentProps<"li">) {
28
+ return (
29
+ <li
30
+ className={cn("inline-flex items-center gap-1.5", className)}
31
+ data-slot="breadcrumb-item"
32
+ {...props}
33
+ />
34
+ );
35
+ }
36
+
37
+ function BreadcrumbLink({
38
+ className,
39
+ render,
40
+ ...props
41
+ }: useRender.ComponentProps<"a">) {
42
+ const defaultProps = {
43
+ className: cn("transition-colors hover:text-foreground", className),
44
+ "data-slot": "breadcrumb-link",
45
+ };
46
+
47
+ return useRender({
48
+ defaultTagName: "a",
49
+ props: mergeProps<"a">(defaultProps, props),
50
+ render,
51
+ });
52
+ }
53
+
54
+ function BreadcrumbPage({ className, ...props }: React.ComponentProps<"span">) {
55
+ return (
56
+ // biome-ignore lint(a11y/useFocusableInteractive): known
57
+ <span
58
+ aria-current="page"
59
+ aria-disabled="true"
60
+ className={cn("font-normal text-foreground", className)}
61
+ data-slot="breadcrumb-page"
62
+ role="link"
63
+ {...props}
64
+ />
65
+ );
66
+ }
67
+
68
+ function BreadcrumbSeparator({
69
+ children,
70
+ className,
71
+ ...props
72
+ }: React.ComponentProps<"li">) {
73
+ return (
74
+ <li
75
+ aria-hidden="true"
76
+ className={cn("opacity-80 [&>svg]:size-4", className)}
77
+ data-slot="breadcrumb-separator"
78
+ role="presentation"
79
+ {...props}
80
+ >
81
+ {children ?? <ChevronRight />}
82
+ </li>
83
+ );
84
+ }
85
+
86
+ function BreadcrumbEllipsis({
87
+ className,
88
+ ...props
89
+ }: React.ComponentProps<"span">) {
90
+ return (
91
+ <span
92
+ aria-hidden="true"
93
+ className={className}
94
+ data-slot="breadcrumb-ellipsis"
95
+ role="presentation"
96
+ {...props}
97
+ >
98
+ <MoreHorizontal className="size-4" />
99
+ <span className="sr-only">More</span>
100
+ </span>
101
+ );
102
+ }
103
+
104
+ export {
105
+ Breadcrumb,
106
+ BreadcrumbList,
107
+ BreadcrumbItem,
108
+ BreadcrumbLink,
109
+ BreadcrumbPage,
110
+ BreadcrumbSeparator,
111
+ BreadcrumbEllipsis,
112
+ };
@@ -0,0 +1,77 @@
1
+ "use client";
2
+
3
+ import { mergeProps } from "@base-ui/react/merge-props";
4
+ import { useRender } from "@base-ui/react/use-render";
5
+ import { cva, type VariantProps } from "class-variance-authority";
6
+ import type * as React from "react";
7
+
8
+ import { cn } from "../../lib/utils/css";
9
+
10
+ const buttonVariants = cva(
11
+ "[&_svg]:-mx-0.5 [&_img]:-mx-0.5 [&_picture]:-mx-0.5 relative inline-flex shrink-0 cursor-pointer items-center justify-center gap-2 whitespace-nowrap rounded-lg border font-medium text-base outline-none transition-[box-shadow,filter] duration-100 [:active:not(:disabled)]:brightness-95 before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] pointer-coarse:after:absolute pointer-coarse:after:size-full pointer-coarse:after:min-h-11 pointer-coarse:after:min-w-11 focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-64 sm:text-sm [&_svg:not([class*='opacity-'])]:opacity-80 [&_img:not([class*='opacity-'])]:opacity-80 [&_picture:not([class*='opacity-'])]:opacity-80 [&_svg:not([class*='size-'])]:size-4.5 [&_img:not([class*='size-'])]:size-4.5 [&_picture:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 sm:[&_img:not([class*='size-'])]:size-4 sm:[&_picture:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_img]:pointer-events-none [&_picture]:pointer-events-none [&_svg]:shrink-0 [&_img]:shrink-0 [&_picture]:shrink-0",
12
+ {
13
+ defaultVariants: {
14
+ size: "default",
15
+ variant: "default",
16
+ },
17
+ variants: {
18
+ size: {
19
+ default: "h-9 px-[calc(--spacing(3)-1px)] sm:h-8",
20
+ icon: "size-9 sm:size-8",
21
+ "icon-lg": "size-10 sm:size-9",
22
+ "icon-sm": "size-8 sm:size-7",
23
+ "icon-xl":
24
+ "size-11 sm:size-10 [&_svg:not([class*='size-'])]:size-5 [&_img:not([class*='size-'])]:size-5 [&_picture:not([class*='size-'])]:size-5 sm:[&_svg:not([class*='size-'])]:size-4.5 sm:[&_img:not([class*='size-'])]:size-4.5 sm:[&_picture:not([class*='size-'])]:size-4.5",
25
+ "icon-xs":
26
+ "size-7 rounded-md before:rounded-[calc(var(--radius-md)-1px)] sm:size-6 not-in-data-[slot=input-group]:[&_svg:not([class*='size-'])]:size-4 not-in-data-[slot=input-group]:[&_img:not([class*='size-'])]:size-4 not-in-data-[slot=input-group]:[&_picture:not([class*='size-'])]:size-4 sm:not-in-data-[slot=input-group]:[&_svg:not([class*='size-'])]:size-3.5 sm:not-in-data-[slot=input-group]:[&_img:not([class*='size-'])]:size-3.5 sm:not-in-data-[slot=input-group]:[&_picture:not([class*='size-'])]:size-3.5",
27
+ lg: "h-10 px-[calc(--spacing(3.5)-1px)] sm:h-9",
28
+ sm: "h-8 gap-1.5 px-[calc(--spacing(2.5)-1px)] sm:h-7",
29
+ xl: "h-11 px-[calc(--spacing(4)-1px)] text-lg sm:h-10 sm:text-base [&_svg:not([class*='size-'])]:size-5 [&_img:not([class*='size-'])]:size-5 [&_picture:not([class*='size-'])]:size-5 sm:[&_svg:not([class*='size-'])]:size-4.5 sm:[&_img:not([class*='size-'])]:size-4.5 sm:[&_picture:not([class*='size-'])]:size-4.5",
30
+ xs: "h-7 gap-1 rounded-md px-[calc(--spacing(2)-1px)] text-sm before:rounded-[calc(var(--radius-md)-1px)] sm:h-6 sm:text-xs [&_svg:not([class*='size-'])]:size-4 [&_img:not([class*='size-'])]:size-4 [&_picture:not([class*='size-'])]:size-4 sm:[&_svg:not([class*='size-'])]:size-3.5 sm:[&_img:not([class*='size-'])]:size-3.5 sm:[&_picture:not([class*='size-'])]:size-3.5",
31
+ },
32
+ variant: {
33
+ default:
34
+ "not-disabled:inset-shadow-[0_1px_--theme(--color-white/16%)] border-primary bg-primary text-primary-foreground shadow-primary/24 shadow-xs [:active,[data-pressed]]:inset-shadow-[0_1px_--theme(--color-black/8%)] [:disabled,:active,[data-pressed]]:shadow-none [:hover,[data-pressed]]:bg-primary/90",
35
+ destructive:
36
+ "not-disabled:inset-shadow-[0_1px_--theme(--color-white/16%)] border-destructive bg-destructive text-white shadow-destructive/24 shadow-xs [:active,[data-pressed]]:inset-shadow-[0_1px_--theme(--color-black/8%)] [:disabled,:active,[data-pressed]]:shadow-none [:hover,[data-pressed]]:bg-destructive/90",
37
+ "destructive-outline":
38
+ "border-input bg-popover not-dark:bg-clip-padding text-destructive-foreground shadow-xs/5 not-disabled:not-active:not-data-pressed:before:shadow-[0_1px_--theme(--color-black/4%)] dark:bg-input/32 dark:not-disabled:before:shadow-[0_-1px_--theme(--color-white/2%)] dark:not-disabled:not-active:not-data-pressed:before:shadow-[0_-1px_--theme(--color-white/6%)] [:disabled,:active,[data-pressed]]:shadow-none [:hover,[data-pressed]]:border-destructive/32 [:hover,[data-pressed]]:bg-destructive/4",
39
+ "destructive-ghost":
40
+ "border-transparent text-destructive-foreground data-pressed:bg-destructive/8 [:hover,[data-pressed]]:bg-destructive/8",
41
+ ghost:
42
+ "border-transparent text-foreground data-pressed:bg-accent [:hover,[data-pressed]]:bg-accent",
43
+ link: "border-transparent pointer-coarse:underline pointer-coarse:underline-offset-4 pointer-fine:after:absolute pointer-fine:after:inset-x-3 pointer-fine:after:bottom-1.5 pointer-fine:after:h-px pointer-fine:after:origin-right pointer-fine:after:scale-x-0 pointer-fine:after:bg-current pointer-fine:after:transition-transform pointer-fine:after:duration-300 pointer-fine:after:ease-out pointer-fine:hover:after:origin-left pointer-fine:hover:after:scale-x-100 pointer-fine:data-pressed:after:origin-left pointer-fine:data-pressed:after:scale-x-100",
44
+ "link-muted":
45
+ "border-transparent text-muted-foreground transition-[box-shadow,filter,color] [:hover,[data-pressed]]:text-foreground pointer-coarse:underline pointer-coarse:underline-offset-4 pointer-fine:after:absolute pointer-fine:after:inset-x-3 pointer-fine:after:bottom-1.5 pointer-fine:after:h-px pointer-fine:after:origin-right pointer-fine:after:scale-x-0 pointer-fine:after:bg-current pointer-fine:after:transition-transform pointer-fine:after:duration-300 pointer-fine:after:ease-out pointer-fine:hover:after:origin-left pointer-fine:hover:after:scale-x-100 pointer-fine:data-pressed:after:origin-left pointer-fine:data-pressed:after:scale-x-100",
46
+ outline:
47
+ "border-input bg-popover not-dark:bg-clip-padding text-foreground shadow-xs/5 not-disabled:not-active:not-data-pressed:before:shadow-[0_1px_--theme(--color-black/4%)] dark:bg-input/32 dark:not-disabled:before:shadow-[0_-1px_--theme(--color-white/2%)] dark:not-disabled:not-active:not-data-pressed:before:shadow-[0_-1px_--theme(--color-white/6%)] [:disabled,:active,[data-pressed]]:shadow-none [:hover,[data-pressed]]:bg-accent/50 dark:[:hover,[data-pressed]]:bg-input/64",
48
+ secondary:
49
+ "border-transparent bg-secondary text-secondary-foreground [:active,[data-pressed]]:bg-secondary/80 [:hover,[data-pressed]]:bg-secondary/90",
50
+ },
51
+ },
52
+ },
53
+ );
54
+
55
+ export interface ButtonProps extends useRender.ComponentProps<"button"> {
56
+ variant?: VariantProps<typeof buttonVariants>["variant"];
57
+ size?: VariantProps<typeof buttonVariants>["size"];
58
+ }
59
+
60
+ function Button({ className, variant, size, render, ...props }: ButtonProps) {
61
+ const typeValue: React.ButtonHTMLAttributes<HTMLButtonElement>["type"] =
62
+ render ? undefined : "button";
63
+
64
+ const defaultProps = {
65
+ className: cn(buttonVariants({ className, size, variant })),
66
+ "data-slot": "button",
67
+ type: typeValue,
68
+ };
69
+
70
+ return useRender({
71
+ defaultTagName: "button",
72
+ props: mergeProps<"button">(defaultProps, props),
73
+ render,
74
+ });
75
+ }
76
+
77
+ export { Button, buttonVariants };
@@ -0,0 +1,137 @@
1
+ "use client";
2
+
3
+ import {
4
+ ChevronLeftIcon,
5
+ ChevronRightIcon,
6
+ ChevronsUpDownIcon,
7
+ } from "lucide-react";
8
+ import type * as React from "react";
9
+ import { DayPicker } from "react-day-picker";
10
+
11
+ import { cn } from "../../lib/utils/css";
12
+
13
+ const buttonClassNames =
14
+ "relative flex size-(--cell-size) text-base sm:text-sm items-center justify-center rounded-lg text-foreground not-in-data-selected:hover:bg-accent disabled:pointer-events-none disabled:opacity-64 [&_svg:not([class*='opacity-'])]:opacity-80 [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0";
15
+
16
+ function Calendar({
17
+ className,
18
+ classNames,
19
+ showOutsideDays = true,
20
+ components: userComponents,
21
+ ...props
22
+ }: React.ComponentProps<typeof DayPicker>) {
23
+ const defaultClassNames = {
24
+ button_next: buttonClassNames,
25
+ button_previous: buttonClassNames,
26
+ caption_label:
27
+ "text-base sm:text-sm font-medium flex items-center gap-2 h-full",
28
+ day: "size-(--cell-size) text-sm py-px",
29
+ day_button: cn(
30
+ buttonClassNames,
31
+ "in-[[data-selected]:not(.range-middle)]:transition-[color,background-color,border-radius,box-shadow] in-data-disabled:pointer-events-none focus-visible:z-1 in-data-selected:bg-primary in-data-selected:text-primary-foreground in-data-disabled:text-muted-foreground/70 in-data-disabled:line-through in-data-outside:text-muted-foreground/70 in-data-selected:in-data-outside:text-primary-foreground outline-none focus-visible:ring-ring/50 focus-visible:ring-[3px] in-[.range-start:not(.range-end)]:rounded-e-none in-[.range-end:not(.range-start)]:rounded-s-none in-[.range-middle]:rounded-none in-[.range-middle]:in-data-selected:bg-accent in-[.range-middle]:in-data-selected:text-foreground",
32
+ ),
33
+ dropdown: "absolute bg-popover inset-0 opacity-0",
34
+ dropdown_root:
35
+ "relative has-focus:border-ring has-focus:ring-ring/50 has-focus:ring-[3px] border border-input shadow-xs/5 rounded-lg px-[calc(--spacing(3)-1px)] h-9 sm:h-8 [&_svg:not([class*='opacity-'])]:opacity-80 [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:-me-1",
36
+ dropdowns:
37
+ "w-full flex items-center text-base sm:text-sm justify-center h-(--cell-size) gap-1.5 *:[span]:font-medium",
38
+ hidden: "invisible",
39
+ month: "w-full",
40
+ month_caption:
41
+ "relative mx-(--cell-size) px-1 mb-1 flex h-(--cell-size) items-center justify-center z-2",
42
+ months: "relative flex flex-col sm:flex-row gap-2",
43
+ nav: "absolute top-0 flex w-full justify-between z-1",
44
+ outside:
45
+ "text-muted-foreground data-selected:bg-accent/50 data-selected:text-muted-foreground",
46
+ range_end: "range-end",
47
+ range_middle: "range-middle",
48
+ range_start: "range-start",
49
+ today:
50
+ "*:after:pointer-events-none *:after:absolute *:after:bottom-1 *:after:start-1/2 *:after:z-1 *:after:size-[3px] *:after:-translate-x-1/2 *:after:rounded-full *:after:bg-primary [&[data-selected]:not(.range-middle)>*]:after:bg-background [&[data-disabled]>*]:after:bg-foreground/30 *:after:transition-colors",
51
+ week_number:
52
+ "size-(--cell-size) p-0 text-xs font-medium text-muted-foreground/70",
53
+ weekday:
54
+ "size-(--cell-size) p-0 text-xs font-medium text-muted-foreground/70",
55
+ };
56
+ const mergedClassNames: typeof defaultClassNames = Object.keys(
57
+ defaultClassNames,
58
+ ).reduce(
59
+ (acc, key) => {
60
+ const userClass = classNames?.[key as keyof typeof classNames];
61
+ const baseClass =
62
+ defaultClassNames[key as keyof typeof defaultClassNames];
63
+
64
+ acc[key as keyof typeof defaultClassNames] = userClass
65
+ ? cn(baseClass, userClass)
66
+ : baseClass;
67
+
68
+ return acc;
69
+ },
70
+ { ...defaultClassNames } as typeof defaultClassNames,
71
+ );
72
+
73
+ const defaultComponents = {
74
+ Chevron: ({
75
+ className,
76
+ orientation,
77
+ ...props
78
+ }: {
79
+ className?: string;
80
+ orientation?: "left" | "right" | "up" | "down";
81
+ }) => {
82
+ if (orientation === "left") {
83
+ return (
84
+ <ChevronLeftIcon
85
+ className={cn(className, "rtl:rotate-180")}
86
+ {...props}
87
+ aria-hidden="true"
88
+ />
89
+ );
90
+ }
91
+
92
+ if (orientation === "right") {
93
+ return (
94
+ <ChevronRightIcon
95
+ className={cn(className, "rtl:rotate-180")}
96
+ {...props}
97
+ aria-hidden="true"
98
+ />
99
+ );
100
+ }
101
+
102
+ return (
103
+ <ChevronsUpDownIcon
104
+ className={className}
105
+ {...props}
106
+ aria-hidden="true"
107
+ />
108
+ );
109
+ },
110
+ };
111
+
112
+ const mergedComponents = {
113
+ ...defaultComponents,
114
+ ...userComponents,
115
+ };
116
+
117
+ return (
118
+ <DayPicker
119
+ className={cn(
120
+ "w-fit [--cell-size:--spacing(10)] sm:[--cell-size:--spacing(9)]",
121
+ className,
122
+ )}
123
+ classNames={mergedClassNames}
124
+ components={mergedComponents}
125
+ data-slot="calendar"
126
+ formatters={{
127
+ formatMonthDropdown: (date) =>
128
+ date.toLocaleString("default", { month: "short" }),
129
+ }}
130
+ mode="single"
131
+ showOutsideDays={showOutsideDays}
132
+ {...props}
133
+ />
134
+ );
135
+ }
136
+
137
+ export { Calendar };
@@ -0,0 +1,244 @@
1
+ "use client";
2
+
3
+ import { mergeProps } from "@base-ui/react/merge-props";
4
+ import { useRender } from "@base-ui/react/use-render";
5
+
6
+ import { cn } from "../../lib/utils/css";
7
+
8
+ function Card({
9
+ className,
10
+ render,
11
+ ...props
12
+ }: useRender.ComponentProps<"div">) {
13
+ const defaultProps = {
14
+ className: cn(
15
+ "relative flex flex-col gap-4 rounded-2xl border bg-card not-dark:bg-clip-padding text-card-foreground shadow-xs/5 before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-2xl)-1px)] before:shadow-[0_1px_--theme(--color-black/6%)] dark:before:shadow-[0_-1px_--theme(--color-white/6%)]",
16
+ className,
17
+ ),
18
+ "data-slot": "card",
19
+ };
20
+
21
+ return useRender({
22
+ defaultTagName: "div",
23
+ props: mergeProps<"div">(defaultProps, props),
24
+ render,
25
+ });
26
+ }
27
+
28
+ function CardFrame({
29
+ className,
30
+ render,
31
+ ...props
32
+ }: useRender.ComponentProps<"div">) {
33
+ const defaultProps = {
34
+ className: cn(
35
+ "flex flex-col relative rounded-2xl border bg-background before:absolute before:inset-0 before:rounded-[inherit] before:bg-muted/72 before:pointer-events-none not-dark:bg-clip-padding text-card-foreground shadow-xs/5 before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-2xl)-1px)] before:shadow-[0_1px_--theme(--color-black/6%)] dark:before:shadow-[0_-1px_--theme(--color-white/6%)] *:data-[slot=card]:-m-px *:not-last:data-[slot=card]:rounded-b-lg *:not-last:data-[slot=card]:before:rounded-b-[calc(var(--radius-lg)-1px)] *:not-first:data-[slot=card]:rounded-t-lg *:not-first:data-[slot=card]:before:rounded-t-[calc(var(--radius-lg)-1px)] *:data-[slot=card]:[clip-path:inset(-1rem_1px)] *:data-[slot=card]:first:[clip-path:inset(1px_1px_-1rem_1px_round_calc(var(--radius-2xl)-1px))] *:data-[slot=card]:last:[clip-path:inset(-1rem_1px_1px_1px_round_calc(var(--radius-2xl)-1px))] *:data-[slot=card]:shadow-none *:data-[slot=card]:before:hidden *:data-[slot=card]:bg-clip-padding",
36
+ className,
37
+ ),
38
+ "data-slot": "card-frame",
39
+ };
40
+
41
+ return useRender({
42
+ defaultTagName: "div",
43
+ props: mergeProps<"div">(defaultProps, props),
44
+ render,
45
+ });
46
+ }
47
+
48
+ function CardFrameHeader({
49
+ className,
50
+ render,
51
+ ...props
52
+ }: useRender.ComponentProps<"div">) {
53
+ const defaultProps = {
54
+ className: cn("flex flex-col px-6 py-4", className),
55
+ "data-slot": "card-frame-header",
56
+ };
57
+
58
+ return useRender({
59
+ defaultTagName: "div",
60
+ props: mergeProps<"div">(defaultProps, props),
61
+ render,
62
+ });
63
+ }
64
+
65
+ function CardFrameTitle({
66
+ className,
67
+ render,
68
+ ...props
69
+ }: useRender.ComponentProps<"div">) {
70
+ const defaultProps = {
71
+ className: cn("font-semibold text-sm", className),
72
+ "data-slot": "card-frame-title",
73
+ };
74
+
75
+ return useRender({
76
+ defaultTagName: "div",
77
+ props: mergeProps<"div">(defaultProps, props),
78
+ render,
79
+ });
80
+ }
81
+
82
+ function CardFrameDescription({
83
+ className,
84
+ render,
85
+ ...props
86
+ }: useRender.ComponentProps<"div">) {
87
+ const defaultProps = {
88
+ className: cn("text-muted-foreground text-sm", className),
89
+ "data-slot": "card-frame-description",
90
+ };
91
+
92
+ return useRender({
93
+ defaultTagName: "div",
94
+ props: mergeProps<"div">(defaultProps, props),
95
+ render,
96
+ });
97
+ }
98
+
99
+ function CardFrameFooter({
100
+ className,
101
+ render,
102
+ ...props
103
+ }: useRender.ComponentProps<"div">) {
104
+ const defaultProps = {
105
+ className: cn("px-6 py-4", className),
106
+ "data-slot": "card-frame-footer",
107
+ };
108
+
109
+ return useRender({
110
+ defaultTagName: "div",
111
+ props: mergeProps<"div">(defaultProps, props),
112
+ render,
113
+ });
114
+ }
115
+
116
+ function CardHeader({
117
+ className,
118
+ render,
119
+ ...props
120
+ }: useRender.ComponentProps<"div">) {
121
+ const defaultProps = {
122
+ className: cn(
123
+ "grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 p-6 in-[[data-slot=card]:has(>[data-slot=card-panel])]:pb-4 has-data-[slot=card-action]:grid-cols-[1fr_auto]",
124
+ className,
125
+ ),
126
+ "data-slot": "card-header",
127
+ };
128
+
129
+ return useRender({
130
+ defaultTagName: "div",
131
+ props: mergeProps<"div">(defaultProps, props),
132
+ render,
133
+ });
134
+ }
135
+
136
+ function CardTitle({
137
+ className,
138
+ render,
139
+ ...props
140
+ }: useRender.ComponentProps<"div">) {
141
+ const defaultProps = {
142
+ className: cn("font-semibold text-lg leading-none", className),
143
+ "data-slot": "card-title",
144
+ };
145
+
146
+ return useRender({
147
+ defaultTagName: "div",
148
+ props: mergeProps<"div">(defaultProps, props),
149
+ render,
150
+ });
151
+ }
152
+
153
+ function CardDescription({
154
+ className,
155
+ render,
156
+ ...props
157
+ }: useRender.ComponentProps<"div">) {
158
+ const defaultProps = {
159
+ className: cn("text-muted-foreground text-sm", className),
160
+ "data-slot": "card-description",
161
+ };
162
+
163
+ return useRender({
164
+ defaultTagName: "div",
165
+ props: mergeProps<"div">(defaultProps, props),
166
+ render,
167
+ });
168
+ }
169
+
170
+ function CardAction({
171
+ className,
172
+ render,
173
+ ...props
174
+ }: useRender.ComponentProps<"div">) {
175
+ const defaultProps = {
176
+ className: cn(
177
+ "col-start-2 row-span-2 row-start-1 self-start justify-self-end inline-flex",
178
+ className,
179
+ ),
180
+ "data-slot": "card-action",
181
+ };
182
+
183
+ return useRender({
184
+ defaultTagName: "div",
185
+ props: mergeProps<"div">(defaultProps, props),
186
+ render,
187
+ });
188
+ }
189
+
190
+ function CardPanel({
191
+ className,
192
+ render,
193
+ ...props
194
+ }: useRender.ComponentProps<"div">) {
195
+ const defaultProps = {
196
+ className: cn(
197
+ "flex-1 p-6 in-[[data-slot=card]:has(>[data-slot=card-header]:not(.border-b))]:pt-0 in-[[data-slot=card]:has(>[data-slot=card-footer]:not(.border-t))]:pb-0",
198
+ className,
199
+ ),
200
+ "data-slot": "card-panel",
201
+ };
202
+
203
+ return useRender({
204
+ defaultTagName: "div",
205
+ props: mergeProps<"div">(defaultProps, props),
206
+ render,
207
+ });
208
+ }
209
+
210
+ function CardFooter({
211
+ className,
212
+ render,
213
+ ...props
214
+ }: useRender.ComponentProps<"div">) {
215
+ const defaultProps = {
216
+ className: cn(
217
+ "flex items-center p-6 in-[[data-slot=card]:has(>[data-slot=card-panel])]:pt-4",
218
+ className,
219
+ ),
220
+ "data-slot": "card-footer",
221
+ };
222
+
223
+ return useRender({
224
+ defaultTagName: "div",
225
+ props: mergeProps<"div">(defaultProps, props),
226
+ render,
227
+ });
228
+ }
229
+
230
+ export {
231
+ Card,
232
+ CardFrame,
233
+ CardFrameHeader,
234
+ CardFrameTitle,
235
+ CardFrameDescription,
236
+ CardFrameFooter,
237
+ CardAction,
238
+ CardDescription,
239
+ CardFooter,
240
+ CardHeader,
241
+ CardPanel,
242
+ CardPanel as CardContent,
243
+ CardTitle,
244
+ };