@dowel-ui/react 0.5.0 → 0.7.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/README.md +1 -1
- package/dist/blocks/admin-dashboard/meta.js +31 -0
- package/dist/blocks/admin-dashboard/meta.js.map +1 -0
- package/dist/blocks/agent-console/meta.js +27 -0
- package/dist/blocks/agent-console/meta.js.map +1 -0
- package/dist/blocks/ai-dashboard/meta.js +25 -0
- package/dist/blocks/ai-dashboard/meta.js.map +1 -0
- package/dist/blocks/ai-workspace/meta.js +33 -0
- package/dist/blocks/ai-workspace/meta.js.map +1 -0
- package/dist/blocks/analytics/meta.js +24 -0
- package/dist/blocks/analytics/meta.js.map +1 -0
- package/dist/blocks/billing/meta.js +25 -0
- package/dist/blocks/billing/meta.js.map +1 -0
- package/dist/blocks/command-center/meta.js +28 -0
- package/dist/blocks/command-center/meta.js.map +1 -0
- package/dist/blocks/crm/meta.js +32 -0
- package/dist/blocks/crm/meta.js.map +1 -0
- package/dist/blocks/onboarding/meta.js +23 -0
- package/dist/blocks/onboarding/meta.js.map +1 -0
- package/dist/components/accordion/accordion.js +1 -1
- package/dist/components/accordion/accordion.js.map +1 -1
- package/dist/components/activity-feed/activity-feed.js +1 -1
- package/dist/components/activity-feed/activity-feed.js.map +1 -1
- package/dist/components/ai-agent-plan/ai-agent-plan.js +1 -1
- package/dist/components/ai-agent-plan/ai-agent-plan.js.map +1 -1
- package/dist/components/ai-extraction-review/ai-extraction-review.js +1 -1
- package/dist/components/ai-extraction-review/ai-extraction-review.js.map +1 -1
- package/dist/components/ai-prompt-input/ai-prompt-input.js +1 -1
- package/dist/components/ai-prompt-input/ai-prompt-input.js.map +1 -1
- package/dist/components/ai-reasoning/ai-reasoning.js +1 -1
- package/dist/components/ai-reasoning/ai-reasoning.js.map +1 -1
- package/dist/components/ai-response/ai-response.js +2 -2
- package/dist/components/ai-response/ai-response.js.map +1 -1
- package/dist/components/ai-tool/ai-tool.js +2 -2
- package/dist/components/ai-tool/ai-tool.js.map +1 -1
- package/dist/components/alert/alert.d.ts +1 -1
- package/dist/components/avatar/avatar.d.ts +1 -1
- package/dist/components/badge/badge.d.ts +1 -1
- package/dist/components/breadcrumb/breadcrumb.d.ts +52 -0
- package/dist/components/breadcrumb/breadcrumb.d.ts.map +1 -0
- package/dist/components/breadcrumb/breadcrumb.js +141 -0
- package/dist/components/breadcrumb/breadcrumb.js.map +1 -0
- package/dist/components/breadcrumb/index.d.ts +2 -0
- package/dist/components/breadcrumb/index.js +2 -0
- package/dist/components/breadcrumb/meta.js +17 -0
- package/dist/components/breadcrumb/meta.js.map +1 -0
- package/dist/components/button/button.d.ts +1 -1
- package/dist/components/calendar/calendar.js +2 -2
- package/dist/components/calendar/calendar.js.map +1 -1
- package/dist/components/code-block/code-block.js +1 -1
- package/dist/components/code-block/code-block.js.map +1 -1
- package/dist/components/collapsible/collapsible.d.ts +30 -0
- package/dist/components/collapsible/collapsible.d.ts.map +1 -0
- package/dist/components/collapsible/collapsible.js +38 -0
- package/dist/components/collapsible/collapsible.js.map +1 -0
- package/dist/components/collapsible/index.d.ts +2 -0
- package/dist/components/collapsible/index.js +2 -0
- package/dist/components/collapsible/meta.js +17 -0
- package/dist/components/collapsible/meta.js.map +1 -0
- package/dist/components/combobox/combobox.js +2 -2
- package/dist/components/combobox/combobox.js.map +1 -1
- package/dist/components/command/command.js +1 -1
- package/dist/components/command/command.js.map +1 -1
- package/dist/components/data-table/data-table.d.ts.map +1 -1
- package/dist/components/data-table/data-table.js +4 -1
- package/dist/components/data-table/data-table.js.map +1 -1
- package/dist/components/dialog/dialog.js +2 -2
- package/dist/components/dialog/dialog.js.map +1 -1
- package/dist/components/diff-viewer/diff-viewer.js +4 -4
- package/dist/components/diff-viewer/diff-viewer.js.map +1 -1
- package/dist/components/direction/direction.d.ts +35 -0
- package/dist/components/direction/direction.d.ts.map +1 -0
- package/dist/components/direction/direction.js +14 -0
- package/dist/components/direction/direction.js.map +1 -0
- package/dist/components/direction/index.d.ts +2 -0
- package/dist/components/direction/index.js +2 -0
- package/dist/components/direction/meta.js +17 -0
- package/dist/components/direction/meta.js.map +1 -0
- package/dist/components/drawer/drawer.js +1 -1
- package/dist/components/drawer/drawer.js.map +1 -1
- package/dist/components/dropdown-menu/dropdown-menu.d.ts.map +1 -1
- package/dist/components/dropdown-menu/dropdown-menu.js +9 -8
- package/dist/components/dropdown-menu/dropdown-menu.js.map +1 -1
- package/dist/components/input/input.js +1 -1
- package/dist/components/input/input.js.map +1 -1
- package/dist/components/log-viewer/log-viewer.js +2 -2
- package/dist/components/log-viewer/log-viewer.js.map +1 -1
- package/dist/components/meter/meter.js +1 -1
- package/dist/components/meter/meter.js.map +1 -1
- package/dist/components/pagination/pagination.d.ts.map +1 -1
- package/dist/components/pagination/pagination.js +3 -2
- package/dist/components/pagination/pagination.js.map +1 -1
- package/dist/components/permission-matrix/permission-matrix.js +3 -3
- package/dist/components/permission-matrix/permission-matrix.js.map +1 -1
- package/dist/components/progress/progress.d.ts +1 -1
- package/dist/components/record-diff/record-diff.js +4 -4
- package/dist/components/record-diff/record-diff.js.map +1 -1
- package/dist/components/select/select.js +2 -2
- package/dist/components/select/select.js.map +1 -1
- package/dist/components/sheet/sheet.d.ts.map +1 -1
- package/dist/components/sheet/sheet.js +2 -2
- package/dist/components/sheet/sheet.js.map +1 -1
- package/dist/components/sidebar/index.d.ts +2 -0
- package/dist/components/sidebar/index.js +2 -0
- package/dist/components/sidebar/meta.js +17 -0
- package/dist/components/sidebar/meta.js.map +1 -0
- package/dist/components/sidebar/sidebar.d.ts +69 -0
- package/dist/components/sidebar/sidebar.d.ts.map +1 -0
- package/dist/components/sidebar/sidebar.js +256 -0
- package/dist/components/sidebar/sidebar.js.map +1 -0
- package/dist/components/spinner/spinner.d.ts +1 -1
- package/dist/components/table/table.js +2 -2
- package/dist/components/table/table.js.map +1 -1
- package/dist/components/tags-input/tags-input.js +1 -1
- package/dist/components/tags-input/tags-input.js.map +1 -1
- package/dist/components/textarea/index.d.ts +2 -0
- package/dist/components/textarea/index.js +2 -0
- package/dist/components/textarea/meta.js +17 -0
- package/dist/components/textarea/meta.js.map +1 -0
- package/dist/components/textarea/textarea.d.ts +43 -0
- package/dist/components/textarea/textarea.d.ts.map +1 -0
- package/dist/components/textarea/textarea.js +119 -0
- package/dist/components/textarea/textarea.js.map +1 -0
- package/dist/components/time-range-picker/time-range-picker.js +3 -3
- package/dist/components/time-range-picker/time-range-picker.js.map +1 -1
- package/dist/components/toast/toast.d.ts +1 -1
- package/dist/components/toast/toast.d.ts.map +1 -1
- package/dist/components/toast/toast.js +2 -2
- package/dist/components/toast/toast.js.map +1 -1
- package/dist/index.d.ts +12 -2
- package/dist/index.js +7 -2
- package/dist/lib/styles.d.ts +16 -1
- package/dist/lib/styles.d.ts.map +1 -1
- package/dist/lib/styles.js +16 -1
- package/dist/lib/styles.js.map +1 -1
- package/dist/registry/blocks.d.ts.map +1 -1
- package/dist/registry/blocks.js +27 -9
- package/dist/registry/blocks.js.map +1 -1
- package/dist/registry/components.d.ts.map +1 -1
- package/dist/registry/components.js +60 -50
- package/dist/registry/components.js.map +1 -1
- package/dist/registry/schema.d.ts +8 -0
- package/dist/registry/schema.d.ts.map +1 -1
- package/dist/registry/schema.js.map +1 -1
- package/package.json +5 -4
- package/src/components/accordion/accordion.tsx +1 -1
- package/src/components/activity-feed/activity-feed.tsx +1 -1
- package/src/components/ai-agent-plan/ai-agent-plan.tsx +0 -0
- package/src/components/ai-extraction-review/ai-extraction-review.tsx +1 -1
- package/src/components/ai-prompt-input/ai-prompt-input.tsx +1 -1
- package/src/components/ai-reasoning/ai-reasoning.tsx +1 -1
- package/src/components/ai-response/ai-response.tsx +2 -2
- package/src/components/ai-tool/ai-tool.tsx +2 -2
- package/src/components/breadcrumb/breadcrumb.tsx +157 -0
- package/src/components/breadcrumb/index.ts +10 -0
- package/src/components/breadcrumb/meta.ts +19 -0
- package/src/components/calendar/calendar.tsx +2 -2
- package/src/components/code-block/code-block.tsx +1 -1
- package/src/components/collapsible/collapsible.tsx +63 -0
- package/src/components/collapsible/index.ts +6 -0
- package/src/components/collapsible/meta.ts +16 -0
- package/src/components/combobox/combobox.tsx +2 -2
- package/src/components/command/command.tsx +1 -1
- package/src/components/data-table/data-table.tsx +14 -3
- package/src/components/dialog/dialog.tsx +2 -2
- package/src/components/diff-viewer/diff-viewer.tsx +4 -4
- package/src/components/direction/direction.tsx +38 -0
- package/src/components/direction/index.ts +1 -0
- package/src/components/direction/meta.ts +19 -0
- package/src/components/drawer/drawer.tsx +1 -1
- package/src/components/dropdown-menu/dropdown-menu.tsx +14 -8
- package/src/components/input/input.tsx +1 -1
- package/src/components/log-viewer/log-viewer.tsx +2 -2
- package/src/components/meter/meter.tsx +1 -1
- package/src/components/pagination/pagination.tsx +13 -2
- package/src/components/permission-matrix/permission-matrix.tsx +4 -4
- package/src/components/record-diff/record-diff.tsx +4 -4
- package/src/components/select/select.tsx +2 -2
- package/src/components/sheet/sheet.tsx +8 -4
- package/src/components/sidebar/index.ts +19 -0
- package/src/components/sidebar/meta.ts +25 -0
- package/src/components/sidebar/sidebar.tsx +374 -0
- package/src/components/table/table.tsx +3 -3
- package/src/components/tags-input/tags-input.tsx +1 -1
- package/src/components/textarea/index.ts +1 -0
- package/src/components/textarea/meta.ts +21 -0
- package/src/components/textarea/textarea.tsx +210 -0
- package/src/components/time-range-picker/time-range-picker.tsx +3 -3
- package/src/components/toast/toast.tsx +14 -6
- package/src/index.ts +5 -0
- package/src/lib/styles.ts +16 -0
- package/src/registry/blocks.ts +18 -0
- package/src/registry/components.ts +10 -0
- package/src/registry/schema.ts +8 -0
- package/src/blocks/admin-users/admin-users.tsx +0 -251
- package/src/blocks/admin-users/index.ts +0 -1
- package/src/blocks/admin-users/meta.ts +0 -27
- package/src/blocks/ai-chat/ai-chat.tsx +0 -280
- package/src/blocks/ai-chat/index.ts +0 -7
- package/src/blocks/ai-chat/meta.ts +0 -32
- package/src/blocks/dashboard/dashboard.tsx +0 -192
- package/src/blocks/dashboard/index.ts +0 -6
- package/src/blocks/dashboard/meta.ts +0 -18
- package/src/blocks/forgot-password/forgot-password.tsx +0 -158
- package/src/blocks/forgot-password/index.ts +0 -1
- package/src/blocks/forgot-password/meta.ts +0 -18
- package/src/blocks/login/index.ts +0 -1
- package/src/blocks/login/login.tsx +0 -178
- package/src/blocks/login/meta.ts +0 -18
- package/src/blocks/pricing/index.ts +0 -1
- package/src/blocks/pricing/meta.ts +0 -18
- package/src/blocks/pricing/pricing.tsx +0 -176
- package/src/blocks/settings/index.ts +0 -6
- package/src/blocks/settings/meta.ts +0 -29
- package/src/blocks/settings/settings.tsx +0 -317
- package/src/blocks/signup/index.ts +0 -1
- package/src/blocks/signup/meta.ts +0 -18
- package/src/blocks/signup/signup.tsx +0 -240
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { Slot } from "radix-ui";
|
|
2
|
+
import type { ComponentPropsWithRef } from "react";
|
|
3
|
+
|
|
4
|
+
import { focusRing, mirrorForDirection } from "@/lib/styles";
|
|
5
|
+
import { cn } from "@/lib/utils";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Where this page sits in the hierarchy.
|
|
9
|
+
*
|
|
10
|
+
* Three things separate a breadcrumb that works from one that only looks like
|
|
11
|
+
* one, and all three are about the last item.
|
|
12
|
+
*
|
|
13
|
+
* It is not a link. A link to the page you are already on is a control that
|
|
14
|
+
* does nothing, and in a screen reader's list of links it is indistinguishable
|
|
15
|
+
* from the ones that go somewhere.
|
|
16
|
+
*
|
|
17
|
+
* It carries `aria-current="page"`. Bolding it says "you are here" to people
|
|
18
|
+
* who can see it and to nobody else.
|
|
19
|
+
*
|
|
20
|
+
* The separators are hidden. A slash between every item is read aloud as
|
|
21
|
+
* "slash" — "Home slash Projects slash Settings" — which is the punctuation of
|
|
22
|
+
* the design leaking into the content.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
export function Breadcrumb({ className, ...props }: ComponentPropsWithRef<"nav">) {
|
|
26
|
+
return (
|
|
27
|
+
<nav
|
|
28
|
+
// Named, because a page can have more than one navigation landmark and
|
|
29
|
+
// "navigation" on its own does not say which this is.
|
|
30
|
+
aria-label="Breadcrumb"
|
|
31
|
+
data-slot="breadcrumb"
|
|
32
|
+
className={cn("min-w-0", className)}
|
|
33
|
+
{...props}
|
|
34
|
+
/>
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function BreadcrumbList({ className, ...props }: ComponentPropsWithRef<"ol">) {
|
|
39
|
+
return (
|
|
40
|
+
<ol
|
|
41
|
+
data-slot="breadcrumb-list"
|
|
42
|
+
className={cn(
|
|
43
|
+
"flex flex-wrap items-center gap-1.5 text-sm text-muted-foreground",
|
|
44
|
+
className,
|
|
45
|
+
)}
|
|
46
|
+
{...props}
|
|
47
|
+
/>
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function BreadcrumbItem({ className, ...props }: ComponentPropsWithRef<"li">) {
|
|
52
|
+
return (
|
|
53
|
+
<li
|
|
54
|
+
data-slot="breadcrumb-item"
|
|
55
|
+
className={cn("inline-flex items-center gap-1.5", className)}
|
|
56
|
+
{...props}
|
|
57
|
+
/>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface BreadcrumbLinkProps extends ComponentPropsWithRef<"a"> {
|
|
62
|
+
/** Render the child as the link, for a router's own component. */
|
|
63
|
+
asChild?: boolean;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function BreadcrumbLink({ className, asChild = false, ...props }: BreadcrumbLinkProps) {
|
|
67
|
+
const Component = asChild ? Slot.Root : "a";
|
|
68
|
+
|
|
69
|
+
return (
|
|
70
|
+
<Component
|
|
71
|
+
data-slot="breadcrumb-link"
|
|
72
|
+
className={cn(
|
|
73
|
+
"rounded-sm transition-colors duration-[var(--duration-fast)]",
|
|
74
|
+
"hover:text-foreground",
|
|
75
|
+
focusRing,
|
|
76
|
+
className,
|
|
77
|
+
)}
|
|
78
|
+
{...props}
|
|
79
|
+
/>
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* The page you are on.
|
|
85
|
+
*
|
|
86
|
+
* A span, not a link: there is nowhere to go. `aria-current="page"` is what
|
|
87
|
+
* says "you are here" to anything that is not looking at the font weight.
|
|
88
|
+
*/
|
|
89
|
+
export function BreadcrumbPage({ className, ...props }: ComponentPropsWithRef<"span">) {
|
|
90
|
+
return (
|
|
91
|
+
<span
|
|
92
|
+
data-slot="breadcrumb-page"
|
|
93
|
+
aria-current="page"
|
|
94
|
+
className={cn("font-medium text-foreground", className)}
|
|
95
|
+
{...props}
|
|
96
|
+
/>
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* The mark between items.
|
|
102
|
+
*
|
|
103
|
+
* Hidden from assistive technology and given no accessible name: the list
|
|
104
|
+
* structure already conveys the sequence, and reading "slash" between every
|
|
105
|
+
* item is the design's punctuation leaking into the content.
|
|
106
|
+
*/
|
|
107
|
+
export function BreadcrumbSeparator({
|
|
108
|
+
className,
|
|
109
|
+
children,
|
|
110
|
+
...props
|
|
111
|
+
}: ComponentPropsWithRef<"li">) {
|
|
112
|
+
return (
|
|
113
|
+
<li
|
|
114
|
+
data-slot="breadcrumb-separator"
|
|
115
|
+
role="presentation"
|
|
116
|
+
aria-hidden
|
|
117
|
+
className={cn("[&>svg]:size-3.5", className)}
|
|
118
|
+
{...props}
|
|
119
|
+
>
|
|
120
|
+
{children ?? (
|
|
121
|
+
<svg viewBox="0 0 24 24" fill="none" className={mirrorForDirection}>
|
|
122
|
+
<path
|
|
123
|
+
d="m9 18 6-6-6-6"
|
|
124
|
+
stroke="currentColor"
|
|
125
|
+
strokeWidth="2"
|
|
126
|
+
strokeLinecap="round"
|
|
127
|
+
strokeLinejoin="round"
|
|
128
|
+
/>
|
|
129
|
+
</svg>
|
|
130
|
+
)}
|
|
131
|
+
</li>
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Stands in for the middle of a long trail.
|
|
137
|
+
*
|
|
138
|
+
* Named rather than hidden, because unlike a separator it is *content*: it
|
|
139
|
+
* says levels have been left out. A bare "…" announces as nothing at all.
|
|
140
|
+
*/
|
|
141
|
+
export function BreadcrumbEllipsis({ className, ...props }: ComponentPropsWithRef<"span">) {
|
|
142
|
+
return (
|
|
143
|
+
<span
|
|
144
|
+
data-slot="breadcrumb-ellipsis"
|
|
145
|
+
role="presentation"
|
|
146
|
+
className={cn("flex size-5 items-center justify-center", className)}
|
|
147
|
+
{...props}
|
|
148
|
+
>
|
|
149
|
+
<svg viewBox="0 0 24 24" fill="none" aria-hidden className="size-4">
|
|
150
|
+
<circle cx="5" cy="12" r="1.5" fill="currentColor" />
|
|
151
|
+
<circle cx="12" cy="12" r="1.5" fill="currentColor" />
|
|
152
|
+
<circle cx="19" cy="12" r="1.5" fill="currentColor" />
|
|
153
|
+
</svg>
|
|
154
|
+
<span className="sr-only">Intermediate levels</span>
|
|
155
|
+
</span>
|
|
156
|
+
);
|
|
157
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { defineMeta } from "@/registry/schema";
|
|
2
|
+
|
|
3
|
+
export const meta = defineMeta({
|
|
4
|
+
name: "breadcrumb",
|
|
5
|
+
title: "Breadcrumb",
|
|
6
|
+
description: "Where the current page sits in the hierarchy, and how to get back up it.",
|
|
7
|
+
category: "navigation",
|
|
8
|
+
status: "stable",
|
|
9
|
+
dependencies: ["radix-ui"],
|
|
10
|
+
registryDependencies: [],
|
|
11
|
+
files: ["breadcrumb.tsx"],
|
|
12
|
+
a11y:
|
|
13
|
+
'The current page is a span carrying aria-current="page", not a link: a link to the page ' +
|
|
14
|
+
"you are already on does nothing, and in a list of links it is indistinguishable from the " +
|
|
15
|
+
"ones that go somewhere. Separators are hidden from assistive technology, because the list " +
|
|
16
|
+
'already conveys the sequence and reading "slash" between every item is the design\'s ' +
|
|
17
|
+
"punctuation leaking into the content. The ellipsis is the exception and is named, because " +
|
|
18
|
+
"it is content: it says levels have been left out.",
|
|
19
|
+
});
|
|
@@ -70,12 +70,12 @@ export function Calendar({
|
|
|
70
70
|
),
|
|
71
71
|
// Range middles keep the muted surface so the two ends stay legible as
|
|
72
72
|
// the actual selection.
|
|
73
|
-
range_start: cn(defaults.range_start, "rounded-
|
|
73
|
+
range_start: cn(defaults.range_start, "rounded-s-md bg-accent"),
|
|
74
74
|
range_middle: cn(
|
|
75
75
|
defaults.range_middle,
|
|
76
76
|
"bg-accent [&>button]:bg-transparent [&>button]:text-accent-foreground",
|
|
77
77
|
),
|
|
78
|
-
range_end: cn(defaults.range_end, "rounded-
|
|
78
|
+
range_end: cn(defaults.range_end, "rounded-e-md bg-accent"),
|
|
79
79
|
today: cn(defaults.today, "[&>button]:font-semibold [&>button]:text-primary"),
|
|
80
80
|
outside: cn(defaults.outside, "text-muted-foreground opacity-50"),
|
|
81
81
|
disabled: cn(defaults.disabled, "opacity-40"),
|
|
@@ -143,7 +143,7 @@ export function CopyButton({
|
|
|
143
143
|
onClick={copy}
|
|
144
144
|
aria-label={label}
|
|
145
145
|
className={cn(
|
|
146
|
-
"
|
|
146
|
+
"ms-auto grid size-6 shrink-0 place-items-center rounded text-muted-foreground",
|
|
147
147
|
"transition-colors duration-[var(--duration-fast)] hover:bg-accent hover:text-foreground",
|
|
148
148
|
focusRing,
|
|
149
149
|
className,
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { Collapsible as CollapsiblePrimitive } from "radix-ui";
|
|
4
|
+
import type { ComponentPropsWithRef } from "react";
|
|
5
|
+
|
|
6
|
+
import { cn } from "@/lib/utils";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* A section that opens and closes.
|
|
10
|
+
*
|
|
11
|
+
* Unlike Accordion, there is no set: one region, one trigger, no notion of
|
|
12
|
+
* "only one open at a time". Reaching for an Accordion with a single item
|
|
13
|
+
* gives that item a `heading` role and a position in a list of one, both of
|
|
14
|
+
* which are noise.
|
|
15
|
+
*
|
|
16
|
+
* The height animation is driven by the primitive's own measured height rather
|
|
17
|
+
* than a guess, so content of any size opens smoothly, and it derives from
|
|
18
|
+
* `--duration-*` so the motion scale applies.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
export type CollapsibleProps = ComponentPropsWithRef<typeof CollapsiblePrimitive.Root>;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Wrapped rather than re-exported.
|
|
25
|
+
*
|
|
26
|
+
* A bare `export const Collapsible = CollapsiblePrimitive.Root` leaves the
|
|
27
|
+
* inferred type pointing into the primitive's own package, which TypeScript
|
|
28
|
+
* cannot name in declaration output (TS2883). It also gives every other
|
|
29
|
+
* component's `data-slot` a hole where this one should be.
|
|
30
|
+
*/
|
|
31
|
+
export function Collapsible({ className, ...props }: CollapsibleProps) {
|
|
32
|
+
return <CollapsiblePrimitive.Root data-slot="collapsible" className={className} {...props} />;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function CollapsibleTrigger({
|
|
36
|
+
className,
|
|
37
|
+
...props
|
|
38
|
+
}: ComponentPropsWithRef<typeof CollapsiblePrimitive.Trigger>) {
|
|
39
|
+
return (
|
|
40
|
+
<CollapsiblePrimitive.Trigger
|
|
41
|
+
data-slot="collapsible-trigger"
|
|
42
|
+
className={cn("outline-none", className)}
|
|
43
|
+
{...props}
|
|
44
|
+
/>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function CollapsibleContent({
|
|
49
|
+
className,
|
|
50
|
+
...props
|
|
51
|
+
}: ComponentPropsWithRef<typeof CollapsiblePrimitive.Content>) {
|
|
52
|
+
return (
|
|
53
|
+
<CollapsiblePrimitive.Content
|
|
54
|
+
data-slot="collapsible-content"
|
|
55
|
+
className={cn(
|
|
56
|
+
"overflow-hidden",
|
|
57
|
+
"data-[state=closed]:animate-collapse-up data-[state=open]:animate-collapse-down",
|
|
58
|
+
className,
|
|
59
|
+
)}
|
|
60
|
+
{...props}
|
|
61
|
+
/>
|
|
62
|
+
);
|
|
63
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { defineMeta } from "@/registry/schema";
|
|
2
|
+
|
|
3
|
+
export const meta = defineMeta({
|
|
4
|
+
name: "collapsible",
|
|
5
|
+
title: "Collapsible",
|
|
6
|
+
description: "A single section that opens and closes, without an accordion's set semantics.",
|
|
7
|
+
category: "layout",
|
|
8
|
+
status: "stable",
|
|
9
|
+
dependencies: ["radix-ui"],
|
|
10
|
+
registryDependencies: [],
|
|
11
|
+
files: ["collapsible.tsx"],
|
|
12
|
+
a11y:
|
|
13
|
+
"The trigger carries aria-expanded and points at the region it controls, both from the " +
|
|
14
|
+
"primitive. Reach for this rather than an Accordion of one item: a single-item Accordion " +
|
|
15
|
+
"gives its trigger a heading role and a position in a list of one, neither of which is true.",
|
|
16
|
+
});
|
|
@@ -499,7 +499,7 @@ export function ComboboxItem({
|
|
|
499
499
|
}
|
|
500
500
|
}}
|
|
501
501
|
className={cn(
|
|
502
|
-
"relative flex cursor-default items-center gap-2 rounded-md py-1.5
|
|
502
|
+
"relative flex cursor-default items-center gap-2 rounded-md py-1.5 ps-2 pe-8 text-sm outline-none select-none",
|
|
503
503
|
"transition-colors duration-[var(--duration-instant)]",
|
|
504
504
|
"data-[active]:bg-accent data-[active]:text-accent-foreground",
|
|
505
505
|
"data-[disabled]:pointer-events-none data-[disabled]:opacity-55",
|
|
@@ -510,7 +510,7 @@ export function ComboboxItem({
|
|
|
510
510
|
>
|
|
511
511
|
{children ?? value}
|
|
512
512
|
{selected ? (
|
|
513
|
-
<span className="absolute
|
|
513
|
+
<span className="absolute end-2 grid size-4 place-items-center">
|
|
514
514
|
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true" className="size-3.5">
|
|
515
515
|
<path
|
|
516
516
|
d="m5 13 4 4L19 7"
|
|
@@ -438,7 +438,7 @@ export function CommandShortcut({ className, ...props }: ComponentPropsWithRef<"
|
|
|
438
438
|
<span
|
|
439
439
|
data-slot="command-shortcut"
|
|
440
440
|
aria-hidden="true"
|
|
441
|
-
className={cn("
|
|
441
|
+
className={cn("ms-auto text-2xs tracking-wide text-muted-foreground", className)}
|
|
442
442
|
{...props}
|
|
443
443
|
/>
|
|
444
444
|
);
|
|
@@ -33,6 +33,7 @@ import {
|
|
|
33
33
|
TableHeader,
|
|
34
34
|
TableRow,
|
|
35
35
|
} from "@/components/table";
|
|
36
|
+
import { mirrorForDirection } from "@/lib/styles";
|
|
36
37
|
import { cn } from "@/lib/utils";
|
|
37
38
|
|
|
38
39
|
/**
|
|
@@ -253,7 +254,7 @@ export function DataTableColumnHeader({
|
|
|
253
254
|
<Button
|
|
254
255
|
variant="ghost"
|
|
255
256
|
size="sm"
|
|
256
|
-
className="-
|
|
257
|
+
className="-ms-2 h-7 gap-1 px-2 font-medium text-muted-foreground data-[state=open]:bg-accent"
|
|
257
258
|
>
|
|
258
259
|
{title}
|
|
259
260
|
<SortIcon direction={sorted === false ? undefined : sorted} />
|
|
@@ -449,7 +450,12 @@ export function DataTablePagination({
|
|
|
449
450
|
table.previousPage();
|
|
450
451
|
}}
|
|
451
452
|
>
|
|
452
|
-
<svg
|
|
453
|
+
<svg
|
|
454
|
+
viewBox="0 0 24 24"
|
|
455
|
+
fill="none"
|
|
456
|
+
aria-hidden="true"
|
|
457
|
+
className={mirrorForDirection}
|
|
458
|
+
>
|
|
453
459
|
<path
|
|
454
460
|
d="m15 18-6-6 6-6"
|
|
455
461
|
stroke="currentColor"
|
|
@@ -468,7 +474,12 @@ export function DataTablePagination({
|
|
|
468
474
|
table.nextPage();
|
|
469
475
|
}}
|
|
470
476
|
>
|
|
471
|
-
<svg
|
|
477
|
+
<svg
|
|
478
|
+
viewBox="0 0 24 24"
|
|
479
|
+
fill="none"
|
|
480
|
+
aria-hidden="true"
|
|
481
|
+
className={mirrorForDirection}
|
|
482
|
+
>
|
|
472
483
|
<path
|
|
473
484
|
d="m9 18 6-6-6-6"
|
|
474
485
|
stroke="currentColor"
|
|
@@ -66,7 +66,7 @@ export function DialogContent({
|
|
|
66
66
|
data-slot="dialog-close"
|
|
67
67
|
aria-label="Close"
|
|
68
68
|
className={cn(
|
|
69
|
-
"absolute
|
|
69
|
+
"absolute end-4 top-4 grid size-7 place-items-center rounded-md text-muted-foreground",
|
|
70
70
|
"transition-colors duration-[var(--duration-fast)] hover:bg-accent hover:text-foreground",
|
|
71
71
|
"[&_svg]:size-4",
|
|
72
72
|
focusRing,
|
|
@@ -91,7 +91,7 @@ export function DialogHeader({ className, ...props }: ComponentPropsWithRef<"div
|
|
|
91
91
|
return (
|
|
92
92
|
<div
|
|
93
93
|
data-slot="dialog-header"
|
|
94
|
-
className={cn("flex flex-col gap-1.5
|
|
94
|
+
className={cn("flex flex-col gap-1.5 pe-8 text-start", className)}
|
|
95
95
|
{...props}
|
|
96
96
|
/>
|
|
97
97
|
);
|
|
@@ -197,10 +197,10 @@ function UnifiedRow({ row }: { row: DiffRow }) {
|
|
|
197
197
|
<tr data-slot="diff-row" data-kind={row.kind} className={ROW_STYLES[row.kind]}>
|
|
198
198
|
<LineNumber value={row.before} />
|
|
199
199
|
<LineNumber value={row.after} />
|
|
200
|
-
<td className="w-4
|
|
200
|
+
<td className="w-4 pe-1 text-center text-muted-foreground select-none" aria-hidden="true">
|
|
201
201
|
{row.kind === "added" ? "+" : row.kind === "removed" ? "−" : ""}
|
|
202
202
|
</td>
|
|
203
|
-
<td className="w-full py-0.5
|
|
203
|
+
<td className="w-full py-0.5 pe-3 break-all whitespace-pre-wrap">
|
|
204
204
|
{/* The kind, for anyone who cannot see the sign or the tint. Reading a
|
|
205
205
|
diff aloud without it is reading the same file twice. */}
|
|
206
206
|
<span className="sr-only">{KIND_LABEL[row.kind]}: </span>
|
|
@@ -226,7 +226,7 @@ function SplitCell({ row, side }: { row: DiffRow | null; side: "before" | "after
|
|
|
226
226
|
<>
|
|
227
227
|
<LineNumber value={side === "before" ? row.before : row.after} />
|
|
228
228
|
<td
|
|
229
|
-
className={cn("w-1/2 py-0.5
|
|
229
|
+
className={cn("w-1/2 py-0.5 pe-3 break-all whitespace-pre-wrap", ROW_STYLES[row.kind])}
|
|
230
230
|
>
|
|
231
231
|
<span className="sr-only">{KIND_LABEL[row.kind]}: </span>
|
|
232
232
|
<RowContent row={row} />
|
|
@@ -267,7 +267,7 @@ function LineNumber({ value }: { value?: number }) {
|
|
|
267
267
|
// Decorative: the line number is orientation for a sighted reader, and
|
|
268
268
|
// announcing two numbers before every line makes the diff unlistenable.
|
|
269
269
|
aria-hidden="true"
|
|
270
|
-
className="w-10 border-
|
|
270
|
+
className="w-10 border-e border-border bg-muted/40 px-2 py-0.5 text-end text-muted-foreground tabular-nums select-none"
|
|
271
271
|
>
|
|
272
272
|
{value ?? ""}
|
|
273
273
|
</td>
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { Direction as DirectionPrimitive } from "radix-ui";
|
|
4
|
+
import type { ReactNode } from "react";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Tells the component set which way the writing runs.
|
|
8
|
+
*
|
|
9
|
+
* Every direction-dependent style in this library is written logically —
|
|
10
|
+
* `ps-`, `me-`, `text-end` — so the CSS follows `dir` on its own. The
|
|
11
|
+
* primitives underneath do not: several of them read direction from React
|
|
12
|
+
* context rather than from the document, and with no provider they assume
|
|
13
|
+
* left-to-right and set `dir="ltr"` on their own elements. The result is a page
|
|
14
|
+
* that mirrors correctly except for its menus, selects and sliders, which is
|
|
15
|
+
* worse than one that does not mirror at all, because it looks deliberate.
|
|
16
|
+
*
|
|
17
|
+
* So an RTL application needs both: `dir` on the document for the CSS, and this
|
|
18
|
+
* for the primitives.
|
|
19
|
+
*
|
|
20
|
+
* ```tsx
|
|
21
|
+
* <html dir="rtl" lang="ar">
|
|
22
|
+
* <body>
|
|
23
|
+
* <DirectionProvider dir="rtl">{children}</DirectionProvider>
|
|
24
|
+
* </body>
|
|
25
|
+
* </html>
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* A left-to-right application needs neither. Nothing here is required to render
|
|
29
|
+
* English correctly, which is why it is easy to ship without it and never know.
|
|
30
|
+
*/
|
|
31
|
+
export interface DirectionProviderProps {
|
|
32
|
+
dir: "ltr" | "rtl";
|
|
33
|
+
children?: ReactNode;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function DirectionProvider({ dir, children }: DirectionProviderProps) {
|
|
37
|
+
return <DirectionPrimitive.Provider dir={dir}>{children}</DirectionPrimitive.Provider>;
|
|
38
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { DirectionProvider, type DirectionProviderProps } from "./direction";
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { defineMeta } from "@/registry/schema";
|
|
2
|
+
|
|
3
|
+
export const meta = defineMeta({
|
|
4
|
+
name: "direction",
|
|
5
|
+
title: "Direction Provider",
|
|
6
|
+
description:
|
|
7
|
+
"Tells the component primitives which way the writing runs, so menus and sliders mirror with the rest of the page.",
|
|
8
|
+
category: "foundation",
|
|
9
|
+
status: "stable",
|
|
10
|
+
dependencies: ["radix-ui"],
|
|
11
|
+
registryDependencies: [],
|
|
12
|
+
files: ["direction.tsx"],
|
|
13
|
+
a11y:
|
|
14
|
+
"Needed only for right-to-left languages, and needed in addition to `dir` on the document " +
|
|
15
|
+
"rather than instead of it. The styling here is written with logical properties and follows " +
|
|
16
|
+
"`dir` by itself; the primitives underneath read direction from React context and assume " +
|
|
17
|
+
"left-to-right without a provider, which mirrors a page correctly except for its menus, " +
|
|
18
|
+
"selects and sliders — worse than not mirroring at all, because it looks deliberate.",
|
|
19
|
+
});
|
|
@@ -221,7 +221,7 @@ export function DrawerHeader({ className, ...props }: ComponentPropsWithRef<"div
|
|
|
221
221
|
return (
|
|
222
222
|
<div
|
|
223
223
|
data-slot="drawer-header"
|
|
224
|
-
className={cn("flex shrink-0 flex-col gap-1.5 px-6 pt-4 pb-2 text-
|
|
224
|
+
className={cn("flex shrink-0 flex-col gap-1.5 px-6 pt-4 pb-2 text-start", className)}
|
|
225
225
|
{...props}
|
|
226
226
|
/>
|
|
227
227
|
);
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import { DropdownMenu as DropdownMenuPrimitive } from "radix-ui";
|
|
4
4
|
import type { ComponentPropsWithRef } from "react";
|
|
5
5
|
|
|
6
|
+
import { mirrorForDirection } from "@/lib/styles";
|
|
6
7
|
import { cn } from "@/lib/utils";
|
|
7
8
|
|
|
8
9
|
/**
|
|
@@ -80,7 +81,7 @@ export function DropdownMenuItem({
|
|
|
80
81
|
data-variant={variant}
|
|
81
82
|
className={cn(
|
|
82
83
|
menuItem,
|
|
83
|
-
inset && "
|
|
84
|
+
inset && "ps-8",
|
|
84
85
|
variant === "destructive" &&
|
|
85
86
|
"text-destructive data-[highlighted]:bg-destructive/10 data-[highlighted]:text-destructive",
|
|
86
87
|
className,
|
|
@@ -94,7 +95,7 @@ export function DropdownMenuItem({
|
|
|
94
95
|
* aria-checked, so announcing it twice would be noise. */
|
|
95
96
|
function ItemIndicator({ radio = false }: { radio?: boolean }) {
|
|
96
97
|
return (
|
|
97
|
-
<span className="pointer-events-none absolute
|
|
98
|
+
<span className="pointer-events-none absolute start-2 grid size-4 place-items-center">
|
|
98
99
|
<DropdownMenuPrimitive.ItemIndicator>
|
|
99
100
|
{radio ? (
|
|
100
101
|
<span className="size-2 rounded-full bg-current" />
|
|
@@ -122,7 +123,7 @@ export function DropdownMenuCheckboxItem({
|
|
|
122
123
|
return (
|
|
123
124
|
<DropdownMenuPrimitive.CheckboxItem
|
|
124
125
|
data-slot="dropdown-menu-checkbox-item"
|
|
125
|
-
className={cn(menuItem, "
|
|
126
|
+
className={cn(menuItem, "ps-8", className)}
|
|
126
127
|
{...props}
|
|
127
128
|
>
|
|
128
129
|
<ItemIndicator />
|
|
@@ -139,7 +140,7 @@ export function DropdownMenuRadioItem({
|
|
|
139
140
|
return (
|
|
140
141
|
<DropdownMenuPrimitive.RadioItem
|
|
141
142
|
data-slot="dropdown-menu-radio-item"
|
|
142
|
-
className={cn(menuItem, "
|
|
143
|
+
className={cn(menuItem, "ps-8", className)}
|
|
143
144
|
{...props}
|
|
144
145
|
>
|
|
145
146
|
<ItemIndicator radio />
|
|
@@ -160,7 +161,7 @@ export function DropdownMenuLabel({ className, inset, ...props }: DropdownMenuLa
|
|
|
160
161
|
data-slot="dropdown-menu-label"
|
|
161
162
|
className={cn(
|
|
162
163
|
"px-2 py-1.5 text-xs font-medium text-muted-foreground",
|
|
163
|
-
inset && "
|
|
164
|
+
inset && "ps-8",
|
|
164
165
|
className,
|
|
165
166
|
)}
|
|
166
167
|
{...props}
|
|
@@ -188,7 +189,7 @@ export function DropdownMenuShortcut({ className, ...props }: ComponentPropsWith
|
|
|
188
189
|
<span
|
|
189
190
|
data-slot="dropdown-menu-shortcut"
|
|
190
191
|
aria-hidden="true"
|
|
191
|
-
className={cn("
|
|
192
|
+
className={cn("ms-auto text-2xs tracking-wide text-muted-foreground", className)}
|
|
192
193
|
{...props}
|
|
193
194
|
/>
|
|
194
195
|
);
|
|
@@ -209,11 +210,16 @@ export function DropdownMenuSubTrigger({
|
|
|
209
210
|
return (
|
|
210
211
|
<DropdownMenuPrimitive.SubTrigger
|
|
211
212
|
data-slot="dropdown-menu-sub-trigger"
|
|
212
|
-
className={cn(menuItem, "data-[state=open]:bg-accent", inset && "
|
|
213
|
+
className={cn(menuItem, "data-[state=open]:bg-accent", inset && "ps-8", className)}
|
|
213
214
|
{...props}
|
|
214
215
|
>
|
|
215
216
|
{children}
|
|
216
|
-
<svg
|
|
217
|
+
<svg
|
|
218
|
+
viewBox="0 0 24 24"
|
|
219
|
+
fill="none"
|
|
220
|
+
aria-hidden="true"
|
|
221
|
+
className={cn("ms-auto size-3.5", mirrorForDirection)}
|
|
222
|
+
>
|
|
217
223
|
<path
|
|
218
224
|
d="m9 18 6-6-6-6"
|
|
219
225
|
stroke="currentColor"
|
|
@@ -9,7 +9,7 @@ const inputVariants = cva(
|
|
|
9
9
|
"flex w-full min-w-0 rounded-md border border-input bg-background text-foreground shadow-xs",
|
|
10
10
|
"transition-[border-color,box-shadow] duration-[var(--duration-fast)] ease-[var(--ease-out-quint)]",
|
|
11
11
|
"placeholder:text-muted-foreground",
|
|
12
|
-
"file:
|
|
12
|
+
"file:me-3 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground",
|
|
13
13
|
"focus-visible:border-ring",
|
|
14
14
|
"disabled:cursor-not-allowed disabled:opacity-55",
|
|
15
15
|
focusRingInset,
|
|
@@ -203,7 +203,7 @@ export function LogViewer({
|
|
|
203
203
|
data-index={item.index}
|
|
204
204
|
data-slot="log-viewer-row"
|
|
205
205
|
data-level={line.level}
|
|
206
|
-
className="absolute
|
|
206
|
+
className="absolute start-0 top-0 w-full"
|
|
207
207
|
style={{ transform: `translateY(${String(item.start)}px)` }}
|
|
208
208
|
>
|
|
209
209
|
<LogViewerRow
|
|
@@ -296,7 +296,7 @@ export function LogViewerRow({ line, expanded = false, onToggle }: LogViewerRowP
|
|
|
296
296
|
{expanded && line.fields ? (
|
|
297
297
|
<dl
|
|
298
298
|
data-slot="log-viewer-fields"
|
|
299
|
-
className="mt-1 mb-1
|
|
299
|
+
className="ms-4 mt-1 mb-1 grid grid-cols-[auto_1fr] gap-x-3 gap-y-0.5 border-s border-border ps-3"
|
|
300
300
|
>
|
|
301
301
|
{Object.entries(line.fields).map(([key, value]) => (
|
|
302
302
|
<div key={key} className="contents">
|
|
@@ -141,7 +141,7 @@ export function Meter({
|
|
|
141
141
|
data-slot="meter-segment"
|
|
142
142
|
data-tone={segment.tone ?? "primary"}
|
|
143
143
|
className={cn(
|
|
144
|
-
"h-full first:rounded-
|
|
144
|
+
"h-full first:rounded-s-full last:rounded-e-full",
|
|
145
145
|
"transition-[width] duration-[var(--duration-slow)] ease-[var(--ease-out-quint)]",
|
|
146
146
|
TONES[segment.tone ?? "primary"],
|
|
147
147
|
)}
|
|
@@ -2,6 +2,7 @@ import { Slot } from "radix-ui";
|
|
|
2
2
|
import type { ComponentPropsWithRef } from "react";
|
|
3
3
|
|
|
4
4
|
import { buttonVariants } from "@/components/button";
|
|
5
|
+
import { mirrorForDirection } from "@/lib/styles";
|
|
5
6
|
import { cn } from "@/lib/utils";
|
|
6
7
|
|
|
7
8
|
/**
|
|
@@ -80,7 +81,12 @@ export function PaginationPrevious({ className, ...props }: PaginationLinkProps)
|
|
|
80
81
|
className={cn("gap-1 px-2.5", className)}
|
|
81
82
|
{...props}
|
|
82
83
|
>
|
|
83
|
-
<svg
|
|
84
|
+
<svg
|
|
85
|
+
viewBox="0 0 24 24"
|
|
86
|
+
fill="none"
|
|
87
|
+
aria-hidden="true"
|
|
88
|
+
className={cn("size-4", mirrorForDirection)}
|
|
89
|
+
>
|
|
84
90
|
<path
|
|
85
91
|
d="m15 18-6-6 6-6"
|
|
86
92
|
stroke="currentColor"
|
|
@@ -103,7 +109,12 @@ export function PaginationNext({ className, ...props }: PaginationLinkProps) {
|
|
|
103
109
|
{...props}
|
|
104
110
|
>
|
|
105
111
|
<span className="hidden sm:inline">Next</span>
|
|
106
|
-
<svg
|
|
112
|
+
<svg
|
|
113
|
+
viewBox="0 0 24 24"
|
|
114
|
+
fill="none"
|
|
115
|
+
aria-hidden="true"
|
|
116
|
+
className={cn("size-4", mirrorForDirection)}
|
|
117
|
+
>
|
|
107
118
|
<path
|
|
108
119
|
d="m9 18 6-6-6-6"
|
|
109
120
|
stroke="currentColor"
|