@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,210 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
4
|
+
import {
|
|
5
|
+
useId,
|
|
6
|
+
useLayoutEffect,
|
|
7
|
+
useRef,
|
|
8
|
+
useState,
|
|
9
|
+
type ChangeEvent,
|
|
10
|
+
type ComponentPropsWithRef,
|
|
11
|
+
} from "react";
|
|
12
|
+
|
|
13
|
+
import { focusRingInset, invalidStyles } from "@/lib/styles";
|
|
14
|
+
import { cn } from "@/lib/utils";
|
|
15
|
+
|
|
16
|
+
const textareaVariants = cva(
|
|
17
|
+
cn(
|
|
18
|
+
"block w-full min-w-0 rounded-md border border-input bg-background text-foreground shadow-xs",
|
|
19
|
+
"transition-[border-color,box-shadow] duration-[var(--duration-fast)] ease-[var(--ease-out-quint)]",
|
|
20
|
+
"placeholder:text-muted-foreground",
|
|
21
|
+
"focus-visible:border-ring",
|
|
22
|
+
"disabled:cursor-not-allowed disabled:opacity-55",
|
|
23
|
+
focusRingInset,
|
|
24
|
+
invalidStyles,
|
|
25
|
+
),
|
|
26
|
+
{
|
|
27
|
+
variants: {
|
|
28
|
+
textareaSize: {
|
|
29
|
+
sm: "px-2.5 py-1.5 text-sm",
|
|
30
|
+
md: "px-3 py-2 text-sm",
|
|
31
|
+
lg: "px-3.5 py-2.5 text-base",
|
|
32
|
+
},
|
|
33
|
+
/**
|
|
34
|
+
* Vertical only by default.
|
|
35
|
+
*
|
|
36
|
+
* The browser default is `both`, and a textarea dragged wider than its
|
|
37
|
+
* container is a layout broken by a control that was only meant to be
|
|
38
|
+
* made taller.
|
|
39
|
+
*/
|
|
40
|
+
resize: {
|
|
41
|
+
none: "resize-none",
|
|
42
|
+
vertical: "resize-y",
|
|
43
|
+
both: "resize",
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
defaultVariants: {
|
|
47
|
+
textareaSize: "md",
|
|
48
|
+
resize: "vertical",
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
export interface TextareaProps
|
|
54
|
+
extends
|
|
55
|
+
Omit<ComponentPropsWithRef<"textarea">, "cols">,
|
|
56
|
+
VariantProps<typeof textareaVariants> {
|
|
57
|
+
/**
|
|
58
|
+
* Grows with its content instead of scrolling, up to `maxRows`.
|
|
59
|
+
*
|
|
60
|
+
* Off by default. A field that changes height as you type moves everything
|
|
61
|
+
* below it, which is the right trade for a comment box and the wrong one for
|
|
62
|
+
* a form of twelve fields.
|
|
63
|
+
*/
|
|
64
|
+
autoResize?: boolean;
|
|
65
|
+
/** Ceiling for `autoResize`, after which it scrolls. */
|
|
66
|
+
maxRows?: number;
|
|
67
|
+
/**
|
|
68
|
+
* Shows a live character count.
|
|
69
|
+
*
|
|
70
|
+
* Needs `maxLength` to have anything to count against.
|
|
71
|
+
*/
|
|
72
|
+
showCount?: boolean;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Multi-line text field.
|
|
77
|
+
*
|
|
78
|
+
* The visual size prop is `textareaSize`, not `size`, for the same reason
|
|
79
|
+
* Input's is `inputSize`: `size` is a native attribute on form controls, and a
|
|
80
|
+
* prop of that name shadows it.
|
|
81
|
+
*
|
|
82
|
+
* The character count is where this differs from most. A counter wired as a
|
|
83
|
+
* live region announces on every keystroke, which is unusable — a screen
|
|
84
|
+
* reader reads "one hundred and forty-one characters remaining" between every
|
|
85
|
+
* letter. So the count is silent while there is room and only announces once
|
|
86
|
+
* it is nearly gone, which is the point at which it is information rather than
|
|
87
|
+
* chatter.
|
|
88
|
+
*/
|
|
89
|
+
export function Textarea({
|
|
90
|
+
className,
|
|
91
|
+
textareaSize,
|
|
92
|
+
resize,
|
|
93
|
+
autoResize = false,
|
|
94
|
+
maxRows = 12,
|
|
95
|
+
showCount = false,
|
|
96
|
+
rows = 3,
|
|
97
|
+
maxLength,
|
|
98
|
+
value,
|
|
99
|
+
defaultValue,
|
|
100
|
+
onChange,
|
|
101
|
+
id,
|
|
102
|
+
"aria-describedby": describedBy,
|
|
103
|
+
ref,
|
|
104
|
+
...props
|
|
105
|
+
}: TextareaProps) {
|
|
106
|
+
const internalRef = useRef<HTMLTextAreaElement | null>(null);
|
|
107
|
+
const generatedId = useId();
|
|
108
|
+
const countId = `${id ?? generatedId}-count`;
|
|
109
|
+
|
|
110
|
+
const counted = showCount && maxLength !== undefined;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Both refs, without a library.
|
|
114
|
+
*
|
|
115
|
+
* React 19 passes `ref` as an ordinary prop, so it arrives here and has to be
|
|
116
|
+
* forwarded on deliberately. Auto-resize needs the element too, and silently
|
|
117
|
+
* dropping the caller's ref would break every form library that reaches for
|
|
118
|
+
* the node.
|
|
119
|
+
*/
|
|
120
|
+
const setRef = (node: HTMLTextAreaElement | null) => {
|
|
121
|
+
internalRef.current = node;
|
|
122
|
+
if (typeof ref === "function") ref(node);
|
|
123
|
+
else if (ref) (ref as { current: HTMLTextAreaElement | null }).current = node;
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
// Measured after layout, so the height is right on the first paint rather
|
|
127
|
+
// than one frame late and visibly settling.
|
|
128
|
+
useLayoutEffect(() => {
|
|
129
|
+
const textarea = internalRef.current;
|
|
130
|
+
if (!textarea || !autoResize) return;
|
|
131
|
+
|
|
132
|
+
textarea.style.height = "auto";
|
|
133
|
+
const lineHeight = Number.parseFloat(getComputedStyle(textarea).lineHeight) || 20;
|
|
134
|
+
const maxHeight = lineHeight * maxRows;
|
|
135
|
+
textarea.style.height = `${String(Math.min(textarea.scrollHeight, maxHeight))}px`;
|
|
136
|
+
textarea.style.overflowY = textarea.scrollHeight > maxHeight ? "auto" : "hidden";
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* The length, for the count.
|
|
141
|
+
*
|
|
142
|
+
* Held in state for the uncontrolled case rather than read off the element
|
|
143
|
+
* during render. Reading the ref looks simpler and does not work: nothing
|
|
144
|
+
* re-renders when an uncontrolled field is typed into, so the count would
|
|
145
|
+
* show whatever it happened to say on first paint and never move again.
|
|
146
|
+
*/
|
|
147
|
+
const [uncontrolledLength, setUncontrolledLength] = useState(
|
|
148
|
+
typeof defaultValue === "string" ? defaultValue.length : 0,
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
const length = typeof value === "string" ? value.length : uncontrolledLength;
|
|
152
|
+
|
|
153
|
+
const remaining = maxLength === undefined ? undefined : maxLength - length;
|
|
154
|
+
// Announce only when it starts to matter: a tenth of the budget, or twenty
|
|
155
|
+
// characters, whichever is larger.
|
|
156
|
+
const announceAt = maxLength === undefined ? 0 : Math.max(20, Math.floor(maxLength / 10));
|
|
157
|
+
const nearLimit = remaining !== undefined && remaining <= announceAt;
|
|
158
|
+
|
|
159
|
+
function handleChange(event: ChangeEvent<HTMLTextAreaElement>) {
|
|
160
|
+
if (value === undefined) setUncontrolledLength(event.target.value.length);
|
|
161
|
+
onChange?.(event);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return (
|
|
165
|
+
<div className={cn("grid gap-1.5", counted && "w-full")}>
|
|
166
|
+
<textarea
|
|
167
|
+
ref={setRef}
|
|
168
|
+
id={id ?? (counted ? generatedId : undefined)}
|
|
169
|
+
data-slot="textarea"
|
|
170
|
+
rows={rows}
|
|
171
|
+
maxLength={maxLength}
|
|
172
|
+
value={value}
|
|
173
|
+
defaultValue={defaultValue}
|
|
174
|
+
onChange={handleChange}
|
|
175
|
+
aria-describedby={cn(describedBy, counted && countId) || undefined}
|
|
176
|
+
className={cn(
|
|
177
|
+
textareaVariants({ textareaSize, resize: autoResize ? "none" : resize }),
|
|
178
|
+
className,
|
|
179
|
+
)}
|
|
180
|
+
{...props}
|
|
181
|
+
/>
|
|
182
|
+
|
|
183
|
+
{counted ? (
|
|
184
|
+
<p
|
|
185
|
+
id={countId}
|
|
186
|
+
data-slot="textarea-count"
|
|
187
|
+
// Polite only once it matters. Left permanently live it reads the
|
|
188
|
+
// count between every keystroke, which is noise, not help.
|
|
189
|
+
aria-live={nearLimit ? "polite" : "off"}
|
|
190
|
+
className={cn(
|
|
191
|
+
"text-xs tabular-nums",
|
|
192
|
+
remaining !== undefined && remaining < 0
|
|
193
|
+
? "text-destructive"
|
|
194
|
+
: nearLimit
|
|
195
|
+
? "text-warning"
|
|
196
|
+
: "text-muted-foreground",
|
|
197
|
+
)}
|
|
198
|
+
>
|
|
199
|
+
{/* Words, not "141/200": a bare ratio is read aloud as two numbers
|
|
200
|
+
with no indication of which is which. */}
|
|
201
|
+
{remaining !== undefined && remaining < 0
|
|
202
|
+
? `${String(Math.abs(remaining))} characters over the limit`
|
|
203
|
+
: `${String(remaining ?? 0)} characters left`}
|
|
204
|
+
</p>
|
|
205
|
+
) : null}
|
|
206
|
+
</div>
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export { textareaVariants };
|
|
@@ -324,7 +324,7 @@ export function TimeRangePresets({
|
|
|
324
324
|
<div
|
|
325
325
|
data-slot="time-range-presets"
|
|
326
326
|
className={cn(
|
|
327
|
-
"max-h-80 min-w-52 overflow-y-auto border-border p-1.5 sm:border-
|
|
327
|
+
"max-h-80 min-w-52 overflow-y-auto border-border p-1.5 sm:border-e",
|
|
328
328
|
className,
|
|
329
329
|
)}
|
|
330
330
|
{...props}
|
|
@@ -344,7 +344,7 @@ export function TimeRangePresets({
|
|
|
344
344
|
close();
|
|
345
345
|
}}
|
|
346
346
|
className={cn(
|
|
347
|
-
"flex w-full items-center rounded-md px-2 py-1.5 text-
|
|
347
|
+
"flex w-full items-center rounded-md px-2 py-1.5 text-start text-sm transition-colors",
|
|
348
348
|
preset.expression === value
|
|
349
349
|
? "bg-accent font-medium text-accent-foreground"
|
|
350
350
|
: "hover:bg-accent hover:text-accent-foreground",
|
|
@@ -482,7 +482,7 @@ export function TimeRangeCalendar({
|
|
|
482
482
|
return (
|
|
483
483
|
<div
|
|
484
484
|
data-slot="time-range-calendar"
|
|
485
|
-
className={cn("border-t border-border p-1 sm:border-
|
|
485
|
+
className={cn("border-t border-border p-1 sm:border-s sm:border-t-0", className)}
|
|
486
486
|
{...props}
|
|
487
487
|
>
|
|
488
488
|
<Calendar
|
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
const toastVariants = cva(
|
|
29
29
|
cn(
|
|
30
30
|
"group pointer-events-auto relative flex w-full items-start gap-3 overflow-hidden",
|
|
31
|
-
"rounded-lg border p-4
|
|
31
|
+
"rounded-lg border p-4 pe-10 shadow-lg",
|
|
32
32
|
"[--slide-x:calc(100%+1rem)]",
|
|
33
33
|
"data-[state=closed]:animate-float-out data-[state=open]:animate-slide-in",
|
|
34
34
|
"data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none",
|
|
@@ -122,7 +122,7 @@ export function ToastClose({
|
|
|
122
122
|
data-slot="toast-close"
|
|
123
123
|
aria-label="Dismiss"
|
|
124
124
|
className={cn(
|
|
125
|
-
"absolute
|
|
125
|
+
"absolute end-3 top-3 grid size-6 place-items-center rounded-md text-muted-foreground",
|
|
126
126
|
"transition-colors duration-[var(--duration-fast)] hover:bg-accent hover:text-foreground",
|
|
127
127
|
focusRing,
|
|
128
128
|
className,
|
|
@@ -144,13 +144,21 @@ export function ToastClose({
|
|
|
144
144
|
export type ToastPosition =
|
|
145
145
|
"top-left" | "top-center" | "top-right" | "bottom-left" | "bottom-center" | "bottom-right";
|
|
146
146
|
|
|
147
|
+
/*
|
|
148
|
+
rtl-ok: the positions are *named* left and right, so they stay physical. A
|
|
149
|
+
toast asked for at `bottom-right` that appears bottom-left in Arabic is the
|
|
150
|
+
same lie as a Sheet asked for on the left that opens on the right — and it is
|
|
151
|
+
worse here, because the slide-in comes from the right edge and the toast would
|
|
152
|
+
fly across the screen to reach the other one. The logical version of this is a
|
|
153
|
+
`bottom-end` position, which is a rename rather than a restyle.
|
|
154
|
+
*/
|
|
147
155
|
const viewportPositions: Record<ToastPosition, string> = {
|
|
148
|
-
"top-left": "top-0 left-0 sm:flex-col-reverse",
|
|
156
|
+
"top-left": "top-0 left-0 sm:flex-col-reverse", // rtl-ok: named position
|
|
149
157
|
"top-center": "top-0 left-1/2 -translate-x-1/2 sm:flex-col-reverse",
|
|
150
|
-
"top-right": "top-0 right-0 sm:flex-col-reverse",
|
|
151
|
-
"bottom-left": "bottom-0 left-0",
|
|
158
|
+
"top-right": "top-0 right-0 sm:flex-col-reverse", // rtl-ok: named position
|
|
159
|
+
"bottom-left": "bottom-0 left-0", // rtl-ok: named position
|
|
152
160
|
"bottom-center": "bottom-0 left-1/2 -translate-x-1/2",
|
|
153
|
-
"bottom-right": "bottom-0 right-0",
|
|
161
|
+
"bottom-right": "bottom-0 right-0", // rtl-ok: named position
|
|
154
162
|
};
|
|
155
163
|
|
|
156
164
|
export interface ToasterProps {
|
package/src/index.ts
CHANGED
|
@@ -21,11 +21,13 @@ export * from "./components/ai-tool";
|
|
|
21
21
|
export * from "./components/alert";
|
|
22
22
|
export * from "./components/avatar";
|
|
23
23
|
export * from "./components/badge";
|
|
24
|
+
export * from "./components/breadcrumb";
|
|
24
25
|
export * from "./components/button";
|
|
25
26
|
export * from "./components/calendar";
|
|
26
27
|
export * from "./components/card";
|
|
27
28
|
export * from "./components/checkbox";
|
|
28
29
|
export * from "./components/code-block";
|
|
30
|
+
export * from "./components/collapsible";
|
|
29
31
|
export * from "./components/combobox";
|
|
30
32
|
export * from "./components/command";
|
|
31
33
|
export * from "./components/confirm-typed";
|
|
@@ -33,6 +35,7 @@ export * from "./components/cron-editor";
|
|
|
33
35
|
export * from "./components/data-table";
|
|
34
36
|
export * from "./components/date-picker";
|
|
35
37
|
export * from "./components/dialog";
|
|
38
|
+
export * from "./components/direction";
|
|
36
39
|
export * from "./components/diff-viewer";
|
|
37
40
|
export * from "./components/dns-record";
|
|
38
41
|
export * from "./components/drawer";
|
|
@@ -56,6 +59,7 @@ export * from "./components/select";
|
|
|
56
59
|
export * from "./components/separator";
|
|
57
60
|
export * from "./components/session-expiry";
|
|
58
61
|
export * from "./components/sheet";
|
|
62
|
+
export * from "./components/sidebar";
|
|
59
63
|
export * from "./components/shortcut-recorder";
|
|
60
64
|
export * from "./components/skeleton";
|
|
61
65
|
export * from "./components/slider";
|
|
@@ -66,6 +70,7 @@ export * from "./components/table";
|
|
|
66
70
|
export * from "./components/tabs";
|
|
67
71
|
export * from "./components/tags-input";
|
|
68
72
|
export * from "./components/time-range-picker";
|
|
73
|
+
export * from "./components/textarea";
|
|
69
74
|
export * from "./components/toast";
|
|
70
75
|
export * from "./components/tooltip";
|
|
71
76
|
|
package/src/lib/styles.ts
CHANGED
|
@@ -24,3 +24,19 @@ export const invalidStyles =
|
|
|
24
24
|
/** Sizes any icon rendered as a direct child of a control. */
|
|
25
25
|
export const iconSlot =
|
|
26
26
|
"[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4";
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Mirrors an icon that points along the reading direction.
|
|
30
|
+
*
|
|
31
|
+
* A chevron meaning "forward" points right in English and left in Arabic.
|
|
32
|
+
* Logical CSS does not help here: the glyph is drawn, not laid out, so the
|
|
33
|
+
* class list mirrors the box while the arrow inside it goes on pointing the
|
|
34
|
+
* wrong way. The result is a fully mirrored page whose "next" button points
|
|
35
|
+
* back the way you came.
|
|
36
|
+
*
|
|
37
|
+
* Only for icons whose meaning is directional. A chevron pointing *down* to
|
|
38
|
+
* open a select means down in every language, and flipping it horizontally
|
|
39
|
+
* would be flipping a thing that was never sided. Nor is a tick, a cross or a
|
|
40
|
+
* spinner.
|
|
41
|
+
*/
|
|
42
|
+
export const mirrorForDirection = "rtl:-scale-x-100";
|
package/src/registry/blocks.ts
CHANGED
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
import type { ComponentMeta } from "./schema";
|
|
2
2
|
|
|
3
|
+
import { meta as adminDashboardMeta } from "@/blocks/admin-dashboard/meta";
|
|
3
4
|
import { meta as adminUsersMeta } from "@/blocks/admin-users/meta";
|
|
5
|
+
import { meta as agentConsoleMeta } from "@/blocks/agent-console/meta";
|
|
4
6
|
import { meta as aiChatMeta } from "@/blocks/ai-chat/meta";
|
|
7
|
+
import { meta as aiDashboardMeta } from "@/blocks/ai-dashboard/meta";
|
|
8
|
+
import { meta as aiWorkspaceMeta } from "@/blocks/ai-workspace/meta";
|
|
9
|
+
import { meta as analyticsMeta } from "@/blocks/analytics/meta";
|
|
10
|
+
import { meta as billingMeta } from "@/blocks/billing/meta";
|
|
11
|
+
import { meta as commandCenterMeta } from "@/blocks/command-center/meta";
|
|
12
|
+
import { meta as crmMeta } from "@/blocks/crm/meta";
|
|
5
13
|
import { meta as dashboardMeta } from "@/blocks/dashboard/meta";
|
|
6
14
|
import { meta as forgotPasswordMeta } from "@/blocks/forgot-password/meta";
|
|
7
15
|
import { meta as loginMeta } from "@/blocks/login/meta";
|
|
16
|
+
import { meta as onboardingMeta } from "@/blocks/onboarding/meta";
|
|
8
17
|
import { meta as pricingMeta } from "@/blocks/pricing/meta";
|
|
9
18
|
import { meta as settingsMeta } from "@/blocks/settings/meta";
|
|
10
19
|
import { meta as signupMeta } from "@/blocks/signup/meta";
|
|
@@ -19,11 +28,20 @@ import { meta as signupMeta } from "@/blocks/signup/meta";
|
|
|
19
28
|
* `meta.test.ts` fails if a block directory exists that is missing from here.
|
|
20
29
|
*/
|
|
21
30
|
export const blockMetas: ComponentMeta[] = [
|
|
31
|
+
adminDashboardMeta,
|
|
22
32
|
adminUsersMeta,
|
|
33
|
+
agentConsoleMeta,
|
|
23
34
|
aiChatMeta,
|
|
35
|
+
aiDashboardMeta,
|
|
36
|
+
aiWorkspaceMeta,
|
|
37
|
+
analyticsMeta,
|
|
38
|
+
billingMeta,
|
|
39
|
+
commandCenterMeta,
|
|
40
|
+
crmMeta,
|
|
24
41
|
dashboardMeta,
|
|
25
42
|
forgotPasswordMeta,
|
|
26
43
|
loginMeta,
|
|
44
|
+
onboardingMeta,
|
|
27
45
|
pricingMeta,
|
|
28
46
|
settingsMeta,
|
|
29
47
|
signupMeta,
|
|
@@ -23,17 +23,20 @@ import { meta as aiToolMeta } from "@/components/ai-tool/meta";
|
|
|
23
23
|
import { meta as alertMeta } from "@/components/alert/meta";
|
|
24
24
|
import { meta as avatarMeta } from "@/components/avatar/meta";
|
|
25
25
|
import { meta as badgeMeta } from "@/components/badge/meta";
|
|
26
|
+
import { meta as breadcrumbMeta } from "@/components/breadcrumb/meta";
|
|
26
27
|
import { meta as buttonMeta } from "@/components/button/meta";
|
|
27
28
|
import { meta as calendarMeta } from "@/components/calendar/meta";
|
|
28
29
|
import { meta as cardMeta } from "@/components/card/meta";
|
|
29
30
|
import { meta as checkboxMeta } from "@/components/checkbox/meta";
|
|
30
31
|
import { meta as codeBlockMeta } from "@/components/code-block/meta";
|
|
32
|
+
import { meta as collapsibleMeta } from "@/components/collapsible/meta";
|
|
31
33
|
import { meta as comboboxMeta } from "@/components/combobox/meta";
|
|
32
34
|
import { meta as commandMeta } from "@/components/command/meta";
|
|
33
35
|
import { meta as confirmTypedMeta } from "@/components/confirm-typed/meta";
|
|
34
36
|
import { meta as cronEditorMeta } from "@/components/cron-editor/meta";
|
|
35
37
|
import { meta as dataTableMeta } from "@/components/data-table/meta";
|
|
36
38
|
import { meta as datePickerMeta } from "@/components/date-picker/meta";
|
|
39
|
+
import { meta as directionMeta } from "@/components/direction/meta";
|
|
37
40
|
import { meta as dialogMeta } from "@/components/dialog/meta";
|
|
38
41
|
import { meta as diffViewerMeta } from "@/components/diff-viewer/meta";
|
|
39
42
|
import { meta as dnsRecordMeta } from "@/components/dns-record/meta";
|
|
@@ -57,6 +60,7 @@ import { meta as secretFieldMeta } from "@/components/secret-field/meta";
|
|
|
57
60
|
import { meta as selectMeta } from "@/components/select/meta";
|
|
58
61
|
import { meta as separatorMeta } from "@/components/separator/meta";
|
|
59
62
|
import { meta as sessionExpiryMeta } from "@/components/session-expiry/meta";
|
|
63
|
+
import { meta as sidebarMeta } from "@/components/sidebar/meta";
|
|
60
64
|
import { meta as sheetMeta } from "@/components/sheet/meta";
|
|
61
65
|
import { meta as shortcutRecorderMeta } from "@/components/shortcut-recorder/meta";
|
|
62
66
|
import { meta as skeletonMeta } from "@/components/skeleton/meta";
|
|
@@ -68,6 +72,7 @@ import { meta as tableMeta } from "@/components/table/meta";
|
|
|
68
72
|
import { meta as tabsMeta } from "@/components/tabs/meta";
|
|
69
73
|
import { meta as tagsInputMeta } from "@/components/tags-input/meta";
|
|
70
74
|
import { meta as timeRangePickerMeta } from "@/components/time-range-picker/meta";
|
|
75
|
+
import { meta as textareaMeta } from "@/components/textarea/meta";
|
|
71
76
|
import { meta as toastMeta } from "@/components/toast/meta";
|
|
72
77
|
import { meta as tooltipMeta } from "@/components/tooltip/meta";
|
|
73
78
|
|
|
@@ -106,11 +111,13 @@ export const componentMetas: ComponentMeta[] = [
|
|
|
106
111
|
alertMeta,
|
|
107
112
|
avatarMeta,
|
|
108
113
|
badgeMeta,
|
|
114
|
+
breadcrumbMeta,
|
|
109
115
|
buttonMeta,
|
|
110
116
|
calendarMeta,
|
|
111
117
|
cardMeta,
|
|
112
118
|
checkboxMeta,
|
|
113
119
|
codeBlockMeta,
|
|
120
|
+
collapsibleMeta,
|
|
114
121
|
comboboxMeta,
|
|
115
122
|
commandMeta,
|
|
116
123
|
confirmTypedMeta,
|
|
@@ -118,6 +125,7 @@ export const componentMetas: ComponentMeta[] = [
|
|
|
118
125
|
dataTableMeta,
|
|
119
126
|
datePickerMeta,
|
|
120
127
|
dialogMeta,
|
|
128
|
+
directionMeta,
|
|
121
129
|
diffViewerMeta,
|
|
122
130
|
dnsRecordMeta,
|
|
123
131
|
drawerMeta,
|
|
@@ -141,6 +149,7 @@ export const componentMetas: ComponentMeta[] = [
|
|
|
141
149
|
separatorMeta,
|
|
142
150
|
sessionExpiryMeta,
|
|
143
151
|
sheetMeta,
|
|
152
|
+
sidebarMeta,
|
|
144
153
|
shortcutRecorderMeta,
|
|
145
154
|
skeletonMeta,
|
|
146
155
|
sliderMeta,
|
|
@@ -151,6 +160,7 @@ export const componentMetas: ComponentMeta[] = [
|
|
|
151
160
|
tabsMeta,
|
|
152
161
|
tagsInputMeta,
|
|
153
162
|
timeRangePickerMeta,
|
|
163
|
+
textareaMeta,
|
|
154
164
|
toastMeta,
|
|
155
165
|
tooltipMeta,
|
|
156
166
|
];
|
package/src/registry/schema.ts
CHANGED
|
@@ -50,6 +50,14 @@ export interface ComponentMeta {
|
|
|
50
50
|
files: string[];
|
|
51
51
|
/** Accessibility notes surfaced on the docs page. */
|
|
52
52
|
a11y?: string;
|
|
53
|
+
/**
|
|
54
|
+
* Whether the source is public.
|
|
55
|
+
*
|
|
56
|
+
* Omitted means `free`, and free is a promise: an item that has shipped
|
|
57
|
+
* installable without a licence stays that way. Marking an existing component
|
|
58
|
+
* `pro` breaks every project that already installs it.
|
|
59
|
+
*/
|
|
60
|
+
access?: "free" | "pro";
|
|
53
61
|
}
|
|
54
62
|
|
|
55
63
|
/** Identity helper that gives editors autocomplete inside `meta.ts`. */
|