@photon-ai/pho-ui 2.3.0 → 2.5.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 (51) hide show
  1. package/dist/chunks/basic-page-w6ftlo0h.js +1284 -0
  2. package/dist/chunks/basic-page-w6ftlo0h.js.map +1 -0
  3. package/dist/chunks/{dialog-fWS3A3Z-.js → dialog-8SRNi_rv.js} +2 -2
  4. package/dist/chunks/{dialog-fWS3A3Z-.js.map → dialog-8SRNi_rv.js.map} +1 -1
  5. package/dist/chunks/{input-CCd6XK7Z.js → input-DjvZoF8v.js} +45 -41
  6. package/dist/chunks/input-DjvZoF8v.js.map +1 -0
  7. package/dist/chunks/{input-group-5AtpIhC_.js → input-group-fc9_jD4d.js} +44 -38
  8. package/dist/chunks/input-group-fc9_jD4d.js.map +1 -0
  9. package/dist/chunks/kbd-DNI10uy7.js +18 -0
  10. package/dist/chunks/kbd-DNI10uy7.js.map +1 -0
  11. package/dist/chunks/{scroll-area-DkZHKfqH.js → scroll-area-Bu7egArU.js} +40 -26
  12. package/dist/chunks/scroll-area-Bu7egArU.js.map +1 -0
  13. package/dist/chunks/sidebar-DvB-G0BP.js +231 -0
  14. package/dist/chunks/sidebar-DvB-G0BP.js.map +1 -0
  15. package/dist/chunks/toast-DoXaRPIZ.js +167 -0
  16. package/dist/chunks/toast-DoXaRPIZ.js.map +1 -0
  17. package/dist/components/command.js +125 -172
  18. package/dist/components/command.js.map +1 -1
  19. package/dist/components/dialog.js +1 -1
  20. package/dist/components/input-group.js +1 -1
  21. package/dist/components/input.js +1 -1
  22. package/dist/components/kbd.js +2 -15
  23. package/dist/components/phone-input.js +1 -1
  24. package/dist/components/scroll-area.js +3 -2
  25. package/dist/components/toast.js +3 -57
  26. package/dist/index.js +65 -58
  27. package/dist/primitives.js +1 -1
  28. package/dist/sections/basic-page.js +15 -8
  29. package/dist/sections/sidebar.js +1 -1
  30. package/dist/src/components/command/command.d.ts +5 -4
  31. package/dist/src/components/input/input.d.ts +10 -1
  32. package/dist/src/components/input-group/input-group.d.ts +9 -2
  33. package/dist/src/components/scroll-area/index.d.ts +1 -0
  34. package/dist/src/components/scroll-area/scroll-area-edges.d.ts +6 -0
  35. package/dist/src/components/scroll-area/scroll-area.d.ts +15 -2
  36. package/dist/src/components/toast/index.d.ts +1 -1
  37. package/dist/src/components/toast/toast.d.ts +22 -7
  38. package/dist/src/sections/basic-page/basic-page.d.ts +140 -3
  39. package/dist/src/sections/basic-page/index.d.ts +1 -1
  40. package/dist/src/sections/sidebar/sidebar.d.ts +33 -3
  41. package/package.json +1 -1
  42. package/src/styles/pho.css +19 -0
  43. package/dist/chunks/basic-page-BkLG3Ybg.js +0 -942
  44. package/dist/chunks/basic-page-BkLG3Ybg.js.map +0 -1
  45. package/dist/chunks/input-CCd6XK7Z.js.map +0 -1
  46. package/dist/chunks/input-group-5AtpIhC_.js.map +0 -1
  47. package/dist/chunks/scroll-area-DkZHKfqH.js.map +0 -1
  48. package/dist/chunks/sidebar-Dt1F_CEP.js +0 -186
  49. package/dist/chunks/sidebar-Dt1F_CEP.js.map +0 -1
  50. package/dist/components/kbd.js.map +0 -1
  51. package/dist/components/toast.js.map +0 -1
package/dist/index.js CHANGED
@@ -1,73 +1,80 @@
1
1
  "use client";
2
- import { t as s } from "./chunks/cn-ChIgwEl3.js";
3
- import { n as r, r as o, t as E } from "./chunks/link-provider-9TFNyDqO.js";
4
- import { t as i } from "./chunks/resolve-variant-CcD8iG5l.js";
5
- import { n as I, r as n, t as A } from "./chunks/use-press-pulse-8iorQPsh.js";
2
+ import { t as a } from "./chunks/cn-ChIgwEl3.js";
3
+ import { n as r, r as E, t as o } from "./chunks/link-provider-9TFNyDqO.js";
4
+ import { t as S } from "./chunks/resolve-variant-CcD8iG5l.js";
5
+ import { n as A, r as T, t as I } from "./chunks/use-press-pulse-8iorQPsh.js";
6
6
  import "./utils.js";
7
- import { a as e, c as R, d as p, i as B, l as C, n as O, o as P, r as f, s as u, t as D, u as N } from "./chunks/button-DNNs5RsT.js";
8
- import { a as c, c as l, i as V, l as U, n as G, o as d, r as M, s as b, t as g } from "./chunks/error-Crs-wqMC.js";
9
- import { a as F, i as W, n as h, o as Z, r as v, s as w, t as x } from "./chunks/basic-page-BkLG3Ybg.js";
10
- import { a as z, c as Y, i as j, n as q, o as y, r as J, s as K, t as Q } from "./chunks/sidebar-Dt1F_CEP.js";
11
- import { t as $ } from "./chunks/input-CCd6XK7Z.js";
12
- import { t as sa } from "./chunks/close-button-GvqWbLl0.js";
13
- import { t as ra } from "./chunks/input-group-5AtpIhC_.js";
14
- import { n as Ea, t as _a } from "./chunks/card-DSW3Uhag.js";
15
- import { n as Sa, t as Ia } from "./chunks/dialog-fWS3A3Z-.js";
16
- import { i as Aa, n as Ta, r as ma, t as ea } from "./chunks/status-view-C8tabjDu.js";
7
+ import { a as m, c as R, d as B, i as p, l as C, n as O, o as f, r as u, s as N, t as P, u as D } from "./chunks/button-DNNs5RsT.js";
8
+ import { a as V, c, i as l, l as U, n as G, o as d, r as M, s as b, t as g } from "./chunks/error-Crs-wqMC.js";
9
+ import { a as F, c as W, d as h, f as v, i as Z, l as w, m as x, n as H, o as Y, p as z, r as X, s as j, t as q, u as y } from "./chunks/basic-page-w6ftlo0h.js";
10
+ import { a as K, c as Q, i as $, n as ss, o as as, r as ts, s as rs, t as Es } from "./chunks/sidebar-DvB-G0BP.js";
11
+ import { t as _s } from "./chunks/input-DjvZoF8v.js";
12
+ import { t as is } from "./chunks/close-button-GvqWbLl0.js";
13
+ import { t as Ts } from "./chunks/input-group-fc9_jD4d.js";
14
+ import { n as ns, t as es } from "./chunks/card-DSW3Uhag.js";
15
+ import { n as Rs, t as Bs } from "./chunks/dialog-8SRNi_rv.js";
16
+ import { i as Cs, n as Os, r as fs, t as us } from "./chunks/status-view-C8tabjDu.js";
17
17
  import "./components/status-view.js";
18
18
  export {
19
- x as BASIC_PAGE_CALLOUT,
20
- h as BASIC_PAGE_CARD,
21
- v as BASIC_PAGE_ITEM,
22
- W as BASIC_PAGE_ITEM_PANEL,
23
- F as BASIC_PAGE_ITEM_PANEL_DIVIDED,
24
- Z as BASIC_PAGE_ROW,
25
- D as BUTTON_COLORS,
19
+ q as AUTO_SAVE_DELAY_MS,
20
+ H as BASIC_PAGE_CALLOUT,
21
+ X as BASIC_PAGE_CARD,
22
+ Z as BASIC_PAGE_ITEM,
23
+ F as BASIC_PAGE_ITEM_PANEL,
24
+ Y as BASIC_PAGE_ITEM_PANEL_DIVIDED,
25
+ j as BASIC_PAGE_ROW,
26
+ P as BUTTON_COLORS,
26
27
  O as BUTTON_SHAPES,
27
- f as BUTTON_SIZES,
28
- B as BUTTON_VARIANTS,
29
- w as BasicPage,
30
- e as Button,
31
- P as ButtonLink,
32
- _a as CARD_SURFACE,
33
- A as CONTROL_PRESS_SCALE,
34
- I as CONTROL_PRESS_SPRING,
35
- Ea as Card,
36
- sa as CloseButton,
37
- Ia as Dialog,
38
- u as EFFECT_BUTTON_SIZES,
28
+ u as BUTTON_SIZES,
29
+ p as BUTTON_VARIANTS,
30
+ W as BasicPage,
31
+ m as Button,
32
+ f as ButtonLink,
33
+ es as CARD_SURFACE,
34
+ w as CONDENSE_BAR_ENTER,
35
+ y as CONDENSE_BAR_RISE_PX,
36
+ h as CONDENSE_BAR_TRAVEL,
37
+ I as CONTROL_PRESS_SCALE,
38
+ A as CONTROL_PRESS_SPRING,
39
+ ns as Card,
40
+ is as CloseButton,
41
+ Bs as Dialog,
42
+ N as EFFECT_BUTTON_SIZES,
39
43
  R as EffectButton,
40
44
  C as EffectButtonLink,
41
45
  g as Error,
42
46
  G as ErrorView,
43
47
  M as GENERIC_ERROR_TITLE,
44
- $ as Input,
45
- ra as InputGroup,
46
- E as LinkProvider,
47
- Q as SIDEBAR_HEADER_INSET,
48
- q as SIDEBAR_ITEM,
49
- J as SIDEBAR_ITEM_ACTIVE,
50
- j as SIDEBAR_ITEM_INACTIVE,
51
- z as SIDEBAR_ROOT,
52
- y as SIDEBAR_ROOT_BASE,
53
- K as SIDEBAR_ROOT_INSET,
54
- ea as STATUS_VIEW,
55
- Ta as STATUS_VIEW_COPY,
56
- ma as STATUS_VIEW_SIZES,
57
- Y as Sidebar,
58
- Aa as StatusView,
59
- N as buttonVariants,
60
- V as capitalizeFirst,
61
- s as cn,
62
- c as describeError,
63
- p as effectButtonVariants,
48
+ _s as Input,
49
+ Ts as InputGroup,
50
+ o as LinkProvider,
51
+ Es as SIDEBAR_HEADER_INSET,
52
+ ss as SIDEBAR_ITEM,
53
+ ts as SIDEBAR_ITEM_ACTIVE,
54
+ $ as SIDEBAR_ITEM_INACTIVE,
55
+ K as SIDEBAR_ROOT,
56
+ as as SIDEBAR_ROOT_BASE,
57
+ rs as SIDEBAR_ROOT_INSET,
58
+ us as STATUS_VIEW,
59
+ Os as STATUS_VIEW_COPY,
60
+ fs as STATUS_VIEW_SIZES,
61
+ Q as Sidebar,
62
+ Cs as StatusView,
63
+ D as buttonVariants,
64
+ l as capitalizeFirst,
65
+ a as cn,
66
+ V as describeError,
67
+ B as effectButtonVariants,
68
+ v as formToasts,
64
69
  d as httpReasonPhrase,
65
70
  b as httpStatusExplanation,
66
- l as isProblem,
67
- o as isReactComponent,
71
+ c as isProblem,
72
+ E as isReactComponent,
68
73
  U as parseProblem,
69
- i as resolveVariant,
70
- Sa as useDialogPending,
74
+ S as resolveVariant,
75
+ z as useAutoSave,
76
+ x as useCondense,
77
+ Rs as useDialogPending,
71
78
  r as useLinkComponent,
72
- n as usePressPulse
79
+ T as usePressPulse
73
80
  };
@@ -48,6 +48,7 @@ export * from "@base-ui/react/popover";
48
48
  export * from "@base-ui/react/avatar";
49
49
  export * from "@base-ui/react/form";
50
50
  export * from "@base-ui/react/menu";
51
+ export * from "@base-ui/react/toast";
51
52
  export * from "@base-ui/react/accordion";
52
53
  export * from "@base-ui/react/alert-dialog";
53
54
  export * from "@base-ui/react/autocomplete";
@@ -75,7 +76,6 @@ export * from "@base-ui/react/select";
75
76
  export * from "@base-ui/react/slider";
76
77
  export * from "@base-ui/react/switch";
77
78
  export * from "@base-ui/react/tabs";
78
- export * from "@base-ui/react/toast";
79
79
  export * from "@base-ui/react/toggle";
80
80
  export * from "@base-ui/react/toggle-group";
81
81
  export * from "@base-ui/react/toolbar";
@@ -1,11 +1,18 @@
1
1
  "use client";
2
- import { a as _, i as E, n as I, o as a, r as s, s as P, t as C } from "../chunks/basic-page-BkLG3Ybg.js";
2
+ import { a as A, c as E, d as s, f as a, i as S, l as C, m as I, n as B, o as P, p as e, r as N, s as o, t as D, u as R } from "../chunks/basic-page-w6ftlo0h.js";
3
3
  export {
4
- C as BASIC_PAGE_CALLOUT,
5
- I as BASIC_PAGE_CARD,
6
- s as BASIC_PAGE_ITEM,
7
- E as BASIC_PAGE_ITEM_PANEL,
8
- _ as BASIC_PAGE_ITEM_PANEL_DIVIDED,
9
- a as BASIC_PAGE_ROW,
10
- P as BasicPage
4
+ D as AUTO_SAVE_DELAY_MS,
5
+ B as BASIC_PAGE_CALLOUT,
6
+ N as BASIC_PAGE_CARD,
7
+ S as BASIC_PAGE_ITEM,
8
+ A as BASIC_PAGE_ITEM_PANEL,
9
+ P as BASIC_PAGE_ITEM_PANEL_DIVIDED,
10
+ o as BASIC_PAGE_ROW,
11
+ E as BasicPage,
12
+ C as CONDENSE_BAR_ENTER,
13
+ R as CONDENSE_BAR_RISE_PX,
14
+ s as CONDENSE_BAR_TRAVEL,
15
+ a as formToasts,
16
+ e as useAutoSave,
17
+ I as useCondense
11
18
  };
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { a as I, c as _, i as A, n as R, o as S, r as a, s, t as T } from "../chunks/sidebar-Dt1F_CEP.js";
2
+ import { a as I, c as _, i as A, n as R, o as S, r as a, s, t as T } from "../chunks/sidebar-DvB-G0BP.js";
3
3
  export {
4
4
  T as SIDEBAR_HEADER_INSET,
5
5
  R as SIDEBAR_ITEM,
@@ -1,7 +1,7 @@
1
1
  import { ComponentProps, ReactNode } from 'react';
2
2
  import { Command as CommandPrimitive, useCommandState } from 'cmdk';
3
3
  import { Dialog as PhoDialog } from '../dialog';
4
- declare function Root({ className, children, ...props }: ComponentProps<typeof CommandPrimitive>): import("react").JSX.Element;
4
+ declare function Root({ shouldFilter, className, children, ...props }: ComponentProps<typeof CommandPrimitive>): import("react").JSX.Element;
5
5
  /**
6
6
  * The input row — a bottom hairline separates it from the list. Position
7
7
  * leading icons absolutely and pad the input (`pl-9`), mirroring
@@ -89,9 +89,10 @@ declare function Dialog({ open, onOpenChange, label, className, children, ...pro
89
89
  /**
90
90
  * Command menu built on `cmdk` — a filterable list of actions driven from a
91
91
  * single input, keyboard-first. Compose inline (`Command.Root`) or as a
92
- * ⌘K-style modal palette (`Command.Dialog`, which owns the overlay). By
93
- * default cmdk filters and ranks items for you; pass `shouldFilter={false}`
94
- * to render your own result set (e.g. hierarchy-preserving navigation).
92
+ * ⌘K-style modal palette (`Command.Dialog`, which owns the overlay).
93
+ * Filtering is yours by default — filter in render so the rows' diff can
94
+ * glide; pass `shouldFilter` to hand matching and ranking to cmdk (its
95
+ * imperative reorder skips the animation).
95
96
  *
96
97
  * Rows share one layout via `Command.Item` `level` — idle
97
98
  * `item` → `subitem` → `subsubitem`, or flat `result` while searching.
@@ -15,6 +15,15 @@ export interface InputProps extends Omit<InputHTMLAttributes<HTMLInputElement>,
15
15
  }>;
16
16
  /** Node rendered at the right edge of the label row (e.g. "Forgot?"). */
17
17
  labelTrailing?: ReactNode;
18
+ /**
19
+ * Quiet word or glyph inside the field at its trailing edge (an
20
+ * auto-save's `Saved`, a live character count). Non-interactive overlay:
21
+ * it never takes the pointer, the invalid icon takes the corner over
22
+ * it, and the input reserves nothing — content that shows only
23
+ * sometimes brings its own surface wash (as `Saved` does) so long text
24
+ * fades beneath it instead of colliding.
25
+ */
26
+ trailing?: ReactNode;
18
27
  /** Class applied to the input wrapper. */
19
28
  wrapperClassName?: string;
20
29
  ref?: Ref<HTMLInputElement>;
@@ -24,7 +33,7 @@ export interface InputProps extends Omit<InputHTMLAttributes<HTMLInputElement>,
24
33
  * Pho's bordered surface, leading icon, invalid state, and a built-in password
25
34
  * reveal toggle.
26
35
  */
27
- export declare function Input({ label, hint, size, invalid, icon: Icon, labelTrailing, disabled, required, type, className, wrapperClassName, id, ref, ...props }: InputProps): import("react").JSX.Element;
36
+ export declare function Input({ label, hint, size, invalid, icon: Icon, labelTrailing, trailing, disabled, required, type, className, wrapperClassName, id, ref, ...props }: InputProps): import("react").JSX.Element;
28
37
  export declare namespace Input {
29
38
  var displayName: string;
30
39
  }
@@ -1,4 +1,4 @@
1
- import { ComponentProps, ElementType, HTMLAttributes, InputHTMLAttributes, Ref } from 'react';
1
+ import { ComponentProps, ElementType, HTMLAttributes, InputHTMLAttributes, Ref, ReactNode } from 'react';
2
2
  import { Separator as BaseSeparator } from '@base-ui/react/separator';
3
3
  /** Override Base UI's `string | (state) => string` className with plain string. */
4
4
  type StyledProps<T extends ElementType> = Omit<ComponentProps<T>, "className"> & {
@@ -20,6 +20,13 @@ export interface InputGroupRootProps extends HTMLAttributes<HTMLDivElement> {
20
20
  */
21
21
  declare function Root({ size, invalid, className, onPointerDown, ref, ...props }: InputGroupRootProps): import("react").JSX.Element;
22
22
  export interface InputGroupInputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "size"> {
23
+ /**
24
+ * Quiet word or glyph over the control's trailing edge, before the
25
+ * addons (an auto-save's `Saved`). Non-interactive overlay; content
26
+ * that shows only sometimes brings its own surface wash so long text
27
+ * fades beneath it. Reserves nothing.
28
+ */
29
+ trailing?: ReactNode;
23
30
  ref?: Ref<HTMLInputElement>;
24
31
  }
25
32
  /**
@@ -27,7 +34,7 @@ export interface InputGroupInputProps extends Omit<InputHTMLAttributes<HTMLInput
27
34
  * `Field.Root` it picks up the label and description wiring automatically;
28
35
  * standalone it behaves as a plain `<input>` (pass `aria-label` then).
29
36
  */
30
- declare function GroupInput({ className, ref, ...props }: InputGroupInputProps): import("react").JSX.Element;
37
+ declare function GroupInput({ className, trailing, ref, ...props }: InputGroupInputProps): import("react").JSX.Element;
31
38
  /**
32
39
  * Inline content beside the control — prefix/suffix text, an icon, a `Kbd`
33
40
  * hint, or a small button. Text and icons render in the secondary tone so the
@@ -1 +1,2 @@
1
1
  export { ScrollArea } from './scroll-area';
2
+ export { BLUR_MAX_PX } from './scroll-area-edges';
@@ -2,6 +2,12 @@ import { Ref } from 'react';
2
2
  /** Overlay strip height — a short ramp, not a banner. `h-8` = 32px. */
3
3
  export declare const EDGE_CLASS = "pointer-events-none absolute inset-x-0 z-10 h-8";
4
4
  export declare const EDGE_REVEAL_PX = 32;
5
+ /**
6
+ * The system's one blur strength. The edge fade peaks here, and a motion
7
+ * that softens (a scope swap, a bar title) borrows the same value, so
8
+ * every soft focus in the product is the same soft focus.
9
+ */
10
+ export declare const BLUR_MAX_PX = 1;
5
11
  export declare function paintEdge(node: HTMLDivElement | null, progress: number): void;
6
12
  export declare function Edge({ edge, edgeRef, surface, className, }: {
7
13
  edge: "top" | "bottom";
@@ -1,9 +1,22 @@
1
- import { ComponentProps, ElementType } from 'react';
1
+ import { ComponentProps, ElementType, Ref } from 'react';
2
2
  import { ScrollArea as BaseScrollArea } from '@base-ui/react/scroll-area';
3
3
  /** Override Base UI's `string | (state) => string` className with plain string. */
4
4
  type StyledProps<T extends ElementType> = Omit<ComponentProps<T>, "className"> & {
5
5
  className?: string;
6
6
  };
7
+ /**
8
+ * The scrolled content. `inset` is a resting inset in the scroll axis —
9
+ * like a scroll view's safe-area padding: the content stands clear of the
10
+ * edges at rest but scrolls past them to the true edge, and the scrollbar
11
+ * and edge fade stay on `Root`'s edges. `insetTop` / `insetBottom` set the
12
+ * ends separately (they win over `inset`).
13
+ */
14
+ declare function Content({ inset, insetTop, insetBottom, style, ref, ...props }: ComponentProps<typeof BaseScrollArea.Content> & {
15
+ inset?: number | string;
16
+ insetTop?: number | string;
17
+ insetBottom?: number | string;
18
+ ref?: Ref<HTMLDivElement>;
19
+ }): import("react").JSX.Element;
7
20
  declare function Root({ className, children, ...props }: StyledProps<typeof BaseScrollArea.Root>): import("react").JSX.Element;
8
21
  declare function Viewport({ className, ref, ...props }: StyledProps<typeof BaseScrollArea.Viewport>): import("react").JSX.Element;
9
22
  declare function Scrollbar({ className, ...props }: StyledProps<typeof BaseScrollArea.Scrollbar>): import("react").JSX.Element;
@@ -18,7 +31,7 @@ declare function Thumb({ className, ...props }: StyledProps<typeof BaseScrollAre
18
31
  export declare const ScrollArea: {
19
32
  Root: typeof Root;
20
33
  Viewport: typeof Viewport;
21
- Content: import('react').ForwardRefExoticComponent<Omit<import('@base-ui/react').ScrollAreaContentProps, "ref"> & import('react').RefAttributes<HTMLDivElement>>;
34
+ Content: typeof Content;
22
35
  Scrollbar: typeof Scrollbar;
23
36
  Thumb: typeof Thumb;
24
37
  Corner: import('react').ForwardRefExoticComponent<Omit<import('@base-ui/react').ScrollAreaCornerProps, "ref"> & import('react').RefAttributes<HTMLDivElement>>;
@@ -1 +1 @@
1
- export { Toast } from './toast';
1
+ export { Toast, Toasty } from './toast';
@@ -1,4 +1,4 @@
1
- import { ComponentProps, ElementType } from 'react';
1
+ import { ComponentProps, ElementType, ReactNode } from 'react';
2
2
  import { Toast as BaseToast } from '@base-ui/react/toast';
3
3
  /** Override Base UI's `string | (state) => string` className with plain string. */
4
4
  type StyledProps<T extends ElementType> = Omit<ComponentProps<T>, "className"> & {
@@ -11,12 +11,27 @@ declare function Title({ className, ...props }: StyledProps<typeof BaseToast.Tit
11
11
  declare function Description({ className, ...props }: StyledProps<typeof BaseToast.Description>): import("react").JSX.Element;
12
12
  declare function Close({ className, ...props }: StyledProps<typeof BaseToast.Close>): import("react").JSX.Element;
13
13
  /**
14
- * Toast built on Base UI `Toast` — a transient, non-blocking notification.
15
- * Wrap your app in `Toast.Provider`, render a `Toast.Portal` → `Viewport` that
16
- * maps `useToastManager().toasts` to `Toast.Root`s, then call
17
- * `useToastManager().add({ title, description })` to show one. Use a toast for
18
- * confirmation of a background action; for a choice the user must make, use
19
- * `Dialog`.
14
+ * Toasty — the whole toast system in one wrapper, Kumo-shaped: provider,
15
+ * portal, viewport, and the stacked card list with status variants. Wrap
16
+ * the app once and call `Toast.useToastManager().add({ title, type })`
17
+ * from any child; pass a `toastManager` from `createToastManager()` so
18
+ * code outside the tree (a form's auto-save, a query cache) can speak
19
+ * through the same lane. `manager.promise` shows loading → success/error
20
+ * with the matching glyphs.
21
+ */
22
+ export declare function Toasty({ children, toastManager, }: {
23
+ children?: ReactNode;
24
+ toastManager?: ComponentProps<typeof BaseToast.Provider>["toastManager"];
25
+ }): import("react").JSX.Element;
26
+ /**
27
+ * Toast built on Base UI `Toast` — transient, non-blocking notifications
28
+ * in a sonner-style stack, styled after Cloudflare's Kumo: at rest the
29
+ * cards collapse into a peek (12px rise and −10% scale per depth, words
30
+ * hidden behind the front card), expand into a true list with a 12px gap
31
+ * on hover or focus, swipe to dismiss, three visible at most. `type`
32
+ * (`success` / `error` / `warning` / `info` / `loading`) tints hairline,
33
+ * glyph, and title together. Reach for `Toasty` unless you need to
34
+ * compose the parts yourself.
20
35
  */
21
36
  export declare const Toast: {
22
37
  Provider: import('react').FC<import('@base-ui/react').ToastProviderProps>;
@@ -70,8 +70,76 @@ export interface BasicPageRootProps extends ComponentProps<"div"> {
70
70
  * for a page that should scroll away whole.
71
71
  */
72
72
  condense?: boolean;
73
+ /**
74
+ * The content column. `base` (default) is the 42rem reading column every
75
+ * settings page uses. `wide` opens it to 80rem for a page that is a list
76
+ * first — rows with several columns — and is the one width that hosts an
77
+ * `Aside`. Forms stay on `base`: across a wide row a label and its
78
+ * control drift out of one glance.
79
+ */
80
+ width?: "base" | "wide";
81
+ }
82
+ declare function Root({ condense, width, className, children, ref, ...props }: BasicPageRootProps): import("react").JSX.Element;
83
+ /**
84
+ * Condensing header — the page's way back once the title has scrolled away.
85
+ * `Root condense` renders a sticky bar in the reserved top zone; `Title` and
86
+ * `Breadcrumbs` report what belongs in it (the heading, the tail crumb)
87
+ * through this context, so the bar assembles itself and consumers only set
88
+ * the flag. The bar stays out of the way until the whole heading has left
89
+ * the scrollport, then fades in pinned to the top.
90
+ */
91
+ interface CondenseTail {
92
+ label: ReactNode;
93
+ href: string;
94
+ onClick?: ComponentProps<"a">["onClick"];
95
+ }
96
+ /**
97
+ * What the condensed bar would show, for an app shell that shows it
98
+ * itself: whether the title has left the pane, the page name, the way
99
+ * back. Idle (`condensed: false`, both null) outside any `CondenseScope`.
100
+ */
101
+ export interface BasicPageCondense {
102
+ condensed: boolean;
103
+ title: ReactNode | null;
104
+ back: CondenseTail | null;
73
105
  }
74
- declare function Root({ condense, className, children, ...props }: BasicPageRootProps): import("react").JSX.Element;
106
+ /**
107
+ * Hands the condensed bar to the app shell. On a narrow viewport the shell
108
+ * already has a bar of its own; two stacked bars is one too many. Wrap the
109
+ * shell (its bar and the routed pages) in `CondenseScope` and read
110
+ * `useCondense()` where the bar is: while `condensed`, show `title` in the
111
+ * middle and `back` as a plain chevron beside the menu button. While
112
+ * `adopt` is true the page renders no bar of its own; pass `adopt={false}`
113
+ * on viewports where the shell bar does not exist (desktop) and the page's
114
+ * bar returns. State still tracks either way — `useCondense()` always
115
+ * answers.
116
+ */
117
+ declare function CondenseScope({ adopt, children, }: {
118
+ adopt?: boolean;
119
+ children?: ReactNode;
120
+ }): import("react").JSX.Element;
121
+ /** The nearest scope's condense state — see `CondenseScope`. */
122
+ export declare function useCondense(): BasicPageCondense;
123
+ /**
124
+ * The condensed bar's motion, exported for a shell that adopts the bar
125
+ * (`CondenseScope`) so its swap moves the same way: 0.2s ease-out, dropping
126
+ * in from 8px above and leaving the same way.
127
+ */
128
+ export declare const CONDENSE_BAR_ENTER: {
129
+ readonly duration: 0.2;
130
+ readonly ease: "easeOut";
131
+ };
132
+ /**
133
+ * The displacement channel of the same move: travel is linear, like the
134
+ * library's other linear transitions (the 100ms control inks), while the
135
+ * fade and the soft focus keep the ease-out. Spread it per axis:
136
+ * `transition={{ ...CONDENSE_BAR_ENTER, y: CONDENSE_BAR_TRAVEL }}`.
137
+ */
138
+ export declare const CONDENSE_BAR_TRAVEL: {
139
+ readonly duration: 0.2;
140
+ readonly ease: "linear";
141
+ };
142
+ export declare const CONDENSE_BAR_RISE_PX = -8;
75
143
  export interface BasicPageTitleProps extends ComponentProps<"h1"> {
76
144
  /**
77
145
  * Shared-element key. Pair with the same `morphId` on the subpage's
@@ -283,9 +351,36 @@ export interface BasicPageAlertProps extends Omit<ComponentProps<"div">, "childr
283
351
  * instead.
284
352
  */
285
353
  declare function Alert({ error: errorProp, show, className, children, ...props }: BasicPageAlertProps): import("react").JSX.Element;
354
+ /**
355
+ * The nearest `Form autoSave`'s trigger, for controls whose changes never
356
+ * bubble as native events (a Base UI checkbox, a select): call it in the
357
+ * control's own onChange and the save runs after the usual pause. Null
358
+ * outside an auto-saving form.
359
+ */
360
+ export declare function useAutoSave(): ((field?: string) => void) | null;
361
+ /** Typing pause before an auto-save fires; blur flushes it immediately. */
362
+ export declare const AUTO_SAVE_DELAY_MS = 800;
363
+ /**
364
+ * The toast lane auto-save failures speak through. Host it once in the app
365
+ * shell — `<Toast.Provider toastManager={formToasts}>` around a viewport —
366
+ * and every `Form autoSave` reaches it without wiring. A failure toast
367
+ * carries Retry and stays until the save lands (the next success closes it).
368
+ */
369
+ export declare const formToasts: import('@base-ui/react').ToastManager<any>;
286
370
  /** Field errors keyed by `name`, the shape Base UI `Form` maps onto fields. */
287
371
  export type BasicPageFormErrors = Record<string, string | string[]>;
288
- export interface BasicPageFormProps<Values extends Record<string, unknown> = Record<string, unknown>> extends Omit<ComponentProps<typeof FormElement>, "onFormSubmit" | "errors" | "action"> {
372
+ export interface BasicPageFormProps<Values extends Record<string, unknown> = Record<string, unknown>> extends Omit<ComponentProps<typeof FormElement>, "onFormSubmit" | "errors" | "action" | "autoSave"> {
373
+ /**
374
+ * Documents save themselves; transactions submit. With `autoSave`, the
375
+ * form runs `action` on its own — after a typing pause, immediately on
376
+ * blur — once native validation passes, and skips quietly while it does
377
+ * not. Controls stay enabled throughout; put a `Saved` in the field's
378
+ * hint for the inline Saving…/Saved word. A failure keeps the value in
379
+ * place and raises a Retry toast on `formToasts` that stays until a
380
+ * save lands. Keep the explicit `Submit` for creations and anything
381
+ * paid or irreversible.
382
+ */
383
+ autoSave?: boolean;
289
384
  /**
290
385
  * The save. Receives the field values keyed by `name`, after native
291
386
  * validation passed. Resolve to finish; return `{ errors }` to put
@@ -315,7 +410,21 @@ export interface BasicPageFormProps<Values extends Record<string, unknown> = Rec
315
410
  * its footer is one block; a form that spans several blocks goes around
316
411
  * the `Stack` instead, and the blocks keep the Stack's rhythm.
317
412
  */
318
- declare function Form<Values extends Record<string, unknown>>({ action, errors: initialErrors, className, children, onChange, ...props }: BasicPageFormProps<Values>): import("react").JSX.Element;
413
+ declare function Form<Values extends Record<string, unknown>>({ action, errors: initialErrors, autoSave, className, children, onChange, onBlur, ...props }: BasicPageFormProps<Values>): import("react").JSX.Element;
414
+ /**
415
+ * The inline word for an auto-saving field — put it inside the field at
416
+ * its trailing edge (`Input trailing`), where the eye already is while
417
+ * typing. Quiet gray, never colored, so it cannot be read as validation:
418
+ * "Saving…" while the save runs, "Saved" for a breath after it lands,
419
+ * then nothing at all — idle it renders nothing and reserves nothing.
420
+ * Words fade through the system's 1px soft focus — no travel — and
421
+ * carry their own surface wash, so long
422
+ * input text fades beneath them instead of colliding. With `name` it
423
+ * speaks only for that field; without, for the whole form.
424
+ */
425
+ declare function Saved({ name, className, ...props }: Omit<ComponentProps<"output">, RevealMotionConflicts> & {
426
+ name?: string;
427
+ }): import("react").JSX.Element;
319
428
  /**
320
429
  * The form card: labelled fields stacked, label above control, one rhythm
321
430
  * (`gap-5`). Where a `Card` of `Row`s is a table of settings, this is a
@@ -544,8 +653,35 @@ declare function RowLink({ label, description, leading, href, className, childre
544
653
  * </BasicPage.Root>
545
654
  * ```
546
655
  */
656
+ export interface BasicPageAsideProps {
657
+ /**
658
+ * Whether a page is in it. Defaults to whether there are children — hand
659
+ * it the router's outlet element (`useOutlet()` in React Router), `null`
660
+ * while no subpage route matches, and the aside opens and closes with
661
+ * the URL.
662
+ */
663
+ open?: boolean;
664
+ /**
665
+ * The way out for a page that carries no `Back` — the close in the
666
+ * panel's corner calls it. A page with a `Back` closes through that link.
667
+ */
668
+ onClose?: () => void;
669
+ children?: ReactNode;
670
+ }
671
+ /**
672
+ * A subpage beside the page. On a pane wide enough for two columns (48rem,
673
+ * Tailwind's `md`) it is a panel at the right edge: the page's column gives
674
+ * way and stays in view, the subpage scrolls on its own, its `Back` is the
675
+ * close in the corner, Escape closes too. On a narrower pane the same
676
+ * subpage is the page — the list steps aside, the subpage takes the pane
677
+ * with its own `Back` — so one subpage component serves both. Needs
678
+ * `Root width="wide"`.
679
+ */
680
+ declare function Aside({ open, onClose, children }: BasicPageAsideProps): import('react').ReactPortal | null;
547
681
  export declare const BasicPage: {
548
682
  Root: typeof Root;
683
+ Aside: typeof Aside;
684
+ CondenseScope: typeof CondenseScope;
549
685
  Breadcrumbs: typeof Breadcrumbs;
550
686
  Crumb: typeof Crumb;
551
687
  Back: typeof Back;
@@ -567,6 +703,7 @@ export declare const BasicPage: {
567
703
  Alert: typeof Alert;
568
704
  Footer: typeof Footer;
569
705
  Form: typeof Form;
706
+ Saved: typeof Saved;
570
707
  Fields: typeof Fields;
571
708
  Inline: typeof Inline;
572
709
  Submit: typeof Submit;
@@ -1 +1 @@
1
- export { BasicPage, BASIC_PAGE_CARD, BASIC_PAGE_CALLOUT, BASIC_PAGE_ROW, BASIC_PAGE_ITEM, BASIC_PAGE_ITEM_PANEL, BASIC_PAGE_ITEM_PANEL_DIVIDED, type BasicPageRootProps, type BasicPageRowProps, type BasicPageRowLinkProps, type BasicPageBackProps, type BasicPageBreadcrumbsProps, type BasicPageCrumbProps, type BasicPageFooterProps, type BasicPageFormProps, type BasicPageFormErrors, type BasicPageItemPanelProps, } from './basic-page';
1
+ export { BasicPage, formToasts, AUTO_SAVE_DELAY_MS, useCondense, useAutoSave, type BasicPageCondense, BASIC_PAGE_CARD, CONDENSE_BAR_ENTER, CONDENSE_BAR_TRAVEL, CONDENSE_BAR_RISE_PX, BASIC_PAGE_CALLOUT, BASIC_PAGE_ROW, BASIC_PAGE_ITEM, BASIC_PAGE_ITEM_PANEL, BASIC_PAGE_ITEM_PANEL_DIVIDED, type BasicPageRootProps, type BasicPageAsideProps, type BasicPageRowProps, type BasicPageRowLinkProps, type BasicPageBackProps, type BasicPageBreadcrumbsProps, type BasicPageCrumbProps, type BasicPageFooterProps, type BasicPageFormProps, type BasicPageFormErrors, type BasicPageItemPanelProps, } from './basic-page';
@@ -1,4 +1,5 @@
1
1
  import { AnchorHTMLAttributes, ButtonHTMLAttributes, ComponentProps, FC, ReactNode, Ref } from 'react';
2
+ import { Button } from '../../components/button';
2
3
  /**
3
4
  * Sidebar — Pho's first SECTION: a composed app rail, not a micro component.
4
5
  * It encodes the navigation rail used across Photon surfaces (the Pho docs
@@ -52,9 +53,37 @@ interface RootProps extends ComponentProps<"aside"> {
52
53
  declare function Root({ className, inset, ...props }: RootProps): import("react").JSX.Element;
53
54
  /** Brand slot at the top of the rail — logo, wordmark, workspace switcher. */
54
55
  declare function Header({ className, ...props }: ComponentProps<"div">): import("react").JSX.Element;
55
- /** The scrollable middle — a stack of `Sidebar.Group`s. */
56
- declare function Nav({ className, ...props }: ComponentProps<"nav">): import("react").JSX.Element;
57
- /** One titled cluster of nav rows: a `GroupLabel` followed by a `List`. */
56
+ /**
57
+ * The rail's search row — an outlined button dressed to `Item` metrics so
58
+ * its label lines up with the rows below, the shortcut at the trailing
59
+ * edge. The press is the Button's own; wire `onClick` (and a global ⌘K)
60
+ * to a `Command.Dialog`.
61
+ */
62
+ declare function Search({ label, kbd, className, ...props }: Omit<ComponentProps<typeof Button>, "children" | "variant" | "size"> & {
63
+ label?: ReactNode;
64
+ kbd?: string;
65
+ }): import("react").JSX.Element;
66
+ /**
67
+ * The scrollable middle — a stack of `Sidebar.Group`s in a `ScrollArea`
68
+ * (overlay scrollbar, edge fade). Pass `scroll={false}` where a parent
69
+ * scrolls the whole rail as one column (a narrow-viewport drawer) — the
70
+ * nav is then a plain stack at its natural height.
71
+ *
72
+ * The nav owns its breathing room toward its neighbors as a resting inset
73
+ * (a scroll view's safe-area padding): 24px above, 16px below by default —
74
+ * rows stand clear of the ends at rest and scroll through the gap, under
75
+ * the edge fade, instead of clipping at a dead margin. `inset` /
76
+ * `insetTop` / `insetBottom` override it; the same values become plain
77
+ * padding when `scroll={false}`, so both modes keep one geometry. A
78
+ * `Header` right before the nav and a `Footer` after it drop their own
79
+ * margins — the gap lives here, not on the neighbors.
80
+ */
81
+ declare function Nav({ scroll, inset, insetTop, insetBottom, className, style, children, ...props }: ComponentProps<"nav"> & {
82
+ scroll?: boolean;
83
+ inset?: number | string;
84
+ insetTop?: number | string;
85
+ insetBottom?: number | string;
86
+ }): import("react").JSX.Element;
58
87
  declare function Group({ className, ...props }: ComponentProps<"div">): import("react").JSX.Element;
59
88
  /** The cluster's caption — description ink, regular weight. */
60
89
  declare function GroupLabel({ className, ...props }: ComponentProps<"div">): import("react").JSX.Element;
@@ -151,6 +180,7 @@ declare function AccountRow({ name, avatarSrc, initials, className, ...props }:
151
180
  export declare const Sidebar: {
152
181
  Root: typeof Root;
153
182
  Header: typeof Header;
183
+ Search: typeof Search;
154
184
  Nav: typeof Nav;
155
185
  Group: typeof Group;
156
186
  GroupLabel: typeof GroupLabel;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@photon-ai/pho-ui",
3
- "version": "2.3.0",
3
+ "version": "2.5.0",
4
4
  "description": "Pho Design System — Photon's React component library, built on Base UI",
5
5
  "license": "UNLICENSED",
6
6
  "repository": {