tembro 4.2.1 → 6.0.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.
- package/CHANGELOG.md +29 -0
- package/dist/components/charts/progress-circle.d.ts +12 -3
- package/dist/components/data-table/data-table.d.ts +2 -2
- package/dist/components/feedback/index.d.ts +0 -2
- package/dist/components/layout/section.d.ts +1 -8
- package/dist/components/patterns/index.d.ts +0 -8
- package/dist/components/patterns/public.d.ts +0 -8
- package/dist/components/ui/hover-card/index.cjs +1 -0
- package/dist/components/ui/hover-card/index.d.ts +11 -0
- package/dist/components/ui/hover-card/index.js +1 -0
- package/dist/components/ui/menubar/index.cjs +1 -0
- package/dist/components/ui/menubar/index.d.ts +42 -0
- package/dist/components/ui/menubar/index.js +1 -0
- package/dist/components/ui/navigation-menu/index.cjs +1 -0
- package/dist/components/ui/navigation-menu/index.d.ts +20 -0
- package/dist/components/ui/navigation-menu/index.js +1 -0
- package/dist/components/ui/number-field/index.cjs +1 -0
- package/dist/components/ui/number-field/index.d.ts +18 -0
- package/dist/components/ui/number-field/index.js +1 -0
- package/dist/components/ui/toggle-group/index.cjs +1 -0
- package/dist/components/ui/toggle-group/index.d.ts +13 -0
- package/dist/components/ui/toggle-group/index.js +1 -0
- package/dist/components/ui/toolbar/index.cjs +1 -0
- package/dist/components/ui/toolbar/index.d.ts +14 -0
- package/dist/components/ui/toolbar/index.js +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/src/components/charts/progress-circle.cjs +1 -1
- package/dist/src/components/charts/progress-circle.js +57 -3
- package/dist/src/components/data-table/data-table.cjs +1 -1
- package/dist/src/components/data-table/data-table.js +102 -100
- package/dist/src/components/feedback/index.cjs +1 -1
- package/dist/src/components/feedback/index.js +2 -4
- package/dist/src/components/layout/index.cjs +1 -1
- package/dist/src/components/layout/index.js +3 -3
- package/dist/src/components/layout/public.cjs +1 -1
- package/dist/src/components/layout/public.js +3 -3
- package/dist/src/components/layout/section.cjs +1 -1
- package/dist/src/components/layout/section.js +2 -26
- package/dist/src/components/patterns/index.cjs +1 -1
- package/dist/src/components/patterns/index.js +2 -10
- package/dist/src/components/patterns/public.cjs +1 -1
- package/dist/src/components/patterns/public.js +2 -10
- package/dist/src/components/ui/hover-card/index.cjs +1 -0
- package/dist/src/components/ui/hover-card/index.js +50 -0
- package/dist/src/components/ui/menubar/index.cjs +1 -0
- package/dist/src/components/ui/menubar/index.js +132 -0
- package/dist/src/components/ui/navigation-menu/index.cjs +1 -0
- package/dist/src/components/ui/navigation-menu/index.js +73 -0
- package/dist/src/components/ui/number-field/index.cjs +1 -0
- package/dist/src/components/ui/number-field/index.js +73 -0
- package/dist/src/components/ui/toggle-group/index.cjs +1 -0
- package/dist/src/components/ui/toggle-group/index.js +32 -0
- package/dist/src/components/ui/toolbar/index.cjs +1 -0
- package/dist/src/components/ui/toolbar/index.js +50 -0
- package/dist/src/index.cjs +1 -1
- package/dist/src/index.js +92 -95
- package/dist/src/public-component-surface.cjs +1 -1
- package/dist/src/public-component-surface.js +31 -42
- package/package.json +1 -1
- package/packages/cli/dist/index.cjs +112 -112
- package/packages/cli/vendor/src/components/charts/progress-circle.tsx +78 -3
- package/packages/cli/vendor/src/components/data-table/data-table.tsx +4 -4
- package/packages/cli/vendor/src/components/feedback/index.ts +0 -2
- package/packages/cli/vendor/src/components/layout/section.tsx +1 -28
- package/packages/cli/vendor/src/components/patterns/index.ts +0 -8
- package/packages/cli/vendor/src/components/patterns/public.ts +0 -8
- package/packages/cli/vendor/src/components/ui/hover-card/index.tsx +72 -0
- package/packages/cli/vendor/src/components/ui/menubar/index.tsx +140 -0
- package/packages/cli/vendor/src/components/ui/navigation-menu/index.tsx +100 -0
- package/packages/cli/vendor/src/components/ui/number-field/index.tsx +89 -0
- package/packages/cli/vendor/src/components/ui/toggle-group/index.tsx +72 -0
- package/packages/cli/vendor/src/components/ui/toolbar/index.tsx +67 -0
- package/packages/cli/vendor/src/index.ts +12 -5
- package/packages/cli/vendor/src/public-component-surface.ts +7 -10
- package/packages/cli/vendor/templates/showcase/src/showcase/data/registry.ts +14 -12
- package/packages/cli/vendor/templates/showcase/src/showcase/layout/HeroSection.tsx +2 -2
- package/packages/cli/vendor/templates/showcase/src/showcase/layout/WorkbenchSidebar.tsx +1 -1
- package/packages/cli/vendor/templates/showcase/src/showcase/sections/ComponentLivePreview.tsx +2 -2
- package/packages/cli/vendor/templates/showcase/src/showcase/sections/FormsSection.tsx +2 -2
- package/packages/cli/vendor/templates/styles/globals.css +5 -5
- package/registry.json +2630 -233
- package/dist/components/charts/progress-ring.cjs +0 -1
- package/dist/components/charts/progress-ring.d.ts +0 -13
- package/dist/components/charts/progress-ring.js +0 -1
- package/dist/components/feedback/loading-state.cjs +0 -1
- package/dist/components/feedback/loading-state.d.ts +0 -9
- package/dist/components/feedback/loading-state.js +0 -1
- package/dist/components/feedback/page-state.cjs +0 -1
- package/dist/components/feedback/page-state.d.ts +0 -18
- package/dist/components/feedback/page-state.js +0 -1
- package/dist/components/layout/page-container.cjs +0 -1
- package/dist/components/layout/page-container.d.ts +0 -7
- package/dist/components/layout/page-container.js +0 -1
- package/dist/components/layout/page-header.cjs +0 -1
- package/dist/components/layout/page-header.d.ts +0 -23
- package/dist/components/layout/page-header.js +0 -1
- package/dist/components/layout/section-header.cjs +0 -1
- package/dist/components/layout/section-header.d.ts +0 -14
- package/dist/components/layout/section-header.js +0 -1
- package/dist/components/layout/sidebar-nav.cjs +0 -1
- package/dist/components/layout/sidebar-nav.d.ts +0 -37
- package/dist/components/layout/sidebar-nav.js +0 -1
- package/dist/components/layout/sticky-footer-bar.cjs +0 -1
- package/dist/components/layout/sticky-footer-bar.d.ts +0 -7
- package/dist/components/layout/sticky-footer-bar.js +0 -1
- package/dist/components/patterns/bulk-action-bar.cjs +0 -1
- package/dist/components/patterns/bulk-action-bar.d.ts +0 -10
- package/dist/components/patterns/bulk-action-bar.js +0 -1
- package/dist/components/patterns/data-view.cjs +0 -1
- package/dist/components/patterns/data-view.d.ts +0 -17
- package/dist/components/patterns/data-view.js +0 -1
- package/dist/components/patterns/detail-layout.cjs +0 -1
- package/dist/components/patterns/detail-layout.d.ts +0 -16
- package/dist/components/patterns/detail-layout.js +0 -1
- package/dist/components/patterns/form-builder.cjs +0 -1
- package/dist/components/patterns/form-builder.d.ts +0 -110
- package/dist/components/patterns/form-builder.js +0 -1
- package/dist/components/patterns/page-toolbar.cjs +0 -1
- package/dist/components/patterns/page-toolbar.d.ts +0 -11
- package/dist/components/patterns/page-toolbar.js +0 -1
- package/dist/components/patterns/resource-detail-page.cjs +0 -1
- package/dist/components/patterns/resource-detail-page.d.ts +0 -39
- package/dist/components/patterns/resource-detail-page.js +0 -1
- package/dist/components/patterns/resource-page.cjs +0 -1
- package/dist/components/patterns/resource-page.d.ts +0 -30
- package/dist/components/patterns/resource-page.js +0 -1
- package/dist/components/patterns/settings-page.cjs +0 -1
- package/dist/components/patterns/settings-page.d.ts +0 -21
- package/dist/components/patterns/settings-page.js +0 -1
- package/dist/src/components/charts/progress-ring.cjs +0 -1
- package/dist/src/components/charts/progress-ring.js +0 -57
- package/dist/src/components/feedback/loading-state.cjs +0 -1
- package/dist/src/components/feedback/loading-state.js +0 -15
- package/dist/src/components/feedback/page-state.cjs +0 -1
- package/dist/src/components/feedback/page-state.js +0 -28
- package/dist/src/components/layout/page-container.cjs +0 -1
- package/dist/src/components/layout/page-container.js +0 -21
- package/dist/src/components/layout/page-header.cjs +0 -1
- package/dist/src/components/layout/page-header.js +0 -92
- package/dist/src/components/layout/section-header.cjs +0 -1
- package/dist/src/components/layout/section-header.js +0 -44
- package/dist/src/components/layout/sidebar-nav.cjs +0 -1
- package/dist/src/components/layout/sidebar-nav.js +0 -220
- package/dist/src/components/layout/sticky-footer-bar.cjs +0 -1
- package/dist/src/components/layout/sticky-footer-bar.js +0 -20
- package/dist/src/components/patterns/bulk-action-bar.cjs +0 -1
- package/dist/src/components/patterns/bulk-action-bar.js +0 -34
- package/dist/src/components/patterns/data-view.cjs +0 -1
- package/dist/src/components/patterns/data-view.js +0 -47
- package/dist/src/components/patterns/detail-layout.cjs +0 -1
- package/dist/src/components/patterns/detail-layout.js +0 -65
- package/dist/src/components/patterns/form-builder.cjs +0 -1
- package/dist/src/components/patterns/form-builder.js +0 -263
- package/dist/src/components/patterns/page-toolbar.cjs +0 -1
- package/dist/src/components/patterns/page-toolbar.js +0 -41
- package/dist/src/components/patterns/resource-detail-page.cjs +0 -1
- package/dist/src/components/patterns/resource-detail-page.js +0 -100
- package/dist/src/components/patterns/resource-page.cjs +0 -1
- package/dist/src/components/patterns/resource-page.js +0 -88
- package/dist/src/components/patterns/settings-page.cjs +0 -1
- package/dist/src/components/patterns/settings-page.js +0 -64
- package/packages/cli/vendor/src/components/charts/progress-ring.tsx +0 -56
- package/packages/cli/vendor/src/components/feedback/loading-state.tsx +0 -15
- package/packages/cli/vendor/src/components/feedback/page-state.tsx +0 -29
- package/packages/cli/vendor/src/components/layout/page-container.tsx +0 -30
- package/packages/cli/vendor/src/components/layout/page-header.tsx +0 -104
- package/packages/cli/vendor/src/components/layout/section-header.tsx +0 -56
- package/packages/cli/vendor/src/components/layout/sidebar-nav.tsx +0 -377
- package/packages/cli/vendor/src/components/layout/sticky-footer-bar.tsx +0 -23
- package/packages/cli/vendor/src/components/patterns/bulk-action-bar.tsx +0 -53
- package/packages/cli/vendor/src/components/patterns/data-view.tsx +0 -64
- package/packages/cli/vendor/src/components/patterns/detail-layout.tsx +0 -75
- package/packages/cli/vendor/src/components/patterns/form-builder.tsx +0 -472
- package/packages/cli/vendor/src/components/patterns/page-toolbar.tsx +0 -61
- package/packages/cli/vendor/src/components/patterns/resource-detail-page.tsx +0 -164
- package/packages/cli/vendor/src/components/patterns/resource-page.tsx +0 -149
- package/packages/cli/vendor/src/components/patterns/settings-page.tsx +0 -84
|
@@ -1,7 +1,82 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as React from "react"
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import { cn } from "@/lib/utils"
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
export type ProgressCircleProps = React.ComponentProps<"svg"> & {
|
|
6
|
+
value?: number
|
|
7
|
+
max?: number
|
|
8
|
+
size?: number
|
|
9
|
+
strokeWidth?: number
|
|
10
|
+
label?: React.ReactNode
|
|
11
|
+
description?: React.ReactNode
|
|
12
|
+
tone?: "default" | "success" | "warning" | "danger"
|
|
13
|
+
loading?: boolean
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const toneClassName = {
|
|
17
|
+
default: "stroke-primary",
|
|
18
|
+
success: "stroke-[color:var(--aui-success,var(--primary))]",
|
|
19
|
+
warning: "stroke-[color:var(--aui-warning,var(--primary))]",
|
|
20
|
+
danger: "stroke-destructive",
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function ProgressCircle({
|
|
24
|
+
value,
|
|
25
|
+
max = 100,
|
|
26
|
+
size = 120,
|
|
27
|
+
strokeWidth = 10,
|
|
28
|
+
label,
|
|
29
|
+
description,
|
|
30
|
+
tone = "default",
|
|
31
|
+
loading = false,
|
|
32
|
+
className,
|
|
33
|
+
...props
|
|
34
|
+
}: ProgressCircleProps) {
|
|
35
|
+
const radius = (size - strokeWidth) / 2
|
|
36
|
+
const circumference = 2 * Math.PI * radius
|
|
37
|
+
const percentage = typeof value === "number" ? Math.min(Math.max(value / max, 0), 1) : 0
|
|
38
|
+
const offset = circumference - percentage * circumference
|
|
39
|
+
const progressLabel = label ?? (typeof value === "number" ? `${Math.round(percentage * 100)}%` : undefined)
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<svg
|
|
43
|
+
data-slot="progress-circle"
|
|
44
|
+
viewBox={`0 0 ${size} ${size}`}
|
|
45
|
+
className={cn("h-auto w-full max-w-32", className)}
|
|
46
|
+
role="img"
|
|
47
|
+
{...props}
|
|
48
|
+
>
|
|
49
|
+
<circle
|
|
50
|
+
cx={size / 2}
|
|
51
|
+
cy={size / 2}
|
|
52
|
+
r={radius}
|
|
53
|
+
fill="none"
|
|
54
|
+
strokeWidth={strokeWidth}
|
|
55
|
+
className="stroke-muted"
|
|
56
|
+
/>
|
|
57
|
+
<circle
|
|
58
|
+
cx={size / 2}
|
|
59
|
+
cy={size / 2}
|
|
60
|
+
r={radius}
|
|
61
|
+
fill="none"
|
|
62
|
+
strokeWidth={strokeWidth}
|
|
63
|
+
strokeLinecap="round"
|
|
64
|
+
strokeDasharray={circumference}
|
|
65
|
+
strokeDashoffset={loading ? circumference * 0.28 : offset}
|
|
66
|
+
className={cn("origin-center -rotate-90 transition-[stroke-dashoffset]", toneClassName[tone], loading && "animate-pulse")}
|
|
67
|
+
/>
|
|
68
|
+
{progressLabel ? (
|
|
69
|
+
<text x="50%" y={description ? "46%" : "52%"} textAnchor="middle" dominantBaseline="middle" className="fill-foreground text-lg font-semibold">
|
|
70
|
+
{progressLabel}
|
|
71
|
+
</text>
|
|
72
|
+
) : null}
|
|
73
|
+
{description ? (
|
|
74
|
+
<text x="50%" y="62%" textAnchor="middle" dominantBaseline="middle" className="fill-muted-foreground text-[10px]">
|
|
75
|
+
{description}
|
|
76
|
+
</text>
|
|
77
|
+
) : null}
|
|
78
|
+
</svg>
|
|
79
|
+
)
|
|
80
|
+
}
|
|
6
81
|
|
|
7
82
|
export { ProgressCircle }
|
|
@@ -28,7 +28,7 @@ import { DataTablePagination, type DataTablePaginationProps } from "@/components
|
|
|
28
28
|
import { type DataTableRowAction } from "@/components/data-table/data-table-row-actions"
|
|
29
29
|
import { DataTableToolbar, type DataTableToolbarProps } from "@/components/data-table/data-table-toolbar"
|
|
30
30
|
import { DataState, type DataStateProps } from "@/components/display/data-state"
|
|
31
|
-
import {
|
|
31
|
+
import { StateView, type StateViewProps } from "@/components/feedback/state-view"
|
|
32
32
|
import { Button } from "@/components/ui/button"
|
|
33
33
|
import { Input, type InputSearchProps } from "@/components/ui/input"
|
|
34
34
|
import { useIsMobile } from "@/hooks/use-is-mobile"
|
|
@@ -130,7 +130,7 @@ export type DataTableProps<TData, TValue = unknown> = Omit<
|
|
|
130
130
|
isError?: boolean
|
|
131
131
|
emptyState?: Omit<DataStateProps, "status">
|
|
132
132
|
errorState?: Omit<DataStateProps, "status">
|
|
133
|
-
loadingState?:
|
|
133
|
+
loadingState?: Omit<StateViewProps, "status">
|
|
134
134
|
loadingVariant?: DataTableLoadingVariant
|
|
135
135
|
toolbar?: React.ReactNode | ((table: TanStackTable<TData>) => React.ReactNode)
|
|
136
136
|
toolbarProps?: DataTableToolbarProps | ((table: TanStackTable<TData>) => DataTableToolbarProps)
|
|
@@ -511,7 +511,7 @@ function DataTable<TData, TValue = unknown>({
|
|
|
511
511
|
))
|
|
512
512
|
|
|
513
513
|
const stateContent = shouldRenderSkeleton ? null : isLoading ? (
|
|
514
|
-
<
|
|
514
|
+
<StateView status="loading" title="Loading data..." {...loadingState} />
|
|
515
515
|
) : isError ? (
|
|
516
516
|
<DataState status="error" title="Could not load data" description="Please try again." variant="plain" {...errorState} />
|
|
517
517
|
) : rows.length === 0 ? (
|
|
@@ -657,7 +657,7 @@ function DataTable<TData, TValue = unknown>({
|
|
|
657
657
|
<div className="grid gap-3">
|
|
658
658
|
{stateContent ??
|
|
659
659
|
(shouldRenderSkeleton ? (
|
|
660
|
-
<
|
|
660
|
+
<StateView status="loading" title="Loading data..." {...loadingState} />
|
|
661
661
|
) : (
|
|
662
662
|
rows.map((row) => (
|
|
663
663
|
<React.Fragment key={row.id}>
|
|
@@ -69,33 +69,6 @@ function Section({
|
|
|
69
69
|
)
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
export type ToolbarProps = React.ComponentProps<"div"> & {
|
|
73
|
-
title?: React.ReactNode
|
|
74
|
-
description?: React.ReactNode
|
|
75
|
-
filters?: React.ReactNode
|
|
76
|
-
actions?: React.ReactNode
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function Toolbar({ title, description, filters, actions, className, children, ...props }: ToolbarProps) {
|
|
80
|
-
return (
|
|
81
|
-
<div data-slot="toolbar" className={cn("flex flex-wrap items-center justify-between gap-3", className)} {...props}>
|
|
82
|
-
{(title || description) && (
|
|
83
|
-
<div className="grid gap-0.5">
|
|
84
|
-
{title && <div className="font-medium text-foreground">{title}</div>}
|
|
85
|
-
{description && <div className="text-sm text-muted-foreground">{description}</div>}
|
|
86
|
-
</div>
|
|
87
|
-
)}
|
|
88
|
-
{children}
|
|
89
|
-
{(filters || actions) && (
|
|
90
|
-
<div className="flex flex-wrap items-center gap-2">
|
|
91
|
-
{filters}
|
|
92
|
-
{actions}
|
|
93
|
-
</div>
|
|
94
|
-
)}
|
|
95
|
-
</div>
|
|
96
|
-
)
|
|
97
|
-
}
|
|
98
|
-
|
|
99
72
|
export type SplitLayoutProps = React.ComponentProps<"div"> & {
|
|
100
73
|
aside: React.ReactNode
|
|
101
74
|
asidePosition?: "start" | "end"
|
|
@@ -125,4 +98,4 @@ function SplitLayout({ aside, asidePosition = "end", asideClassName, contentClas
|
|
|
125
98
|
)
|
|
126
99
|
}
|
|
127
100
|
|
|
128
|
-
export { Section, SplitLayout
|
|
101
|
+
export { Section, SplitLayout }
|
|
@@ -1,9 +1 @@
|
|
|
1
|
-
export * from './form-builder'
|
|
2
|
-
export * from './resource-page'
|
|
3
|
-
export * from './resource-detail-page'
|
|
4
1
|
export * from "./empty-state"
|
|
5
|
-
export * from "./page-toolbar"
|
|
6
|
-
export * from "./bulk-action-bar"
|
|
7
|
-
export * from "./detail-layout"
|
|
8
|
-
export * from "./settings-page"
|
|
9
|
-
export * from "./data-view"
|
|
@@ -1,9 +1 @@
|
|
|
1
|
-
export * from "./form-builder"
|
|
2
|
-
export * from "./resource-page"
|
|
3
|
-
export * from "./resource-detail-page"
|
|
4
1
|
export * from "./empty-state"
|
|
5
|
-
export * from "./page-toolbar"
|
|
6
|
-
export * from "./bulk-action-bar"
|
|
7
|
-
export * from "./detail-layout"
|
|
8
|
-
export * from "./settings-page"
|
|
9
|
-
export * from "./data-view"
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import { PreviewCard as PreviewCardPrimitive } from "@base-ui/react/preview-card"
|
|
5
|
+
|
|
6
|
+
import { cn } from "@/lib/utils"
|
|
7
|
+
|
|
8
|
+
export type HoverCardProps = PreviewCardPrimitive.Root.Props
|
|
9
|
+
export type HoverCardTriggerProps = PreviewCardPrimitive.Trigger.Props
|
|
10
|
+
export type HoverCardContentProps = PreviewCardPrimitive.Popup.Props &
|
|
11
|
+
Pick<
|
|
12
|
+
PreviewCardPrimitive.Positioner.Props,
|
|
13
|
+
"align" | "alignOffset" | "collisionBoundary" | "collisionPadding" | "side" | "sideOffset"
|
|
14
|
+
>
|
|
15
|
+
export type HoverCardArrowProps = PreviewCardPrimitive.Arrow.Props
|
|
16
|
+
|
|
17
|
+
function HoverCard({ ...props }: HoverCardProps) {
|
|
18
|
+
return <PreviewCardPrimitive.Root data-slot="hover-card" {...props} />
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function HoverCardTrigger({ ...props }: HoverCardTriggerProps) {
|
|
22
|
+
if (!("render" in props) && React.isValidElement(props.children)) {
|
|
23
|
+
const { children, ...rest } = props
|
|
24
|
+
return <PreviewCardPrimitive.Trigger data-slot="hover-card-trigger" render={children} {...rest} />
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return <PreviewCardPrimitive.Trigger data-slot="hover-card-trigger" {...props} />
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function HoverCardContent({
|
|
31
|
+
className,
|
|
32
|
+
align = "center",
|
|
33
|
+
alignOffset = 0,
|
|
34
|
+
collisionPadding = 12,
|
|
35
|
+
side = "bottom",
|
|
36
|
+
sideOffset = 8,
|
|
37
|
+
...props
|
|
38
|
+
}: HoverCardContentProps) {
|
|
39
|
+
return (
|
|
40
|
+
<PreviewCardPrimitive.Portal>
|
|
41
|
+
<PreviewCardPrimitive.Positioner
|
|
42
|
+
align={align}
|
|
43
|
+
alignOffset={alignOffset}
|
|
44
|
+
collisionPadding={collisionPadding}
|
|
45
|
+
side={side}
|
|
46
|
+
sideOffset={sideOffset}
|
|
47
|
+
className="isolate z-50 outline-none"
|
|
48
|
+
>
|
|
49
|
+
<PreviewCardPrimitive.Popup
|
|
50
|
+
data-slot="hover-card-content"
|
|
51
|
+
className={cn(
|
|
52
|
+
"z-50 grid max-h-[min(var(--available-height),calc(100dvh-1rem))] w-80 max-w-[calc(100vw-1rem)] origin-(--transform-origin) gap-3 overflow-y-auto rounded-[var(--radius-lg)] border border-border bg-popover p-4 text-popover-foreground shadow-lg outline-none duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
|
|
53
|
+
className
|
|
54
|
+
)}
|
|
55
|
+
{...props}
|
|
56
|
+
/>
|
|
57
|
+
</PreviewCardPrimitive.Positioner>
|
|
58
|
+
</PreviewCardPrimitive.Portal>
|
|
59
|
+
)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function HoverCardArrow({ className, ...props }: HoverCardArrowProps) {
|
|
63
|
+
return (
|
|
64
|
+
<PreviewCardPrimitive.Arrow
|
|
65
|
+
data-slot="hover-card-arrow"
|
|
66
|
+
className={cn("z-50 flex size-3 rotate-45 border border-border bg-popover", className)}
|
|
67
|
+
{...props}
|
|
68
|
+
/>
|
|
69
|
+
)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export { HoverCard, HoverCardArrow, HoverCardContent, HoverCardTrigger }
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import { Menubar as MenubarPrimitive } from "@base-ui/react/menubar"
|
|
5
|
+
import { Menu as MenuPrimitive } from "@base-ui/react/menu"
|
|
6
|
+
import { CheckIcon, ChevronRightIcon } from "lucide-react"
|
|
7
|
+
|
|
8
|
+
import { cn } from "@/lib/utils"
|
|
9
|
+
|
|
10
|
+
export type MenubarProps = MenubarPrimitive.Props
|
|
11
|
+
export type MenubarMenuProps = MenuPrimitive.Root.Props
|
|
12
|
+
export type MenubarTriggerProps = MenuPrimitive.Trigger.Props
|
|
13
|
+
export type MenubarContentProps = MenuPrimitive.Popup.Props &
|
|
14
|
+
Pick<MenuPrimitive.Positioner.Props, "align" | "alignOffset" | "side" | "sideOffset">
|
|
15
|
+
export type MenubarItemProps = MenuPrimitive.Item.Props & { inset?: boolean; variant?: "default" | "destructive" }
|
|
16
|
+
export type MenubarCheckboxItemProps = MenuPrimitive.CheckboxItem.Props & { inset?: boolean }
|
|
17
|
+
export type MenubarRadioGroupProps = MenuPrimitive.RadioGroup.Props
|
|
18
|
+
export type MenubarRadioItemProps = MenuPrimitive.RadioItem.Props & { inset?: boolean }
|
|
19
|
+
export type MenubarSubProps = MenuPrimitive.SubmenuRoot.Props
|
|
20
|
+
export type MenubarSubTriggerProps = MenuPrimitive.SubmenuTrigger.Props & { inset?: boolean }
|
|
21
|
+
export type MenubarSeparatorProps = MenuPrimitive.Separator.Props
|
|
22
|
+
export type MenubarLabelProps = React.ComponentProps<"div"> & { inset?: boolean }
|
|
23
|
+
export type MenubarShortcutProps = React.ComponentProps<"span">
|
|
24
|
+
|
|
25
|
+
const itemClassName =
|
|
26
|
+
"relative flex min-h-8 cursor-default select-none items-center gap-2 rounded-[var(--radius-md)] px-2.5 py-1.5 text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset=true]:pl-8 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus-visible:bg-destructive/10 data-[variant=destructive]:hover:bg-destructive/10"
|
|
27
|
+
|
|
28
|
+
function Menubar({ className, ...props }: MenubarProps) {
|
|
29
|
+
return (
|
|
30
|
+
<MenubarPrimitive
|
|
31
|
+
data-slot="menubar"
|
|
32
|
+
className={cn("flex h-10 items-center gap-1 rounded-[var(--radius-lg)] border border-border bg-card p-1 text-card-foreground shadow-sm", className)}
|
|
33
|
+
{...props}
|
|
34
|
+
/>
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function MenubarMenu({ ...props }: MenubarMenuProps) {
|
|
39
|
+
return <MenuPrimitive.Root data-slot="menubar-menu" {...props} />
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function MenubarTrigger({ className, ...props }: MenubarTriggerProps) {
|
|
43
|
+
return (
|
|
44
|
+
<MenuPrimitive.Trigger
|
|
45
|
+
data-slot="menubar-trigger"
|
|
46
|
+
className={cn("inline-flex h-8 items-center justify-center rounded-[var(--radius-md)] px-3 text-sm font-medium outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground data-[popup-open]:bg-accent data-[popup-open]:text-accent-foreground disabled:pointer-events-none disabled:opacity-50", className)}
|
|
47
|
+
{...props}
|
|
48
|
+
/>
|
|
49
|
+
)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function MenubarContent({ className, align = "start", alignOffset = 0, side = "bottom", sideOffset = 6, ...props }: MenubarContentProps) {
|
|
53
|
+
return (
|
|
54
|
+
<MenuPrimitive.Portal>
|
|
55
|
+
<MenuPrimitive.Positioner align={align} alignOffset={alignOffset} side={side} sideOffset={sideOffset} className="isolate z-50 outline-none">
|
|
56
|
+
<MenuPrimitive.Popup
|
|
57
|
+
data-slot="menubar-content"
|
|
58
|
+
className={cn("z-50 min-w-48 origin-(--transform-origin) overflow-hidden rounded-[var(--radius-lg)] border border-border bg-popover p-1 text-popover-foreground shadow-lg outline-none duration-100 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", className)}
|
|
59
|
+
{...props}
|
|
60
|
+
/>
|
|
61
|
+
</MenuPrimitive.Positioner>
|
|
62
|
+
</MenuPrimitive.Portal>
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function MenubarItem({ className, inset, variant = "default", ...props }: MenubarItemProps) {
|
|
67
|
+
return <MenuPrimitive.Item data-slot="menubar-item" data-inset={inset || undefined} data-variant={variant} className={cn(itemClassName, className)} {...props} />
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function MenubarCheckboxItem({ className, children, checked, inset, ...props }: MenubarCheckboxItemProps) {
|
|
71
|
+
return (
|
|
72
|
+
<MenuPrimitive.CheckboxItem data-slot="menubar-checkbox-item" data-inset={inset || undefined} className={cn(itemClassName, "pl-8", className)} checked={checked} {...props}>
|
|
73
|
+
<span className="absolute left-2 inline-flex size-4 items-center justify-center">
|
|
74
|
+
<MenuPrimitive.CheckboxItemIndicator><CheckIcon className="size-4" /></MenuPrimitive.CheckboxItemIndicator>
|
|
75
|
+
</span>
|
|
76
|
+
{children}
|
|
77
|
+
</MenuPrimitive.CheckboxItem>
|
|
78
|
+
)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function MenubarRadioGroup({ ...props }: MenubarRadioGroupProps) {
|
|
82
|
+
return <MenuPrimitive.RadioGroup data-slot="menubar-radio-group" {...props} />
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function MenubarRadioItem({ className, children, inset, ...props }: MenubarRadioItemProps) {
|
|
86
|
+
return (
|
|
87
|
+
<MenuPrimitive.RadioItem data-slot="menubar-radio-item" data-inset={inset || undefined} className={cn(itemClassName, "pl-8", className)} {...props}>
|
|
88
|
+
<span className="absolute left-2 inline-flex size-4 items-center justify-center">
|
|
89
|
+
<MenuPrimitive.RadioItemIndicator><CheckIcon className="size-4" /></MenuPrimitive.RadioItemIndicator>
|
|
90
|
+
</span>
|
|
91
|
+
{children}
|
|
92
|
+
</MenuPrimitive.RadioItem>
|
|
93
|
+
)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function MenubarSub({ ...props }: MenubarSubProps) {
|
|
97
|
+
return <MenuPrimitive.SubmenuRoot data-slot="menubar-sub" {...props} />
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function MenubarSubTrigger({ className, children, inset, ...props }: MenubarSubTriggerProps) {
|
|
101
|
+
return (
|
|
102
|
+
<MenuPrimitive.SubmenuTrigger data-slot="menubar-sub-trigger" data-inset={inset || undefined} className={cn(itemClassName, className)} {...props}>
|
|
103
|
+
{children}
|
|
104
|
+
<ChevronRightIcon className="ml-auto size-4" />
|
|
105
|
+
</MenuPrimitive.SubmenuTrigger>
|
|
106
|
+
)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function MenubarSubContent(props: MenubarContentProps) {
|
|
110
|
+
return <MenubarContent data-slot="menubar-sub-content" side="right" align="start" alignOffset={-4} sideOffset={0} {...props} />
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function MenubarSeparator({ className, ...props }: MenubarSeparatorProps) {
|
|
114
|
+
return <MenuPrimitive.Separator data-slot="menubar-separator" className={cn("-mx-1 my-1 h-px bg-border", className)} {...props} />
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function MenubarLabel({ className, inset, ...props }: MenubarLabelProps) {
|
|
118
|
+
return <div data-slot="menubar-label" data-inset={inset || undefined} className={cn("px-2.5 py-1.5 text-xs font-semibold text-muted-foreground data-[inset=true]:pl-8", className)} {...props} />
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function MenubarShortcut({ className, ...props }: MenubarShortcutProps) {
|
|
122
|
+
return <span data-slot="menubar-shortcut" className={cn("ml-auto text-xs tracking-widest text-muted-foreground", className)} {...props} />
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export {
|
|
126
|
+
Menubar,
|
|
127
|
+
MenubarCheckboxItem,
|
|
128
|
+
MenubarContent,
|
|
129
|
+
MenubarItem,
|
|
130
|
+
MenubarLabel,
|
|
131
|
+
MenubarMenu,
|
|
132
|
+
MenubarRadioGroup,
|
|
133
|
+
MenubarRadioItem,
|
|
134
|
+
MenubarSeparator,
|
|
135
|
+
MenubarShortcut,
|
|
136
|
+
MenubarSub,
|
|
137
|
+
MenubarSubContent,
|
|
138
|
+
MenubarSubTrigger,
|
|
139
|
+
MenubarTrigger,
|
|
140
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import { NavigationMenu as NavigationMenuPrimitive } from "@base-ui/react/navigation-menu"
|
|
4
|
+
import { ChevronDownIcon } from "lucide-react"
|
|
5
|
+
|
|
6
|
+
import { cn } from "@/lib/utils"
|
|
7
|
+
|
|
8
|
+
export type NavigationMenuProps = NavigationMenuPrimitive.Root.Props
|
|
9
|
+
export type NavigationMenuListProps = NavigationMenuPrimitive.List.Props
|
|
10
|
+
export type NavigationMenuItemProps = NavigationMenuPrimitive.Item.Props
|
|
11
|
+
export type NavigationMenuTriggerProps = NavigationMenuPrimitive.Trigger.Props
|
|
12
|
+
export type NavigationMenuContentProps = NavigationMenuPrimitive.Content.Props
|
|
13
|
+
export type NavigationMenuLinkProps = NavigationMenuPrimitive.Link.Props
|
|
14
|
+
export type NavigationMenuViewportProps = NavigationMenuPrimitive.Viewport.Props
|
|
15
|
+
export type NavigationMenuPositionerProps = NavigationMenuPrimitive.Positioner.Props
|
|
16
|
+
export type NavigationMenuArrowProps = NavigationMenuPrimitive.Arrow.Props
|
|
17
|
+
|
|
18
|
+
function NavigationMenu({ className, ...props }: NavigationMenuProps) {
|
|
19
|
+
return <NavigationMenuPrimitive.Root data-slot="navigation-menu" className={cn("relative z-10 flex max-w-max flex-1 items-center justify-center", className)} {...props} />
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function NavigationMenuList({ className, ...props }: NavigationMenuListProps) {
|
|
23
|
+
return <NavigationMenuPrimitive.List data-slot="navigation-menu-list" className={cn("flex flex-1 list-none items-center justify-center gap-1", className)} {...props} />
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function NavigationMenuItem({ className, ...props }: NavigationMenuItemProps) {
|
|
27
|
+
return <NavigationMenuPrimitive.Item data-slot="navigation-menu-item" className={cn("relative", className)} {...props} />
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function NavigationMenuTrigger({ className, children, ...props }: NavigationMenuTriggerProps) {
|
|
31
|
+
return (
|
|
32
|
+
<NavigationMenuPrimitive.Trigger
|
|
33
|
+
data-slot="navigation-menu-trigger"
|
|
34
|
+
className={cn("group inline-flex h-10 items-center justify-center gap-1 rounded-[var(--radius-md)] px-4 py-2 text-sm font-medium outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground data-[popup-open]:bg-accent data-[popup-open]:text-accent-foreground disabled:pointer-events-none disabled:opacity-50", className)}
|
|
35
|
+
{...props}
|
|
36
|
+
>
|
|
37
|
+
{children}
|
|
38
|
+
<ChevronDownIcon className="size-4 shrink-0 transition-transform duration-200 group-data-[popup-open]:rotate-180" />
|
|
39
|
+
</NavigationMenuPrimitive.Trigger>
|
|
40
|
+
)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function NavigationMenuContent({ className, ...props }: NavigationMenuContentProps) {
|
|
44
|
+
return (
|
|
45
|
+
<NavigationMenuPrimitive.Content
|
|
46
|
+
data-slot="navigation-menu-content"
|
|
47
|
+
className={cn("left-0 top-0 w-full p-4 md:absolute md:w-auto", className)}
|
|
48
|
+
{...props}
|
|
49
|
+
/>
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function NavigationMenuLink({ className, ...props }: NavigationMenuLinkProps) {
|
|
54
|
+
return (
|
|
55
|
+
<NavigationMenuPrimitive.Link
|
|
56
|
+
data-slot="navigation-menu-link"
|
|
57
|
+
className={cn("block select-none rounded-[var(--radius-md)] p-3 text-sm leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground data-[active]:bg-accent data-[active]:text-accent-foreground", className)}
|
|
58
|
+
{...props}
|
|
59
|
+
/>
|
|
60
|
+
)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function NavigationMenuPositioner({ className, sideOffset = 8, ...props }: NavigationMenuPositionerProps) {
|
|
64
|
+
return (
|
|
65
|
+
<NavigationMenuPrimitive.Portal>
|
|
66
|
+
<NavigationMenuPrimitive.Positioner
|
|
67
|
+
data-slot="navigation-menu-positioner"
|
|
68
|
+
sideOffset={sideOffset}
|
|
69
|
+
className={cn("isolate z-50 flex justify-center", className)}
|
|
70
|
+
{...props}
|
|
71
|
+
/>
|
|
72
|
+
</NavigationMenuPrimitive.Portal>
|
|
73
|
+
)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function NavigationMenuViewport({ className, ...props }: NavigationMenuViewportProps) {
|
|
77
|
+
return (
|
|
78
|
+
<NavigationMenuPrimitive.Viewport
|
|
79
|
+
data-slot="navigation-menu-viewport"
|
|
80
|
+
className={cn("relative h-(--height) w-full min-w-80 origin-(--transform-origin) overflow-hidden rounded-[var(--radius-lg)] border border-border bg-popover text-popover-foreground shadow-lg duration-100 md:w-(--width) data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", className)}
|
|
81
|
+
{...props}
|
|
82
|
+
/>
|
|
83
|
+
)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function NavigationMenuArrow({ className, ...props }: NavigationMenuArrowProps) {
|
|
87
|
+
return <NavigationMenuPrimitive.Arrow data-slot="navigation-menu-arrow" className={cn("z-50 flex size-3 rotate-45 border border-border bg-popover", className)} {...props} />
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export {
|
|
91
|
+
NavigationMenu,
|
|
92
|
+
NavigationMenuArrow,
|
|
93
|
+
NavigationMenuContent,
|
|
94
|
+
NavigationMenuItem,
|
|
95
|
+
NavigationMenuLink,
|
|
96
|
+
NavigationMenuList,
|
|
97
|
+
NavigationMenuPositioner,
|
|
98
|
+
NavigationMenuTrigger,
|
|
99
|
+
NavigationMenuViewport,
|
|
100
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import { NumberField as NumberFieldPrimitive } from "@base-ui/react/number-field"
|
|
5
|
+
import { ChevronDownIcon, ChevronUpIcon } from "lucide-react"
|
|
6
|
+
|
|
7
|
+
import { cn } from "@/lib/utils"
|
|
8
|
+
|
|
9
|
+
export type NumberFieldProps = NumberFieldPrimitive.Root.Props
|
|
10
|
+
export type NumberFieldGroupProps = NumberFieldPrimitive.Group.Props
|
|
11
|
+
export type NumberFieldInputProps = NumberFieldPrimitive.Input.Props
|
|
12
|
+
export type NumberFieldIncrementProps = NumberFieldPrimitive.Increment.Props
|
|
13
|
+
export type NumberFieldDecrementProps = NumberFieldPrimitive.Decrement.Props
|
|
14
|
+
export type NumberFieldScrubAreaProps = NumberFieldPrimitive.ScrubArea.Props
|
|
15
|
+
export type NumberFieldScrubAreaCursorProps = NumberFieldPrimitive.ScrubAreaCursor.Props
|
|
16
|
+
|
|
17
|
+
function NumberField({ className, ...props }: NumberFieldProps) {
|
|
18
|
+
return <NumberFieldPrimitive.Root data-slot="number-field" className={cn("grid gap-2", className)} {...props} />
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function NumberFieldGroup({ className, ...props }: NumberFieldGroupProps) {
|
|
22
|
+
return (
|
|
23
|
+
<NumberFieldPrimitive.Group
|
|
24
|
+
data-slot="number-field-group"
|
|
25
|
+
className={cn(
|
|
26
|
+
"flex min-h-10 w-full overflow-hidden rounded-[var(--radius-md)] border border-input bg-background text-foreground shadow-xs transition-[border-color,box-shadow] focus-within:border-ring focus-within:ring-2 focus-within:ring-ring/35 has-[:disabled]:cursor-not-allowed has-[:disabled]:opacity-50",
|
|
27
|
+
className
|
|
28
|
+
)}
|
|
29
|
+
{...props}
|
|
30
|
+
/>
|
|
31
|
+
)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function NumberFieldInput({ className, ...props }: NumberFieldInputProps) {
|
|
35
|
+
return (
|
|
36
|
+
<NumberFieldPrimitive.Input
|
|
37
|
+
data-slot="number-field-input"
|
|
38
|
+
className={cn("min-w-0 flex-1 bg-transparent px-3 py-2 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed", className)}
|
|
39
|
+
{...props}
|
|
40
|
+
/>
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function NumberFieldIncrement({ className, children, ...props }: NumberFieldIncrementProps) {
|
|
45
|
+
return (
|
|
46
|
+
<NumberFieldPrimitive.Increment
|
|
47
|
+
data-slot="number-field-increment"
|
|
48
|
+
className={cn("flex h-5 w-8 items-center justify-center border-l border-border text-muted-foreground transition-colors hover:bg-muted hover:text-foreground disabled:pointer-events-none disabled:opacity-40", className)}
|
|
49
|
+
{...props}
|
|
50
|
+
>
|
|
51
|
+
{children ?? <ChevronUpIcon aria-hidden="true" className="size-3.5" />}
|
|
52
|
+
</NumberFieldPrimitive.Increment>
|
|
53
|
+
)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function NumberFieldDecrement({ className, children, ...props }: NumberFieldDecrementProps) {
|
|
57
|
+
return (
|
|
58
|
+
<NumberFieldPrimitive.Decrement
|
|
59
|
+
data-slot="number-field-decrement"
|
|
60
|
+
className={cn("flex h-5 w-8 items-center justify-center border-l border-t border-border text-muted-foreground transition-colors hover:bg-muted hover:text-foreground disabled:pointer-events-none disabled:opacity-40", className)}
|
|
61
|
+
{...props}
|
|
62
|
+
>
|
|
63
|
+
{children ?? <ChevronDownIcon aria-hidden="true" className="size-3.5" />}
|
|
64
|
+
</NumberFieldPrimitive.Decrement>
|
|
65
|
+
)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function NumberFieldStepper({ className, ...props }: React.ComponentProps<"div">) {
|
|
69
|
+
return <div data-slot="number-field-stepper" className={cn("grid shrink-0 grid-rows-2", className)} {...props} />
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function NumberFieldScrubArea({ className, ...props }: NumberFieldScrubAreaProps) {
|
|
73
|
+
return <NumberFieldPrimitive.ScrubArea data-slot="number-field-scrub-area" className={cn("cursor-ew-resize select-none", className)} {...props} />
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function NumberFieldScrubAreaCursor({ className, ...props }: NumberFieldScrubAreaCursorProps) {
|
|
77
|
+
return <NumberFieldPrimitive.ScrubAreaCursor data-slot="number-field-scrub-area-cursor" className={cn("fixed z-50 rounded bg-foreground px-2 py-1 text-xs text-background shadow-lg", className)} {...props} />
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export {
|
|
81
|
+
NumberField,
|
|
82
|
+
NumberFieldDecrement,
|
|
83
|
+
NumberFieldGroup,
|
|
84
|
+
NumberFieldIncrement,
|
|
85
|
+
NumberFieldInput,
|
|
86
|
+
NumberFieldScrubArea,
|
|
87
|
+
NumberFieldScrubAreaCursor,
|
|
88
|
+
NumberFieldStepper,
|
|
89
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import { Toggle } from "@base-ui/react/toggle"
|
|
4
|
+
import { ToggleGroup as ToggleGroupPrimitive } from "@base-ui/react/toggle-group"
|
|
5
|
+
|
|
6
|
+
import { cn } from "@/lib/utils"
|
|
7
|
+
|
|
8
|
+
export type ToggleGroupProps<TValue extends string = string> = ToggleGroupPrimitive.Props<TValue> & {
|
|
9
|
+
variant?: "default" | "outline" | "ghost"
|
|
10
|
+
size?: "sm" | "md" | "lg"
|
|
11
|
+
}
|
|
12
|
+
export type ToggleGroupItemProps<TValue extends string = string> = Toggle.Props<TValue> & {
|
|
13
|
+
variant?: ToggleGroupProps<TValue>["variant"]
|
|
14
|
+
size?: ToggleGroupProps<TValue>["size"]
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const sizeClassName = {
|
|
18
|
+
sm: "h-8 min-w-8 px-2 text-xs",
|
|
19
|
+
md: "h-9 min-w-9 px-3 text-sm",
|
|
20
|
+
lg: "h-10 min-w-10 px-3.5 text-sm",
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function ToggleGroup<TValue extends string = string>({
|
|
24
|
+
className,
|
|
25
|
+
variant = "default",
|
|
26
|
+
size = "md",
|
|
27
|
+
orientation = "horizontal",
|
|
28
|
+
...props
|
|
29
|
+
}: ToggleGroupProps<TValue>) {
|
|
30
|
+
return (
|
|
31
|
+
<ToggleGroupPrimitive
|
|
32
|
+
data-slot="toggle-group"
|
|
33
|
+
data-variant={variant}
|
|
34
|
+
data-size={size}
|
|
35
|
+
orientation={orientation}
|
|
36
|
+
className={cn(
|
|
37
|
+
"inline-flex items-center gap-1 rounded-[var(--radius-lg)]",
|
|
38
|
+
variant === "default" && "border border-border bg-muted/60 p-1",
|
|
39
|
+
variant === "outline" && "gap-0 overflow-hidden rounded-[var(--radius-lg)] border border-border",
|
|
40
|
+
orientation === "vertical" && "flex-col items-stretch",
|
|
41
|
+
className
|
|
42
|
+
)}
|
|
43
|
+
{...props}
|
|
44
|
+
/>
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function ToggleGroupItem<TValue extends string = string>({
|
|
49
|
+
className,
|
|
50
|
+
variant = "default",
|
|
51
|
+
size = "md",
|
|
52
|
+
...props
|
|
53
|
+
}: ToggleGroupItemProps<TValue>) {
|
|
54
|
+
return (
|
|
55
|
+
<Toggle
|
|
56
|
+
data-slot="toggle-group-item"
|
|
57
|
+
data-variant={variant}
|
|
58
|
+
data-size={size}
|
|
59
|
+
className={cn(
|
|
60
|
+
"inline-flex items-center justify-center gap-1.5 whitespace-nowrap font-medium outline-none transition-[background-color,color,border-color,box-shadow] disabled:pointer-events-none disabled:opacity-50 data-[pressed]:text-foreground focus-visible:ring-2 focus-visible:ring-ring [&_svg]:size-4 [&_svg]:shrink-0",
|
|
61
|
+
sizeClassName[size],
|
|
62
|
+
variant === "default" && "rounded-[calc(var(--radius-md)-1px)] text-muted-foreground hover:bg-background/70 data-[pressed]:bg-background data-[pressed]:shadow-sm",
|
|
63
|
+
variant === "outline" && "-m-px border border-border text-muted-foreground hover:bg-muted/60 data-[pressed]:bg-muted data-[pressed]:shadow-inner first:rounded-l-[var(--radius-md)] last:rounded-r-[var(--radius-md)]",
|
|
64
|
+
variant === "ghost" && "rounded-[var(--radius-md)] text-muted-foreground hover:bg-muted/70 data-[pressed]:bg-muted",
|
|
65
|
+
className
|
|
66
|
+
)}
|
|
67
|
+
{...props}
|
|
68
|
+
/>
|
|
69
|
+
)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export { ToggleGroup, ToggleGroupItem }
|