@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,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,102 @@
1
+ "use client";
2
+
3
+ import { Fragment } from "react";
4
+ import type * as React from "react";
5
+ import { ChevronRight } from "lucide-react";
6
+
7
+ import { cn } from "../../lib/utils/css";
8
+
9
+ interface PipelineStage {
10
+ /** The headline number for the stage. */
11
+ value: React.ReactNode;
12
+ /** The stage caption, e.g. "Target accounts". */
13
+ label: React.ReactNode;
14
+ /** Render the value in the brand/primary color (e.g. a final stage). */
15
+ accent?: boolean;
16
+ }
17
+
18
+ interface PipelineProps extends React.ComponentProps<"div"> {
19
+ /** Ordered funnel stages, left to right. */
20
+ stages: PipelineStage[];
21
+ /**
22
+ * Step-to-step conversion markers. `conversions[i]` is the share of stage `i`
23
+ * that advances to stage `i + 1`, and is shown as a pill right beside stage
24
+ * `i`'s number (length = `stages.length - 1`). Typically a percentage string.
25
+ */
26
+ conversions?: React.ReactNode[];
27
+ }
28
+
29
+ /**
30
+ * A conversion funnel — equal-width stages laid left to right. Each stage
31
+ * carries its own step-to-step conversion in a pill next to the number, and a
32
+ * chevron points to the next stage, so the row reads as a flow rather than a
33
+ * set of loose stats.
34
+ *
35
+ * The component is its own container query context: when it gets narrow (e.g.
36
+ * beside a docked panel) the chevrons hide and the stages reflow into a
37
+ * two-column grid, staying readable without squashing the numbers.
38
+ */
39
+ function Pipeline({ stages, conversions = [], className, ...props }: PipelineProps) {
40
+ return (
41
+ <div
42
+ className={cn(
43
+ "@container flex items-stretch @max-[560px]:grid @max-[560px]:grid-cols-2 @max-[560px]:gap-x-6 @max-[560px]:gap-y-5",
44
+ className,
45
+ )}
46
+ data-slot="pipeline"
47
+ {...props}
48
+ >
49
+ {stages.map((stage, i) => {
50
+ const conv = i < stages.length - 1 ? conversions[i] : undefined;
51
+ return (
52
+ <Fragment key={i}>
53
+ <div className="min-w-0 flex-1 px-0.5" data-slot="pipeline-stage">
54
+ <div className="flex items-center gap-2">
55
+ <span
56
+ className={cn(
57
+ "font-sans font-bold text-3xl text-foreground leading-none tabular-nums tracking-tight",
58
+ stage.accent && "text-success",
59
+ )}
60
+ >
61
+ {stage.value}
62
+ </span>
63
+ {conv != null ? <PipelineConversion>{conv}</PipelineConversion> : null}
64
+ </div>
65
+ <div className="mt-2 text-muted-foreground text-xs leading-snug">
66
+ {stage.label}
67
+ </div>
68
+ </div>
69
+ {conv != null ? (
70
+ <div
71
+ className="flex flex-none items-center px-1 @max-[560px]:hidden"
72
+ data-slot="pipeline-arrow"
73
+ aria-hidden
74
+ >
75
+ <ChevronRight className="size-3.5 text-muted-foreground/40" />
76
+ </div>
77
+ ) : null}
78
+ </Fragment>
79
+ );
80
+ })}
81
+ </div>
82
+ );
83
+ }
84
+
85
+ /** The conversion pill sitting beside a stage number. */
86
+ function PipelineConversion({
87
+ className,
88
+ ...props
89
+ }: React.ComponentProps<"span">) {
90
+ return (
91
+ <span
92
+ className={cn(
93
+ "inline-flex items-center rounded-full border border-success/20 bg-success/10 px-2 py-0.5 font-medium text-[11px] text-success tabular-nums dark:bg-success/16",
94
+ className,
95
+ )}
96
+ data-slot="pipeline-conversion"
97
+ {...props}
98
+ />
99
+ );
100
+ }
101
+
102
+ export { Pipeline, PipelineConversion, type PipelineProps, type PipelineStage };
@@ -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
+ };