@cntyclub/ui-react 0.1.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 (124) hide show
  1. package/dist/chunk-HDGMSYQS.js +26461 -0
  2. package/dist/chunk-HDGMSYQS.js.map +1 -0
  3. package/dist/chunk-PR4QN5HX.js +39 -0
  4. package/dist/chunk-PR4QN5HX.js.map +1 -0
  5. package/dist/form.d.ts +175 -0
  6. package/dist/form.js +5207 -0
  7. package/dist/form.js.map +1 -0
  8. package/dist/index.d.ts +1462 -0
  9. package/dist/index.js +81862 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/input-CZvh825j.d.ts +24 -0
  12. package/dist/qr-code-styling-3Y6LZH6V.js +1123 -0
  13. package/dist/qr-code-styling-3Y6LZH6V.js.map +1 -0
  14. package/package.json +79 -0
  15. package/src/components/form/checkbox-group-field.tsx +101 -0
  16. package/src/components/form/date-field.tsx +79 -0
  17. package/src/components/form/date-range-field.tsx +106 -0
  18. package/src/components/form/form-context.ts +10 -0
  19. package/src/components/form/form.tsx +54 -0
  20. package/src/components/form/number-field.tsx +69 -0
  21. package/src/components/form/select-field.tsx +76 -0
  22. package/src/components/form/submit-button.tsx +28 -0
  23. package/src/components/form/text-field.tsx +107 -0
  24. package/src/components/layout/dashboard-header.tsx +54 -0
  25. package/src/components/layout/dashboard-panel.tsx +34 -0
  26. package/src/components/theme-provider.tsx +403 -0
  27. package/src/components/ui/accordion.tsx +69 -0
  28. package/src/components/ui/alert-dialog.tsx +169 -0
  29. package/src/components/ui/alert.tsx +80 -0
  30. package/src/components/ui/animated-theme-toggler.tsx +265 -0
  31. package/src/components/ui/app-store-buttons.tsx +182 -0
  32. package/src/components/ui/aspect-ratio.tsx +23 -0
  33. package/src/components/ui/autocomplete.tsx +296 -0
  34. package/src/components/ui/avatar-group.tsx +95 -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/checkbox-group.tsx +16 -0
  45. package/src/components/ui/checkbox.tsx +82 -0
  46. package/src/components/ui/collapsible.tsx +45 -0
  47. package/src/components/ui/combobox.tsx +411 -0
  48. package/src/components/ui/command.tsx +264 -0
  49. package/src/components/ui/context-menu.tsx +271 -0
  50. package/src/components/ui/credit-card.tsx +214 -0
  51. package/src/components/ui/dialog.tsx +196 -0
  52. package/src/components/ui/drawer.tsx +135 -0
  53. package/src/components/ui/empty.tsx +127 -0
  54. package/src/components/ui/featured-icon.tsx +149 -0
  55. package/src/components/ui/field.tsx +88 -0
  56. package/src/components/ui/fieldset.tsx +29 -0
  57. package/src/components/ui/form.tsx +17 -0
  58. package/src/components/ui/frame.tsx +82 -0
  59. package/src/components/ui/generic-empty.tsx +142 -0
  60. package/src/components/ui/group.tsx +97 -0
  61. package/src/components/ui/horizontal-scroll-fader.tsx +228 -0
  62. package/src/components/ui/input-group.tsx +102 -0
  63. package/src/components/ui/input-otp.tsx +96 -0
  64. package/src/components/ui/input.tsx +66 -0
  65. package/src/components/ui/item.tsx +198 -0
  66. package/src/components/ui/kbd.tsx +30 -0
  67. package/src/components/ui/label.tsx +28 -0
  68. package/src/components/ui/menu.tsx +312 -0
  69. package/src/components/ui/menubar.tsx +93 -0
  70. package/src/components/ui/meter.tsx +67 -0
  71. package/src/components/ui/multi-select.tsx +308 -0
  72. package/src/components/ui/navigation-menu.tsx +143 -0
  73. package/src/components/ui/number-field.tsx +160 -0
  74. package/src/components/ui/pagination-controls.tsx +74 -0
  75. package/src/components/ui/pagination.tsx +149 -0
  76. package/src/components/ui/popover.tsx +119 -0
  77. package/src/components/ui/preview-card.tsx +55 -0
  78. package/src/components/ui/progress.tsx +289 -0
  79. package/src/components/ui/qr-code.tsx +150 -0
  80. package/src/components/ui/radio-group.tsx +103 -0
  81. package/src/components/ui/resizable.tsx +56 -0
  82. package/src/components/ui/scroll-area.tsx +90 -0
  83. package/src/components/ui/scroller.tsx +38 -0
  84. package/src/components/ui/section-header.tsx +118 -0
  85. package/src/components/ui/select.tsx +181 -0
  86. package/src/components/ui/separator.tsx +23 -0
  87. package/src/components/ui/sheet.tsx +224 -0
  88. package/src/components/ui/sidebar.tsx +744 -0
  89. package/src/components/ui/skeleton.tsx +16 -0
  90. package/src/components/ui/slider.tsx +108 -0
  91. package/src/components/ui/smooth-scroll.tsx +143 -0
  92. package/src/components/ui/social-button.tsx +247 -0
  93. package/src/components/ui/spinner-on-demand.tsx +32 -0
  94. package/src/components/ui/spinner.tsx +18 -0
  95. package/src/components/ui/stat.tsx +187 -0
  96. package/src/components/ui/stepper.tsx +167 -0
  97. package/src/components/ui/switch.tsx +56 -0
  98. package/src/components/ui/table.tsx +126 -0
  99. package/src/components/ui/tabs.tsx +90 -0
  100. package/src/components/ui/tag.tsx +229 -0
  101. package/src/components/ui/target-countdown.tsx +46 -0
  102. package/src/components/ui/text-editor.tsx +313 -0
  103. package/src/components/ui/textarea.tsx +51 -0
  104. package/src/components/ui/timeline.tsx +116 -0
  105. package/src/components/ui/toast.tsx +268 -0
  106. package/src/components/ui/toggle-group.tsx +101 -0
  107. package/src/components/ui/toggle.tsx +45 -0
  108. package/src/components/ui/toolbar.tsx +89 -0
  109. package/src/components/ui/tooltip.tsx +102 -0
  110. package/src/components/ui/vertical-scroll-fader.tsx +250 -0
  111. package/src/components/ui/video-player.tsx +275 -0
  112. package/src/components/upload/avatar-upload-base.tsx +131 -0
  113. package/src/components/upload/image-upload-base.tsx +112 -0
  114. package/src/form.ts +17 -0
  115. package/src/index.ts +125 -0
  116. package/src/lib/hooks/use-callback-ref.ts +15 -0
  117. package/src/lib/hooks/use-first-render.ts +11 -0
  118. package/src/lib/hooks/use-hover.ts +53 -0
  119. package/src/lib/hooks/use-is-tab-active.ts +17 -0
  120. package/src/lib/hooks/use-media-query.ts +164 -0
  121. package/src/lib/utils/css.ts +6 -0
  122. package/src/styles.css +300 -0
  123. package/src/types/helpers.ts +24 -0
  124. package/src/types/react.d.ts +7 -0
@@ -0,0 +1,160 @@
1
+ "use client";
2
+
3
+ import { NumberField as NumberFieldPrimitive } from "@base-ui/react/number-field";
4
+ import { MinusIcon, PlusIcon } from "lucide-react";
5
+ import * as React from "react";
6
+ import { Label } from "./label";
7
+ import { cn } from "../../lib/utils/css";
8
+
9
+ const NumberFieldContext = React.createContext<{
10
+ fieldId: string;
11
+ } | null>(null);
12
+
13
+ function NumberField({
14
+ id,
15
+ className,
16
+ size = "default",
17
+ ...props
18
+ }: NumberFieldPrimitive.Root.Props & {
19
+ size?: "sm" | "default" | "lg";
20
+ }) {
21
+ const generatedId = React.useId();
22
+ const fieldId = id ?? generatedId;
23
+
24
+ return (
25
+ <NumberFieldContext.Provider value={{ fieldId }}>
26
+ <NumberFieldPrimitive.Root
27
+ className={cn("flex w-full flex-col items-start gap-2", className)}
28
+ data-size={size}
29
+ data-slot="number-field"
30
+ id={fieldId}
31
+ {...props}
32
+ />
33
+ </NumberFieldContext.Provider>
34
+ );
35
+ }
36
+
37
+ function NumberFieldGroup({
38
+ className,
39
+ ...props
40
+ }: NumberFieldPrimitive.Group.Props) {
41
+ return (
42
+ <NumberFieldPrimitive.Group
43
+ className={cn(
44
+ "relative flex w-full justify-between rounded-lg border border-input bg-background not-dark:bg-clip-padding text-base text-foreground shadow-xs/5 ring-ring/24 transition-shadow before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] not-data-disabled:not-focus-within:not-aria-invalid:before:shadow-[0_1px_--theme(--color-black/6%)] focus-within:border-ring focus-within:ring-[3px] has-aria-invalid:border-destructive/36 focus-within:has-aria-invalid:border-destructive/64 focus-within:has-aria-invalid:ring-destructive/48 data-disabled:pointer-events-none data-disabled:opacity-64 sm:text-sm dark:bg-input/32 dark:has-aria-invalid:ring-destructive/24 dark:not-data-disabled:not-focus-within:not-aria-invalid:before:shadow-[0_-1px_--theme(--color-white/6%)] [&_svg:not([class*='size-'])]:size-4.5 sm:[&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0 [[data-disabled],:focus-within,[aria-invalid]]:shadow-none",
45
+ className,
46
+ )}
47
+ data-slot="number-field-group"
48
+ {...props}
49
+ />
50
+ );
51
+ }
52
+
53
+ function NumberFieldDecrement({
54
+ className,
55
+ ...props
56
+ }: NumberFieldPrimitive.Decrement.Props) {
57
+ return (
58
+ <NumberFieldPrimitive.Decrement
59
+ className={cn(
60
+ "relative flex shrink-0 cursor-pointer items-center justify-center rounded-s-[calc(var(--radius-lg)-1px)] in-data-[size=sm]:px-[calc(--spacing(2.5)-1px)] px-[calc(--spacing(3)-1px)] transition-colors pointer-coarse:after:absolute pointer-coarse:after:size-full pointer-coarse:after:min-h-11 pointer-coarse:after:min-w-11 hover:bg-accent",
61
+ className,
62
+ )}
63
+ data-slot="number-field-decrement"
64
+ {...props}
65
+ >
66
+ <MinusIcon />
67
+ </NumberFieldPrimitive.Decrement>
68
+ );
69
+ }
70
+
71
+ function NumberFieldIncrement({
72
+ className,
73
+ ...props
74
+ }: NumberFieldPrimitive.Increment.Props) {
75
+ return (
76
+ <NumberFieldPrimitive.Increment
77
+ className={cn(
78
+ "relative flex shrink-0 cursor-pointer items-center justify-center rounded-e-[calc(var(--radius-lg)-1px)] in-data-[size=sm]:px-[calc(--spacing(2.5)-1px)] px-[calc(--spacing(3)-1px)] transition-colors pointer-coarse:after:absolute pointer-coarse:after:size-full pointer-coarse:after:min-h-11 pointer-coarse:after:min-w-11 hover:bg-accent",
79
+ className,
80
+ )}
81
+ data-slot="number-field-increment"
82
+ {...props}
83
+ >
84
+ <PlusIcon />
85
+ </NumberFieldPrimitive.Increment>
86
+ );
87
+ }
88
+
89
+ function NumberFieldInput({
90
+ className,
91
+ ...props
92
+ }: NumberFieldPrimitive.Input.Props) {
93
+ return (
94
+ <NumberFieldPrimitive.Input
95
+ className={cn(
96
+ "h-8.5 in-data-[size=lg]:h-9.5 in-data-[size=sm]:h-7.5 w-full min-w-0 grow bg-transparent in-data-[size=sm]:px-[calc(--spacing(2.5)-1px)] px-[calc(--spacing(3)-1px)] text-center tabular-nums in-data-[size=lg]:leading-9.5 in-data-[size=sm]:leading-7.5 leading-8.5 outline-none sm:h-7.5 sm:in-data-[size=lg]:h-8.5 sm:in-data-[size=sm]:h-6.5 sm:in-data-[size=lg]:leading-8.5 sm:in-data-[size=sm]:leading-8.5 sm:leading-7.5",
97
+ className,
98
+ )}
99
+ data-slot="number-field-input"
100
+ {...props}
101
+ />
102
+ );
103
+ }
104
+
105
+ function NumberFieldScrubArea({
106
+ className,
107
+ label,
108
+ ...props
109
+ }: NumberFieldPrimitive.ScrubArea.Props & {
110
+ label: string;
111
+ }) {
112
+ const context = React.useContext(NumberFieldContext);
113
+
114
+ if (!context) {
115
+ throw new Error(
116
+ "NumberFieldScrubArea must be used within a NumberField component for accessibility.",
117
+ );
118
+ }
119
+
120
+ return (
121
+ <NumberFieldPrimitive.ScrubArea
122
+ className={cn("flex cursor-ew-resize", className)}
123
+ data-slot="number-field-scrub-area"
124
+ {...props}
125
+ >
126
+ <Label className="cursor-ew-resize" htmlFor={context.fieldId}>
127
+ {label}
128
+ </Label>
129
+ <NumberFieldPrimitive.ScrubAreaCursor className="drop-shadow-[0_1px_1px_#0008] filter">
130
+ <CursorGrowIcon />
131
+ </NumberFieldPrimitive.ScrubAreaCursor>
132
+ </NumberFieldPrimitive.ScrubArea>
133
+ );
134
+ }
135
+
136
+ function CursorGrowIcon(props: React.ComponentProps<"svg">) {
137
+ return (
138
+ // biome-ignore lint/a11y/noSvgWithoutTitle: Imported from library
139
+ <svg
140
+ fill="black"
141
+ height="14"
142
+ stroke="white"
143
+ viewBox="0 0 24 14"
144
+ width="26"
145
+ xmlns="http://www.w3.org/2000/svg"
146
+ {...props}
147
+ >
148
+ <path d="M19.5 5.5L6.49737 5.51844V2L1 6.9999L6.5 12L6.49737 8.5L19.5 8.5V12L25 6.9999L19.5 2V5.5Z" />
149
+ </svg>
150
+ );
151
+ }
152
+
153
+ export {
154
+ NumberField,
155
+ NumberFieldScrubArea,
156
+ NumberFieldDecrement,
157
+ NumberFieldIncrement,
158
+ NumberFieldGroup,
159
+ NumberFieldInput,
160
+ };
@@ -0,0 +1,74 @@
1
+ import {
2
+ Pagination,
3
+ PaginationContent,
4
+ PaginationEllipsis,
5
+ PaginationItem,
6
+ PaginationLink,
7
+ type PaginationLinkProps,
8
+ PaginationNext,
9
+ PaginationPrevious,
10
+ } from "./pagination";
11
+
12
+ export function PaginationControls(props: {
13
+ page: number;
14
+ pageCount: number;
15
+ renderPageLink: (page: number) => PaginationLinkProps["render"];
16
+ }) {
17
+ const { page, pageCount, renderPageLink } = props;
18
+
19
+ if (pageCount <= 1) return null;
20
+
21
+ return (
22
+ <Pagination>
23
+ <PaginationContent>
24
+ {/* Prev/Next are always rendered (disabled at the bounds) so they fade
25
+ between states instead of popping in and out. */}
26
+ <PaginationItem>
27
+ <PaginationPrevious
28
+ disabled={page <= 1}
29
+ render={page > 1 ? renderPageLink(page - 1) : <span />}
30
+ />
31
+ </PaginationItem>
32
+
33
+ {page > 1 && (
34
+ <PaginationItem>
35
+ <PaginationLink render={renderPageLink(1)}>1</PaginationLink>
36
+ </PaginationItem>
37
+ )}
38
+
39
+ {page > 2 && (
40
+ <PaginationItem>
41
+ <PaginationEllipsis />
42
+ </PaginationItem>
43
+ )}
44
+
45
+ <PaginationItem>
46
+ <PaginationLink render={renderPageLink(page)} isActive>
47
+ {page}
48
+ </PaginationLink>
49
+ </PaginationItem>
50
+
51
+ {pageCount > page + 1 && (
52
+ <PaginationItem>
53
+ <PaginationEllipsis />
54
+ </PaginationItem>
55
+ )}
56
+
57
+ {pageCount > page && (
58
+ <PaginationItem>
59
+ <PaginationLink render={renderPageLink(pageCount)}>
60
+ {pageCount}
61
+ </PaginationLink>
62
+ </PaginationItem>
63
+ )}
64
+
65
+ <PaginationItem>
66
+ <PaginationNext
67
+ disabled={page >= pageCount}
68
+ render={page < pageCount ? renderPageLink(page + 1) : <span />}
69
+ />
70
+ </PaginationItem>
71
+ </PaginationContent>
72
+ </Pagination>
73
+ );
74
+ }
@@ -0,0 +1,149 @@
1
+ "use client";
2
+
3
+ import { mergeProps } from "@base-ui/react/merge-props";
4
+ import { useRender } from "@base-ui/react/use-render";
5
+ import {
6
+ ChevronLeftIcon,
7
+ ChevronRightIcon,
8
+ MoreHorizontalIcon,
9
+ } from "lucide-react";
10
+ import type * as React from "react";
11
+ import { type Button, buttonVariants } from "./button";
12
+ import { cn } from "../../lib/utils/css";
13
+
14
+ function Pagination({ className, ...props }: React.ComponentProps<"nav">) {
15
+ return (
16
+ <nav
17
+ aria-label="pagination"
18
+ className={cn("mx-auto flex w-full justify-center", className)}
19
+ data-slot="pagination"
20
+ {...props}
21
+ />
22
+ );
23
+ }
24
+
25
+ function PaginationContent({
26
+ className,
27
+ ...props
28
+ }: React.ComponentProps<"ul">) {
29
+ return (
30
+ <ul
31
+ className={cn("flex flex-row items-center gap-1", className)}
32
+ data-slot="pagination-content"
33
+ {...props}
34
+ />
35
+ );
36
+ }
37
+
38
+ function PaginationItem({ className, ...props }: React.ComponentProps<"li">) {
39
+ return (
40
+ <li
41
+ className={cn(
42
+ "animate-in fade-in-0 zoom-in-95 duration-200 ease-out",
43
+ className,
44
+ )}
45
+ data-slot="pagination-item"
46
+ {...props}
47
+ />
48
+ );
49
+ }
50
+
51
+ export type PaginationLinkProps = {
52
+ isActive?: boolean;
53
+ disabled?: boolean;
54
+ size?: React.ComponentProps<typeof Button>["size"];
55
+ } & useRender.ComponentProps<"a">;
56
+
57
+ function PaginationLink({
58
+ className,
59
+ isActive,
60
+ disabled,
61
+ size = "icon",
62
+ render,
63
+ ...props
64
+ }: PaginationLinkProps) {
65
+ const defaultProps = {
66
+ "aria-current": isActive ? ("page" as const) : undefined,
67
+ "aria-disabled": disabled || undefined,
68
+ className: cn(
69
+ buttonVariants({
70
+ size,
71
+ variant: isActive ? "outline" : "ghost",
72
+ }),
73
+ "transition-[opacity,box-shadow,filter] duration-200 ease-out",
74
+ disabled && "pointer-events-none opacity-50",
75
+ className,
76
+ ),
77
+ "data-active": isActive,
78
+ "data-disabled": disabled || undefined,
79
+ "data-slot": "pagination-link",
80
+ tabIndex: disabled ? -1 : undefined,
81
+ };
82
+
83
+ return useRender({
84
+ defaultTagName: "a",
85
+ props: mergeProps<"a">(defaultProps, props),
86
+ render,
87
+ });
88
+ }
89
+
90
+ function PaginationPrevious({
91
+ className,
92
+ ...props
93
+ }: React.ComponentProps<typeof PaginationLink>) {
94
+ return (
95
+ <PaginationLink
96
+ aria-label="Go to previous page"
97
+ className={cn("max-sm:aspect-square max-sm:p-0", className)}
98
+ size="default"
99
+ {...props}
100
+ >
101
+ <ChevronLeftIcon className="sm:-ms-1" />
102
+ <span className="max-sm:hidden">Previous</span>
103
+ </PaginationLink>
104
+ );
105
+ }
106
+
107
+ function PaginationNext({
108
+ className,
109
+ ...props
110
+ }: React.ComponentProps<typeof PaginationLink>) {
111
+ return (
112
+ <PaginationLink
113
+ aria-label="Go to next page"
114
+ className={cn("max-sm:aspect-square max-sm:p-0", className)}
115
+ size="default"
116
+ {...props}
117
+ >
118
+ <span className="max-sm:hidden">Next</span>
119
+ <ChevronRightIcon className="sm:-me-1" />
120
+ </PaginationLink>
121
+ );
122
+ }
123
+
124
+ function PaginationEllipsis({
125
+ className,
126
+ ...props
127
+ }: React.ComponentProps<"span">) {
128
+ return (
129
+ <span
130
+ aria-hidden
131
+ className={cn("flex min-w-7 justify-center", className)}
132
+ data-slot="pagination-ellipsis"
133
+ {...props}
134
+ >
135
+ <MoreHorizontalIcon className="size-5 sm:size-4" />
136
+ <span className="sr-only">More pages</span>
137
+ </span>
138
+ );
139
+ }
140
+
141
+ export {
142
+ Pagination,
143
+ PaginationContent,
144
+ PaginationLink,
145
+ PaginationItem,
146
+ PaginationPrevious,
147
+ PaginationNext,
148
+ PaginationEllipsis,
149
+ };
@@ -0,0 +1,119 @@
1
+ "use client";
2
+
3
+ import { Popover as PopoverPrimitive } from "@base-ui/react/popover";
4
+
5
+ import { cn } from "../../lib/utils/css";
6
+
7
+ const PopoverCreateHandle = PopoverPrimitive.createHandle;
8
+
9
+ const Popover = PopoverPrimitive.Root;
10
+
11
+ function PopoverTrigger({
12
+ className,
13
+ children,
14
+ ...props
15
+ }: PopoverPrimitive.Trigger.Props) {
16
+ return (
17
+ <PopoverPrimitive.Trigger
18
+ className={className}
19
+ data-slot="popover-trigger"
20
+ {...props}
21
+ >
22
+ {children}
23
+ </PopoverPrimitive.Trigger>
24
+ );
25
+ }
26
+
27
+ function PopoverPopup({
28
+ children,
29
+ className,
30
+ side = "bottom",
31
+ align = "center",
32
+ sideOffset = 4,
33
+ alignOffset = 0,
34
+ tooltipStyle = false,
35
+ anchor,
36
+ ...props
37
+ }: PopoverPrimitive.Popup.Props & {
38
+ side?: PopoverPrimitive.Positioner.Props["side"];
39
+ align?: PopoverPrimitive.Positioner.Props["align"];
40
+ sideOffset?: PopoverPrimitive.Positioner.Props["sideOffset"];
41
+ alignOffset?: PopoverPrimitive.Positioner.Props["alignOffset"];
42
+ tooltipStyle?: boolean;
43
+ anchor?: PopoverPrimitive.Positioner.Props["anchor"];
44
+ }) {
45
+ return (
46
+ <PopoverPrimitive.Portal>
47
+ <PopoverPrimitive.Positioner
48
+ align={align}
49
+ alignOffset={alignOffset}
50
+ anchor={anchor}
51
+ className="z-50 h-(--positioner-height) w-(--positioner-width) max-w-(--available-width) transition-[top,left,right,bottom,transform] data-instant:transition-none"
52
+ data-slot="popover-positioner"
53
+ side={side}
54
+ sideOffset={sideOffset}
55
+ >
56
+ <PopoverPrimitive.Popup
57
+ className={cn(
58
+ "relative flex h-(--popup-height,auto) w-(--popup-width,auto) origin-(--transform-origin) rounded-lg border bg-popover not-dark:bg-clip-padding text-popover-foreground shadow-lg/5 outline-none transition-[width,height,scale,opacity] before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] before:shadow-[0_1px_--theme(--color-black/4%)] has-data-[slot=calendar]:rounded-xl has-data-[slot=calendar]:before:rounded-[calc(var(--radius-xl)-1px)] data-ending-style:scale-98 data-ending-style:opacity-0 data-starting-style:scale-98 data-starting-style:opacity-0 dark:before:shadow-[0_-1px_--theme(--color-white/6%)]",
59
+ tooltipStyle &&
60
+ "w-fit text-balance rounded-md text-xs shadow-md/5 before:rounded-[calc(var(--radius-md)-1px)]",
61
+ className,
62
+ )}
63
+ data-slot="popover-popup"
64
+ {...props}
65
+ >
66
+ <PopoverPrimitive.Viewport
67
+ className={cn(
68
+ "relative size-full max-h-(--available-height) overflow-clip px-(--viewport-inline-padding) py-4 [--viewport-inline-padding:--spacing(4)] has-data-[slot=calendar]:p-2 data-instant:transition-none **:data-current:data-ending-style:opacity-0 **:data-current:data-starting-style:opacity-0 **:data-previous:data-ending-style:opacity-0 **:data-previous:data-starting-style:opacity-0 **:data-current:w-[calc(var(--popup-width)-2*var(--viewport-inline-padding)-2px)] **:data-previous:w-[calc(var(--popup-width)-2*var(--viewport-inline-padding)-2px)] **:data-current:opacity-100 **:data-previous:opacity-100 **:data-current:transition-opacity **:data-previous:transition-opacity",
69
+ tooltipStyle
70
+ ? "py-1 [--viewport-inline-padding:--spacing(2)]"
71
+ : "not-data-transitioning:overflow-y-auto",
72
+ )}
73
+ data-slot="popover-viewport"
74
+ >
75
+ {children}
76
+ </PopoverPrimitive.Viewport>
77
+ </PopoverPrimitive.Popup>
78
+ </PopoverPrimitive.Positioner>
79
+ </PopoverPrimitive.Portal>
80
+ );
81
+ }
82
+
83
+ function PopoverClose({ ...props }: PopoverPrimitive.Close.Props) {
84
+ return <PopoverPrimitive.Close data-slot="popover-close" {...props} />;
85
+ }
86
+
87
+ function PopoverTitle({ className, ...props }: PopoverPrimitive.Title.Props) {
88
+ return (
89
+ <PopoverPrimitive.Title
90
+ className={cn("font-semibold text-lg leading-none", className)}
91
+ data-slot="popover-title"
92
+ {...props}
93
+ />
94
+ );
95
+ }
96
+
97
+ function PopoverDescription({
98
+ className,
99
+ ...props
100
+ }: PopoverPrimitive.Description.Props) {
101
+ return (
102
+ <PopoverPrimitive.Description
103
+ className={cn("text-muted-foreground text-sm", className)}
104
+ data-slot="popover-description"
105
+ {...props}
106
+ />
107
+ );
108
+ }
109
+
110
+ export {
111
+ PopoverCreateHandle,
112
+ Popover,
113
+ PopoverTrigger,
114
+ PopoverPopup,
115
+ PopoverPopup as PopoverContent,
116
+ PopoverTitle,
117
+ PopoverDescription,
118
+ PopoverClose,
119
+ };
@@ -0,0 +1,55 @@
1
+ "use client";
2
+
3
+ import { PreviewCard as PreviewCardPrimitive } from "@base-ui/react/preview-card";
4
+
5
+ import { cn } from "../../lib/utils/css";
6
+
7
+ const PreviewCard = PreviewCardPrimitive.Root;
8
+
9
+ function PreviewCardTrigger({ ...props }: PreviewCardPrimitive.Trigger.Props) {
10
+ return (
11
+ <PreviewCardPrimitive.Trigger data-slot="preview-card-trigger" {...props} />
12
+ );
13
+ }
14
+
15
+ function PreviewCardPopup({
16
+ className,
17
+ children,
18
+ align = "center",
19
+ sideOffset = 4,
20
+ ...props
21
+ }: PreviewCardPrimitive.Popup.Props & {
22
+ align?: PreviewCardPrimitive.Positioner.Props["align"];
23
+ sideOffset?: PreviewCardPrimitive.Positioner.Props["sideOffset"];
24
+ }) {
25
+ return (
26
+ <PreviewCardPrimitive.Portal>
27
+ <PreviewCardPrimitive.Positioner
28
+ align={align}
29
+ className="z-50"
30
+ data-slot="preview-card-positioner"
31
+ sideOffset={sideOffset}
32
+ >
33
+ <PreviewCardPrimitive.Popup
34
+ className={cn(
35
+ "relative flex w-64 origin-(--transform-origin) text-balance rounded-lg border bg-popover not-dark:bg-clip-padding p-4 text-popover-foreground text-sm shadow-lg/5 transition-[scale,opacity] before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-lg)-1px)] before:shadow-[0_1px_--theme(--color-black/6%)] data-ending-style:scale-98 data-starting-style:scale-98 data-ending-style:opacity-0 data-starting-style:opacity-0 dark:before:shadow-[0_-1px_--theme(--color-white/6%)]",
36
+ className,
37
+ )}
38
+ data-slot="preview-card-content"
39
+ {...props}
40
+ >
41
+ {children}
42
+ </PreviewCardPrimitive.Popup>
43
+ </PreviewCardPrimitive.Positioner>
44
+ </PreviewCardPrimitive.Portal>
45
+ );
46
+ }
47
+
48
+ export {
49
+ PreviewCard,
50
+ PreviewCard as HoverCard,
51
+ PreviewCardTrigger,
52
+ PreviewCardTrigger as HoverCardTrigger,
53
+ PreviewCardPopup,
54
+ PreviewCardPopup as HoverCardContent,
55
+ };