@photon-ai/pho-ui 4.10.0 → 4.12.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 (58) hide show
  1. package/dist/chunks/animated-height-zr7BmFY1.js +56 -0
  2. package/dist/chunks/animated-height-zr7BmFY1.js.map +1 -0
  3. package/dist/chunks/{bar-chart-HsoFFaPb.js → bar-chart-By5gWQqP.js} +2 -2
  4. package/dist/chunks/{bar-chart-HsoFFaPb.js.map → bar-chart-By5gWQqP.js.map} +1 -1
  5. package/dist/chunks/basic-page-CJ11ekjH.js +2217 -0
  6. package/dist/chunks/basic-page-CJ11ekjH.js.map +1 -0
  7. package/dist/chunks/{chart-BrIXaMue.js → chart-Dx3rjeFn.js} +527 -490
  8. package/dist/chunks/chart-Dx3rjeFn.js.map +1 -0
  9. package/dist/chunks/{chat-B0WIgEyM.js → chat-CU3XVm99.js} +2 -2
  10. package/dist/chunks/{chat-B0WIgEyM.js.map → chat-CU3XVm99.js.map} +1 -1
  11. package/dist/chunks/{checkbox-CLPmblNA.js → checkbox-CwvoEJhd.js} +2 -2
  12. package/dist/chunks/{checkbox-CLPmblNA.js.map → checkbox-CwvoEJhd.js.map} +1 -1
  13. package/dist/chunks/choice-card-_Ocs0iUj.js +17 -0
  14. package/dist/chunks/choice-card-_Ocs0iUj.js.map +1 -0
  15. package/dist/chunks/{command-iYvU6Mhf.js → command-D5g49VqR.js} +3 -3
  16. package/dist/chunks/{command-iYvU6Mhf.js.map → command-D5g49VqR.js.map} +1 -1
  17. package/dist/chunks/{data-table-B1dmrN6r.js → data-table-Ce_c6T73.js} +3 -3
  18. package/dist/chunks/{data-table-B1dmrN6r.js.map → data-table-Ce_c6T73.js.map} +1 -1
  19. package/dist/chunks/{dialog-MPvem7yV.js → dialog-ChS0tdHa.js} +120 -116
  20. package/dist/chunks/dialog-ChS0tdHa.js.map +1 -0
  21. package/dist/chunks/{filter-bar-B-oYYBsU.js → filter-bar-CMkvhvgL.js} +2 -2
  22. package/dist/chunks/{filter-bar-B-oYYBsU.js.map → filter-bar-CMkvhvgL.js.map} +1 -1
  23. package/dist/chunks/{input-DjvZoF8v.js → input-fFWvPJOf.js} +2 -1
  24. package/dist/chunks/{input-DjvZoF8v.js.map → input-fFWvPJOf.js.map} +1 -1
  25. package/dist/chunks/{line-chart-Bv25WyGp.js → line-chart-CAe09fqr.js} +2 -2
  26. package/dist/chunks/{line-chart-Bv25WyGp.js.map → line-chart-CAe09fqr.js.map} +1 -1
  27. package/dist/components/bar-chart.js +1 -1
  28. package/dist/components/chart.js +1 -1
  29. package/dist/components/chat.js +1 -1
  30. package/dist/components/checkbox.js +1 -1
  31. package/dist/components/command.js +1 -1
  32. package/dist/components/data-table.js +1 -1
  33. package/dist/components/dialog.js +1 -1
  34. package/dist/components/field.js +34 -29
  35. package/dist/components/field.js.map +1 -1
  36. package/dist/components/filter-bar.js +1 -1
  37. package/dist/components/input.js +1 -1
  38. package/dist/components/line-chart.js +1 -1
  39. package/dist/components/radio-group.js +64 -59
  40. package/dist/components/radio-group.js.map +1 -1
  41. package/dist/index.js +9 -9
  42. package/dist/sections/basic-page.js +2 -2
  43. package/dist/src/components/dialog/dialog.d.ts +9 -1
  44. package/dist/src/components/field/field.d.ts +11 -1
  45. package/dist/src/components/radio-group/radio-card.d.ts +11 -4
  46. package/dist/src/sections/basic-page/basic-page.d.ts +230 -15
  47. package/dist/src/sections/basic-page/index.d.ts +1 -1
  48. package/dist/src/utils/animated-height.d.ts +16 -7
  49. package/dist/src/utils/choice-card.d.ts +8 -1
  50. package/package.json +1 -1
  51. package/dist/chunks/animated-height-I44sUq0n.js +0 -48
  52. package/dist/chunks/animated-height-I44sUq0n.js.map +0 -1
  53. package/dist/chunks/basic-page-DzT8yecB.js +0 -1801
  54. package/dist/chunks/basic-page-DzT8yecB.js.map +0 -1
  55. package/dist/chunks/chart-BrIXaMue.js.map +0 -1
  56. package/dist/chunks/choice-card-BVNP1NB6.js +0 -17
  57. package/dist/chunks/choice-card-BVNP1NB6.js.map +0 -1
  58. package/dist/chunks/dialog-MPvem7yV.js.map +0 -1
@@ -8,12 +8,12 @@ import { CodeBlock } from '../../components/code-block';
8
8
  * card's own: Stack used to force `gap-3` onto a bare Card and open 12px
9
9
  * bands between `divide-y` rows. The marker below lets Stack skip it.
10
10
  */
11
- 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 gap-0";
11
+ export declare const BASIC_PAGE_CARD = "rounded-base border border-pho-secondary bg-pho-primary [--choice-card-inset:0.75rem] divide-y divide-pho-secondary [&>:has(+[data-basic-page-alert])]:border-b-0 gap-0";
12
12
  /**
13
13
  * Standalone callout surface — featured block (invite form, notice, etc.).
14
14
  * Don't wrap in `Card`; this is the outer chrome.
15
15
  */
16
- export declare const BASIC_PAGE_CALLOUT = "flex min-w-0 flex-col gap-3 rounded-base border border-pho-secondary bg-pho-page p-5";
16
+ export declare const BASIC_PAGE_CALLOUT = "flex min-w-0 flex-col gap-3 rounded-base border border-pho-secondary bg-pho-page p-5 [--choice-card-inset:0.75rem]";
17
17
  /**
18
18
  * One row — label (+ optional description) left, control right.
19
19
  * `min-h-[4.25rem]` (68px) keeps avatar/control rows from collapsing shorter
@@ -227,6 +227,25 @@ export interface BasicPageTitleProps extends ComponentProps<"h1"> {
227
227
  trailing?: ReactNode;
228
228
  ref?: Ref<HTMLHeadingElement>;
229
229
  }
230
+ export interface BasicPageTitleAccessoryProps {
231
+ /**
232
+ * Whether it goes with the words into the condensed bar once the title
233
+ * has scrolled away. A status the name can't be read without does (a
234
+ * badge); an action on the page doesn't (a Rename pencil): the bar is a
235
+ * way back and a name, not a toolbar.
236
+ * @default true
237
+ */
238
+ inBar?: boolean;
239
+ children?: ReactNode;
240
+ }
241
+ /**
242
+ * A part of the title beside its words — a badge, a status, an action on
243
+ * the page itself — that says whether it follows the words into the
244
+ * condensed bar (`Root condense`). Put it inside `Title` after the words.
245
+ * Everything in a title's children goes into the bar unless it says
246
+ * otherwise; `Title`'s `trailing` never does.
247
+ */
248
+ declare function TitleAccessory({ inBar, children, }: BasicPageTitleAccessoryProps): import("react").JSX.Element | null;
230
249
  /**
231
250
  * Page title — largest heading on the surface. Plain-text children get a slug
232
251
  * `id` for hash targets (`#profile`); the heading itself is not a link.
@@ -308,11 +327,12 @@ export interface BasicPageHeaderProps extends Omit<ComponentProps<"div">, Reveal
308
327
  declare function Header({ enter: enterProp, className, ...props }: BasicPageHeaderProps): import("react").JSX.Element;
309
328
  /**
310
329
  * An action at the header row's end — a small button (or two) seated in
311
- * the `Header` grid the way `Search` is: top-right of the block, its top
312
- * edge on the header's top, its right edge on the title / card-content
313
- * inset (`mr-5` matching `SectionTitle`'s `px-5`). A callout already
314
- * carries `p-5` and its title has no `px-5`, so the inset drops there.
315
- * Text shorter than the seat centers against it. Put it inside `Header`
330
+ * the `Header` grid the way `Search` is, its right edge on the title /
331
+ * card-content inset (`mr-5` matching `SectionTitle`'s `px-5`). A callout
332
+ * already carries `p-5` and its title has no `px-5`, so the inset drops
333
+ * there. It centers on the text block whichever is taller: beside a
334
+ * description that wraps to a third line it stays on the block's middle,
335
+ * and text shorter than it centers against it. Put it inside `Header`
316
336
  * after the text; with a `Search` present it stands to the search's right.
317
337
  */
318
338
  declare function HeaderAction({ className, ...props }: ComponentProps<"div"> & {
@@ -425,6 +445,16 @@ declare function CalloutDescription({ className, ...props }: ComponentProps<"p">
425
445
  ref?: Ref<HTMLParagraphElement>;
426
446
  }): import("react").JSX.Element;
427
447
  export interface BasicPageOnboardProps extends ComponentProps<"ol"> {
448
+ /**
449
+ * One page per step, the steps in a row above it, instead of the card
450
+ * with the step at hand folded open — for a setup whose steps are
451
+ * pages of their own: a registration that asks who is registering,
452
+ * then for the brand, then for the campaign. Each `Step`'s children are
453
+ * its page (a `Stack`, or a `Form` around one), and the paged `Onboard`
454
+ * stands where the page's `Stack` would, under the `Title`. The rest of
455
+ * the props go to the row, the ordered list of steps.
456
+ */
457
+ paged?: boolean;
428
458
  ref?: Ref<HTMLOListElement>;
429
459
  }
430
460
  /**
@@ -438,30 +468,40 @@ export interface BasicPageOnboardProps extends ComponentProps<"ol"> {
438
468
  * with a check and what they came to, the waiting ones muted. A step
439
469
  * finishing folds closed as the next opens, on the Accordion's spring.
440
470
  * When the last step is done the service is on — render the page in its
441
- * place.
471
+ * place. `paged` turns the card into a row of steps over the page at
472
+ * hand (see `PagedOnboard`).
442
473
  */
443
- declare function Onboard({ className, children, ...props }: BasicPageOnboardProps): import("react").JSX.Element;
474
+ declare function Onboard({ paged, className, children, ...props }: BasicPageOnboardProps): import("react").JSX.Element;
444
475
  export interface BasicPageStepProps extends Omit<ComponentProps<"li">, "title"> {
445
476
  /**
446
477
  * Decorative glyph for the step at hand, top-right of its body the way a
447
478
  * `Callout`'s is — typically a Tabler outline icon at stroke 1.25. It is
448
479
  * aria-hidden (keep the meaning in the title) and folds away with the
449
- * body: a done or waiting step shows none.
480
+ * body: a done or waiting step shows none. In a paged list it is what a
481
+ * done step came to, drawn in its ring in place of the check — the
482
+ * choice a step made, say — and a step without one keeps the check.
450
483
  */
451
484
  icon?: ReactNode;
452
485
  /**
453
486
  * Something to look at beside the step at hand — a code to scan, with
454
487
  * its caption — in the corner where the `icon` would be, its top on the
455
488
  * title's, holding still as the fold opens beside it. It takes the
456
- * icon's place when both are given, and folds away with the body.
489
+ * icon's place when both are given, and folds away with the body. Not
490
+ * shown in a paged list.
457
491
  */
458
492
  aside?: ReactNode;
459
- /** The title: a verb and its object — "Choose a number". */
493
+ /**
494
+ * The title: a verb and its object — "Choose a number". In a paged
495
+ * list, the step's name in the row, a word or two — "Brand" — which a
496
+ * done step may trade for what it came to ("Business"); the row
497
+ * crossfades it.
498
+ */
460
499
  title: ReactNode;
461
500
  /**
462
501
  * The line under the title while the step is at hand: what it involves,
463
502
  * or, while it waits, how long. Folded away with the rest once the step
464
- * is done or before its turn.
503
+ * is done or before its turn. Not shown in a paged list; the page says
504
+ * it in its own `Header`.
465
505
  */
466
506
  description?: ReactNode;
467
507
  /**
@@ -486,11 +526,95 @@ export interface BasicPageStepProps extends Omit<ComponentProps<"li">, "title">
486
526
  /**
487
527
  * At hand: the step's action — a small `Button` or `ButtonLink` — under
488
528
  * its line. Done: what it came to — a `Value` — at the title's end.
489
- * Waiting its turn: not shown.
529
+ * Waiting its turn: not shown. In a paged list, the step's page — a
530
+ * `Stack`, or a `Form` around one — shown under the row while the step
531
+ * is at hand.
532
+ */
533
+ children?: ReactNode;
534
+ ref?: Ref<HTMLLIElement>;
535
+ }
536
+ /**
537
+ * Where a check stands. As `Step`'s: `done` draws the check, `working`
538
+ * spins while Photon is at it, `pending` is dashed while it waits on
539
+ * someone else (a carrier, a DNS host, the visitor), `upcoming` is faint
540
+ * while it waits its turn. `failed` trades the ring for an X and says so.
541
+ */
542
+ export type BasicPageCheckState = "done" | "working" | "pending" | "upcoming" | "failed";
543
+ /**
544
+ * A list of checks Photon reports on, one line each: DNS records found, a
545
+ * registration's stages. Not steps someone takes (that is `Onboard`), and
546
+ * not a percentage (that is `Progress`). It speaks the `Onboard` ring's
547
+ * language at the line's size. The check where the list stands, whatever
548
+ * came of it, is its current step: its label one weight up, and
549
+ * `aria-current` for assistive tech. Put it in a `Card`'s `Item`, and say
550
+ * when it was last checked, if that matters, in a `SectionFooter`.
551
+ */
552
+ declare function Checklist({ className, children, ...props }: ComponentProps<"ul"> & {
553
+ ref?: Ref<HTMLUListElement>;
554
+ }): import("react").JSX.Element;
555
+ export interface BasicPageCheckProps extends Omit<ComponentProps<"li">, "value"> {
556
+ /** @default "upcoming" */
557
+ state?: BasicPageCheckState;
558
+ /**
559
+ * What the check came to, at the line's end in description ink: the
560
+ * date it passed, a count.
561
+ */
562
+ value?: ReactNode;
563
+ /**
564
+ * A line (or a few) right under the label, on its start edge, at
565
+ * `text-xs`: why a failed check failed, in error ink with no surface of
566
+ * its own (the X already marks it); otherwise what the check waits on,
567
+ * in description ink. Several reasons are several block children.
568
+ */
569
+ description?: ReactNode;
570
+ /**
571
+ * What a failed check's failure is called, beside its label in error
572
+ * ink: "Rejected", "Suspended". Read only when `state` is `failed`.
573
+ * @default "Failed"
574
+ */
575
+ failure?: ReactNode;
576
+ ref?: Ref<HTMLLIElement>;
577
+ }
578
+ /**
579
+ * One check: its ring, its label, its `value` at the line's end, and its
580
+ * `description` under the label. The ring is `Step`'s at the text's size;
581
+ * a check that turns done draws its mark on, one that loads done shows it
582
+ * drawn. The list says which check is current; its label and a failed
583
+ * one's "Failed" go one weight up.
584
+ */
585
+ declare function Check({ state, value, description, failure, className, children, ...props }: BasicPageCheckProps): import("react").JSX.Element;
586
+ /**
587
+ * What happened, in order: a registration's reviews, a domain's checks
588
+ * over time, a key's uses. One event per `TimelineItem`, newest first
589
+ * unless the page says otherwise, each on the checklist's mark with a
590
+ * faint line down to the next. Where `Checklist` is where things stand
591
+ * now, a timeline is how they got there. Put it in a `Card`'s `Item`.
592
+ */
593
+ declare function Timeline({ className, ...props }: ComponentProps<"ol"> & {
594
+ ref?: Ref<HTMLOListElement>;
595
+ }): import("react").JSX.Element;
596
+ export interface BasicPageTimelineItemProps extends Omit<ComponentProps<"li">, "title"> {
597
+ /** What came of the event, on the checklist's mark. @default "done" */
598
+ state?: BasicPageCheckState;
599
+ /** The event, in words: "Carrier review failed". */
600
+ title: ReactNode;
601
+ /** When it happened, under the title in description ink. */
602
+ time?: ReactNode;
603
+ /**
604
+ * What there is to say about it, under the time at `text-xs` in
605
+ * description ink: a reviewer's reasons, a note. A record, not an alarm:
606
+ * a failure's mark says it failed, and the page's current state says
607
+ * what to do about it.
490
608
  */
491
609
  children?: ReactNode;
492
610
  ref?: Ref<HTMLLIElement>;
493
611
  }
612
+ /**
613
+ * One event: its mark on the rail, a line from it down to the next
614
+ * event's, and beside it the title, the time and the details. The mark
615
+ * sits on the title's line; the last event draws no line.
616
+ */
617
+ declare function TimelineItem({ state, title, time, className, children, ...props }: BasicPageTimelineItemProps): import("react").JSX.Element;
494
618
  /**
495
619
  * One step of an `Onboard`, left to right: the ring, the words, the
496
620
  * corner. The ring and the title share one row and center on each
@@ -503,7 +627,8 @@ export interface BasicPageStepProps extends Omit<ComponentProps<"li">, "title">
503
627
  * does; the others stay on the card's white. The title and the line wear the
504
628
  * section's type — `SectionTitle` over `Description`, both
505
629
  * `text-display-xs`. Its standing comes from the list; on its own it is
506
- * the step at hand.
630
+ * the step at hand. In a paged list it is its place in the row instead
631
+ * (`StepInRow`), and the list shows its children as the page.
507
632
  */
508
633
  declare function Step({ icon, aside, title, description, done, working, pending, className, children, ...props }: BasicPageStepProps): import("react").JSX.Element;
509
634
  export interface BasicPageRowProps extends Omit<ComponentProps<"div">, "title" | RevealMotionConflicts> {
@@ -533,6 +658,87 @@ declare function Row({ label, description, htmlFor, stacked, className, children
533
658
  declare function Value({ className, ...props }: ComponentProps<"p"> & {
534
659
  ref?: Ref<HTMLParagraphElement>;
535
660
  }): import("react").JSX.Element;
661
+ export interface BasicPageReceiptProps extends ComponentProps<"ul"> {
662
+ /**
663
+ * What the receipt says with nothing on it, in the card's place for the
664
+ * lines: "No usage yet this period." Shown when no line, group, or total
665
+ * is given.
666
+ */
667
+ empty?: ReactNode;
668
+ ref?: Ref<HTMLUListElement>;
669
+ }
670
+ /**
671
+ * Charges that add up: the usage a billing period has run to so far, an
672
+ * order before it is paid, an invoice's lines. A card of its own, one line
673
+ * per charge in three columns (the name, how much of it, what it came to),
674
+ * with the figures right-aligned in tabular digits so a column of amounts
675
+ * reads down its decimal points. `ReceiptGroup` gathers lines under a
676
+ * name; `ReceiptTotal` closes the receipt under a hairline.
677
+ *
678
+ * ```tsx
679
+ * <BasicPage.Receipt>
680
+ * <BasicPage.ReceiptGroup label="Messaging">
681
+ * <BasicPage.ReceiptLine label="SMS" quantity="1,204 messages" amount="$9.51" />
682
+ * <BasicPage.ReceiptLine label="MMS" quantity="86 messages" amount="$1.72" />
683
+ * </BasicPage.ReceiptGroup>
684
+ * <BasicPage.ReceiptTotal label="Total so far" amount="$11.23" />
685
+ * </BasicPage.Receipt>
686
+ * ```
687
+ */
688
+ declare function Receipt({ empty, className, children, ...props }: BasicPageReceiptProps): import("react").JSX.Element;
689
+ export interface BasicPageReceiptGroupProps extends Omit<ComponentProps<"li">, "title" | RevealMotionConflicts> {
690
+ /**
691
+ * What the group's lines have in common: a category, a plan, a project.
692
+ * Left out, the group is a block of lines under a hairline, the way to
693
+ * set a subtotal and its tax apart from the items above them.
694
+ */
695
+ label?: ReactNode;
696
+ ref?: Ref<HTMLLIElement>;
697
+ }
698
+ /**
699
+ * Lines that belong together, as one block of the receipt: its name in
700
+ * the ink of a total over the lines, a hairline between it and whatever
701
+ * came before. The lines ride in with the group when the page's data
702
+ * arrives.
703
+ */
704
+ declare function ReceiptGroup({ label, className, children, ...props }: BasicPageReceiptGroupProps): import("react").JSX.Element;
705
+ export interface BasicPageReceiptLineProps extends Omit<ComponentProps<"li">, "title" | "children" | RevealMotionConflicts> {
706
+ /** What was charged: "SMS", "Dedicated line", "Business plan". */
707
+ label: ReactNode;
708
+ /**
709
+ * How much of it, with its unit: "1,204 messages", "312 minutes", "× 2".
710
+ * Left out, the name takes the column too.
711
+ */
712
+ quantity?: ReactNode;
713
+ /**
714
+ * What it came to, formatted by the host: "$9.51". Left out (a charge
715
+ * not priced yet), the line shows no figure there and the name reaches
716
+ * into the columns left free.
717
+ */
718
+ amount?: ReactNode;
719
+ ref?: Ref<HTMLLIElement>;
720
+ }
721
+ /**
722
+ * One charge: its name, how much of it, and what it came to, in the
723
+ * receipt's columns. Name and amount in the rows' secondary ink, the
724
+ * quantity a step quieter, so the total below is the one figure at full
725
+ * ink.
726
+ */
727
+ declare function ReceiptLine({ label, quantity, amount, className, ...props }: BasicPageReceiptLineProps): import("react").JSX.Element;
728
+ export interface BasicPageReceiptTotalProps extends Omit<ComponentProps<"li">, "title" | "children" | RevealMotionConflicts> {
729
+ /** What the lines add up to: "Total", "Total so far", "Due Oct 1". */
730
+ label: ReactNode;
731
+ /** The sum, formatted by the host: "$11.23". */
732
+ amount: ReactNode;
733
+ ref?: Ref<HTMLLIElement>;
734
+ }
735
+ /**
736
+ * What the lines come to, under a hairline: name and amount at full ink
737
+ * and medium weight, the amount on the lines' amount column. Totals in a
738
+ * row share one block, one per currency when the lines carry more than
739
+ * one.
740
+ */
741
+ declare function ReceiptTotal({ label, amount, className, ...props }: BasicPageReceiptTotalProps): import("react").JSX.Element;
536
742
  export interface BasicPageAlertProps extends Omit<ComponentProps<"div">, "children"> {
537
743
  /** The caught value — a problem body, an `Error` wrapping one, or unknown. */
538
744
  error?: unknown;
@@ -1058,6 +1264,7 @@ export declare const BasicPage: {
1058
1264
  Crumb: typeof Crumb;
1059
1265
  Back: typeof Back;
1060
1266
  Title: typeof Title;
1267
+ TitleAccessory: typeof TitleAccessory;
1061
1268
  Stack: typeof Stack;
1062
1269
  Columns: typeof Columns;
1063
1270
  Header: typeof Header;
@@ -1074,11 +1281,19 @@ export declare const BasicPage: {
1074
1281
  CalloutDescription: typeof CalloutDescription;
1075
1282
  Onboard: typeof Onboard;
1076
1283
  Step: typeof Step;
1284
+ Checklist: typeof Checklist;
1285
+ Check: typeof Check;
1286
+ Timeline: typeof Timeline;
1287
+ TimelineItem: typeof TimelineItem;
1077
1288
  Row: typeof Row;
1078
1289
  RowLink: typeof RowLink;
1079
1290
  Value: typeof Value;
1080
1291
  Meta: ({ layout, columns, className, ...props }: import('.').BasicPageMetaProps) => import("react").JSX.Element;
1081
1292
  MetaItem: ({ label, value, children, mono, copy, optional, empty, className, ...props }: import('.').BasicPageMetaItemProps) => import("react").JSX.Element;
1293
+ Receipt: typeof Receipt;
1294
+ ReceiptGroup: typeof ReceiptGroup;
1295
+ ReceiptLine: typeof ReceiptLine;
1296
+ ReceiptTotal: typeof ReceiptTotal;
1082
1297
  Alert: typeof Alert;
1083
1298
  Footer: typeof Footer;
1084
1299
  Form: typeof Form;
@@ -1,3 +1,3 @@
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 BasicPageColumnsProps, type BasicPageAsideProps, type BasicPageAsideWidth, type BasicPageAsidePresentation, type BasicPageRowProps, type BasicPageRowLinkProps, type BasicPageBackProps, type BasicPageBreadcrumbsProps, type BasicPageCrumbProps, type BasicPageFooterProps, type BasicPageFormProps, type BasicPageFormErrors, type BasicPageItemPanelProps, type BasicPageOnboardProps, type BasicPageStepProps, } 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 BasicPageColumnsProps, type BasicPageAsideProps, type BasicPageAsideWidth, type BasicPageAsidePresentation, type BasicPageRowProps, type BasicPageRowLinkProps, type BasicPageBackProps, type BasicPageBreadcrumbsProps, type BasicPageCrumbProps, type BasicPageFooterProps, type BasicPageFormProps, type BasicPageFormErrors, type BasicPageItemPanelProps, type BasicPageOnboardProps, type BasicPageStepProps, type BasicPageTitleAccessoryProps, type BasicPageCheckProps, type BasicPageCheckState, type BasicPageTimelineItemProps, type BasicPageReceiptProps, type BasicPageReceiptGroupProps, type BasicPageReceiptLineProps, type BasicPageReceiptTotalProps, } from './basic-page';
2
2
  export { createColumns, type DataTableColumn, type DataTableColumnMeta, type DataTableProps, type SortingState, } from '../../components/data-table';
3
3
  export { type DescriptionListRootProps as BasicPageMetaProps, type DescriptionListItemProps as BasicPageMetaItemProps, type DescriptionListLayout as BasicPageMetaLayout, } from '../../components/description-list';
@@ -1,15 +1,24 @@
1
- import { ReactNode } from 'react';
2
- import { ValueAnimationTransition } from 'motion/react';
1
+ import { ReactNode, RefObject } from 'react';
2
+ import { MotionValue, ValueAnimationTransition } from 'motion/react';
3
3
  /**
4
- * Animates its own height to follow the measured height of `children`, so
5
- * content swaps (search filtering, skeleton → data) glide instead of jumping.
6
- * Honors `prefers-reduced-motion` by snapping height with no spring.
4
+ * Keeps a container's size on one axis following the measured size of its
5
+ * content on a spring — the core of `AnimatedHeight`, and of any part whose
6
+ * box should glide as its content changes (a paged `Onboard`'s step titles
7
+ * follow their words' width this way). Returns the motion value to put on
8
+ * the container's `style`. Reduced motion snaps it.
7
9
  *
8
10
  * The container clips only while the spring is in flight. ResizeObserver
9
11
  * callbacks run after layout but before paint, so the clip lands before the
10
12
  * swap frame can show; once the spring settles it is lifted again, so a focus
11
- * ring, an effect button's rim, or any other overhang on the last row paints
12
- * normally at rest instead of being cut off at the container's edge.
13
+ * ring, an effect button's rim, or any other overhang paints normally at
14
+ * rest instead of being cut off at the container's edge.
15
+ */
16
+ export declare function useSizeFollow(axis: "height" | "width", containerRef: RefObject<HTMLElement | null>, contentRef: RefObject<HTMLElement | null>, transition: ValueAnimationTransition<number | "auto">): MotionValue<number | "auto">;
17
+ /**
18
+ * Animates its own height to follow the measured height of `children`, so
19
+ * content swaps (search filtering, skeleton → data) glide instead of jumping.
20
+ * Honors `prefers-reduced-motion` by snapping height with no spring. Clips
21
+ * only while the spring is in flight (see `useSizeFollow`).
13
22
  */
14
23
  export declare function AnimatedHeight({ className, transition, children, }: {
15
24
  className?: string;
@@ -4,8 +4,15 @@ import { Transition } from 'motion/react';
4
4
  * tile. Applied to the radio/checkbox root itself so the whole tile is the
5
5
  * hit target. Hover fills (`bg-pho-ghost-hover`); selected uses the brand
6
6
  * ring. Press feedback lives on this surface (see `usePressPulse`).
7
+ *
8
+ * The side padding is `--choice-card-inset`, 12px unless the page says
9
+ * otherwise, and the padding above and below is three quarters of it: a
10
+ * `BasicPage.Stack` sets it to the page's text edge (20px), so tiles
11
+ * standing on the page as its surfaces reach the column's edge as a card
12
+ * does and start their words on the headings' line; a card, sheet or
13
+ * callout sets it back, so tiles inside one stay compact.
7
14
  */
8
- export declare const CHOICE_CARD_BASE = "group outline-pho-brand flex flex-1 cursor-pointer items-start gap-2.5 rounded-base p-3 text-base text-pho-secondary ring-1 ring-pho-primary ring-inset transition-[box-shadow,background-color] duration-150 ease-out select-none hover:bg-pho-ghost-hover data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50 data-[disabled]:hover:bg-transparent data-[checked]:ring-2 data-[checked]:ring-pho-brand has-[[data-checked]]:ring-2 has-[[data-checked]]:ring-pho-brand focus-visible:outline-2 focus-visible:outline-offset-2 has-[:focus-visible]:outline-2 has-[:focus-visible]:outline-offset-2";
15
+ export declare const CHOICE_CARD_BASE = "group outline-pho-brand flex flex-1 cursor-pointer items-start gap-2.5 rounded-base px-[var(--choice-card-inset,0.75rem)] py-[calc(var(--choice-card-inset,0.75rem)*0.75)] text-base text-pho-secondary ring-1 ring-pho-primary ring-inset transition-[box-shadow,background-color] duration-150 ease-out select-none hover:bg-pho-ghost-hover data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50 data-[disabled]:hover:bg-transparent data-[checked]:ring-2 data-[checked]:ring-pho-brand has-[[data-checked]]:ring-2 has-[[data-checked]]:ring-pho-brand focus-visible:outline-2 focus-visible:outline-offset-2 has-[:focus-visible]:outline-2 has-[:focus-visible]:outline-offset-2";
9
16
  /** Stacked icon above the copy — tighter than the checkbox/radio row gap. */
10
17
  export declare const CHOICE_CARD_WITH_ICON = "flex-col gap-1.5";
11
18
  /** Same press as Select's default trigger — field-sized, not Button's whileTap. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@photon-ai/pho-ui",
3
- "version": "4.10.0",
3
+ "version": "4.12.0",
4
4
  "description": "Pho Design System — Photon's React component library, built on Base UI",
5
5
  "license": "UNLICENSED",
6
6
  "repository": {
@@ -1,48 +0,0 @@
1
- "use client";
2
- import { SPRING_SETTLE as b } from "../motion.js";
3
- import { useEffect as R, useRef as m } from "react";
4
- import { jsx as d } from "react/jsx-runtime";
5
- import { animate as x, motion as S, useMotionValue as g, useReducedMotion as w } from "motion/react";
6
- var y = b;
7
- function G({ className: p, transition: s, children: v }) {
8
- const i = m(null), c = m(null), t = g("auto"), l = w();
9
- return R(() => {
10
- const o = i.current, n = c.current;
11
- if (!o || !n) return;
12
- let e = null;
13
- const u = new ResizeObserver((h) => {
14
- const f = h[0]?.borderBoxSize?.[0], r = f ? f.blockSize : n.offsetHeight, a = t.get();
15
- if (a === "auto" || l) {
16
- e?.stop(), e = null, o.style.overflow = "", t.set(r);
17
- return;
18
- }
19
- !e && Math.abs(a - r) < 0.5 || (o.style.overflow = "hidden", e?.stop(), e = x(t, r, {
20
- ...s ?? y,
21
- onComplete: () => {
22
- e = null, o.style.overflow = "";
23
- }
24
- }));
25
- });
26
- return u.observe(n), () => {
27
- u.disconnect(), e?.stop();
28
- };
29
- }, [
30
- t,
31
- l,
32
- s
33
- ]), /* @__PURE__ */ d(S.div, {
34
- ref: i,
35
- className: "min-h-0",
36
- style: { height: t },
37
- children: /* @__PURE__ */ d("div", {
38
- ref: c,
39
- className: p,
40
- children: v
41
- })
42
- });
43
- }
44
- export {
45
- G as t
46
- };
47
-
48
- //# sourceMappingURL=animated-height-I44sUq0n.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"animated-height-I44sUq0n.js","names":[],"sources":["../../src/utils/animated-height.tsx"],"sourcesContent":["import { useEffect, useRef, type ReactNode } from \"react\";\nimport { SPRING_SETTLE } from \"../motion\";\nimport {\n animate,\n motion,\n useMotionValue,\n useReducedMotion,\n type ValueAnimationTransition,\n} from \"motion/react\";\n\n/**\n * Height spring for container-size transitions — same feel as the onboarding /\n * invite card and BasicPage footer reveal: quick, critically damped (no\n * overshoot that would flash clipped content).\n */\nconst HEIGHT_SPRING = SPRING_SETTLE;\n\n/**\n * Animates its own height to follow the measured height of `children`, so\n * content swaps (search filtering, skeleton → data) glide instead of jumping.\n * Honors `prefers-reduced-motion` by snapping height with no spring.\n *\n * The container clips only while the spring is in flight. ResizeObserver\n * callbacks run after layout but before paint, so the clip lands before the\n * swap frame can show; once the spring settles it is lifted again, so a focus\n * ring, an effect button's rim, or any other overhang on the last row paints\n * normally at rest instead of being cut off at the container's edge.\n */\nexport function AnimatedHeight({\n className,\n transition,\n children,\n}: {\n className?: string;\n /** Spring override for the height follow. @default the Command spring */\n transition?: ValueAnimationTransition<number | \"auto\">;\n children: ReactNode;\n}) {\n const containerRef = useRef<HTMLDivElement>(null);\n const contentRef = useRef<HTMLDivElement>(null);\n const height = useMotionValue<number | \"auto\">(\"auto\");\n const reduceMotion = useReducedMotion();\n\n useEffect(() => {\n const container = containerRef.current;\n const content = contentRef.current;\n if (!container || !content) return;\n\n let animation: ReturnType<typeof animate> | null = null;\n\n const observer = new ResizeObserver((entries) => {\n const box = entries[0]?.borderBoxSize?.[0];\n const next = box ? box.blockSize : content.offsetHeight;\n const current = height.get();\n if (current === \"auto\" || reduceMotion) {\n animation?.stop();\n animation = null;\n container.style.overflow = \"\";\n height.set(next);\n return;\n }\n if (!animation && Math.abs(current - next) < 0.5) return;\n container.style.overflow = \"hidden\";\n animation?.stop();\n animation = animate(height, next, {\n ...(transition ?? HEIGHT_SPRING),\n // Not fired on stop(), so a retarget can't lift the clip early.\n onComplete: () => {\n animation = null;\n container.style.overflow = \"\";\n },\n });\n });\n observer.observe(content);\n\n return () => {\n observer.disconnect();\n animation?.stop();\n };\n }, [height, reduceMotion, transition]);\n\n return (\n <motion.div\n ref={containerRef}\n // Stack (and other flex parents) set `min-height: auto` on children,\n // which sizes to content and swallows the height spring. Allow\n // shrinking so the measured height can actually animate; the clip is\n // applied imperatively for the spring's duration only (see above).\n className=\"min-h-0\"\n style={{ height }}\n >\n <div ref={contentRef} className={className}>\n {children}\n </div>\n </motion.div>\n );\n}\n"],"mappings":";;;;;AAeA,IAAM,IAAgB;AAatB,SAAgB,EAAe,EAC7B,WAAA,GACA,YAAA,GACA,UAAA,EAAA,GAMC;AACD,QAAM,IAAe,EAAuB,IAAI,GAC1C,IAAa,EAAuB,IAAI,GACxC,IAAS,EAAgC,MAAM,GAC/C,IAAe,EAAiB;AAEtC,SAAA,EAAA,MAAgB;AACd,UAAM,IAAY,EAAa,SACzB,IAAU,EAAW;AAC3B,QAAI,CAAC,KAAa,CAAC,EAAS;AAE5B,QAAI,IAA+C;AAEnD,UAAM,IAAW,IAAI,eAAA,CAAgB,MAAY;AAC/C,YAAM,IAAM,EAAQ,CAAA,GAAI,gBAAgB,CAAA,GAClC,IAAO,IAAM,EAAI,YAAY,EAAQ,cACrC,IAAU,EAAO,IAAI;AAC3B,UAAI,MAAY,UAAU,GAAc;AACtC,QAAA,GAAW,KAAK,GAChB,IAAY,MACZ,EAAU,MAAM,WAAW,IAC3B,EAAO,IAAI,CAAI;AACf;AAAA,MACF;AACA,MAAI,CAAC,KAAa,KAAK,IAAI,IAAU,CAAI,IAAI,QAC7C,EAAU,MAAM,WAAW,UAC3B,GAAW,KAAK,GAChB,IAAY,EAAQ,GAAQ,GAAM;AAAA,QAChC,GAAI,KAAc;AAAA,QAElB,YAAA,MAAkB;AAChB,UAAA,IAAY,MACZ,EAAU,MAAM,WAAW;AAAA,QAC7B;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AACD,WAAA,EAAS,QAAQ,CAAO,GAExB,MAAa;AACX,MAAA,EAAS,WAAW,GACpB,GAAW,KAAK;AAAA,IAClB;AAAA,EACF,GAAG;AAAA,IAAC;AAAA,IAAQ;AAAA,IAAc;AAAA,EAAU,CAAC,GAGnC,gBAAA,EAAC,EAAO,KAAR;AAAA,IACE,KAAK;AAAA,IAKL,WAAU;AAAA,IACV,OAAO,EAAE,QAAA,EAAO;AAAA,IAEhB,UAAA,gBAAA,EAAC,OAAD;AAAA,MAAK,KAAK;AAAA,MAAuB,WAAA;AAAA,MAC9B,UAAA;AAAA,IACE,CAAA;AAAA,EACK,CAAA;AAEhB"}