harebear-ui 0.9.0 → 0.11.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/dist/components/admin/app-nav.d.ts +11 -1
- package/dist/components/admin/app-nav.js +26 -9
- package/dist/components/admin/checklist-editor.d.ts +20 -0
- package/dist/components/admin/checklist-editor.js +69 -0
- package/dist/components/admin/comment-thread.d.ts +26 -0
- package/dist/components/admin/comment-thread.js +68 -0
- package/dist/components/admin/copy-field.d.ts +3 -1
- package/dist/components/admin/copy-field.js +10 -5
- package/dist/components/admin/date-time-picker.js +1 -1
- package/dist/components/admin/detail-sheet.js +3 -0
- package/dist/components/admin/markdown-editor.d.ts +2 -5
- package/dist/components/admin/markdown-editor.js +13 -9
- package/dist/components/admin/page-header.d.ts +3 -1
- package/dist/components/admin/page-header.js +17 -9
- package/dist/components/admin/page.d.ts +16 -0
- package/dist/components/admin/page.js +42 -0
- package/dist/components/admin/prompt-dialog.d.ts +19 -0
- package/dist/components/admin/prompt-dialog.js +83 -0
- package/dist/components/admin/settings.d.ts +4 -2
- package/dist/components/admin/settings.js +37 -30
- package/dist/components/admin/time-zone-picker.d.ts +12 -0
- package/dist/components/admin/time-zone-picker.js +31 -0
- package/dist/components/admin/user-menu.d.ts +3 -1
- package/dist/components/admin/user-menu.js +21 -10
- package/dist/components/ai/action-receipt.d.ts +1 -1
- package/dist/components/ai/action-receipt.js +1 -1
- package/dist/components/ai/approval.d.ts +1 -1
- package/dist/components/ai/approval.js +2 -2
- package/dist/components/ai/ask-box.js +1 -1
- package/dist/components/ai/assistant.d.ts +3 -1
- package/dist/components/ai/assistant.js +3 -2
- package/dist/components/ai/chat.js +1 -1
- package/dist/components/ai/code-block.js +3 -3
- package/dist/components/ai/markdown.d.ts +13 -0
- package/dist/components/ai/markdown.js +41 -0
- package/dist/components/ai/tool-steps.d.ts +2 -2
- package/dist/components/ai/tool-steps.js +5 -4
- package/dist/components/auth/auth.d.ts +41 -5
- package/dist/components/auth/auth.js +165 -155
- package/dist/components/data/day-strip.d.ts +6 -1
- package/dist/components/data/day-strip.js +15 -5
- package/dist/components/layout/collapse.js +1 -1
- package/dist/components/layout/text.d.ts +3 -3
- package/dist/components/layout/text.js +6 -1
- package/dist/components/ui/button.js +1 -1
- package/dist/components/ui/check-circle.js +1 -1
- package/dist/components/ui/code-block.js +2 -2
- package/dist/components/ui/combobox.js +1 -0
- package/dist/components/ui/dialog.d.ts +1 -1
- package/dist/components/ui/dialog.js +3 -1
- package/dist/components/ui/drawer.d.ts +1 -1
- package/dist/components/ui/drawer.js +3 -1
- package/dist/components/ui/input-group.js +1 -1
- package/dist/components/ui/input.js +1 -1
- package/dist/components/ui/sheet.d.ts +1 -1
- package/dist/components/ui/sheet.js +3 -1
- package/dist/components/ui/sonner.d.ts +2 -2
- package/dist/components/ui/sonner.js +3 -2
- package/dist/components/ui/toggle.js +1 -1
- package/dist/components/ui/trace.js +1 -1
- package/dist/index.d.ts +9 -3
- package/dist/index.js +9 -3
- package/dist/lib/{date.js → internal/date.js} +1 -1
- package/dist/lib/{toast-clearance.js → internal/toast-clearance.js} +12 -2
- package/dist/styles.css +25 -5
- package/docs/COMPONENTS.md +157 -33
- package/docs/ROADMAP.md +2 -1
- package/llms.txt +7 -6
- package/package.json +3 -1
- package/skills/harebear-ui/SKILL.md +5 -4
|
@@ -4,10 +4,9 @@ import { Card, CardContent } from "../ui/card.js";
|
|
|
4
4
|
import { Field, FieldDescription, FieldError, FieldGroup, FieldLabel, FieldSeparator } from "../ui/field.js";
|
|
5
5
|
import { Input } from "../ui/input.js";
|
|
6
6
|
import { PasswordInput } from "../ui/password-input.js";
|
|
7
|
-
import { Spinner } from "../ui/spinner.js";
|
|
8
7
|
import { cn } from "../../lib/utils.js";
|
|
9
8
|
import * as React from "react";
|
|
10
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
11
10
|
// src/components/auth/auth.tsx
|
|
12
11
|
/** Full-page wrapper for sign-in and sign-up screens. Put LoginForm or SignupForm inside. */
|
|
13
12
|
function AuthLayout({ variant = "centered", brand, image, footer, className, children }) {
|
|
@@ -71,7 +70,7 @@ function AuthLayout({ variant = "centered", brand, image, footer, className, chi
|
|
|
71
70
|
})
|
|
72
71
|
});
|
|
73
72
|
}
|
|
74
|
-
function ProviderButtons({ providers, verb, onProviderClick
|
|
73
|
+
function ProviderButtons({ providers, verb, onProviderClick }) {
|
|
75
74
|
const compact = providers.length >= 3 && providers.every((p) => p.icon);
|
|
76
75
|
return /* @__PURE__ */ jsx(Field, {
|
|
77
76
|
className: cn(compact && "grid gap-3"),
|
|
@@ -79,7 +78,6 @@ function ProviderButtons({ providers, verb, onProviderClick, disabled }) {
|
|
|
79
78
|
children: providers.map((p) => /* @__PURE__ */ jsxs(Button, {
|
|
80
79
|
type: "button",
|
|
81
80
|
variant: "outline",
|
|
82
|
-
disabled,
|
|
83
81
|
onClick: () => onProviderClick?.(p.id),
|
|
84
82
|
"aria-label": compact ? `${verb} with ${p.label}` : void 0,
|
|
85
83
|
children: [p.icon, !compact && `${verb} with ${p.label}`]
|
|
@@ -120,64 +118,127 @@ function AppleIcon(props) {
|
|
|
120
118
|
...props
|
|
121
119
|
});
|
|
122
120
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
}
|
|
121
|
+
/** The shell LoginForm, SignupForm and NewPasswordForm share: heading, your fields, error, submit button. */
|
|
122
|
+
function AuthForm({ title, description, children, error, submitLabel, loading, onSubmit, footer, className, ...props }) {
|
|
123
|
+
return /* @__PURE__ */ jsx("form", {
|
|
124
|
+
"data-slot": "auth-form",
|
|
125
|
+
className: cn("flex flex-col gap-6", className),
|
|
126
|
+
onSubmit: (e) => {
|
|
127
|
+
if (!onSubmit) return;
|
|
128
|
+
e.preventDefault();
|
|
129
|
+
onSubmit(new FormData(e.currentTarget));
|
|
130
|
+
},
|
|
131
|
+
"aria-busy": loading || void 0,
|
|
132
|
+
...props,
|
|
133
|
+
children: /* @__PURE__ */ jsx("fieldset", {
|
|
134
|
+
disabled: loading,
|
|
135
|
+
className: "contents",
|
|
136
|
+
children: /* @__PURE__ */ jsxs(FieldGroup, { children: [
|
|
137
|
+
/* @__PURE__ */ jsxs("div", {
|
|
138
|
+
className: "flex flex-col items-center gap-1.5 text-center",
|
|
139
|
+
children: [/* @__PURE__ */ jsx("h1", {
|
|
140
|
+
className: "text-2xl font-semibold tracking-[-0.02em]",
|
|
141
|
+
children: title
|
|
142
|
+
}), description && /* @__PURE__ */ jsx("p", {
|
|
143
|
+
className: "text-sm text-balance text-muted-foreground",
|
|
144
|
+
children: description
|
|
145
|
+
})]
|
|
146
|
+
}),
|
|
147
|
+
children,
|
|
148
|
+
error && /* @__PURE__ */ jsx(FieldError, { children: error }),
|
|
149
|
+
/* @__PURE__ */ jsx(Field, { children: /* @__PURE__ */ jsx(Button, {
|
|
150
|
+
type: "submit",
|
|
151
|
+
loading,
|
|
152
|
+
children: submitLabel
|
|
153
|
+
}) }),
|
|
154
|
+
footer
|
|
155
|
+
] })
|
|
156
|
+
})
|
|
133
157
|
});
|
|
134
158
|
}
|
|
135
|
-
|
|
136
|
-
|
|
159
|
+
const text = (data, name) => {
|
|
160
|
+
const v = data.get(name);
|
|
161
|
+
return typeof v === "string" ? v : "";
|
|
162
|
+
};
|
|
163
|
+
function EmailField({ id }) {
|
|
164
|
+
return /* @__PURE__ */ jsxs(Field, { children: [/* @__PURE__ */ jsx(FieldLabel, {
|
|
165
|
+
htmlFor: `${id}-email`,
|
|
166
|
+
children: "Email"
|
|
167
|
+
}), /* @__PURE__ */ jsx(Input, {
|
|
168
|
+
id: `${id}-email`,
|
|
169
|
+
name: "email",
|
|
170
|
+
type: "email",
|
|
171
|
+
autoComplete: "email",
|
|
172
|
+
placeholder: "you@example.com",
|
|
173
|
+
required: true
|
|
174
|
+
})] });
|
|
175
|
+
}
|
|
176
|
+
/** "password" and optional "confirm" fields; a mismatch makes "confirm" invalid so the browser blocks the submit. */
|
|
177
|
+
function NewPasswordFields({ id, label, confirm, minLength, hint }) {
|
|
178
|
+
const check = (form) => {
|
|
179
|
+
const password = form?.elements.namedItem("password");
|
|
180
|
+
const again = form?.elements.namedItem("confirm");
|
|
181
|
+
again?.setCustomValidity(again.value && again.value !== password?.value ? "Passwords do not match" : "");
|
|
182
|
+
};
|
|
183
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs(Field, { children: [
|
|
184
|
+
/* @__PURE__ */ jsx(FieldLabel, {
|
|
185
|
+
htmlFor: `${id}-password`,
|
|
186
|
+
children: label
|
|
187
|
+
}),
|
|
188
|
+
/* @__PURE__ */ jsx(PasswordInput, {
|
|
189
|
+
id: `${id}-password`,
|
|
190
|
+
name: "password",
|
|
191
|
+
autoComplete: "new-password",
|
|
192
|
+
minLength,
|
|
193
|
+
required: true,
|
|
194
|
+
onInput: (e) => check(e.currentTarget.form)
|
|
195
|
+
}),
|
|
196
|
+
/* @__PURE__ */ jsx(FieldDescription, { children: hint ?? `At least ${minLength} characters.` })
|
|
197
|
+
] }), confirm && /* @__PURE__ */ jsxs(Field, { children: [/* @__PURE__ */ jsx(FieldLabel, {
|
|
198
|
+
htmlFor: `${id}-confirm`,
|
|
199
|
+
children: "Confirm password"
|
|
200
|
+
}), /* @__PURE__ */ jsx(PasswordInput, {
|
|
201
|
+
id: `${id}-confirm`,
|
|
202
|
+
name: "confirm",
|
|
203
|
+
autoComplete: "new-password",
|
|
204
|
+
required: true,
|
|
205
|
+
onInput: (e) => check(e.currentTarget.form)
|
|
206
|
+
})] })] });
|
|
137
207
|
}
|
|
138
208
|
/** Email + password sign-in form with optional SSO buttons. Pair with AuthLayout. */
|
|
139
|
-
function LoginForm({ title = "Welcome back", description, onSubmit, mode = "password", providers = [], onProviderClick, providersFirst, forgotPasswordHref, signupHref, submitLabel,
|
|
209
|
+
function LoginForm({ title = "Welcome back", description, onSubmit, mode = "password", providers = [], onProviderClick, providersFirst, forgotPasswordHref, signupHref, submitLabel, ...props }) {
|
|
140
210
|
const id = React.useId();
|
|
141
211
|
const emailOnly = mode === "email-only";
|
|
142
|
-
const desc = description ?? (emailOnly ? "Enter your email and we'll send you a sign-in link" : "Sign in to your account");
|
|
143
212
|
const sso = providers.length > 0 && /* @__PURE__ */ jsx(ProviderButtons, {
|
|
144
213
|
providers,
|
|
145
214
|
verb: "Continue",
|
|
146
|
-
onProviderClick
|
|
147
|
-
disabled: loading
|
|
215
|
+
onProviderClick
|
|
148
216
|
});
|
|
149
|
-
return /* @__PURE__ */
|
|
217
|
+
return /* @__PURE__ */ jsxs(AuthForm, {
|
|
150
218
|
"data-slot": "login-form",
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
219
|
+
title,
|
|
220
|
+
description: description ?? (emailOnly ? "Enter your email and we'll send you a sign-in link" : "Sign in to your account"),
|
|
221
|
+
submitLabel: submitLabel ?? (emailOnly ? "Send sign-in link" : "Sign in"),
|
|
222
|
+
onSubmit: onSubmit && ((data) => onSubmit(emailOnly ? { email: text(data, "email") } : {
|
|
223
|
+
email: text(data, "email"),
|
|
224
|
+
password: text(data, "password")
|
|
225
|
+
})),
|
|
226
|
+
footer: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
227
|
+
!providersFirst && sso && /* @__PURE__ */ jsx(FieldSeparator, { children: "Or continue with" }),
|
|
228
|
+
!providersFirst && sso,
|
|
229
|
+
signupHref && /* @__PURE__ */ jsxs(FieldDescription, {
|
|
230
|
+
className: "text-center",
|
|
231
|
+
children: ["Don't have an account? ", /* @__PURE__ */ jsx("a", {
|
|
232
|
+
href: signupHref,
|
|
233
|
+
children: "Sign up"
|
|
234
|
+
})]
|
|
235
|
+
})
|
|
236
|
+
] }),
|
|
161
237
|
...props,
|
|
162
|
-
children:
|
|
163
|
-
/* @__PURE__ */ jsx(Header, {
|
|
164
|
-
title,
|
|
165
|
-
description: desc
|
|
166
|
-
}),
|
|
238
|
+
children: [
|
|
167
239
|
providersFirst && sso,
|
|
168
240
|
providersFirst && sso && /* @__PURE__ */ jsx(FieldSeparator, { children: "Or continue with email" }),
|
|
169
|
-
/* @__PURE__ */
|
|
170
|
-
htmlFor: `${id}-email`,
|
|
171
|
-
children: "Email"
|
|
172
|
-
}), /* @__PURE__ */ jsx(Input, {
|
|
173
|
-
id: `${id}-email`,
|
|
174
|
-
name: "email",
|
|
175
|
-
type: "email",
|
|
176
|
-
autoComplete: "email",
|
|
177
|
-
placeholder: "you@example.com",
|
|
178
|
-
required: true,
|
|
179
|
-
disabled: loading
|
|
180
|
-
})] }),
|
|
241
|
+
/* @__PURE__ */ jsx(EmailField, { id }),
|
|
181
242
|
!emailOnly && /* @__PURE__ */ jsxs(Field, { children: [/* @__PURE__ */ jsxs("div", {
|
|
182
243
|
className: "flex items-center",
|
|
183
244
|
children: [/* @__PURE__ */ jsx(FieldLabel, {
|
|
@@ -185,74 +246,52 @@ function LoginForm({ title = "Welcome back", description, onSubmit, mode = "pass
|
|
|
185
246
|
children: "Password"
|
|
186
247
|
}), forgotPasswordHref && /* @__PURE__ */ jsx("a", {
|
|
187
248
|
href: forgotPasswordHref,
|
|
188
|
-
className: "ms-auto text-sm text-muted-foreground underline-offset-4 hover:text-foreground hover:underline",
|
|
249
|
+
className: "ms-auto rounded-sm text-sm text-muted-foreground underline-offset-4 outline-none hover:text-foreground hover:underline focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
|
|
189
250
|
children: "Forgot password?"
|
|
190
251
|
})]
|
|
191
252
|
}), /* @__PURE__ */ jsx(PasswordInput, {
|
|
192
253
|
id: `${id}-password`,
|
|
193
254
|
name: "password",
|
|
194
255
|
autoComplete: "current-password",
|
|
195
|
-
required: true
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
error && /* @__PURE__ */ jsx(FieldError, { children: error }),
|
|
199
|
-
/* @__PURE__ */ jsx(Field, { children: /* @__PURE__ */ jsxs(Button, {
|
|
200
|
-
type: "submit",
|
|
201
|
-
disabled: loading,
|
|
202
|
-
children: [loading && /* @__PURE__ */ jsx(Spinner, {}), submitLabel ?? (emailOnly ? "Send sign-in link" : "Sign in")]
|
|
203
|
-
}) }),
|
|
204
|
-
!providersFirst && sso && /* @__PURE__ */ jsx(FieldSeparator, { children: "Or continue with" }),
|
|
205
|
-
!providersFirst && sso,
|
|
206
|
-
signupHref && /* @__PURE__ */ jsxs(FieldDescription, {
|
|
207
|
-
className: "text-center",
|
|
208
|
-
children: ["Don't have an account? ", /* @__PURE__ */ jsx("a", {
|
|
209
|
-
href: signupHref,
|
|
210
|
-
children: "Sign up"
|
|
211
|
-
})]
|
|
212
|
-
})
|
|
213
|
-
] })
|
|
256
|
+
required: true
|
|
257
|
+
})] })
|
|
258
|
+
]
|
|
214
259
|
});
|
|
215
260
|
}
|
|
216
261
|
/** Account creation form: name, email, password (+ confirm), optional SSO. Pair with AuthLayout. */
|
|
217
|
-
function SignupForm({ title = "Create your account", description = "Enter your details to get started", onSubmit, nameField = true, confirmPassword = true, passwordHint, minPasswordLength = 8, providers = [], onProviderClick, providersFirst, loginHref, submitLabel = "Create account",
|
|
262
|
+
function SignupForm({ title = "Create your account", description = "Enter your details to get started", onSubmit, children, nameField = true, confirmPassword = true, passwordHint, minPasswordLength = 8, providers = [], onProviderClick, providersFirst, loginHref, submitLabel = "Create account", ...props }) {
|
|
218
263
|
const id = React.useId();
|
|
219
264
|
const sso = providers.length > 0 && /* @__PURE__ */ jsx(ProviderButtons, {
|
|
220
265
|
providers,
|
|
221
266
|
verb: "Sign up",
|
|
222
|
-
onProviderClick
|
|
223
|
-
disabled: loading
|
|
267
|
+
onProviderClick
|
|
224
268
|
});
|
|
225
|
-
return /* @__PURE__ */
|
|
269
|
+
return /* @__PURE__ */ jsxs(AuthForm, {
|
|
226
270
|
"data-slot": "signup-form",
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
},
|
|
247
|
-
"aria-busy": loading || void 0,
|
|
271
|
+
title,
|
|
272
|
+
description,
|
|
273
|
+
submitLabel,
|
|
274
|
+
onSubmit: onSubmit && ((data) => onSubmit({
|
|
275
|
+
...nameField ? { name: text(data, "name") } : {},
|
|
276
|
+
email: text(data, "email"),
|
|
277
|
+
password: text(data, "password")
|
|
278
|
+
}, data)),
|
|
279
|
+
footer: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
280
|
+
!providersFirst && sso && /* @__PURE__ */ jsx(FieldSeparator, { children: "Or continue with" }),
|
|
281
|
+
!providersFirst && sso,
|
|
282
|
+
loginHref && /* @__PURE__ */ jsxs(FieldDescription, {
|
|
283
|
+
className: "text-center",
|
|
284
|
+
children: ["Already have an account? ", /* @__PURE__ */ jsx("a", {
|
|
285
|
+
href: loginHref,
|
|
286
|
+
children: "Sign in"
|
|
287
|
+
})]
|
|
288
|
+
})
|
|
289
|
+
] }),
|
|
248
290
|
...props,
|
|
249
|
-
children:
|
|
250
|
-
/* @__PURE__ */ jsx(Header, {
|
|
251
|
-
title,
|
|
252
|
-
description
|
|
253
|
-
}),
|
|
291
|
+
children: [
|
|
254
292
|
providersFirst && sso,
|
|
255
293
|
providersFirst && sso && /* @__PURE__ */ jsx(FieldSeparator, { children: "Or sign up with email" }),
|
|
294
|
+
children,
|
|
256
295
|
nameField && /* @__PURE__ */ jsxs(Field, { children: [/* @__PURE__ */ jsx(FieldLabel, {
|
|
257
296
|
htmlFor: `${id}-name`,
|
|
258
297
|
children: "Full name"
|
|
@@ -260,64 +299,35 @@ function SignupForm({ title = "Create your account", description = "Enter your d
|
|
|
260
299
|
id: `${id}-name`,
|
|
261
300
|
name: "name",
|
|
262
301
|
autoComplete: "name",
|
|
263
|
-
required: true
|
|
264
|
-
disabled: loading
|
|
265
|
-
})] }),
|
|
266
|
-
/* @__PURE__ */ jsxs(Field, { children: [/* @__PURE__ */ jsx(FieldLabel, {
|
|
267
|
-
htmlFor: `${id}-email`,
|
|
268
|
-
children: "Email"
|
|
269
|
-
}), /* @__PURE__ */ jsx(Input, {
|
|
270
|
-
id: `${id}-email`,
|
|
271
|
-
name: "email",
|
|
272
|
-
type: "email",
|
|
273
|
-
autoComplete: "email",
|
|
274
|
-
placeholder: "you@example.com",
|
|
275
|
-
required: true,
|
|
276
|
-
disabled: loading
|
|
302
|
+
required: true
|
|
277
303
|
})] }),
|
|
278
|
-
/* @__PURE__ */
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
name: "password",
|
|
286
|
-
autoComplete: "new-password",
|
|
287
|
-
onInput: (e) => (e.currentTarget.form?.elements.namedItem("confirm"))?.setCustomValidity(""),
|
|
288
|
-
minLength: minPasswordLength,
|
|
289
|
-
required: true,
|
|
290
|
-
disabled: loading
|
|
291
|
-
}),
|
|
292
|
-
/* @__PURE__ */ jsx(FieldDescription, { children: passwordHint ?? `At least ${minPasswordLength} characters.` })
|
|
293
|
-
] }),
|
|
294
|
-
confirmPassword && /* @__PURE__ */ jsxs(Field, { children: [/* @__PURE__ */ jsx(FieldLabel, {
|
|
295
|
-
htmlFor: `${id}-confirm`,
|
|
296
|
-
children: "Confirm password"
|
|
297
|
-
}), /* @__PURE__ */ jsx(PasswordInput, {
|
|
298
|
-
id: `${id}-confirm`,
|
|
299
|
-
name: "confirm",
|
|
300
|
-
autoComplete: "new-password",
|
|
301
|
-
required: true,
|
|
302
|
-
disabled: loading,
|
|
303
|
-
onInput: (e) => e.currentTarget.setCustomValidity("")
|
|
304
|
-
})] }),
|
|
305
|
-
error && /* @__PURE__ */ jsx(FieldError, { children: error }),
|
|
306
|
-
/* @__PURE__ */ jsx(Field, { children: /* @__PURE__ */ jsxs(Button, {
|
|
307
|
-
type: "submit",
|
|
308
|
-
disabled: loading,
|
|
309
|
-
children: [loading && /* @__PURE__ */ jsx(Spinner, {}), submitLabel]
|
|
310
|
-
}) }),
|
|
311
|
-
!providersFirst && sso && /* @__PURE__ */ jsx(FieldSeparator, { children: "Or continue with" }),
|
|
312
|
-
!providersFirst && sso,
|
|
313
|
-
loginHref && /* @__PURE__ */ jsxs(FieldDescription, {
|
|
314
|
-
className: "text-center",
|
|
315
|
-
children: ["Already have an account? ", /* @__PURE__ */ jsx("a", {
|
|
316
|
-
href: loginHref,
|
|
317
|
-
children: "Sign in"
|
|
318
|
-
})]
|
|
304
|
+
/* @__PURE__ */ jsx(EmailField, { id }),
|
|
305
|
+
/* @__PURE__ */ jsx(NewPasswordFields, {
|
|
306
|
+
id,
|
|
307
|
+
label: "Password",
|
|
308
|
+
confirm: confirmPassword,
|
|
309
|
+
minLength: minPasswordLength,
|
|
310
|
+
hint: passwordHint
|
|
319
311
|
})
|
|
320
|
-
]
|
|
312
|
+
]
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
/** Password reset or first password: new password + confirm. Pair with AuthLayout. */
|
|
316
|
+
function NewPasswordForm({ title = "Choose a new password", onSubmit, minPasswordLength = 8, passwordHint, submitLabel = "Save password", ...props }) {
|
|
317
|
+
const id = React.useId();
|
|
318
|
+
return /* @__PURE__ */ jsx(AuthForm, {
|
|
319
|
+
"data-slot": "new-password-form",
|
|
320
|
+
title,
|
|
321
|
+
submitLabel,
|
|
322
|
+
onSubmit: onSubmit && ((data) => onSubmit({ password: text(data, "password") })),
|
|
323
|
+
...props,
|
|
324
|
+
children: /* @__PURE__ */ jsx(NewPasswordFields, {
|
|
325
|
+
id,
|
|
326
|
+
label: "New password",
|
|
327
|
+
confirm: true,
|
|
328
|
+
minLength: minPasswordLength,
|
|
329
|
+
hint: passwordHint
|
|
330
|
+
})
|
|
321
331
|
});
|
|
322
332
|
}
|
|
323
|
-
export { AppleIcon, AuthLayout, GitHubIcon, GoogleIcon, LoginForm, SignupForm };
|
|
333
|
+
export { AppleIcon, AuthForm, AuthLayout, GitHubIcon, GoogleIcon, LoginForm, NewPasswordForm, SignupForm };
|
|
@@ -13,10 +13,15 @@ export interface DayStripProps extends React.ComponentProps<"nav"> {
|
|
|
13
13
|
value?: string;
|
|
14
14
|
/** Called with the day's id after it scrolls that element into view. */
|
|
15
15
|
onValueChange?: (id: string) => void;
|
|
16
|
+
/**
|
|
17
|
+
* Sticks to the top of the page (or `top-*` you pass) while it scrolls, and lands jumped-to days below the strip
|
|
18
|
+
* instead of under it. Works in any scroll container, the document included.
|
|
19
|
+
*/
|
|
20
|
+
sticky?: boolean;
|
|
16
21
|
}
|
|
17
22
|
/**
|
|
18
23
|
* A row of day buttons (weekday, date, a dot when there are plans) that jump to the element with the day's id.
|
|
19
24
|
* Scrolls inside itself when the days do not fit. Smooth scrolling is off under prefers-reduced-motion.
|
|
20
25
|
*/
|
|
21
|
-
declare function DayStrip({ days, value, onValueChange, className, "aria-label": ariaLabel, ...props }: DayStripProps): React.JSX.Element;
|
|
26
|
+
declare function DayStrip({ days, value, onValueChange, sticky, className, "aria-label": ariaLabel, ...props }: DayStripProps): React.JSX.Element;
|
|
22
27
|
export { DayStrip };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { parseLocalDate } from "../../lib/date.js";
|
|
2
|
+
import { parseLocalDate } from "../../lib/internal/date.js";
|
|
3
3
|
import { cn } from "../../lib/utils.js";
|
|
4
4
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
5
|
// src/components/data/day-strip.tsx
|
|
@@ -7,12 +7,17 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
7
7
|
* A row of day buttons (weekday, date, a dot when there are plans) that jump to the element with the day's id.
|
|
8
8
|
* Scrolls inside itself when the days do not fit. Smooth scrolling is off under prefers-reduced-motion.
|
|
9
9
|
*/
|
|
10
|
-
function DayStrip({ days, value, onValueChange, className, "aria-label": ariaLabel, ...props }) {
|
|
10
|
+
function DayStrip({ days, value, onValueChange, sticky = false, className, "aria-label": ariaLabel, ...props }) {
|
|
11
11
|
const jump = (e, id) => {
|
|
12
12
|
e.preventDefault();
|
|
13
13
|
const reduce = window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
|
|
14
14
|
const el = document.getElementById(id);
|
|
15
15
|
if (el) {
|
|
16
|
+
const strip = sticky ? e.currentTarget.closest("[data-slot=day-strip]") : null;
|
|
17
|
+
if (strip) {
|
|
18
|
+
const top = Number.parseFloat(getComputedStyle(strip).top) || 0;
|
|
19
|
+
el.style.scrollMarginTop = `${strip.offsetHeight + top + 8}px`;
|
|
20
|
+
}
|
|
16
21
|
el.scrollIntoView?.({
|
|
17
22
|
behavior: reduce ? "auto" : "smooth",
|
|
18
23
|
block: "start"
|
|
@@ -25,7 +30,7 @@ function DayStrip({ days, value, onValueChange, className, "aria-label": ariaLab
|
|
|
25
30
|
return /* @__PURE__ */ jsx("nav", {
|
|
26
31
|
"data-slot": "day-strip",
|
|
27
32
|
"aria-label": ariaLabel ?? "Jump to a day",
|
|
28
|
-
className: cn("min-w-0 overflow-x-auto", className),
|
|
33
|
+
className: cn("min-w-0 overflow-x-auto", sticky && "sticky top-0 z-10 bg-background", className),
|
|
29
34
|
...props,
|
|
30
35
|
children: /* @__PURE__ */ jsx("ul", {
|
|
31
36
|
className: "flex gap-2 p-1",
|
|
@@ -42,15 +47,20 @@ function DayStrip({ days, value, onValueChange, className, "aria-label": ariaLab
|
|
|
42
47
|
children: /* @__PURE__ */ jsxs("a", {
|
|
43
48
|
href: `#${day.id}`,
|
|
44
49
|
"aria-current": selected ? "true" : void 0,
|
|
45
|
-
"aria-label": day.hasPlans ? `${label}, has plans` : label,
|
|
46
50
|
onClick: (e) => jump(e, day.id),
|
|
47
|
-
className: cn("flex min-h-21 flex-1 flex-col items-center justify-center gap-0.5 rounded-xl px-1 py-2 outline-none transition-colors focus-visible:ring-
|
|
51
|
+
className: cn("flex min-h-21 flex-1 flex-col items-center justify-center gap-0.5 rounded-xl px-1 py-2 outline-none transition-colors focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background motion-reduce:transition-none", selected ? "bg-primary text-primary-foreground" : "bg-card text-foreground shadow-card hover:bg-muted"),
|
|
48
52
|
children: [
|
|
49
53
|
/* @__PURE__ */ jsx("span", {
|
|
54
|
+
className: "sr-only",
|
|
55
|
+
children: day.hasPlans ? `${label}, has plans` : label
|
|
56
|
+
}),
|
|
57
|
+
/* @__PURE__ */ jsx("span", {
|
|
58
|
+
"aria-hidden": "true",
|
|
50
59
|
className: cn("text-xs font-medium", selected ? "text-primary-foreground" : "text-muted-foreground"),
|
|
51
60
|
children: date.toLocaleDateString(void 0, { weekday: "short" })
|
|
52
61
|
}),
|
|
53
62
|
/* @__PURE__ */ jsx("span", {
|
|
63
|
+
"aria-hidden": "true",
|
|
54
64
|
className: "text-[22px] leading-tight font-semibold tracking-tight tabular-nums",
|
|
55
65
|
children: date.getDate()
|
|
56
66
|
}),
|
|
@@ -16,7 +16,7 @@ function Collapse({ open, contentClassName, className, children, ...props }) {
|
|
|
16
16
|
className: cn("grid transition-[grid-template-rows,opacity] duration-200 ease-out motion-reduce:transition-none", open ? "grid-rows-[1fr] opacity-100" : "grid-rows-[0fr] opacity-0", className),
|
|
17
17
|
...props,
|
|
18
18
|
children: /* @__PURE__ */ jsx("div", {
|
|
19
|
-
className: cn("min-h-0 overflow-
|
|
19
|
+
className: cn("min-h-0 min-w-0 overflow-x-visible overflow-y-clip", contentClassName),
|
|
20
20
|
children
|
|
21
21
|
})
|
|
22
22
|
});
|
|
@@ -29,9 +29,9 @@ export interface TextProps extends Omit<React.ComponentProps<"span">, "ref"> {
|
|
|
29
29
|
/** Text with props instead of classes: size, tone, weight, mono, truncate, lines. */
|
|
30
30
|
declare function Text({ size, tone, weight, mono, truncate, lines, tabular, as: As, className, ...props }: TextProps): React.JSX.Element;
|
|
31
31
|
export interface HeadingProps extends React.ComponentProps<"h3"> {
|
|
32
|
-
/** 3: a section title in a card. 4: a small uppercase label over a group. */
|
|
33
|
-
level?: 3 | 4;
|
|
32
|
+
/** 2: a page section title under the page's h1. 3: a section title in a card. 4: a small uppercase label over a group. */
|
|
33
|
+
level?: 2 | 3 | 4;
|
|
34
34
|
}
|
|
35
|
-
/** Section heading inside a card or panel. */
|
|
35
|
+
/** Section heading on a page (2) or inside a card or panel (3, 4). */
|
|
36
36
|
declare function Heading({ level, className, ...props }: HeadingProps): React.JSX.Element;
|
|
37
37
|
export { Heading, Text };
|
|
@@ -36,8 +36,13 @@ function Text({ size = "base", tone = "default", weight = "normal", mono, trunca
|
|
|
36
36
|
...props
|
|
37
37
|
});
|
|
38
38
|
}
|
|
39
|
-
/** Section heading inside a card or panel. */
|
|
39
|
+
/** Section heading on a page (2) or inside a card or panel (3, 4). */
|
|
40
40
|
function Heading({ level = 3, className, ...props }) {
|
|
41
|
+
if (level === 2) return /* @__PURE__ */ jsx("h2", {
|
|
42
|
+
"data-slot": "heading",
|
|
43
|
+
className: cn("text-lg leading-snug font-semibold", className),
|
|
44
|
+
...props
|
|
45
|
+
});
|
|
41
46
|
if (level === 4) return /* @__PURE__ */ jsx("h4", {
|
|
42
47
|
"data-slot": "heading",
|
|
43
48
|
className: cn("text-xs font-medium tracking-wide text-muted-foreground uppercase", className),
|
|
@@ -5,7 +5,7 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
|
5
5
|
import { cva } from "class-variance-authority";
|
|
6
6
|
import { Slot } from "radix-ui";
|
|
7
7
|
// src/components/ui/button.tsx
|
|
8
|
-
const buttonVariants = cva("group/button inline-flex shrink-0 items-center justify-center rounded-md border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-[background-color,color,box-shadow,border-color] outline-none select-none focus-visible:ring-4 focus-visible:ring-ring/20 focus-visible:border-ring active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-[18px]", {
|
|
8
|
+
const buttonVariants = cva("group/button relative inline-flex shrink-0 items-center justify-center rounded-md border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-[background-color,color,box-shadow,border-color] outline-none select-none focus-visible:ring-4 focus-visible:ring-ring/20 focus-visible:border-ring active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-[18px] pointer-coarse:after:absolute pointer-coarse:after:inset-[min(0px,calc(50%-1.375rem))]", {
|
|
9
9
|
variants: {
|
|
10
10
|
variant: {
|
|
11
11
|
default: "bg-primary text-primary-foreground hover:bg-[color-mix(in_oklab,var(--primary),black_10%)]",
|
|
@@ -24,7 +24,7 @@ function CheckCircle({ tone = "default", className, onCheckedChange, onAnimation
|
|
|
24
24
|
setPop(false);
|
|
25
25
|
onAnimationEnd?.(e);
|
|
26
26
|
},
|
|
27
|
-
className: cn("peer relative grid size-6 shrink-0 place-items-center rounded-full border-2 border-muted-foreground/45 bg-card text-primary-foreground transition-[background-color,border-color
|
|
27
|
+
className: cn("peer relative grid size-6 shrink-0 place-items-center rounded-full border-2 border-muted-foreground/45 bg-card text-primary-foreground transition-[background-color,border-color] outline-none after:absolute after:-inset-3 hover:border-primary focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary focus-visible:outline-solid motion-reduce:transition-none disabled:cursor-not-allowed disabled:opacity-50 data-[tone=important]:border-warning data-[tone=important]:bg-warning/10 data-checked:border-primary data-checked:bg-primary motion-safe:data-[pop]:animate-check-pop", className),
|
|
28
28
|
...props,
|
|
29
29
|
children: /* @__PURE__ */ jsx(Checkbox.Indicator, {
|
|
30
30
|
"data-slot": "check-circle-indicator",
|
|
@@ -39,7 +39,7 @@ function CodeBlockTitle({ className, ...props }) {
|
|
|
39
39
|
function CodeBlockActions({ className, ...props }) {
|
|
40
40
|
return /* @__PURE__ */ jsx("div", {
|
|
41
41
|
"data-slot": "code-block-actions",
|
|
42
|
-
className: cn("-my-1 ms-auto -me-1.5 flex shrink-0 items-center gap-1 [[data-slot=code-block]>&]:absolute [[data-slot=code-block]>&]:end-2 [[data-slot=code-block]>&]:top-2 [[data-slot=code-block]>&]:z-10 [[data-slot=code-block]>&]:m-0 [[data-slot=code-block]>&]:opacity-0 [[data-slot=code-block]>&]:transition-opacity [[data-slot=code-block]>&]:group-focus-within/code-block:opacity-100 [[data-slot=code-block]>&]:group-hover/code-block:opacity-100 group-data-[size=sm]/code-block:[[data-slot=code-block]>&]:end-1.5 group-data-[size=sm]/code-block:[[data-slot=code-block]>&]:top-1.5 [[data-slot=code-block]>&]:pointer-coarse:opacity-100 [[data-slot=code-block]>&]:*:[button]:bg-background [[data-slot=code-block]>&]:*:[button]:ring-1 [[data-slot=code-block]>&]:*:[button]:ring-foreground/10", className),
|
|
42
|
+
className: cn("-my-1 ms-auto -me-1.5 flex shrink-0 items-center gap-1 pointer-coarse:my-0 [[data-slot=code-block]>&]:absolute [[data-slot=code-block]>&]:end-2 [[data-slot=code-block]>&]:top-2 [[data-slot=code-block]>&]:z-10 [[data-slot=code-block]>&]:m-0 [[data-slot=code-block]>&]:opacity-0 [[data-slot=code-block]>&]:transition-opacity [[data-slot=code-block]>&]:group-focus-within/code-block:opacity-100 [[data-slot=code-block]>&]:group-hover/code-block:opacity-100 group-data-[size=sm]/code-block:[[data-slot=code-block]>&]:end-1.5 group-data-[size=sm]/code-block:[[data-slot=code-block]>&]:top-1.5 [[data-slot=code-block]>&]:pointer-coarse:opacity-100 [[data-slot=code-block]>&]:*:[button]:bg-background [[data-slot=code-block]>&]:*:[button]:ring-1 [[data-slot=code-block]>&]:*:[button]:ring-foreground/10", className),
|
|
43
43
|
...props
|
|
44
44
|
});
|
|
45
45
|
}
|
|
@@ -57,7 +57,7 @@ function CodeBlockCopyButton({ value, variant = "ghost", size = "icon-xs", type
|
|
|
57
57
|
variant,
|
|
58
58
|
size,
|
|
59
59
|
"aria-label": copied ? "Copied" : "Copy",
|
|
60
|
-
className: cn(className),
|
|
60
|
+
className: cn("pointer-coarse:size-11", className),
|
|
61
61
|
onClick: (event) => {
|
|
62
62
|
onClick?.(event);
|
|
63
63
|
navigator.clipboard.writeText(value).then(() => setCopied(true)).catch(() => {});
|
|
@@ -49,6 +49,7 @@ function ComboboxInput({ className, children, disabled = false, showTrigger = tr
|
|
|
49
49
|
variant: "ghost",
|
|
50
50
|
asChild: true,
|
|
51
51
|
"data-slot": "input-group-button",
|
|
52
|
+
"aria-label": "Show options",
|
|
52
53
|
className: "group-has-data-[slot=combobox-clear]/input-group:hidden data-pressed:bg-transparent",
|
|
53
54
|
disabled,
|
|
54
55
|
children: /* @__PURE__ */ jsx(ComboboxTrigger, {})
|
|
@@ -5,7 +5,7 @@ declare function DialogTrigger({ ...props }: React.ComponentProps<typeof Dialog$
|
|
|
5
5
|
declare function DialogPortal({ ...props }: React.ComponentProps<typeof Dialog$1.Portal>): React.JSX.Element;
|
|
6
6
|
declare function DialogClose({ ...props }: React.ComponentProps<typeof Dialog$1.Close>): React.JSX.Element;
|
|
7
7
|
declare function DialogOverlay({ className, ...props }: React.ComponentProps<typeof Dialog$1.Overlay>): React.JSX.Element;
|
|
8
|
-
declare function DialogContent({ className, children, showCloseButton, ...props }: React.ComponentProps<typeof Dialog$1.Content> & {
|
|
8
|
+
declare function DialogContent({ className, children, showCloseButton, onInteractOutside, ...props }: React.ComponentProps<typeof Dialog$1.Content> & {
|
|
9
9
|
showCloseButton?: boolean;
|
|
10
10
|
}): React.JSX.Element;
|
|
11
11
|
declare function DialogHeader({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
import { keepOpenOnToast } from "../../lib/internal/toast-clearance.js";
|
|
2
3
|
import { cn } from "../../lib/utils.js";
|
|
3
4
|
import { Button } from "./button.js";
|
|
4
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -36,11 +37,12 @@ function DialogOverlay({ className, ...props }) {
|
|
|
36
37
|
...props
|
|
37
38
|
});
|
|
38
39
|
}
|
|
39
|
-
function DialogContent({ className, children, showCloseButton = true, ...props }) {
|
|
40
|
+
function DialogContent({ className, children, showCloseButton = true, onInteractOutside, ...props }) {
|
|
40
41
|
return /* @__PURE__ */ jsxs(DialogPortal, { children: [/* @__PURE__ */ jsx(DialogOverlay, {}), /* @__PURE__ */ jsxs(Dialog$1.Content, {
|
|
41
42
|
"data-slot": "dialog-content",
|
|
42
43
|
className: cn("fixed top-1/2 left-1/2 z-50 grid w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl bg-popover p-4 text-sm text-popover-foreground ring-1 ring-foreground/10 duration-100 outline-none sm:max-w-sm data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", className),
|
|
43
44
|
...props,
|
|
45
|
+
onInteractOutside: keepOpenOnToast(onInteractOutside),
|
|
44
46
|
children: [children, showCloseButton && /* @__PURE__ */ jsx(Dialog$1.Close, {
|
|
45
47
|
"data-slot": "dialog-close",
|
|
46
48
|
asChild: true,
|
|
@@ -5,7 +5,7 @@ declare function DrawerTrigger({ ...props }: React.ComponentProps<typeof Drawer$
|
|
|
5
5
|
declare function DrawerPortal({ ...props }: React.ComponentProps<typeof Drawer$1.Portal>): React.JSX.Element;
|
|
6
6
|
declare function DrawerClose({ ...props }: React.ComponentProps<typeof Drawer$1.Close>): React.JSX.Element;
|
|
7
7
|
declare function DrawerOverlay({ className, ...props }: React.ComponentProps<typeof Drawer$1.Overlay>): React.JSX.Element;
|
|
8
|
-
declare function DrawerContent({ className, children, ...props }: React.ComponentProps<typeof Drawer$1.Content>): React.JSX.Element;
|
|
8
|
+
declare function DrawerContent({ className, children, onInteractOutside, ...props }: React.ComponentProps<typeof Drawer$1.Content>): React.JSX.Element;
|
|
9
9
|
declare function DrawerHeader({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
|
|
10
10
|
declare function DrawerFooter({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
|
|
11
11
|
declare function DrawerTitle({ className, ...props }: React.ComponentProps<typeof Drawer$1.Title>): React.JSX.Element;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
import { keepOpenOnToast } from "../../lib/internal/toast-clearance.js";
|
|
2
3
|
import { cn } from "../../lib/utils.js";
|
|
3
4
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
5
|
import { Drawer as Drawer$1 } from "vaul";
|
|
@@ -34,13 +35,14 @@ function DrawerOverlay({ className, ...props }) {
|
|
|
34
35
|
...props
|
|
35
36
|
});
|
|
36
37
|
}
|
|
37
|
-
function DrawerContent({ className, children, ...props }) {
|
|
38
|
+
function DrawerContent({ className, children, onInteractOutside, ...props }) {
|
|
38
39
|
return /* @__PURE__ */ jsxs(DrawerPortal, {
|
|
39
40
|
"data-slot": "drawer-portal",
|
|
40
41
|
children: [/* @__PURE__ */ jsx(DrawerOverlay, {}), /* @__PURE__ */ jsxs(Drawer$1.Content, {
|
|
41
42
|
"data-slot": "drawer-content",
|
|
42
43
|
className: cn("group/drawer-content fixed z-50 flex h-auto flex-col bg-popover text-sm text-popover-foreground data-[vaul-drawer-direction=bottom]:inset-x-0 data-[vaul-drawer-direction=bottom]:bottom-0 data-[vaul-drawer-direction=bottom]:mt-24 data-[vaul-drawer-direction=bottom]:max-h-[80vh] data-[vaul-drawer-direction=bottom]:rounded-t-xl data-[vaul-drawer-direction=bottom]:border-t data-[vaul-drawer-direction=left]:inset-y-0 data-[vaul-drawer-direction=left]:left-0 data-[vaul-drawer-direction=left]:w-3/4 data-[vaul-drawer-direction=left]:rounded-r-xl data-[vaul-drawer-direction=left]:border-r data-[vaul-drawer-direction=right]:inset-y-0 data-[vaul-drawer-direction=right]:right-0 data-[vaul-drawer-direction=right]:w-3/4 data-[vaul-drawer-direction=right]:rounded-l-xl data-[vaul-drawer-direction=right]:border-l data-[vaul-drawer-direction=top]:inset-x-0 data-[vaul-drawer-direction=top]:top-0 data-[vaul-drawer-direction=top]:mb-24 data-[vaul-drawer-direction=top]:max-h-[80vh] data-[vaul-drawer-direction=top]:rounded-b-xl data-[vaul-drawer-direction=top]:border-b data-[vaul-drawer-direction=left]:sm:max-w-sm data-[vaul-drawer-direction=right]:sm:max-w-sm", className),
|
|
43
44
|
...props,
|
|
45
|
+
onInteractOutside: keepOpenOnToast(onInteractOutside),
|
|
44
46
|
children: [/* @__PURE__ */ jsx("div", { className: "mx-auto mt-4 hidden h-1 w-[100px] shrink-0 rounded-full bg-muted group-data-[vaul-drawer-direction=bottom]/drawer-content:block" }), children]
|
|
45
47
|
})]
|
|
46
48
|
});
|