@factorialco/f0-react 6.98.0 → 6.100.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.
@@ -1,3 +1,6 @@
1
+ import { AiCalloutAction as AiCalloutAction_2 } from './types';
2
+ import { AiCalloutFinding as AiCalloutFinding_2 } from './types';
3
+ import { AiCalloutStatus as AiCalloutStatus_2 } from './types';
1
4
  import { AlertAvatarProps as AlertAvatarProps_2 } from './F0AvatarAlert';
2
5
  import { AlertTagCellValue } from './types/alertTag';
3
6
  import { AlertTagCellValue as AlertTagCellValue_2 } from './experimental';
@@ -28,6 +31,7 @@ import { CompoundCellValue } from './types/compound';
28
31
  import { Context } from 'react';
29
32
  import { CountCellValue } from './types/count';
30
33
  import { CountryCellValue } from './types/country';
34
+ import { DataAttributes as DataAttributes_2 } from './experimental';
31
35
  import { DateCellValue } from './types/date';
32
36
  import { DateCellValue as DateCellValue_2 } from './experimental';
33
37
  import { DateFilterOptions } from './DateFilter/DateFilter';
@@ -62,6 +66,7 @@ import { HTMLAttributeAnchorTarget } from 'react';
62
66
  import { HTMLAttributes } from 'react';
63
67
  import { HTMLInputTypeAttribute } from 'react';
64
68
  import { IconCellValue } from './types/icon';
69
+ import { IconType as IconType_2 } from './experimental';
65
70
  import { InFilterOptions } from './InFilter/types';
66
71
  import { ItemProps } from './types';
67
72
  import { JSONContent } from '@tiptap/react';
@@ -445,6 +450,252 @@ declare type AIButton = {
445
450
  editable?: boolean;
446
451
  };
447
452
 
453
+ export declare type AiCalloutAction = {
454
+ label: string;
455
+ onClick: () => void;
456
+ icon?: IconType;
457
+ disabled?: boolean;
458
+ };
459
+
460
+ /**
461
+ * One entry in a stacked callout. Each finding is resolved on its own, so each
462
+ * carries its own action — "Review" on a duplicate invoice does something
463
+ * different from "Review" on a tax mismatch.
464
+ */
465
+ export declare type AiCalloutFinding = {
466
+ /**
467
+ * Stable across renders. Findings are resolved and removed one at a time, so
468
+ * an index would re-key the survivors and animate the wrong rows out.
469
+ */
470
+ id: string;
471
+ title: string;
472
+ description: ReactNode;
473
+ action?: AiCalloutAction;
474
+ };
475
+
476
+ declare type AiCalloutSharedProps = DataAttributes_3 & {
477
+ /**
478
+ * Required on purpose — there is no safe default. Defaulting a blocking
479
+ * finding to a mild status is the one mistake nobody catches in review,
480
+ * because the callout still looks correct.
481
+ *
482
+ * One callout is **one evaluation with one severity**, whether it carries a
483
+ * single verdict or a list of findings. Mixed severity is two callouts, not
484
+ * one: "Suggestions to review" in `warning` beside "Issues to resolve" in
485
+ * `critical`, which is how the design draws it.
486
+ */
487
+ status: AiCalloutStatus;
488
+ /**
489
+ * A single verdict ("Possible duplicate") when the callout carries one, or
490
+ * what the list adds up to ("Issues to resolve") when it stacks.
491
+ *
492
+ * **This is the only text in the tinted zone, and it is always about the
493
+ * record — never about One and never the record's identity.** Both are
494
+ * already on screen: the byline says who produced this, and the page says
495
+ * which record it is. "One drafted a resolution plan" spends the coloured
496
+ * zone re-announcing the byline; "Six steps to set up this workstation" says
497
+ * what the reader is looking at. It carries the colour because it is the one
498
+ * line that carries severity, so it has to be the conclusion, not the
499
+ * provenance.
500
+ */
501
+ title: string;
502
+ /**
503
+ * Overrides the glyph the status would pick. Required for `neutral`, which
504
+ * has no semantic glyph of its own — pass one that describes the content
505
+ * (e.g. `Summary` from `@/icons/ai`).
506
+ */
507
+ icon?: IconType;
508
+ };
509
+
510
+ declare type AiCalloutSingleProps = AiCalloutSharedProps & {
511
+ /**
512
+ * The reason, in one line. "Two of five policy checks failed."
513
+ *
514
+ * **This is the title of the white card**, and the split from the tinted one
515
+ * is by job, not by importance: up there is *what it is*, down here is *why*.
516
+ * Same size and weight on purpose — they are one sentence broken in two, not
517
+ * a heading and a subheading — which is exactly why they must not be two
518
+ * nouns of the same kind. Never a score, a count or a status word here.
519
+ *
520
+ * There are four prose jobs in this shape and each slot gets exactly one:
521
+ * `title` is the verdict, this is the reason, `children` is the nuance that
522
+ * changes what the reader does, and `evidence` is the proof. The test: read
523
+ * only the emphasised text — `title` plus this — and it has to stand alone as
524
+ * a decision. "Rejection recommended · Two of five policy checks failed"
525
+ * does; "Rejection recommended · Client lunch · $712.65" does not, which is
526
+ * why this must not carry the record's identity. The page around the callout
527
+ * already says which expense this is.
528
+ */
529
+ summary?: string;
530
+ /** The reasoning behind the verdict. Accepts a list when there is more than one reason. */
531
+ children: ReactNode;
532
+ /**
533
+ * **The move the verdict recommends**, rendered outlined. That binding is the
534
+ * rule: if the reasoning above actually concludes something else, the verdict
535
+ * is wrong, not the button. A callout titled "Rejection recommended" whose
536
+ * outlined action is "Request changes" is telling the reader two different
537
+ * things and making them guess which one One meant.
538
+ */
539
+ action?: AiCalloutAction;
540
+ /**
541
+ * **The way out of the recommendation** — "Approve anyway" against "Reject".
542
+ * Ghost, so the pair reads as a hierarchy and not as two peers.
543
+ *
544
+ * It has to be the *override*, not a third option. Pairing "Reject" with
545
+ * "Request changes" looks like two buttons but is really three paths with one
546
+ * missing, and the reader cannot tell which of them One is recommending.
547
+ *
548
+ * This reopens the "one action, and only one" rule on purpose. That rule was
549
+ * right for a plain callout, where two outlined buttons were noise for a
550
+ * message with no room to justify either. A recommendation with an auditable
551
+ * rationale is the case the rule pointed at: a decision that needs two paths,
552
+ * somewhere that has the room to explain them.
553
+ */
554
+ secondaryAction?: AiCalloutAction;
555
+ /** Dismisses the callout. Acts on the container, so it lives in the header. */
556
+ onClose?: () => void;
557
+ /**
558
+ * The reasoning that led to the verdict, revealed on demand. The header
559
+ * gains a toggle; nothing in the body is truncated or clamped, so the
560
+ * description stays fully readable whether this is open or closed.
561
+ */
562
+ evidence?: {
563
+ /**
564
+ * **Names what is behind the disclosure, as a noun phrase** — "the 5
565
+ * checks", "the six steps", "why this was rejected". The component supplies
566
+ * the verb, so it renders as "See the 5 checks" closed and "Hide the 5
567
+ * checks" open.
568
+ *
569
+ * It is required because a bare chevron says "there is more", which is what
570
+ * a list of separate recommendations says too; naming the content is what
571
+ * tells the reader these are not more verdicts. Splitting it this way is
572
+ * also what keeps the label honest: the product cannot pass a verb, so the
573
+ * label can only ever name something.
574
+ */
575
+ name: string;
576
+ /**
577
+ * One line per step of the reasoning. Plain nodes rather than
578
+ * title/description pairs: a policy check is usually a single fact, and
579
+ * splitting it in two padded "Receipt verified / Passed." into a heading
580
+ * with a body. Emphasis goes inline, where the number or the rule actually
581
+ * is, instead of always landing on the check's name.
582
+ *
583
+ * They carry no action, and that absence is the contract: the day one
584
+ * needs a button it has become a finding, and the callout should carry
585
+ * `findings`. Work with no button is still fine here — see `kind`.
586
+ */
587
+ items: ReactNode[];
588
+ /**
589
+ * What the disclosure holds, which is the one thing the label cannot
590
+ * enforce on its own.
591
+ *
592
+ * `rationale` (the default) is why the verdict is the verdict: sentences,
593
+ * bulleted, read once and never touched again.
594
+ *
595
+ * `steps` is a plan the reader works through, and the only difference is
596
+ * the marker: numbered, because the order is part of the content — you
597
+ * confirm the device before you order it. Numbers do that job on their own,
598
+ * which is why there are no checkboxes here. Per-item state is work the
599
+ * record already tracks better than a message can, and a message that
600
+ * remembers things is no longer a message.
601
+ *
602
+ * The contract above holds in both: no CTA per item. A step is work the
603
+ * reader does elsewhere, over hours or days, and the moment one needs its
604
+ * own button this is `findings`.
605
+ */
606
+ kind?: "rationale" | "steps";
607
+ };
608
+ /**
609
+ * Uncontrolled initial state of the rationale. Defaults to folded, which is
610
+ * the opposite of the stacked default and deliberately so: here the verdict
611
+ * is already on screen and the reasoning is optional, so opening it is the
612
+ * reader's move, not ours.
613
+ */
614
+ defaultOpen?: boolean;
615
+ /** Controlled state. */
616
+ open?: boolean;
617
+ onOpenChange?: (open: boolean) => void;
618
+ findings?: never;
619
+ };
620
+
621
+ declare interface AiCalloutSkeletonProps {
622
+ status?: AiCalloutStatus;
623
+ /** Drops the footer, for callouts that will load without an action. */
624
+ compact?: boolean;
625
+ }
626
+
627
+ declare type AiCalloutStackedProps = AiCalloutSharedProps & {
628
+ /**
629
+ * Switches the callout to its stacked layout: the byline moves up beside the
630
+ * title because the whole evaluation shares one provenance, each finding gets
631
+ * its own row and its own action, and the header gains a toggle. Passing the
632
+ * list is what turns this on — there is no `stacked` flag, because the product
633
+ * already knows whether it holds one verdict or several.
634
+ *
635
+ * **Order matters.** `findings[0]` is the headline: it stays on screen when
636
+ * the rest are folded, so it is the one row the reader is guaranteed to see.
637
+ * Sort by severity, not by detection order.
638
+ *
639
+ * A list of one is a valid state, not a degenerate case: an evaluation that
640
+ * started with four findings and has had three resolved should not change
641
+ * shape on the last one. It simply loses the toggle and the deck, since
642
+ * folding would hide nothing.
643
+ */
644
+ findings: AiCalloutFinding[];
645
+ /**
646
+ * Uncontrolled initial state. Defaults to open — a folded finding is a
647
+ * finding nobody read. Folded still shows the headline row behind a deck edge,
648
+ * never just the header.
649
+ */
650
+ defaultOpen?: boolean;
651
+ /** Controlled state, for folding several callouts together. */
652
+ open?: boolean;
653
+ onOpenChange?: (open: boolean) => void;
654
+ children?: never;
655
+ summary?: never;
656
+ action?: never;
657
+ secondaryAction?: never;
658
+ /**
659
+ * A stacked callout already is its own list. Evidence is the other shape:
660
+ * one verdict whose reasoning can be audited.
661
+ */
662
+ evidence?: never;
663
+ /**
664
+ * Not available while stacked, and the fold is why. Folding keeps the headline
665
+ * finding on screen, so there is deliberately no state in which the callout
666
+ * shows nothing — one that can be reduced to a tinted strip with no finding on
667
+ * it is dismissable under another name, and unresolved findings would go with
668
+ * it.
669
+ */
670
+ onClose?: never;
671
+ };
672
+
673
+ export declare type AiCalloutStatus = (typeof aiCalloutStatuses)[number];
674
+
675
+ /**
676
+ * How much the message matters, from a report the reader can skim to something
677
+ * they have to act on now.
678
+ *
679
+ * | status | use it when | example |
680
+ * | ---------- | --------------------------------------------- | --------------------------- |
681
+ * | `neutral` | nothing is asked of the reader | Summary of a device history |
682
+ * | `info` | there is something to do, nothing is wrong | 5 invoices linked |
683
+ * | `positive` | One endorses what the reader already did | Approval recommended |
684
+ * | `warning` | something may be wrong — look | Requires review |
685
+ * | `critical` | something is wrong — act | Request repayment |
686
+ *
687
+ * `neutral` or `info` is the only pair worth spelling out. `neutral` is the
688
+ * absence of a status — 4% surface, uncoloured title, no glyph of its own —
689
+ * and means there is nothing to do at all, so passing it an `action` warns in
690
+ * development. `info` means the reader has work even when there is no button
691
+ * to offer: the work is often elsewhere, and the button is a convenience,
692
+ * never what earns the colour.
693
+ *
694
+ * One callout is **one evaluation with one severity**. Mixed severity is two
695
+ * callouts, not one.
696
+ */
697
+ export declare const aiCalloutStatuses: readonly ["neutral", "info", "positive", "warning", "critical"];
698
+
448
699
  /**
449
700
  * Credits configuration for the AI chat.
450
701
  * Groups all credits-related props into a single object.
@@ -4071,7 +4322,7 @@ declare type Data<R extends RecordType> = {
4071
4322
  */
4072
4323
  export declare type DataAdapter<R extends RecordType, Filters extends FiltersDefinition> = BaseDataAdapter<R, Filters, BaseFetchOptions<Filters>, BaseResponse<R>> | PaginatedDataAdapter<R, Filters, PaginatedFetchOptions<Filters>, PaginatedResponse<R>>;
4073
4324
 
4074
- declare type DataAttributes_2 = {
4325
+ declare type DataAttributes_3 = {
4075
4326
  [key: `data-${string}`]: string | undefined;
4076
4327
  };
4077
4328
 
@@ -5243,6 +5494,11 @@ declare const defaultTranslations: {
5243
5494
  readonly thinking: "Thinking...";
5244
5495
  readonly thinkingElapsedSeconds: "{{seconds}}s";
5245
5496
  readonly thinkingElapsedMinutes: "{{minutes}}m {{seconds}}s";
5497
+ readonly attribution: "Suggested by One";
5498
+ readonly evidence: {
5499
+ readonly show: "See {{name}}";
5500
+ readonly hide: "Hide {{name}}";
5501
+ };
5246
5502
  readonly feedbackModal: {
5247
5503
  readonly positive: {
5248
5504
  readonly title: "What did you like about this response?";
@@ -6141,7 +6397,7 @@ declare type DropdownInternalProps = {
6141
6397
  * @default false
6142
6398
  */
6143
6399
  disabled?: boolean;
6144
- } & DataAttributes_2;
6400
+ } & DataAttributes_3;
6145
6401
 
6146
6402
  export declare type DropdownItem = DropdownItemObject | DropdownItemSeparator | DropdownItemLabel;
6147
6403
 
@@ -6634,12 +6890,73 @@ export declare interface F0ActionBarRef {
6634
6890
  wiggle: (options?: WiggleOptions) => void;
6635
6891
  }
6636
6892
 
6893
+ /**
6894
+ * @deprecated Use `F0AiCallout` instead.
6895
+ *
6896
+ * It carries no status, so it cannot say how much a message matters, and it
6897
+ * signals "this came from AI" with a gradient instead — two signals for one
6898
+ * message, drawn from raw hex rather than tokens, so it cannot follow a theme.
6899
+ * Its two actions are both outlined, which reads as two peers where there is
6900
+ * really a recommendation and a way out of it.
6901
+ *
6902
+ * `F0AiCallout` says where the message came from in words, in every shape, and
6903
+ * `status="neutral"` is the rung for exactly this case: AI output with nothing
6904
+ * to decide.
6905
+ *
6906
+ * @removeIn 7.0.0
6907
+ * @migration `title` unchanged. `content` becomes `children` and takes nodes
6908
+ * rather than a string. Add `status="neutral"` with an `icon` that describes
6909
+ * the content (e.g. `Summary` from `@/icons/ai`) — `neutral` has no glyph of
6910
+ * its own. `primaryAction` becomes `action` and `secondaryAction` stays, but
6911
+ * only when it is the way out of the first rather than a second peer.
6912
+ * `F0AiBanner.Skeleton` becomes `F0AiCallout.Skeleton`.
6913
+ */
6637
6914
  export declare const F0AiBanner: ForwardRefExoticComponent<Omit<AiBannerInternalProps & RefAttributes<HTMLDivElement> & WithDataTestIdProps_2, "ref"> & RefAttributes<HTMLDivElement>> & Pick<ForwardRefExoticComponent<AiBannerInternalProps & RefAttributes<HTMLDivElement>>, never> & {
6638
6915
  Skeleton: ({ compact }: AiBannerSkeletonProps) => JSX_2.Element;
6639
6916
  };
6640
6917
 
6641
6918
  export declare type F0AiBannerProps = AiBannerInternalProps;
6642
6919
 
6920
+ export declare const F0AiCallout: ForwardRefExoticComponent<(Omit<DataAttributes_2 & {
6921
+ status: AiCalloutStatus_2;
6922
+ title: string;
6923
+ icon?: IconType_2;
6924
+ } & {
6925
+ summary?: string;
6926
+ children: ReactNode;
6927
+ action?: AiCalloutAction_2;
6928
+ secondaryAction?: AiCalloutAction_2;
6929
+ onClose?: () => void;
6930
+ evidence?: {
6931
+ name: string;
6932
+ items: ReactNode[];
6933
+ kind?: "rationale" | "steps";
6934
+ };
6935
+ defaultOpen?: boolean;
6936
+ open?: boolean;
6937
+ onOpenChange?: (open: boolean) => void;
6938
+ findings?: never;
6939
+ } & RefAttributes<HTMLDivElement> & WithDataTestIdProps_2, "ref"> | Omit<DataAttributes_2 & {
6940
+ status: AiCalloutStatus_2;
6941
+ title: string;
6942
+ icon?: IconType_2;
6943
+ } & {
6944
+ findings: AiCalloutFinding_2[];
6945
+ defaultOpen?: boolean;
6946
+ open?: boolean;
6947
+ onOpenChange?: (open: boolean) => void;
6948
+ children?: never;
6949
+ summary?: never;
6950
+ action?: never;
6951
+ secondaryAction?: never;
6952
+ evidence?: never;
6953
+ onClose?: never;
6954
+ } & RefAttributes<HTMLDivElement> & WithDataTestIdProps_2, "ref">) & RefAttributes<HTMLDivElement>> & Pick<ForwardRefExoticComponent<F0AiCalloutProps & RefAttributes<HTMLDivElement>>, never> & {
6955
+ Skeleton: ({ status, compact }: AiCalloutSkeletonProps) => JSX_2.Element;
6956
+ };
6957
+
6958
+ export declare type F0AiCalloutProps = AiCalloutSingleProps | AiCalloutStackedProps;
6959
+
6643
6960
  /**
6644
6961
  * A card shown below the composer on the fullscreen welcome screen, rendered
6645
6962
  * as an `F0CardHorizontal`. Each card owns its behavior via `onClick`, so
@@ -6988,6 +7305,26 @@ declare type F0ButtonToggleInternalProps = {
6988
7305
 
6989
7306
  export declare type F0ButtonToggleProps = Omit<F0ButtonToggleInternalProps, (typeof privateProps_2)[number]>;
6990
7307
 
7308
+ /**
7309
+ * @deprecated Use `F0AiCallout` instead.
7310
+ *
7311
+ * `F0AiCallout` is the same construction — tinted container, white card, action
7312
+ * row — brought in line with the design, and it fixes two things this one gets
7313
+ * wrong: `critical` renders with no icon and an uncoloured title (the strongest
7314
+ * status is the only one that isn't signalled), and the `ai` variant stacks a
7315
+ * gradient on top of a semantic colour, which is two signals for one message.
7316
+ * It also makes attribution structural: the byline is always rendered, so the
7317
+ * callout can never fail to say where it came from.
7318
+ *
7319
+ * @removeIn 7.0.0
7320
+ * @migration Replace `F0Callout` with `F0AiCallout` from the same entry point.
7321
+ * `variant` becomes `status`, and `variant="ai"` becomes `status="neutral"`,
7322
+ * which additionally requires an `icon` because `neutral` has no glyph of its
7323
+ * own. `children` is unchanged. `actions: [a, b]` becomes `action={a}` plus
7324
+ * `secondaryAction={b}`, and only when the second is the way out of the first
7325
+ * rather than a third path — otherwise drop it. Remove nothing for the byline:
7326
+ * it is not a prop, every `F0AiCallout` renders it.
7327
+ */
6991
7328
  export declare const F0Callout: ForwardRefExoticComponent<Omit<CalloutInternalProps & RefAttributes<HTMLDivElement> & WithDataTestIdProps_2, "ref"> & RefAttributes<HTMLDivElement>> & Pick<ForwardRefExoticComponent<CalloutInternalProps & RefAttributes<HTMLDivElement>>, never> & {
6992
7329
  Skeleton: ({ compact, variant }: CalloutSkeletonProps) => JSX_2.Element;
6993
7330
  };
@@ -8928,7 +9265,7 @@ compact?: boolean;
8928
9265
  }) => JSX_2.Element;
8929
9266
  }>;
8930
9267
 
8931
- export declare interface F0MeetingCardProps extends WithDataTestIdProps, DataAttributes_2 {
9268
+ export declare interface F0MeetingCardProps extends WithDataTestIdProps, DataAttributes_3 {
8932
9269
  /** Lifecycle of the meeting. See {@link meetingStates}. */
8933
9270
  state: MeetingState;
8934
9271
  /**
@@ -12029,7 +12366,7 @@ export declare type NavigationGranularityKey = GranularityDefinitionKey | "perio
12029
12366
 
12030
12367
  declare type NavigationItem = Pick<LinkProps, "href" | "exactMatch" | "onClick"> & {
12031
12368
  label: string;
12032
- } & DataAttributes_2;
12369
+ } & DataAttributes_3;
12033
12370
 
12034
12371
  export declare type NavigationProps = {
12035
12372
  previous?: NavigationTarget;
@@ -14592,7 +14929,7 @@ export declare const Switch: typeof _Switch;
14592
14929
 
14593
14930
  declare function _Switch({ title, onCheckedChange, id, disabled, checked, value, hideLabel, presentational, required, ...rest }: SwitchProps): JSX_2.Element;
14594
14931
 
14595
- declare interface SwitchProps extends DataAttributes_2 {
14932
+ declare interface SwitchProps extends DataAttributes_3 {
14596
14933
  /**
14597
14934
  * The title of the switch
14598
14935
  */
@@ -14641,7 +14978,7 @@ export declare type TabItem = {
14641
14978
  index?: boolean;
14642
14979
  variant?: "default" | "upsell";
14643
14980
  onClick?: () => void;
14644
- } & DataAttributes_2 & ({
14981
+ } & DataAttributes_3 & ({
14645
14982
  href: string;
14646
14983
  } | {
14647
14984
  id: string;