harebear-ui 0.9.0 → 0.10.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.
Files changed (53) hide show
  1. package/dist/components/admin/app-nav.d.ts +11 -1
  2. package/dist/components/admin/app-nav.js +26 -9
  3. package/dist/components/admin/checklist-editor.d.ts +20 -0
  4. package/dist/components/admin/checklist-editor.js +69 -0
  5. package/dist/components/admin/comment-thread.d.ts +26 -0
  6. package/dist/components/admin/comment-thread.js +68 -0
  7. package/dist/components/admin/copy-field.d.ts +3 -1
  8. package/dist/components/admin/copy-field.js +10 -5
  9. package/dist/components/admin/date-time-picker.js +1 -1
  10. package/dist/components/admin/markdown-editor.d.ts +2 -5
  11. package/dist/components/admin/markdown-editor.js +13 -9
  12. package/dist/components/admin/page-header.d.ts +3 -1
  13. package/dist/components/admin/page-header.js +17 -9
  14. package/dist/components/admin/page.d.ts +16 -0
  15. package/dist/components/admin/page.js +42 -0
  16. package/dist/components/admin/prompt-dialog.d.ts +19 -0
  17. package/dist/components/admin/prompt-dialog.js +83 -0
  18. package/dist/components/admin/settings.d.ts +4 -2
  19. package/dist/components/admin/settings.js +37 -30
  20. package/dist/components/admin/time-zone-picker.d.ts +12 -0
  21. package/dist/components/admin/time-zone-picker.js +31 -0
  22. package/dist/components/admin/user-menu.d.ts +3 -1
  23. package/dist/components/admin/user-menu.js +21 -10
  24. package/dist/components/ai/assistant.js +1 -1
  25. package/dist/components/ai/code-block.js +3 -3
  26. package/dist/components/ai/markdown.d.ts +13 -0
  27. package/dist/components/ai/markdown.js +41 -0
  28. package/dist/components/auth/auth.d.ts +41 -5
  29. package/dist/components/auth/auth.js +165 -155
  30. package/dist/components/data/day-strip.d.ts +6 -1
  31. package/dist/components/data/day-strip.js +15 -5
  32. package/dist/components/layout/collapse.js +1 -1
  33. package/dist/components/layout/text.d.ts +3 -3
  34. package/dist/components/layout/text.js +6 -1
  35. package/dist/components/ui/button.js +1 -1
  36. package/dist/components/ui/check-circle.js +1 -1
  37. package/dist/components/ui/code-block.js +2 -2
  38. package/dist/components/ui/combobox.js +1 -0
  39. package/dist/components/ui/input-group.js +1 -1
  40. package/dist/components/ui/input.js +1 -1
  41. package/dist/components/ui/sonner.d.ts +2 -2
  42. package/dist/components/ui/sonner.js +1 -1
  43. package/dist/components/ui/toggle.js +1 -1
  44. package/dist/index.d.ts +9 -3
  45. package/dist/index.js +9 -3
  46. package/dist/lib/{date.js → internal/date.js} +1 -1
  47. package/dist/lib/{toast-clearance.js → internal/toast-clearance.js} +1 -1
  48. package/dist/styles.css +6 -1
  49. package/docs/COMPONENTS.md +150 -26
  50. package/docs/ROADMAP.md +1 -0
  51. package/llms.txt +7 -6
  52. package/package.json +3 -1
  53. package/skills/harebear-ui/SKILL.md +5 -4
@@ -29,8 +29,8 @@ function SettingsSection({ title, description, className, children, ...props })
29
29
  })]
30
30
  });
31
31
  }
32
- /** One setting: label and description at the left, a control at the right, optional expandable content. */
33
- function SettingsRow({ label, description, htmlFor, control, content, open: openProp, defaultOpen = false, onOpenChange, expandLabel = "Change", className, ...props }) {
32
+ /** One setting: label and description at the left, a control at the right, optional body and expandable content. */
33
+ function SettingsRow({ label, description, htmlFor, control, body, content, open: openProp, defaultOpen = false, onOpenChange, expandLabel = "Change", className, ...props }) {
34
34
  const [openState, setOpenState] = React.useState(defaultOpen);
35
35
  const open = openProp ?? openState;
36
36
  const setOpen = (next) => {
@@ -44,35 +44,42 @@ function SettingsRow({ label, description, htmlFor, control, content, open: open
44
44
  "data-state": content ? open ? "open" : "closed" : void 0,
45
45
  className: cn("py-3.5", className),
46
46
  ...props,
47
- children: [/* @__PURE__ */ jsxs("div", {
48
- className: "flex flex-wrap items-center gap-x-4 gap-y-2",
49
- children: [/* @__PURE__ */ jsxs("div", {
50
- className: "flex min-w-0 flex-1 basis-48 flex-col",
51
- children: [/* @__PURE__ */ jsx(Label, {
52
- htmlFor,
53
- className: "text-sm font-medium",
54
- children: label
55
- }), description && /* @__PURE__ */ jsx("span", {
56
- className: "text-[13px] text-muted-foreground",
57
- children: description
58
- })]
59
- }), control ?? (content ? /* @__PURE__ */ jsx(Button, {
60
- type: "button",
61
- variant: "outline",
62
- size: "sm",
63
- "aria-expanded": open,
64
- "aria-controls": contentId,
65
- onClick: () => setOpen(!open),
66
- children: open ? "Cancel" : expandLabel
67
- }) : null)]
68
- }), content && /* @__PURE__ */ jsx(Collapse, {
69
- open,
70
- id: contentId,
71
- children: /* @__PURE__ */ jsx("div", {
72
- className: "pt-3.5",
73
- children: content
47
+ children: [
48
+ /* @__PURE__ */ jsxs("div", {
49
+ className: "flex flex-wrap items-center gap-x-4 gap-y-2",
50
+ children: [/* @__PURE__ */ jsxs("div", {
51
+ className: "flex min-w-0 flex-1 basis-48 flex-col",
52
+ children: [/* @__PURE__ */ jsx(Label, {
53
+ htmlFor,
54
+ className: "text-sm font-medium",
55
+ children: label
56
+ }), description && /* @__PURE__ */ jsx("span", {
57
+ className: "text-[13px] text-muted-foreground",
58
+ children: description
59
+ })]
60
+ }), control ?? (content ? /* @__PURE__ */ jsx(Button, {
61
+ type: "button",
62
+ variant: "outline",
63
+ size: "sm",
64
+ "aria-expanded": open,
65
+ "aria-controls": contentId,
66
+ onClick: () => setOpen(!open),
67
+ children: open ? "Cancel" : expandLabel
68
+ }) : null)]
69
+ }),
70
+ body && /* @__PURE__ */ jsx("div", {
71
+ className: "pt-3",
72
+ children: body
73
+ }),
74
+ content && /* @__PURE__ */ jsx(Collapse, {
75
+ open,
76
+ id: contentId,
77
+ children: /* @__PURE__ */ jsx("div", {
78
+ className: "pt-3.5",
79
+ children: content
80
+ })
74
81
  })
75
- })]
82
+ ]
76
83
  });
77
84
  }
78
85
  export { SettingsRow, SettingsSection };
@@ -0,0 +1,12 @@
1
+ import * as React from "react";
2
+ export interface TimeZonePickerProps {
3
+ /** IANA name, e.g. "America/Vancouver". */
4
+ value: string;
5
+ onValueChange: (value: string) => void;
6
+ /** id of the search input, for a FieldLabel or SettingsRow `htmlFor`. */
7
+ id?: string;
8
+ className?: string;
9
+ }
10
+ /** Searchable IANA time zone list (Intl.supportedValuesOf("timeZone")), built on Combobox. */
11
+ declare function TimeZonePicker({ value, onValueChange, id, className }: TimeZonePickerProps): React.JSX.Element;
12
+ export { TimeZonePicker };
@@ -0,0 +1,31 @@
1
+ "use client";
2
+ import { Combobox, ComboboxContent, ComboboxEmpty, ComboboxInput, ComboboxItem, ComboboxList } from "../ui/combobox.js";
3
+ import { cn } from "../../lib/utils.js";
4
+ import * as React from "react";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ // src/components/admin/time-zone-picker.tsx
7
+ const label = (zone) => zone.replaceAll("_", " ");
8
+ /** Searchable IANA time zone list (Intl.supportedValuesOf("timeZone")), built on Combobox. */
9
+ function TimeZonePicker({ value, onValueChange, id, className }) {
10
+ const zones = React.useMemo(() => {
11
+ const all = Intl.supportedValuesOf("timeZone");
12
+ return value && !all.includes(value) ? [value, ...all] : all;
13
+ }, [value]);
14
+ return /* @__PURE__ */ jsxs(Combobox, {
15
+ items: zones,
16
+ value,
17
+ onValueChange: (next) => next && onValueChange(next),
18
+ itemToStringLabel: label,
19
+ children: [/* @__PURE__ */ jsx(ComboboxInput, {
20
+ id,
21
+ placeholder: "Search time zones",
22
+ showTrigger: false,
23
+ className: cn("w-full", className)
24
+ }), /* @__PURE__ */ jsxs(ComboboxContent, { children: [/* @__PURE__ */ jsx(ComboboxEmpty, { children: "No matching time zone." }), /* @__PURE__ */ jsx(ComboboxList, { children: (zone) => /* @__PURE__ */ jsx(ComboboxItem, {
25
+ value: zone,
26
+ className: "pointer-coarse:min-h-11",
27
+ children: label(zone)
28
+ }, zone) })] })]
29
+ });
30
+ }
31
+ export { TimeZonePicker };
@@ -15,11 +15,13 @@ export interface UserMenuProps {
15
15
  onSignOut?: () => void;
16
16
  /** Default "Sign out". */
17
17
  signOutLabel?: React.ReactNode;
18
+ /** Trigger is just the avatar (44px on touch screens) and the menu opens below it, e.g. in a phone page header. */
19
+ compact?: boolean;
18
20
  className?: string;
19
21
  }
20
22
  /**
21
23
  * The signed-in user as a menu button, for a sidebar footer or top bar: theme choice, app items such as
22
24
  * Settings, and sign out. In a sidebar icon rail the trigger is just the avatar and the menu opens to the side.
23
25
  */
24
- declare function UserMenu({ name, subtitle, avatarUrl, color, children, themeSwitch, onSignOut, signOutLabel, className }: UserMenuProps): React.JSX.Element;
26
+ declare function UserMenu({ name, subtitle, avatarUrl, color, children, themeSwitch, onSignOut, signOutLabel, compact, className }: UserMenuProps): React.JSX.Element;
25
27
  export { UserMenu };
@@ -1,6 +1,8 @@
1
1
  "use client";
2
- import { UserChip } from "./user-chip.js";
2
+ import { categoryBg } from "./category.js";
3
+ import { UserChip, initials } from "./user-chip.js";
3
4
  import { useTheme } from "../theme/theme-provider.js";
5
+ import { Avatar, AvatarFallback, AvatarImage } from "../ui/avatar.js";
4
6
  import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuTrigger } from "../ui/dropdown-menu.js";
5
7
  import { useSidebarOptional } from "../ui/sidebar.js";
6
8
  import { cn } from "../../lib/utils.js";
@@ -28,26 +30,35 @@ const themes = [
28
30
  * The signed-in user as a menu button, for a sidebar footer or top bar: theme choice, app items such as
29
31
  * Settings, and sign out. In a sidebar icon rail the trigger is just the avatar and the menu opens to the side.
30
32
  */
31
- function UserMenu({ name, subtitle, avatarUrl, color, children, themeSwitch = true, onSignOut, signOutLabel = "Sign out", className }) {
33
+ function UserMenu({ name, subtitle, avatarUrl, color, children, themeSwitch = true, onSignOut, signOutLabel = "Sign out", compact = false, className }) {
32
34
  const { mode, setMode } = useTheme();
33
35
  const sidebar = useSidebarOptional();
34
36
  const rail = sidebar?.state === "collapsed" && !sidebar.isMobile;
35
- return /* @__PURE__ */ jsxs(DropdownMenu, { children: [/* @__PURE__ */ jsxs(DropdownMenuTrigger, {
37
+ return /* @__PURE__ */ jsxs(DropdownMenu, { children: [/* @__PURE__ */ jsx(DropdownMenuTrigger, {
36
38
  "data-slot": "user-menu-trigger",
37
- "aria-label": `Account menu for ${name}`,
38
- className: cn("flex w-full min-w-0 items-center gap-2 rounded-lg px-2 py-1.5 text-left transition-colors outline-none hover:bg-muted focus-visible:ring-2 focus-visible:ring-ring/40 data-[state=open]:bg-muted group-data-[collapsible=icon]:mx-auto group-data-[collapsible=icon]:size-10 group-data-[collapsible=icon]:justify-center group-data-[collapsible=icon]:rounded-full group-data-[collapsible=icon]:p-0", className),
39
- children: [/* @__PURE__ */ jsx(UserChip, {
39
+ "aria-label": compact ? `Account menu for ${name}` : rail ? name : void 0,
40
+ className: cn(compact ? "grid size-10 shrink-0 place-items-center rounded-full outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background pointer-coarse:size-11" : "flex w-full min-w-0 items-center gap-2 rounded-lg px-2 py-1.5 text-left transition-colors outline-none hover:bg-muted focus-visible:ring-2 focus-visible:ring-ring data-[state=open]:bg-muted group-data-[collapsible=icon]:mx-auto group-data-[collapsible=icon]:size-10 group-data-[collapsible=icon]:justify-center group-data-[collapsible=icon]:rounded-full group-data-[collapsible=icon]:p-0", className),
41
+ children: compact || rail ? /* @__PURE__ */ jsxs(Avatar, {
42
+ "aria-hidden": "true",
43
+ children: [avatarUrl && /* @__PURE__ */ jsx(AvatarImage, {
44
+ src: avatarUrl,
45
+ alt: ""
46
+ }), /* @__PURE__ */ jsx(AvatarFallback, {
47
+ "data-initials": initials(name),
48
+ className: cn("after:content-[attr(data-initials)]", color && [categoryBg[color], "text-category-foreground"])
49
+ })]
50
+ }) : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(UserChip, {
40
51
  name,
41
52
  subtitle,
42
53
  avatarUrl,
43
54
  color,
44
55
  className: "flex-1"
45
- }), /* @__PURE__ */ jsx(ChevronsUpDownIcon, { className: "size-4 shrink-0 text-muted-foreground group-data-[collapsible=icon]:hidden" })]
56
+ }), /* @__PURE__ */ jsx(ChevronsUpDownIcon, { className: "size-4 shrink-0 text-muted-foreground group-data-[collapsible=icon]:hidden" })] })
46
57
  }), /* @__PURE__ */ jsxs(DropdownMenuContent, {
47
58
  "data-slot": "user-menu",
48
- side: rail ? "right" : "top",
49
- align: rail ? "end" : "start",
50
- className: "w-(--radix-dropdown-menu-trigger-width) min-w-60",
59
+ side: compact ? "bottom" : rail ? "right" : "top",
60
+ align: compact || rail ? "end" : "start",
61
+ className: compact ? "min-w-60" : "w-(--radix-dropdown-menu-trigger-width) min-w-60",
51
62
  children: [
52
63
  /* @__PURE__ */ jsxs(DropdownMenuLabel, {
53
64
  className: "flex min-w-0 flex-col font-normal",
@@ -2,7 +2,7 @@
2
2
  import { AskBox } from "./ask-box.js";
3
3
  import { AssistantAvatar, ChatMessage, ChatThread, TypingIndicator } from "./chat.js";
4
4
  import { Button } from "../ui/button.js";
5
- import { useToastClearance } from "../../lib/toast-clearance.js";
5
+ import { useToastClearance } from "../../lib/internal/toast-clearance.js";
6
6
  import { cn } from "../../lib/utils.js";
7
7
  import * as React from "react";
8
8
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -30,9 +30,9 @@ function CodeSnippet({ code, language, highlight = true, lineNumbers, hideCopy,
30
30
  type: "button",
31
31
  variant: "ghost",
32
32
  size: "sm",
33
- className: "ms-auto",
33
+ className: "ms-auto pointer-coarse:h-11",
34
34
  onClick: () => copy(code),
35
- "aria-label": "Copy code",
35
+ "aria-label": copied ? void 0 : "Copy code",
36
36
  children: [copied ? /* @__PURE__ */ jsx(CheckIcon, {}) : /* @__PURE__ */ jsx(CopyIcon, {}), copied ? "Copied" : "Copy"]
37
37
  })]
38
38
  }), /* @__PURE__ */ jsx(CodeBlockContent, {
@@ -106,7 +106,7 @@ function withTips(children) {
106
106
  function Prose({ className, children, ...props }) {
107
107
  return /* @__PURE__ */ jsx("div", {
108
108
  "data-slot": "prose",
109
- className: cn("flex min-w-0 flex-col gap-3.5 text-[15px] leading-[1.65] wrap-anywhere text-foreground", "[&_ol]:flex [&_ol]:list-decimal [&_ol]:flex-col [&_ol]:gap-2 [&_ol]:pl-5.5", "[&_ul]:flex [&_ul]:list-disc [&_ul]:flex-col [&_ul]:gap-2 [&_ul]:pl-5.5", "[&_strong]:font-semibold [&_a]:text-primary [&_a]:underline-offset-4 hover:[&_a]:underline", "[&_h1]:text-xl [&_h1]:font-semibold [&_h2]:text-lg [&_h2]:font-semibold [&_h3]:font-semibold [&_h4]:font-semibold", "[&_blockquote]:border-l-2 [&_blockquote]:pl-4 [&_blockquote]:text-muted-foreground", "[&_:not(pre)>code]:rounded-[6px] [&_:not(pre)>code]:bg-muted [&_:not(pre)>code]:px-1.5 [&_:not(pre)>code]:py-0.5 [&_:not(pre)>code]:font-mono [&_:not(pre)>code]:text-[12.5px]", "[&_pre]:overflow-x-auto [&_pre]:rounded-lg [&_pre]:bg-muted [&_pre]:p-4.5 [&_pre]:font-mono [&_pre]:text-[13px]", "[&_table]:w-full [&_table]:text-sm [&_td]:border-b [&_td]:py-2 [&_th]:border-b [&_th]:py-2 [&_th]:text-left [&_th]:font-medium", className),
109
+ className: cn("flex min-w-0 flex-col gap-3.5 text-[15px] leading-[1.65] wrap-anywhere text-foreground", "[&_ol]:flex [&_ol]:list-decimal [&_ol]:flex-col [&_ol]:gap-2 [&_ol]:pl-5.5", "[&_ul]:flex [&_ul]:list-disc [&_ul]:flex-col [&_ul]:gap-2 [&_ul]:pl-5.5", "[&_strong]:font-semibold [&_a]:text-primary [&_a]:underline [&_a]:decoration-primary/40 [&_a]:underline-offset-4 hover:[&_a]:decoration-primary [&_a]:rounded-sm [&_a:focus-visible]:outline-2 [&_a:focus-visible]:outline-offset-2 [&_a:focus-visible]:outline-ring", "[&_h1]:text-xl [&_h1]:font-semibold [&_h2]:text-lg [&_h2]:font-semibold [&_h3]:font-semibold [&_h4]:font-semibold", "[&_blockquote]:border-l-2 [&_blockquote]:pl-4 [&_blockquote]:text-muted-foreground", "[&_:not(pre)>code]:rounded-[6px] [&_:not(pre)>code]:bg-muted [&_:not(pre)>code]:px-1.5 [&_:not(pre)>code]:py-0.5 [&_:not(pre)>code]:font-mono [&_:not(pre)>code]:text-[12.5px]", "[&_pre]:overflow-x-auto [&_pre]:rounded-lg [&_pre]:bg-muted [&_pre]:p-4.5 [&_pre]:font-mono [&_pre]:text-[13px]", "[&_table]:w-full [&_table]:text-sm [&_td]:border-b [&_td]:py-2 [&_th]:border-b [&_th]:py-2 [&_th]:text-left [&_th]:font-medium", className),
110
110
  ...props,
111
111
  children: withTips(children)
112
112
  });
@@ -0,0 +1,13 @@
1
+ import * as React from "react";
2
+ export interface MarkdownProps extends Omit<React.ComponentProps<"div">, "children"> {
3
+ /** The Markdown source. GitHub flavoured (tables, task lists, strikethrough, autolinks). Raw HTML is dropped. */
4
+ children: string;
5
+ /** Component for in-app links (href without a scheme, e.g. "/lists/2"), e.g. Next.js or React Router Link. Gets `href`. */
6
+ linkComponent?: React.ElementType;
7
+ }
8
+ /**
9
+ * Renders Markdown safely inside Prose: no raw HTML, unsafe URLs (javascript:) removed, `> Tip:` blockquotes as
10
+ * a Callout. Other props go to the Prose wrapper.
11
+ */
12
+ declare function Markdown({ children, linkComponent: Link, ...props }: MarkdownProps): React.JSX.Element;
13
+ export { Markdown };
@@ -0,0 +1,41 @@
1
+ "use client";
2
+ import { Prose, ProseBlockquote } from "./code-block.js";
3
+ import * as React from "react";
4
+ import { jsx } from "react/jsx-runtime";
5
+ import ReactMarkdown from "react-markdown";
6
+ import remarkGfm from "remark-gfm";
7
+ // src/components/ai/markdown.tsx
8
+ const plugins = [remarkGfm];
9
+ const SCHEME = /^([a-z][a-z\d+.-]*:|\/\/)/i;
10
+ /**
11
+ * Renders Markdown safely inside Prose: no raw HTML, unsafe URLs (javascript:) removed, `> Tip:` blockquotes as
12
+ * a Callout. Other props go to the Prose wrapper.
13
+ */
14
+ function Markdown({ children, linkComponent: Link, ...props }) {
15
+ const components = React.useMemo(() => ({
16
+ blockquote: ProseBlockquote,
17
+ a: ({ node: _node, href = "", ...rest }) => Link && !SCHEME.test(href) ? /* @__PURE__ */ jsx(Link, {
18
+ href,
19
+ ...rest
20
+ }) : /* @__PURE__ */ jsx("a", {
21
+ href,
22
+ ...rest
23
+ }),
24
+ input: ({ node: _node, checked, ...rest }) => /* @__PURE__ */ jsx("input", {
25
+ ...rest,
26
+ checked,
27
+ "aria-label": checked ? "Done" : "Not done"
28
+ })
29
+ }), [Link]);
30
+ return /* @__PURE__ */ jsx(Prose, {
31
+ "data-slot": "markdown",
32
+ ...props,
33
+ children: /* @__PURE__ */ jsx(ReactMarkdown, {
34
+ remarkPlugins: plugins,
35
+ components,
36
+ skipHtml: true,
37
+ children
38
+ })
39
+ });
40
+ }
41
+ export { Markdown };
@@ -33,6 +33,23 @@ declare function GitHubIcon(props: React.ComponentProps<"svg">): React.JSX.Eleme
33
33
  declare function GoogleIcon(props: React.ComponentProps<"svg">): React.JSX.Element;
34
34
  /** Apple mark, for AuthProvider icons. */
35
35
  declare function AppleIcon(props: React.ComponentProps<"svg">): React.JSX.Element;
36
+ export interface AuthFormProps extends Omit<React.ComponentProps<"form">, "onSubmit" | "title"> {
37
+ title: React.ReactNode;
38
+ description?: React.ReactNode;
39
+ /** The fields. Give each a `name`; they arrive in onSubmit's FormData. */
40
+ children?: React.ReactNode;
41
+ /** Form-level error, e.g. "Invalid email or password". */
42
+ error?: React.ReactNode;
43
+ submitLabel: React.ReactNode;
44
+ /** Shows a spinner on the submit button and disables every control. */
45
+ loading?: boolean;
46
+ /** Called with the form's data once the browser's validation passes. Omit to submit natively (e.g. to an `action`). */
47
+ onSubmit?: (data: FormData) => void | Promise<void>;
48
+ /** Under the submit button: provider buttons, a "Sign in" link. */
49
+ footer?: React.ReactNode;
50
+ }
51
+ /** The shell LoginForm, SignupForm and NewPasswordForm share: heading, your fields, error, submit button. */
52
+ declare function AuthForm({ title, description, children, error, submitLabel, loading, onSubmit, footer, className, ...props }: AuthFormProps): React.JSX.Element;
36
53
  interface AuthFormBase extends Omit<React.ComponentProps<"form">, "onSubmit" | "title"> {
37
54
  title?: React.ReactNode;
38
55
  description?: React.ReactNode;
@@ -51,7 +68,7 @@ export interface LoginValues {
51
68
  /** Absent in "email-only" mode. */
52
69
  password?: string;
53
70
  }
54
- export interface LoginFormProps extends AuthFormBase {
71
+ export interface LoginFormProps extends Omit<AuthFormBase, "children"> {
55
72
  /** Called with the entered values. Omit to let the form submit natively (e.g. to an `action`). */
56
73
  onSubmit?: (values: LoginValues) => void | Promise<void>;
57
74
  /** "email-only" drops the password field for magic-link or OTP flows (shadcn login-05). */
@@ -61,14 +78,17 @@ export interface LoginFormProps extends AuthFormBase {
61
78
  submitLabel?: React.ReactNode;
62
79
  }
63
80
  /** Email + password sign-in form with optional SSO buttons. Pair with AuthLayout. */
64
- declare function LoginForm({ title, description, onSubmit, mode, providers, onProviderClick, providersFirst, forgotPasswordHref, signupHref, submitLabel, loading, error, className, ...props }: LoginFormProps): React.JSX.Element;
81
+ declare function LoginForm({ title, description, onSubmit, mode, providers, onProviderClick, providersFirst, forgotPasswordHref, signupHref, submitLabel, ...props }: LoginFormProps): React.JSX.Element;
65
82
  export interface SignupValues {
66
83
  name?: string;
67
84
  email: string;
68
85
  password: string;
69
86
  }
70
87
  export interface SignupFormProps extends AuthFormBase {
71
- onSubmit?: (values: SignupValues) => void | Promise<void>;
88
+ /** `data` holds every field, including your own `children` fields. */
89
+ onSubmit?: (values: SignupValues, data: FormData) => void | Promise<void>;
90
+ /** Extra fields shown before the name field (e.g. a household name). Give each a `name`; read it from `data`. */
91
+ children?: React.ReactNode;
72
92
  /** Ask for a full name. Default true. */
73
93
  nameField?: boolean;
74
94
  /** Ask for the password twice; mismatches are reported before onSubmit. Default true. */
@@ -81,5 +101,21 @@ export interface SignupFormProps extends AuthFormBase {
81
101
  submitLabel?: React.ReactNode;
82
102
  }
83
103
  /** Account creation form: name, email, password (+ confirm), optional SSO. Pair with AuthLayout. */
84
- declare function SignupForm({ title, description, onSubmit, nameField, confirmPassword, passwordHint, minPasswordLength, providers, onProviderClick, providersFirst, loginHref, submitLabel, loading, error, className, ...props }: SignupFormProps): React.JSX.Element;
85
- export { AppleIcon, AuthLayout, GitHubIcon, GoogleIcon, LoginForm, SignupForm };
104
+ declare function SignupForm({ title, description, onSubmit, children, nameField, confirmPassword, passwordHint, minPasswordLength, providers, onProviderClick, providersFirst, loginHref, submitLabel, ...props }: SignupFormProps): React.JSX.Element;
105
+ export interface NewPasswordFormProps extends Omit<React.ComponentProps<"form">, "onSubmit" | "title" | "children">, Pick<AuthFormProps, "description" | "error" | "loading"> {
106
+ /** Default "Choose a new password". */
107
+ title?: React.ReactNode;
108
+ /** Called once both fields match. */
109
+ onSubmit?: (values: {
110
+ password: string;
111
+ }) => void | Promise<void>;
112
+ /** Minimum length enforced by the browser. Default 8. */
113
+ minPasswordLength?: number;
114
+ /** Hint under the password field. Default "At least N characters." */
115
+ passwordHint?: React.ReactNode;
116
+ /** Default "Save password". */
117
+ submitLabel?: React.ReactNode;
118
+ }
119
+ /** Password reset or first password: new password + confirm. Pair with AuthLayout. */
120
+ declare function NewPasswordForm({ title, onSubmit, minPasswordLength, passwordHint, submitLabel, ...props }: NewPasswordFormProps): React.JSX.Element;
121
+ export { AppleIcon, AuthForm, AuthLayout, GitHubIcon, GoogleIcon, LoginForm, NewPasswordForm, SignupForm };