tembro 5.0.0 → 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 +14 -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/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 +3 -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/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 -91
- package/dist/src/public-component-surface.cjs +1 -1
- package/dist/src/public-component-surface.js +15 -0
- package/package.json +1 -1
- package/packages/cli/dist/index.cjs +63 -63
- 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/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 +6 -3
- package/packages/cli/vendor/src/public-component-surface.ts +3 -0
- package/packages/cli/vendor/templates/showcase/src/showcase/data/registry.ts +4 -2
- 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 +962 -431
- 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/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/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
|
@@ -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 }
|
|
@@ -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 }
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import { Toolbar as ToolbarPrimitive } from "@base-ui/react/toolbar"
|
|
4
|
+
|
|
5
|
+
import { cn } from "@/lib/utils"
|
|
6
|
+
|
|
7
|
+
export type ToolbarProps = ToolbarPrimitive.Root.Props
|
|
8
|
+
export type ToolbarGroupProps = ToolbarPrimitive.Group.Props
|
|
9
|
+
export type ToolbarButtonProps = ToolbarPrimitive.Button.Props
|
|
10
|
+
export type ToolbarLinkProps = ToolbarPrimitive.Link.Props
|
|
11
|
+
export type ToolbarInputProps = ToolbarPrimitive.Input.Props
|
|
12
|
+
export type ToolbarSeparatorProps = ToolbarPrimitive.Separator.Props
|
|
13
|
+
|
|
14
|
+
function Toolbar({ className, orientation = "horizontal", ...props }: ToolbarProps) {
|
|
15
|
+
return (
|
|
16
|
+
<ToolbarPrimitive.Root
|
|
17
|
+
data-slot="toolbar"
|
|
18
|
+
orientation={orientation}
|
|
19
|
+
className={cn(
|
|
20
|
+
"flex min-w-0 items-center gap-1 rounded-[var(--radius-lg)] border border-border bg-card p-1 text-card-foreground shadow-xs",
|
|
21
|
+
orientation === "vertical" && "w-max flex-col items-stretch",
|
|
22
|
+
className
|
|
23
|
+
)}
|
|
24
|
+
{...props}
|
|
25
|
+
/>
|
|
26
|
+
)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function ToolbarGroup({ className, ...props }: ToolbarGroupProps) {
|
|
30
|
+
return <ToolbarPrimitive.Group data-slot="toolbar-group" className={cn("flex min-w-0 items-center gap-1", className)} {...props} />
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function ToolbarButton({ className, ...props }: ToolbarButtonProps) {
|
|
34
|
+
return (
|
|
35
|
+
<ToolbarPrimitive.Button
|
|
36
|
+
data-slot="toolbar-button"
|
|
37
|
+
className={cn("inline-flex h-8 min-w-8 items-center justify-center gap-1.5 rounded-[var(--radius-md)] px-2.5 text-sm font-medium text-muted-foreground outline-none transition-colors hover:bg-muted hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 data-[pressed]:bg-muted data-[pressed]:text-foreground [&_svg]:size-4 [&_svg]:shrink-0", className)}
|
|
38
|
+
{...props}
|
|
39
|
+
/>
|
|
40
|
+
)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function ToolbarLink({ className, ...props }: ToolbarLinkProps) {
|
|
44
|
+
return (
|
|
45
|
+
<ToolbarPrimitive.Link
|
|
46
|
+
data-slot="toolbar-link"
|
|
47
|
+
className={cn("inline-flex h-8 items-center justify-center gap-1.5 rounded-[var(--radius-md)] px-2.5 text-sm font-medium text-muted-foreground outline-none transition-colors hover:bg-muted hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring", className)}
|
|
48
|
+
{...props}
|
|
49
|
+
/>
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function ToolbarInput({ className, ...props }: ToolbarInputProps) {
|
|
54
|
+
return (
|
|
55
|
+
<ToolbarPrimitive.Input
|
|
56
|
+
data-slot="toolbar-input"
|
|
57
|
+
className={cn("h-8 min-w-32 rounded-[var(--radius-md)] border border-input bg-background px-2.5 text-sm outline-none placeholder:text-muted-foreground focus-visible:ring-2 focus-visible:ring-ring", className)}
|
|
58
|
+
{...props}
|
|
59
|
+
/>
|
|
60
|
+
)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function ToolbarSeparator({ className, ...props }: ToolbarSeparatorProps) {
|
|
64
|
+
return <ToolbarPrimitive.Separator data-slot="toolbar-separator" className={cn("mx-1 h-5 w-px bg-border data-[orientation=vertical]:h-px data-[orientation=vertical]:w-full", className)} {...props} />
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export { Toolbar, ToolbarButton, ToolbarGroup, ToolbarInput, ToolbarLink, ToolbarSeparator }
|
|
@@ -24,9 +24,12 @@ export * from './components/ui/segmented-control'
|
|
|
24
24
|
export * from './components/ui/spinner'
|
|
25
25
|
export * from './components/ui/tooltip'
|
|
26
26
|
export * from './components/ui/kbd'
|
|
27
|
-
export * from './components/ui/radio-group'
|
|
28
|
-
export * from './components/ui/scroll-box'
|
|
29
|
-
export * from './components/ui/right-click-menu'
|
|
27
|
+
export * from './components/ui/radio-group'
|
|
28
|
+
export * from './components/ui/scroll-box'
|
|
29
|
+
export * from './components/ui/right-click-menu'
|
|
30
|
+
export * from './components/ui/number-field'
|
|
31
|
+
export * from './components/ui/toggle-group'
|
|
32
|
+
export * from './components/ui/toolbar'
|
|
30
33
|
|
|
31
34
|
// Reusable groups
|
|
32
35
|
export * from './components/actions/public'
|
|
@@ -16,6 +16,9 @@ export const documentedPublicComponentSurfaces: readonly PublicComponentSurfaceE
|
|
|
16
16
|
{ slug: "checkbox", registryName: "checkbox", surface: "documented" },
|
|
17
17
|
{ slug: "switch", registryName: "switch", surface: "documented" },
|
|
18
18
|
{ slug: "radio-group", registryName: "radio-group", surface: "documented" },
|
|
19
|
+
{ slug: "number-field", registryName: "number-field", surface: "documented" },
|
|
20
|
+
{ slug: "toggle-group", registryName: "toggle-group", surface: "documented" },
|
|
21
|
+
{ slug: "toolbar", registryName: "toolbar", surface: "documented" },
|
|
19
22
|
{ slug: "overlay", registryName: "dialog", surface: "documented" },
|
|
20
23
|
{ slug: "dropdown-menu", registryName: "dropdown-menu", surface: "documented" },
|
|
21
24
|
{ slug: "popover", registryName: "popover", surface: "documented" },
|
|
@@ -52,6 +52,8 @@ export const registryGroups: RegistryGroup[] = [
|
|
|
52
52
|
component("kbd", "stable", "src/components/ui/kbd"),
|
|
53
53
|
component("scroll-box", "stable", "src/components/ui/scroll-box"),
|
|
54
54
|
component("right-click-menu", "stable", "src/components/ui/right-click-menu"),
|
|
55
|
+
component("toggle-group", "preview", "src/components/ui/toggle-group"),
|
|
56
|
+
component("toolbar", "preview", "src/components/ui/toolbar"),
|
|
55
57
|
component("collapse", "preview", "src/components/ui/collapse"),
|
|
56
58
|
component("command", "preview", "src/components/ui/command"),
|
|
57
59
|
component("divider", "preview", "src/components/ui/divider"),
|
|
@@ -80,6 +82,7 @@ export const registryGroups: RegistryGroup[] = [
|
|
|
80
82
|
component("inline-editable", "preview", "src/components/inputs/inline-editable.tsx"),
|
|
81
83
|
component("json-input", "preview", "src/components/inputs/json-input.tsx"),
|
|
82
84
|
component("time-picker", "preview", "src/components/inputs/time-picker.tsx"),
|
|
85
|
+
component("number-field", "preview", "src/components/ui/number-field"),
|
|
83
86
|
],
|
|
84
87
|
},
|
|
85
88
|
{
|
|
@@ -139,8 +142,7 @@ export const registryGroups: RegistryGroup[] = [
|
|
|
139
142
|
{
|
|
140
143
|
name: "feedback",
|
|
141
144
|
components: [
|
|
142
|
-
component("
|
|
143
|
-
component("page-state", "preview", "src/components/feedback/page-state.tsx"),
|
|
145
|
+
component("state-view", "stable", "src/components/feedback/state-view.tsx"),
|
|
144
146
|
component("alert", "preview", "src/components/feedback/alert.tsx"),
|
|
145
147
|
],
|
|
146
148
|
},
|
|
@@ -25,7 +25,7 @@ export function HeroSection() {
|
|
|
25
25
|
<div className="flex flex-wrap gap-2">
|
|
26
26
|
<Button leftIcon={<PlusIcon className="size-4" />}>Create</Button>
|
|
27
27
|
<Button variant="outline" leftIcon={<SettingsIcon className="size-4" />}>Settings</Button>
|
|
28
|
-
<CopyButton value="npx tembro@
|
|
28
|
+
<CopyButton value="npx tembro@6.0.0 list --json">Copy list command</CopyButton>
|
|
29
29
|
</div>
|
|
30
30
|
</div>
|
|
31
31
|
|
|
@@ -33,7 +33,7 @@ export function HeroSection() {
|
|
|
33
33
|
<StatisticCard label="Registry components" value={moduleCount} change="visible below" trend="up" description="tembro add <name>" />
|
|
34
34
|
<StatisticCard label="Local source files" value="152" change="with hooks/lib" trend="up" description="installed by CLI" />
|
|
35
35
|
<StatisticCard label="Categories" value={registryGroups.length} change="all shown" trend="up" description="actions to wizard" />
|
|
36
|
-
<StatisticCard label="Build" value="Pass" change="doctor pass" trend="up" description="tembro@
|
|
36
|
+
<StatisticCard label="Build" value="Pass" change="doctor pass" trend="up" description="tembro@6.0.0" />
|
|
37
37
|
</StatisticGrid>
|
|
38
38
|
</div>
|
|
39
39
|
</section>
|
package/packages/cli/vendor/templates/showcase/src/showcase/sections/ComponentLivePreview.tsx
CHANGED
|
@@ -19,7 +19,7 @@ import { StatusLegend } from "@/components/display/status-legend"
|
|
|
19
19
|
import { Tag, TagGroup } from "@/components/display/tag"
|
|
20
20
|
import { Timeline } from "@/components/display/timeline"
|
|
21
21
|
import { Alert } from "@/components/feedback/alert"
|
|
22
|
-
import {
|
|
22
|
+
import { StateView } from "@/components/feedback/state-view"
|
|
23
23
|
import { Pagination } from "@/components/navigation/pagination"
|
|
24
24
|
import { EmptyState } from "@/components/patterns/empty-state"
|
|
25
25
|
import { Badge } from "@/components/ui/badge"
|
|
@@ -283,7 +283,7 @@ function DirectComponentSurface({ group, component }: ComponentLivePreviewProps)
|
|
|
283
283
|
if (group.name === "form") return <FormsSection />
|
|
284
284
|
if (group.name === "display") return <DisplayPreview />
|
|
285
285
|
if (group.name === "calendar" || group.name === "navigation") return group.name === "navigation" ? <Pagination page={2} pageCount={8} onPageChange={() => undefined} /> : <CalendarSection />
|
|
286
|
-
if (group.name === "feedback") return component.name === "alert" ? <Alert tone="success" title="Alert component" description="Rendered from feedback/alert." /> : <
|
|
286
|
+
if (group.name === "feedback") return component.name === "alert" ? <Alert tone="success" title="Alert component" description="Rendered from feedback/alert." /> : <StateView status="loading" title="StateView" description="Rendered from feedback/state-view." />
|
|
287
287
|
if (group.name === "patterns") return <EmptyState title="EmptyState component" description="Rendered from patterns/empty-state." primaryAction={{ label: "Create item" }} secondaryAction={{ label: "Reset" }} />
|
|
288
288
|
if (group.name === "wizard") return <WizardSection />
|
|
289
289
|
if (group.name === "overlay") return <OverlaySection />
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ProgressCard } from "@/components/display/progress"
|
|
2
|
-
import {
|
|
2
|
+
import { StateView } from "@/components/feedback/state-view"
|
|
3
3
|
import { Rating } from "@/components/inputs/rating"
|
|
4
4
|
import { RangeSlider, Slider } from "@/components/inputs/slider"
|
|
5
5
|
import { Badge } from "@/components/ui/badge"
|
|
@@ -20,7 +20,7 @@ export function FormsSection() {
|
|
|
20
20
|
</CardContent>
|
|
21
21
|
</Card>
|
|
22
22
|
<ProgressCard title="Form completeness" description="input, select, switch, textarea" value={86} tone="success" footer={<Badge label="forms" status="success" />} />
|
|
23
|
-
<
|
|
23
|
+
<StateView status="loading" title="Loading state" description="Spinner/skeleton/progress state component." />
|
|
24
24
|
</div>
|
|
25
25
|
)
|
|
26
26
|
}
|
|
@@ -1876,17 +1876,17 @@
|
|
|
1876
1876
|
[data-slot="statistic-change"][data-trend="up"] { color: var(--aui-success-fg); background: var(--aui-success-bg); }
|
|
1877
1877
|
[data-slot="statistic-change"][data-trend="down"] { color: var(--destructive); background: color-mix(in oklch, var(--destructive), transparent 90%); }
|
|
1878
1878
|
|
|
1879
|
-
[data-slot="
|
|
1879
|
+
[data-slot="state-view"] {
|
|
1880
1880
|
border-color: var(--aui-card-border, var(--border));
|
|
1881
1881
|
border-radius: var(--aui-radius-panel);
|
|
1882
1882
|
background: var(--card);
|
|
1883
1883
|
box-shadow: var(--aui-card-shadow, var(--aui-shadow-xs));
|
|
1884
1884
|
}
|
|
1885
1885
|
|
|
1886
|
-
[data-slot="
|
|
1887
|
-
[data-slot="
|
|
1888
|
-
[data-slot="
|
|
1889
|
-
[data-slot="
|
|
1886
|
+
[data-slot="state-view-icon"] { color: var(--muted-foreground); background: var(--aui-surface-muted); }
|
|
1887
|
+
[data-slot="state-view"][data-tone="danger"] [data-slot="state-view-icon"] { color: var(--destructive); background: color-mix(in oklch, var(--destructive), transparent 90%); }
|
|
1888
|
+
[data-slot="state-view"][data-tone="success"] [data-slot="state-view-icon"] { color: var(--aui-success-fg); background: var(--aui-success-bg); }
|
|
1889
|
+
[data-slot="state-view"][data-tone="info"] [data-slot="state-view-icon"] { color: var(--aui-info-fg); background: var(--aui-info-bg); }
|
|
1890
1890
|
|
|
1891
1891
|
[data-slot="file-upload-dropzone"],
|
|
1892
1892
|
[data-slot="file-upload-item"] {
|