@photon-ai/pho-ui 2.2.0 → 2.4.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/chunks/basic-page-c_7Ii5Fr.js +1117 -0
- package/dist/chunks/basic-page-c_7Ii5Fr.js.map +1 -0
- package/dist/chunks/{button-BmhyLgy5.js → button-DNNs5RsT.js} +6 -6
- package/dist/chunks/{button-BmhyLgy5.js.map → button-DNNs5RsT.js.map} +1 -1
- package/dist/chunks/{dialog-DtFO7oy0.js → dialog-8SRNi_rv.js} +3 -3
- package/dist/chunks/{dialog-DtFO7oy0.js.map → dialog-8SRNi_rv.js.map} +1 -1
- package/dist/chunks/{error-Da7P5WZi.js → error-Crs-wqMC.js} +14 -14
- package/dist/chunks/{error-Da7P5WZi.js.map → error-Crs-wqMC.js.map} +1 -1
- package/dist/chunks/form-AiHbbw4m.js +17 -0
- package/dist/chunks/form-AiHbbw4m.js.map +1 -0
- package/dist/chunks/{input-QSAUO30c.js → input-DjvZoF8v.js} +48 -43
- package/dist/chunks/input-DjvZoF8v.js.map +1 -0
- package/dist/chunks/{input-group-5AtpIhC_.js → input-group-fc9_jD4d.js} +44 -38
- package/dist/chunks/input-group-fc9_jD4d.js.map +1 -0
- package/dist/chunks/kbd-DNI10uy7.js +18 -0
- package/dist/chunks/kbd-DNI10uy7.js.map +1 -0
- package/dist/chunks/{menu-Cgj3lq9z.js → menu-BQeprfxB.js} +5 -5
- package/dist/chunks/{menu-Cgj3lq9z.js.map → menu-BQeprfxB.js.map} +1 -1
- package/dist/chunks/scroll-area-Bu7egArU.js +166 -0
- package/dist/chunks/scroll-area-Bu7egArU.js.map +1 -0
- package/dist/chunks/sidebar-DvB-G0BP.js +231 -0
- package/dist/chunks/sidebar-DvB-G0BP.js.map +1 -0
- package/dist/chunks/toast-DoXaRPIZ.js +167 -0
- package/dist/chunks/toast-DoXaRPIZ.js.map +1 -0
- package/dist/components/button.js +1 -1
- package/dist/components/command.js +125 -172
- package/dist/components/command.js.map +1 -1
- package/dist/components/context-menu.js +23 -23
- package/dist/components/dialog.js +1 -1
- package/dist/components/error.js +1 -1
- package/dist/components/field.js +12 -5
- package/dist/components/field.js.map +1 -1
- package/dist/components/form.js +2 -14
- package/dist/components/input-group.js +1 -1
- package/dist/components/input.js +1 -1
- package/dist/components/kbd.js +2 -15
- package/dist/components/menu.js +1 -1
- package/dist/components/phone-input.js +1 -1
- package/dist/components/scroll-area.js +3 -2
- package/dist/components/toast.js +3 -57
- package/dist/index.js +65 -58
- package/dist/primitives.js +3 -3
- package/dist/sections/basic-page.js +15 -8
- package/dist/sections/sidebar.js +1 -1
- package/dist/src/components/command/command.d.ts +5 -4
- package/dist/src/components/field/field.d.ts +9 -0
- package/dist/src/components/input/input.d.ts +10 -1
- package/dist/src/components/input-group/input-group.d.ts +9 -2
- package/dist/src/components/scroll-area/index.d.ts +1 -0
- package/dist/src/components/scroll-area/scroll-area-edges.d.ts +11 -1
- package/dist/src/components/scroll-area/scroll-area.d.ts +15 -2
- package/dist/src/components/toast/index.d.ts +1 -1
- package/dist/src/components/toast/toast.d.ts +22 -7
- package/dist/src/sections/basic-page/basic-page.d.ts +210 -30
- package/dist/src/sections/basic-page/index.d.ts +1 -1
- package/dist/src/sections/sidebar/sidebar.d.ts +33 -3
- package/package.json +1 -1
- package/src/styles/pho.css +19 -0
- package/dist/chunks/basic-page-CB36yrpL.js +0 -643
- package/dist/chunks/basic-page-CB36yrpL.js.map +0 -1
- package/dist/chunks/input-QSAUO30c.js.map +0 -1
- package/dist/chunks/input-group-5AtpIhC_.js.map +0 -1
- package/dist/chunks/scroll-area-Cw4JFqNG.js +0 -152
- package/dist/chunks/scroll-area-Cw4JFqNG.js.map +0 -1
- package/dist/chunks/sidebar-BETMObNj.js +0 -186
- package/dist/chunks/sidebar-BETMObNj.js.map +0 -1
- package/dist/components/form.js.map +0 -1
- package/dist/components/kbd.js.map +0 -1
- package/dist/components/toast.js.map +0 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { AnchorHTMLAttributes, ComponentProps, ReactNode, Ref } from 'react';
|
|
2
|
-
import { ButtonLinkProps } from '../../components/button';
|
|
2
|
+
import { ButtonLinkProps, ButtonProps } from '../../components/button';
|
|
3
|
+
import { Form as FormElement } from '../../components/form';
|
|
3
4
|
/** Bordered card that stacks rows with hairline dividers. */
|
|
4
5
|
export declare const BASIC_PAGE_CARD = "rounded-base border border-pho-secondary bg-pho-primary divide-y divide-pho-secondary [&>:has(+[data-basic-page-alert])]:border-b-0";
|
|
5
6
|
/**
|
|
@@ -59,9 +60,78 @@ export declare const BASIC_PAGE_ITEM_PANEL_DIVIDED = "-mx-2 -mt-1.5 flex items-c
|
|
|
59
60
|
* `Title` and `Back` (the page chrome) stay put while the body below rises
|
|
60
61
|
* in.
|
|
61
62
|
*/
|
|
62
|
-
|
|
63
|
+
export interface BasicPageRootProps extends ComponentProps<"div"> {
|
|
63
64
|
ref?: Ref<HTMLDivElement>;
|
|
65
|
+
/**
|
|
66
|
+
* Condense on scroll — on by default. Once the title has scrolled out of
|
|
67
|
+
* the pane, a sticky bar pins to the top with the way back and the page
|
|
68
|
+
* name: the large title collapsing into its bar. It assembles itself
|
|
69
|
+
* from `Title` and the trail's tail crumb; nothing to wire. Pass `false`
|
|
70
|
+
* for a page that should scroll away whole.
|
|
71
|
+
*/
|
|
72
|
+
condense?: boolean;
|
|
73
|
+
}
|
|
74
|
+
declare function Root({ condense, className, children, ...props }: BasicPageRootProps): import("react").JSX.Element;
|
|
75
|
+
/**
|
|
76
|
+
* Condensing header — the page's way back once the title has scrolled away.
|
|
77
|
+
* `Root condense` renders a sticky bar in the reserved top zone; `Title` and
|
|
78
|
+
* `Breadcrumbs` report what belongs in it (the heading, the tail crumb)
|
|
79
|
+
* through this context, so the bar assembles itself and consumers only set
|
|
80
|
+
* the flag. The bar stays out of the way until the whole heading has left
|
|
81
|
+
* the scrollport, then fades in pinned to the top.
|
|
82
|
+
*/
|
|
83
|
+
interface CondenseTail {
|
|
84
|
+
label: ReactNode;
|
|
85
|
+
href: string;
|
|
86
|
+
onClick?: ComponentProps<"a">["onClick"];
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* What the condensed bar would show, for an app shell that shows it
|
|
90
|
+
* itself: whether the title has left the pane, the page name, the way
|
|
91
|
+
* back. Idle (`condensed: false`, both null) outside any `CondenseScope`.
|
|
92
|
+
*/
|
|
93
|
+
export interface BasicPageCondense {
|
|
94
|
+
condensed: boolean;
|
|
95
|
+
title: ReactNode | null;
|
|
96
|
+
back: CondenseTail | null;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Hands the condensed bar to the app shell. On a narrow viewport the shell
|
|
100
|
+
* already has a bar of its own; two stacked bars is one too many. Wrap the
|
|
101
|
+
* shell (its bar and the routed pages) in `CondenseScope` and read
|
|
102
|
+
* `useCondense()` where the bar is: while `condensed`, show `title` in the
|
|
103
|
+
* middle and `back` as a plain chevron beside the menu button. While
|
|
104
|
+
* `adopt` is true the page renders no bar of its own; pass `adopt={false}`
|
|
105
|
+
* on viewports where the shell bar does not exist (desktop) and the page's
|
|
106
|
+
* bar returns. State still tracks either way — `useCondense()` always
|
|
107
|
+
* answers.
|
|
108
|
+
*/
|
|
109
|
+
declare function CondenseScope({ adopt, children, }: {
|
|
110
|
+
adopt?: boolean;
|
|
111
|
+
children?: ReactNode;
|
|
64
112
|
}): import("react").JSX.Element;
|
|
113
|
+
/** The nearest scope's condense state — see `CondenseScope`. */
|
|
114
|
+
export declare function useCondense(): BasicPageCondense;
|
|
115
|
+
/**
|
|
116
|
+
* The condensed bar's motion, exported for a shell that adopts the bar
|
|
117
|
+
* (`CondenseScope`) so its swap moves the same way: 0.2s ease-out, dropping
|
|
118
|
+
* in from 8px above and leaving the same way.
|
|
119
|
+
*/
|
|
120
|
+
export declare const CONDENSE_BAR_ENTER: {
|
|
121
|
+
readonly duration: 0.2;
|
|
122
|
+
readonly ease: "easeOut";
|
|
123
|
+
};
|
|
124
|
+
/**
|
|
125
|
+
* The displacement channel of the same move: travel is linear, like the
|
|
126
|
+
* library's other linear transitions (the 100ms control inks), while the
|
|
127
|
+
* fade and the soft focus keep the ease-out. Spread it per axis:
|
|
128
|
+
* `transition={{ ...CONDENSE_BAR_ENTER, y: CONDENSE_BAR_TRAVEL }}`.
|
|
129
|
+
*/
|
|
130
|
+
export declare const CONDENSE_BAR_TRAVEL: {
|
|
131
|
+
readonly duration: 0.2;
|
|
132
|
+
readonly ease: "linear";
|
|
133
|
+
};
|
|
134
|
+
export declare const CONDENSE_BAR_RISE_PX = -8;
|
|
65
135
|
export interface BasicPageTitleProps extends ComponentProps<"h1"> {
|
|
66
136
|
/**
|
|
67
137
|
* Shared-element key. Pair with the same `morphId` on the subpage's
|
|
@@ -113,7 +183,7 @@ export interface BasicPageStackProps extends Omit<ComponentProps<"div">, RevealM
|
|
|
113
183
|
*
|
|
114
184
|
* Static under reduced motion.
|
|
115
185
|
*/
|
|
116
|
-
declare function Stack({ className, ...props }: BasicPageStackProps): import("react").JSX.Element;
|
|
186
|
+
declare function Stack({ className, children, ...props }: BasicPageStackProps): import("react").JSX.Element;
|
|
117
187
|
/**
|
|
118
188
|
* Title + optional description pair. No gap between them — the block's
|
|
119
189
|
* `gap-3` only applies between this header and the card.
|
|
@@ -178,7 +248,7 @@ declare function Card({ animateHeight, className, children, ...props }: BasicPag
|
|
|
178
248
|
* </BasicPage.Card>
|
|
179
249
|
* ```
|
|
180
250
|
*/
|
|
181
|
-
declare function Item({ className, ...props }: ComponentProps<"div"> & {
|
|
251
|
+
declare function Item({ className, ...props }: Omit<ComponentProps<"div">, RevealMotionConflicts> & {
|
|
182
252
|
ref?: Ref<HTMLDivElement>;
|
|
183
253
|
}): import("react").JSX.Element;
|
|
184
254
|
export interface BasicPageItemPanelProps extends ComponentProps<"div"> {
|
|
@@ -222,7 +292,7 @@ declare function CalloutTitle({ id, className, children, ...props }: ComponentPr
|
|
|
222
292
|
declare function CalloutDescription({ className, ...props }: ComponentProps<"p"> & {
|
|
223
293
|
ref?: Ref<HTMLParagraphElement>;
|
|
224
294
|
}): import("react").JSX.Element;
|
|
225
|
-
export interface BasicPageRowProps extends Omit<ComponentProps<"div">, "title"> {
|
|
295
|
+
export interface BasicPageRowProps extends Omit<ComponentProps<"div">, "title" | RevealMotionConflicts> {
|
|
226
296
|
/** Left-side field name — plain text, or compose with a trailing hint. */
|
|
227
297
|
label: ReactNode;
|
|
228
298
|
/** Optional helper under the label. */
|
|
@@ -272,23 +342,117 @@ export interface BasicPageAlertProps extends Omit<ComponentProps<"div">, "childr
|
|
|
272
342
|
* For a page that failed to load outright, swap the stack for an `ErrorView`
|
|
273
343
|
* instead.
|
|
274
344
|
*/
|
|
275
|
-
declare function Alert({ error, show, className, children, ...props }: BasicPageAlertProps): import("react").JSX.Element;
|
|
345
|
+
declare function Alert({ error: errorProp, show, className, children, ...props }: BasicPageAlertProps): import("react").JSX.Element;
|
|
346
|
+
/**
|
|
347
|
+
* The nearest `Form autoSave`'s trigger, for controls whose changes never
|
|
348
|
+
* bubble as native events (a Base UI checkbox, a select): call it in the
|
|
349
|
+
* control's own onChange and the save runs after the usual pause. Null
|
|
350
|
+
* outside an auto-saving form.
|
|
351
|
+
*/
|
|
352
|
+
export declare function useAutoSave(): ((field?: string) => void) | null;
|
|
353
|
+
/** Typing pause before an auto-save fires; blur flushes it immediately. */
|
|
354
|
+
export declare const AUTO_SAVE_DELAY_MS = 800;
|
|
355
|
+
/**
|
|
356
|
+
* The toast lane auto-save failures speak through. Host it once in the app
|
|
357
|
+
* shell — `<Toast.Provider toastManager={formToasts}>` around a viewport —
|
|
358
|
+
* and every `Form autoSave` reaches it without wiring. A failure toast
|
|
359
|
+
* carries Retry and stays until the save lands (the next success closes it).
|
|
360
|
+
*/
|
|
361
|
+
export declare const formToasts: import('@base-ui/react').ToastManager<any>;
|
|
362
|
+
/** Field errors keyed by `name`, the shape Base UI `Form` maps onto fields. */
|
|
363
|
+
export type BasicPageFormErrors = Record<string, string | string[]>;
|
|
364
|
+
export interface BasicPageFormProps<Values extends Record<string, unknown> = Record<string, unknown>> extends Omit<ComponentProps<typeof FormElement>, "onFormSubmit" | "errors" | "action" | "autoSave"> {
|
|
365
|
+
/**
|
|
366
|
+
* Documents save themselves; transactions submit. With `autoSave`, the
|
|
367
|
+
* form runs `action` on its own — after a typing pause, immediately on
|
|
368
|
+
* blur — once native validation passes, and skips quietly while it does
|
|
369
|
+
* not. Controls stay enabled throughout; put a `Saved` in the field's
|
|
370
|
+
* hint for the inline Saving…/Saved word. A failure keeps the value in
|
|
371
|
+
* place and raises a Retry toast on `formToasts` that stays until a
|
|
372
|
+
* save lands. Keep the explicit `Submit` for creations and anything
|
|
373
|
+
* paid or irreversible.
|
|
374
|
+
*/
|
|
375
|
+
autoSave?: boolean;
|
|
376
|
+
/**
|
|
377
|
+
* The save. Receives the field values keyed by `name`, after native
|
|
378
|
+
* validation passed. Resolve to finish; return `{ errors }` to put
|
|
379
|
+
* messages on fields; throw (a `Problem`, an `Error`) for the form's
|
|
380
|
+
* `Alert`. While it runs, every control and the submit are disabled.
|
|
381
|
+
*/
|
|
382
|
+
action?: (values: Values) => void | {
|
|
383
|
+
errors?: BasicPageFormErrors;
|
|
384
|
+
} | Promise<void | {
|
|
385
|
+
errors?: BasicPageFormErrors;
|
|
386
|
+
}>;
|
|
387
|
+
/** Field errors to start with — from a previous round trip. */
|
|
388
|
+
errors?: BasicPageFormErrors;
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* The form. A `<form>` that owns the save lifecycle so the page parts can
|
|
392
|
+
* read it: `Submit` shows pending, `Footer show="dirty"` appears after the
|
|
393
|
+
* first edit and leaves when the action lands, `Alert` shows what the
|
|
394
|
+
* action threw, and field errors the action returns land under their
|
|
395
|
+
* fields. Uncontrolled by design — give fields `defaultValue` and a `name`,
|
|
396
|
+
* and remount with `key` when the record changes; there is no state to
|
|
397
|
+
* seed. Lay the fields out in `Fields` (the form card, its `Footer` inside
|
|
398
|
+
* at the bottom), or keep a `Card` of `Row`s for a settings page that
|
|
399
|
+
* saves, its `Footer` following the card one block gap below.
|
|
400
|
+
*
|
|
401
|
+
* The form adds no spacing. Inside a `Stack`, one form around a card and
|
|
402
|
+
* its footer is one block; a form that spans several blocks goes around
|
|
403
|
+
* the `Stack` instead, and the blocks keep the Stack's rhythm.
|
|
404
|
+
*/
|
|
405
|
+
declare function Form<Values extends Record<string, unknown>>({ action, errors: initialErrors, autoSave, className, children, onChange, onBlur, ...props }: BasicPageFormProps<Values>): import("react").JSX.Element;
|
|
406
|
+
/**
|
|
407
|
+
* The inline word for an auto-saving field — put it inside the field at
|
|
408
|
+
* its trailing edge (`Input trailing`), where the eye already is while
|
|
409
|
+
* typing. Quiet gray, never colored, so it cannot be read as validation:
|
|
410
|
+
* "Saving…" while the save runs, "Saved" for a breath after it lands,
|
|
411
|
+
* then nothing at all — idle it renders nothing and reserves nothing.
|
|
412
|
+
* Words fade through the system's 1px soft focus — no travel — and
|
|
413
|
+
* carry their own surface wash, so long
|
|
414
|
+
* input text fades beneath them instead of colliding. With `name` it
|
|
415
|
+
* speaks only for that field; without, for the whole form.
|
|
416
|
+
*/
|
|
417
|
+
declare function Saved({ name, className, ...props }: Omit<ComponentProps<"output">, RevealMotionConflicts> & {
|
|
418
|
+
name?: string;
|
|
419
|
+
}): import("react").JSX.Element;
|
|
420
|
+
/**
|
|
421
|
+
* The form card: labelled fields stacked, label above control, one rhythm
|
|
422
|
+
* (`gap-5`). Where a `Card` of `Row`s is a table of settings, this is a
|
|
423
|
+
* sheet to fill in — a create page, a long edit. `Input` brings its own
|
|
424
|
+
* label and hint; wrap other controls in `Field`. `Alert` and `Footer`
|
|
425
|
+
* sit inside, at the bottom — unlike a `Card` of rows, a sheet keeps its
|
|
426
|
+
* submit: the button's box lines up with the fields' edge.
|
|
427
|
+
*/
|
|
428
|
+
declare function Fields({ className, ...props }: ComponentProps<"div"> & {
|
|
429
|
+
ref?: Ref<HTMLDivElement>;
|
|
430
|
+
}): import("react").JSX.Element;
|
|
431
|
+
/** Fields side by side from `sm` (a first and last name), stacked below. */
|
|
432
|
+
declare function Inline({ className, ...props }: ComponentProps<"div"> & {
|
|
433
|
+
ref?: Ref<HTMLDivElement>;
|
|
434
|
+
}): import("react").JSX.Element;
|
|
435
|
+
/** The submit. A small effect `Button`, pending while the action runs. */
|
|
436
|
+
declare function Submit({ children, ...props }: Omit<ButtonProps, "type">): import("react").JSX.Element;
|
|
276
437
|
export interface BasicPageFooterProps extends ComponentProps<"div"> {
|
|
277
438
|
/**
|
|
278
|
-
* Animated presence for dirty-state
|
|
279
|
-
* height spring while the
|
|
280
|
-
* footer (no animation). No reveal plays on first
|
|
439
|
+
* Animated presence for the dirty-state action: the card glides
|
|
440
|
+
* open/closed on a height spring while the button fades. Omit for a
|
|
441
|
+
* static, always-visible footer (no animation). No reveal plays on first
|
|
442
|
+
* mount — only on flips.
|
|
281
443
|
*/
|
|
282
|
-
show?: boolean;
|
|
444
|
+
show?: boolean | "dirty";
|
|
283
445
|
ref?: Ref<HTMLDivElement>;
|
|
284
446
|
}
|
|
285
447
|
/**
|
|
286
|
-
*
|
|
287
|
-
*
|
|
288
|
-
*
|
|
289
|
-
*
|
|
448
|
+
* Save action for a card. After a `Card` of rows it sits outside, below the
|
|
449
|
+
* surface, its trailing edge on the rows' text edge, so the card
|
|
450
|
+
* holds only rows; inside `Fields` it sits at the bottom of the sheet.
|
|
451
|
+
* Typically a submit button that appears after the form is dirty; pass
|
|
452
|
+
* `show` (instead of conditional rendering) to animate it in and out
|
|
453
|
+
* following the onboarding card's motion language.
|
|
290
454
|
*/
|
|
291
|
-
declare function Footer({ show, className, ...props }: BasicPageFooterProps): import("react").JSX.Element;
|
|
455
|
+
declare function Footer({ show: showProp, className, ...props }: BasicPageFooterProps): import("react").JSX.Element;
|
|
292
456
|
/**
|
|
293
457
|
* DOM handlers whose React signatures clash with Motion's gesture props of
|
|
294
458
|
* the same name on `motion.*` elements — excluded from `Reveal`'s public API
|
|
@@ -304,12 +468,19 @@ export interface BasicPageRevealProps extends Omit<ComponentProps<"div">, Reveal
|
|
|
304
468
|
* the one-shot data-arrival entrance.
|
|
305
469
|
*/
|
|
306
470
|
show?: boolean;
|
|
471
|
+
/**
|
|
472
|
+
* Clip the block while its height animates (the default). Pass `false`
|
|
473
|
+
* for a block whose content must show whole from the first frame — a
|
|
474
|
+
* button with a rim, a shadow — and let it fade in as the space opens.
|
|
475
|
+
*/
|
|
476
|
+
clip?: boolean;
|
|
307
477
|
/**
|
|
308
478
|
* Which gap the presence variant compensates while collapsing —
|
|
309
|
-
* `"stack"` for a Stack block (`gap-10`), `"
|
|
479
|
+
* `"stack"` for a Stack block (`gap-10`), `"fields"` for a field in a
|
|
480
|
+
* `Fields` sheet (`gap-5`), `"block"` for an element
|
|
310
481
|
* inside a block (`gap-3`). @default "stack"
|
|
311
482
|
*/
|
|
312
|
-
gap?: "stack" | "block";
|
|
483
|
+
gap?: "stack" | "block" | "fields";
|
|
313
484
|
/**
|
|
314
485
|
* Set when this wraps multiple `Card` rows — the extra element Reveal
|
|
315
486
|
* needs for `AnimatePresence` sits between them and the card's own
|
|
@@ -334,7 +505,7 @@ export interface BasicPageRevealProps extends Omit<ComponentProps<"div">, Reveal
|
|
|
334
505
|
* `Footer` grammar): a whole section of the Stack that appears or leaves at
|
|
335
506
|
* runtime glides open/closed while its neighbours follow.
|
|
336
507
|
*/
|
|
337
|
-
declare function Reveal({ show, gap, dividers, className, ...props }: BasicPageRevealProps): import("react").JSX.Element;
|
|
508
|
+
declare function Reveal({ show, clip, gap, dividers, className, ...props }: BasicPageRevealProps): import("react").JSX.Element;
|
|
338
509
|
export interface BasicPageBreadcrumbsProps extends ComponentProps<"nav"> {
|
|
339
510
|
/** `Crumb`s, root-most first; the last one is the immediate parent. */
|
|
340
511
|
children: ReactNode;
|
|
@@ -342,23 +513,26 @@ export interface BasicPageBreadcrumbsProps extends ComponentProps<"nav"> {
|
|
|
342
513
|
/**
|
|
343
514
|
* The trail above the title — where this page sits, root-most crumb first,
|
|
344
515
|
* ending with the immediate parent; the current page is the `Title` below.
|
|
345
|
-
* Place inside `Root`, before `Title`. It floats in
|
|
346
|
-
*
|
|
347
|
-
*
|
|
348
|
-
* one.
|
|
516
|
+
* Place inside `Root`, before `Title`. It floats in the page's top-left
|
|
517
|
+
* corner instead of taking layout space, and the column reserves a 64px
|
|
518
|
+
* top zone for it, so `Title` sits at the same position whether or not a
|
|
519
|
+
* page has one.
|
|
349
520
|
*
|
|
350
521
|
* One form at every depth: `‹ parent / parent / parent` — the chevron opens
|
|
351
522
|
* the trail (it is the way up), slashes separate the crumbs (they are the
|
|
352
523
|
* path), one crumb or many. Below `sm` the path collapses to `‹ parent` —
|
|
353
524
|
* the last crumb alone. Crumbs render through the host's `LinkProvider`.
|
|
354
525
|
*
|
|
355
|
-
*
|
|
356
|
-
*
|
|
357
|
-
*
|
|
358
|
-
*
|
|
359
|
-
*
|
|
360
|
-
*
|
|
361
|
-
*
|
|
526
|
+
* Four crumbs or more, the middle folds: `‹ root / … / parent / parent`,
|
|
527
|
+
* with the folded pages behind the ellipsis as a menu. The trail keeps a
|
|
528
|
+
* width ceiling at any depth, and the fold never touches the tail, so the
|
|
529
|
+
* title morph is unaffected.
|
|
530
|
+
*
|
|
531
|
+
* It sits in the page's top-left corner — `top-4 left-3`, the chevron ink
|
|
532
|
+
* 20px from the edge, the column gutter's width — as chrome of the pane,
|
|
533
|
+
* not of the column: on a wide pane it stays at the corner while the
|
|
534
|
+
* column centers. `top-4` centers the 32px buttons in the 64px reserved
|
|
535
|
+
* zone; the ghost hover pills hang in the corner padding.
|
|
362
536
|
*
|
|
363
537
|
* Motion between pages: the tail crumb is the morph partner of the child
|
|
364
538
|
* page's `Title` (pair their `morphId`s); everything before it holds still.
|
|
@@ -393,7 +567,7 @@ export type BasicPageBackProps = BasicPageCrumbProps;
|
|
|
393
567
|
* path with `Breadcrumbs` + `Crumb` instead.
|
|
394
568
|
*/
|
|
395
569
|
declare function Back({ className, ...props }: BasicPageBackProps): import("react").JSX.Element;
|
|
396
|
-
export interface BasicPageRowLinkProps extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>, "href" | "title"> {
|
|
570
|
+
export interface BasicPageRowLinkProps extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>, "href" | "title" | RevealMotionConflicts> {
|
|
397
571
|
/** Left-side field name — plain text, or compose with a trailing badge. */
|
|
398
572
|
label: ReactNode;
|
|
399
573
|
/** Optional helper under the label. */
|
|
@@ -473,6 +647,7 @@ declare function RowLink({ label, description, leading, href, className, childre
|
|
|
473
647
|
*/
|
|
474
648
|
export declare const BasicPage: {
|
|
475
649
|
Root: typeof Root;
|
|
650
|
+
CondenseScope: typeof CondenseScope;
|
|
476
651
|
Breadcrumbs: typeof Breadcrumbs;
|
|
477
652
|
Crumb: typeof Crumb;
|
|
478
653
|
Back: typeof Back;
|
|
@@ -493,6 +668,11 @@ export declare const BasicPage: {
|
|
|
493
668
|
Value: typeof Value;
|
|
494
669
|
Alert: typeof Alert;
|
|
495
670
|
Footer: typeof Footer;
|
|
671
|
+
Form: typeof Form;
|
|
672
|
+
Saved: typeof Saved;
|
|
673
|
+
Fields: typeof Fields;
|
|
674
|
+
Inline: typeof Inline;
|
|
675
|
+
Submit: typeof Submit;
|
|
496
676
|
Reveal: typeof Reveal;
|
|
497
677
|
};
|
|
498
678
|
export {};
|
|
@@ -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 BasicPageRowProps, type BasicPageRowLinkProps, type BasicPageBackProps, type BasicPageBreadcrumbsProps, type BasicPageCrumbProps, type BasicPageFooterProps, 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 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
|
-
/**
|
|
56
|
-
|
|
57
|
-
|
|
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
package/src/styles/pho.css
CHANGED
|
@@ -36,6 +36,25 @@
|
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
@layer base {
|
|
40
|
+
/* Each block surface registers itself, so anything that needs to fade
|
|
41
|
+
into "the background it sits on" (a scroll area's edge wash) reads
|
|
42
|
+
`--pho-surface` and inherits the nearest surface ancestor's color —
|
|
43
|
+
live across themes, no wiring. */
|
|
44
|
+
.bg-pho-page {
|
|
45
|
+
--pho-surface: var(--background-color-pho-page);
|
|
46
|
+
}
|
|
47
|
+
.bg-pho-primary {
|
|
48
|
+
--pho-surface: var(--background-color-pho-primary);
|
|
49
|
+
}
|
|
50
|
+
.bg-pho-secondary {
|
|
51
|
+
--pho-surface: var(--background-color-pho-secondary);
|
|
52
|
+
}
|
|
53
|
+
.bg-pho-inverse {
|
|
54
|
+
--pho-surface: var(--background-color-pho-inverse);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
39
58
|
/* True squircle corners (progressive enhancement; falls back to border-radius
|
|
40
59
|
where `corner-shape` is unsupported). Pair with a `rounded-*` utility. */
|
|
41
60
|
@utility squircle {
|