@factorialco/f0-react 7.33.0 → 7.34.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 (45) hide show
  1. package/dist/{ChatPdfThumbnail-CewvkWu-.js → ChatPdfThumbnail-CFEB3FYp.js} +1 -1
  2. package/dist/{ChatPostComposerDialog-CKwdWt5B.js → ChatPostComposerDialog-DnuStGGi.js} +3 -3
  3. package/dist/{DocumentToolbar-BdgPc16e.js → DocumentToolbar-BT7Ks9jN.js} +2 -2
  4. package/dist/{DocxViewer-HWpF_G9w.js → DocxViewer-DzCul5m1.js} +2 -2
  5. package/dist/{F0AiProcessingOverlay-DxlgF3Pt.js → F0AiProcessingOverlay-C3q5kdSu.js} +960 -957
  6. package/dist/{F0CanvasPanel-BCZjxhVB.js → F0CanvasPanel-DB32LsaK.js} +12768 -12684
  7. package/dist/{F0Map-DZtgpSnS.js → F0Map-CFivWqOr.js} +4 -4
  8. package/dist/{F0VideoPlayer-EqXupZV9.js → F0VideoPlayer-C5TOVGjz.js} +356 -377
  9. package/dist/{MapProvider-C4K2ey4N.js → MapProvider-COBzcEBa.js} +214 -189
  10. package/dist/{SheetViewer-yK40OmE1.js → SheetViewer-Bvv7GLJ5.js} +2 -2
  11. package/dist/{TextViewer-BYFQn6S1.js → TextViewer-CTLt0pvu.js} +2 -2
  12. package/dist/ai.d.ts +13 -8
  13. package/dist/ai.js +2 -2
  14. package/dist/component-status.d.ts +8 -8
  15. package/dist/component-status.js +1 -1
  16. package/dist/{experimental-BKF7swb0.js → experimental-B0saLXEl.js} +11986 -11293
  17. package/dist/experimental.d.ts +387 -40
  18. package/dist/experimental.js +280 -278
  19. package/dist/f0.d.ts +13 -8
  20. package/dist/f0.js +10 -10
  21. package/dist/i18n-provider-defaults.d.ts +13 -8
  22. package/dist/i18n-provider-defaults.js +8 -0
  23. package/dist/{index-C_LLYE_o.js → index-AqJa6oaL.js} +3 -3
  24. package/dist/{index-BzA0lEl1.js → index-BdKI708R.js} +2 -2
  25. package/dist/index-C2VXFg3o.js +4 -0
  26. package/dist/{index-DlMbfdLc.js → index-Dq029AUw.js} +1 -1
  27. package/dist/{index-Ca0rOdez.js → index-H07Crbx2.js} +3 -3
  28. package/dist/{pdfWorker-CA3xmb-5.js → pdfWorker-CJFmh5Jp.js} +2 -2
  29. package/dist/styles.css +1 -1
  30. package/icons/app/Floating.d.ts.map +1 -1
  31. package/icons/app/Floating.js +1 -1
  32. package/icons/app/Fullscreen.d.ts +4 -0
  33. package/icons/app/Fullscreen.d.ts.map +1 -0
  34. package/icons/app/Fullscreen.js +5 -0
  35. package/icons/app/PanelLeft.d.ts +4 -0
  36. package/icons/app/PanelLeft.d.ts.map +1 -0
  37. package/icons/app/PanelLeft.js +5 -0
  38. package/icons/app/PanelRight.d.ts +4 -0
  39. package/icons/app/PanelRight.d.ts.map +1 -0
  40. package/icons/app/PanelRight.js +5 -0
  41. package/icons/app/index.d.ts +3 -0
  42. package/icons/app/index.d.ts.map +1 -1
  43. package/icons/app/index.js +3 -0
  44. package/package.json +2 -2
  45. package/dist/index-Bt9DLm3D.js +0 -4
@@ -1682,9 +1682,18 @@ declare interface BreakType {
1682
1682
  }
1683
1683
 
1684
1684
  /**
1685
- * Flattens the roster into tiles, preserving the host's participant order.
1685
+ * Flattens the roster into tiles: shares, then everyone else, then you.
1686
+ *
1686
1687
  * Screen shares come first so they are never pushed off the visible page by a
1687
- * long roster.
1688
+ * long roster — your own included, because when you share, what you are
1689
+ * sharing is the thing the room is looking at.
1690
+ *
1691
+ * YOUR CAMERA GOES LAST, and it is the one place the host's order is not
1692
+ * preserved. Without it a one-to-one traded sides: the spotlight rule puts the
1693
+ * other person on the left, while the plain grid took the roster order, which
1694
+ * puts you first — so pinning and unpinning swapped the two of you over. Two
1695
+ * rules ordering the same room. This is the rule they now share, and it reads
1696
+ * the same way everywhere: the people you are talking to lead, you follow.
1688
1697
  */
1689
1698
  export declare const buildTiles: (participants: F0MeetingParticipant[]) => F0MeetingTile[];
1690
1699
 
@@ -6107,12 +6116,15 @@ declare const defaultTranslations: {
6107
6116
  readonly muted: "Muted";
6108
6117
  readonly waitingToJoin: "Waiting…";
6109
6118
  readonly sharingScreen: "Sharing screen";
6119
+ readonly audioRoom: "People in this call";
6110
6120
  readonly chatPanel: "Chat";
6111
6121
  readonly transcriptPanel: "Transcript";
6112
6122
  readonly notesPanel: "Notes";
6113
6123
  readonly openChat: "Open chat";
6114
6124
  readonly closeChat: "Close chat";
6115
6125
  readonly closePanel: "Close panel";
6126
+ readonly resizeChatPanel: "Resize chat panel";
6127
+ readonly chatPanelWidth: "{{width}} pixels";
6116
6128
  readonly notesPlaceholder: "Take notes for everyone in the call…";
6117
6129
  readonly roomChatPlaceholder: "Message this call…";
6118
6130
  readonly roomChatEmpty: "Messages here are only for this call and disappear when it ends.";
@@ -6175,6 +6187,8 @@ declare const defaultTranslations: {
6175
6187
  readonly movedToFloating: "Meeting in a floating window";
6176
6188
  readonly movedToSidePanel: "Meeting in the side panel";
6177
6189
  readonly movedToMinimized: "Meeting minimized";
6190
+ readonly audioOnlyAnnouncement: "Audio only. There is not enough room for video";
6191
+ readonly videoResumed: "Video is back";
6178
6192
  readonly movedInline: "Meeting on the page";
6179
6193
  readonly movedToPictureInPicture: "Meeting in a picture-in-picture window";
6180
6194
  };
@@ -7274,6 +7288,18 @@ declare type ExtractVisualizationSettings<T> = T extends {
7274
7288
  };
7275
7289
  } ? S : never;
7276
7290
 
7291
+ /**
7292
+ * WHERE A HOST HANGS SOMETHING OFF THE CONVERSATION'S NAME — a coachmark
7293
+ * explaining a limit, a tour step, a hint. F0 owns the header's markup, so it
7294
+ * owns the promise that there is a stable thing to point at; a host guessing
7295
+ * at class names would break on the next restyle.
7296
+ *
7297
+ * It resolves ONLY once the title has arrived (the skeleton does not carry it),
7298
+ * which is what makes an overlay anchored to it wait for a header worth
7299
+ * pointing at instead of opening over a pulsing grey bar.
7300
+ */
7301
+ export declare const F0_CHAT_HEADER_TITLE_SELECTOR = "[data-f0-chat-header-title]";
7302
+
7277
7303
  export declare const F0ActionBar: WithDataTestIdReturnType_2<ForwardRefExoticComponent<F0ActionBarProps & RefAttributes<F0ActionBarRef>>>;
7278
7304
 
7279
7305
  declare interface F0ActionBarProps {
@@ -7969,7 +7995,7 @@ export declare interface F0CarouselDialogProps extends Pick<F0DialogInternalProp
7969
7995
  * the {@link F0ChatRuntime} from a surrounding `F0ChatProvider`. Panel controls
7970
7996
  * (fullscreen / close) are wired by the host so F0Chat stays transport-agnostic.
7971
7997
  */
7972
- export declare const F0Chat: (props: F0ChatProps) => ReactNode;
7998
+ export declare const F0Chat: ({ surface, ...props }: F0ChatProps) => ReactNode;
7973
7999
 
7974
8000
  /** Attachment family, as the transcript classifies it (see
7975
8001
  * `utils/attachments.ts`). Note `video` is not an {@link F0ChatAttachment}
@@ -8469,6 +8495,97 @@ export declare type F0ChatHeaderAction = {
8469
8495
  placement?: "menu" | "inline";
8470
8496
  /** Restrict the action to given channel types. Omit for all of them. */
8471
8497
  channelTypes?: F0ChatChannelType[];
8498
+ /**
8499
+ * TURNS AN INLINE ACTION INTO A TOGGLE, because that is what it has become:
8500
+ * something with an on and an off. Starting a huddle is a button until the
8501
+ * call exists — from then on the same control means "you are in it", and a
8502
+ * reader coming back to the conversation has to be able to see that without
8503
+ * pressing anything.
8504
+ *
8505
+ * Set it and F0 renders a real toggle with its `aria-pressed`, bordered so
8506
+ * the on state reads as a state rather than as a hover that stuck. Leave it
8507
+ * undefined for an action that only ever fires, which is most of them —
8508
+ * `false` is not the same thing as absent here.
8509
+ *
8510
+ * Ignored in the overflow menu: a menu item is a line of text you press, and
8511
+ * it has nowhere to wear a state.
8512
+ */
8513
+ active?: boolean;
8514
+ /** The glyph for the `active` half, when it differs. Omit to keep `icon` in
8515
+ * both states. */
8516
+ activeIcon?: IconType;
8517
+ /**
8518
+ * Marks the action as destructive, so it reads as one in the overflow menu.
8519
+ * Leaving a channel or archiving a conversation is not the same kind of thing
8520
+ * as muting it, and a menu that renders them identically says it is.
8521
+ * Ignored for `inline` actions — the row of icon buttons has no such state.
8522
+ */
8523
+ critical?: boolean;
8524
+ };
8525
+
8526
+ /**
8527
+ * THE HOST'S STATEMENT THAT HISTORY IS BEING WITHHELD. The loaded window has
8528
+ * reached a boundary behind which there IS older history the reader is not
8529
+ * allowed to see — a plan that only includes the last N days, a retention
8530
+ * policy, a legal hold.
8531
+ *
8532
+ * F0 neither computes nor enforces it: the host filters `messages` itself and
8533
+ * sets this together with `hasMoreOlder: false`. It cannot be derived here —
8534
+ * after the host has filtered, "the conversation started 10 days ago" and
8535
+ * "there are three years behind this" look identical from inside the panel.
8536
+ *
8537
+ * ABSENT ⇒ the oldest loaded message is the true beginning, or simply not
8538
+ * loaded yet. A conversation that genuinely started last week must never carry
8539
+ * one: the notice would claim something was taken away when nothing was.
8540
+ *
8541
+ * It is drawn as an `F0Card` whose only control is an upsell button, and the
8542
+ * host owns every part of it. The copy for the same reason
8543
+ * {@link F0ChatChannel.readOnlyNotice} is host-owned: only the host knows which
8544
+ * plan this is, and it is the one with the translations. And the button as the
8545
+ * WHOLE {@link UpsellingButtonProps} surface rather than a bare `onClick`,
8546
+ * because asking for a plan to change is a REQUEST with an outcome — the
8547
+ * loading label, the success and error copy and the next steps its confirmation
8548
+ * dialog shows are all part of what a host configures. An action that merely
8549
+ * navigates sets `showConfirmation: false`.
8550
+ */
8551
+ export declare type F0ChatHistoryLimit = {
8552
+ /** Headline. Says what is missing, not what to buy. */
8553
+ title: string;
8554
+ /** One sentence of context — which window is included, what lies behind it. */
8555
+ description?: string;
8556
+ /** Mark shown beside the copy. */
8557
+ icon?: IconType;
8558
+ /** The upsell request, whole — see above. */
8559
+ action: UpsellingButtonProps;
8560
+ };
8561
+
8562
+ /**
8563
+ * WHAT A CONVERSATION WITH A WITHHELD PAST SAYS FOR ITSELF — the card F0 puts
8564
+ * at the top of such a transcript, exported because the host needs THE SAME ONE
8565
+ * for the pop-up it floats over the conversation on arrival.
8566
+ *
8567
+ * Exported rather than left to each host to rebuild: two cards that must look
8568
+ * identical and are written twice are two cards that drift. They differ in one
8569
+ * thing only, and it is the one thing they should differ in — the floating copy
8570
+ * can be dismissed, the one at the top of history cannot. A close button there
8571
+ * would take the explanation away from a boundary the reader reaches again on
8572
+ * the next scroll, and F0 has nowhere to remember that it was closed.
8573
+ *
8574
+ * Its only standing control is an `UpsellingButton`: the request it sends and
8575
+ * everything its confirmation dialog says belong to the host — see
8576
+ * {@link F0ChatHistoryLimit}.
8577
+ */
8578
+ export declare const F0ChatHistoryLimitCard: ({ notice, dismissActions, }: {
8579
+ notice: F0ChatHistoryLimit;
8580
+ /** Rendered after the upsell, in the order given. Omit where there is no way
8581
+ * out — see above. */
8582
+ dismissActions?: F0ChatHistoryLimitDismissAction[];
8583
+ }) => ReactNode;
8584
+
8585
+ /** A way out of the card, for hosts that render it somewhere dismissable. */
8586
+ export declare type F0ChatHistoryLimitDismissAction = {
8587
+ label: string;
8588
+ onClick: () => void;
8472
8589
  };
8473
8590
 
8474
8591
  export declare type F0ChatImageAttachment = {
@@ -8852,11 +8969,22 @@ export declare type F0ChatPostRequiredAction = {
8852
8969
  };
8853
8970
 
8854
8971
  export declare type F0ChatProps = {
8855
- /** Whether the hosting panel is in fullscreen (controls the header toggle icon). */
8972
+ /**
8973
+ * Where the chat is mounted — see {@link F0ChatSurface}. On `"page"` the
8974
+ * panel controls below are ignored, not merely unused: a conversation that is
8975
+ * the page has nothing to close and nowhere to expand to, and leaving that to
8976
+ * the convention of "don't pass the callback" is how it comes back.
8977
+ * @default "panel"
8978
+ */
8979
+ surface?: F0ChatSurface;
8980
+ /** Whether the hosting panel is in fullscreen (controls the header toggle
8981
+ * icon). Ignored on the `page` surface. */
8856
8982
  isFullscreen?: boolean;
8857
- /** Toggle the hosting panel's fullscreen. Hidden when omitted. */
8983
+ /** Toggle the hosting panel's fullscreen. Hidden when omitted, and always on
8984
+ * the `page` surface. */
8858
8985
  onToggleFullscreen?: () => void;
8859
- /** Close the hosting panel. Hidden when omitted. */
8986
+ /** Close the hosting panel. Hidden when omitted, and always on the `page`
8987
+ * surface. */
8860
8988
  onClose?: () => void;
8861
8989
  /**
8862
8990
  * Host-provided header actions (pin, mute, edit group…). Search is the only
@@ -8874,6 +9002,43 @@ export declare type F0ChatProps = {
8874
9002
  * Undefined keeps the default header, so no existing usage changes.
8875
9003
  */
8876
9004
  header?: ReactNode | null;
9005
+ /**
9006
+ * Host chrome pinned to the END of the built-in header's action row, after
9007
+ * the overflow menu and any inline actions.
9008
+ *
9009
+ * Not an `F0ChatHeaderAction`: those are things you do TO the conversation,
9010
+ * and they are labels and icons F0 lays out. This is a rendered control that
9011
+ * belongs to the app around the chat — the One switch on a full-page
9012
+ * conversation, where there is no page header left to carry it.
9013
+ *
9014
+ * Ignored when `header` replaces the built-in one; that host already owns
9015
+ * the whole row.
9016
+ */
9017
+ headerContent?: ReactNode;
9018
+ /**
9019
+ * THE HOST'S POP-UP OVER THE TOP OF THE CONVERSATION — full width, floating.
9020
+ *
9021
+ * Where a host says something ABOUT the conversation rather than in it:
9022
+ * "older messages aren't included in your plan", "this channel is archived on
9023
+ * Friday". It sits under the header and over the transcript, the width of the
9024
+ * panel, and it is the shape a warning like that wants: a popover anchored to
9025
+ * something in the header would be a fixed-width panel with an arrow pointing
9026
+ * at a title that has nothing to do with what it says.
9027
+ *
9028
+ * IT FLOATS, and that is the point. Taking layout space would push the whole
9029
+ * transcript down on arrival and pull it back up on dismissal — the reader's
9030
+ * place in the conversation moving twice for a message they are about to
9031
+ * close. Floating also means the virtualizer never measures around it, and
9032
+ * the sticky date pill steps below it on its own
9033
+ * (`CHAT_NOTICE_HEIGHT_PROPERTY`).
9034
+ *
9035
+ * It survives scrolling: this is a standing fact about the conversation, not
9036
+ * something tied to where the reader is in it. Dismissing is the host's — F0
9037
+ * renders what it is handed and remembers nothing, because when it shows and
9038
+ * whether a dismissal outlives the session both depend on things F0 cannot
9039
+ * see.
9040
+ */
9041
+ notice?: ReactNode;
8877
9042
  };
8878
9043
 
8879
9044
  /**
@@ -8919,6 +9084,17 @@ export declare type F0ChatRuntime = {
8919
9084
  typingUsers: F0ChatUser[];
8920
9085
  hasMoreOlder: boolean;
8921
9086
  loadingOlder: boolean;
9087
+ /**
9088
+ * Set ONLY once the window has reached a boundary the plan (or a retention
9089
+ * rule) puts on history — see {@link F0ChatHistoryLimit}. F0 renders it at
9090
+ * the very top of the transcript, and only in the settled state
9091
+ * (`!hasMoreOlder && !loadingOlder`), so it can never appear above rows that
9092
+ * are still being paginated in.
9093
+ *
9094
+ * It is the host's job to also report `hasMoreOlder: false` here: left true,
9095
+ * the transcript would keep asking for pages it is never going to get.
9096
+ */
9097
+ historyLimit?: F0ChatHistoryLimit;
8922
9098
  /**
8923
9099
  * Whether there are newer messages than the loaded window — true after jumping
8924
9100
  * to an old message (e.g. a search hit), so the transcript isn't anchored to
@@ -9258,6 +9434,20 @@ export declare type F0ChatShelfAction = {
9258
9434
  */
9259
9435
  export declare type F0ChatStatus = "connecting" | "ready" | "reconnecting" | "offline" | "error";
9260
9436
 
9437
+ /**
9438
+ * Where the chat lives, which is the one thing it cannot work out for itself.
9439
+ *
9440
+ * `"panel"` (default) is a card inside the side panel: it can be closed and
9441
+ * expanded, and the panel draws the border around it.
9442
+ *
9443
+ * `"page"` is the main content of a route — the conversation IS the page, so
9444
+ * there is nothing to close and nowhere to expand to. `onClose`,
9445
+ * `onToggleFullscreen` and `isFullscreen` are ignored rather than merely
9446
+ * unused, the side panel is never consulted, and the header draws its own seam
9447
+ * against the transcript in place of the card border it no longer has.
9448
+ */
9449
+ export declare type F0ChatSurface = "panel" | "page";
9450
+
9261
9451
  /**
9262
9452
  * Membership / lifecycle events rendered as a centered system row. Closed
9263
9453
  * union — the host maps unknown transport event kinds to a body-only system
@@ -10926,8 +11116,10 @@ export declare type F0MeetingRuntime = {
10926
11116
  localParticipantId: string;
10927
11117
  /**
10928
11118
  * Everyone in the room INCLUDING the local participant, in a stable order the
10929
- * host controls (join order). F0 owns speaker promotion and pagination on top
10930
- * of this — a host that reorders on every speaker change makes the grid churn.
11119
+ * host controls (join order). F0 owns speaker promotion, pagination and the
11120
+ * local participant's own position on top of this — your camera is always the
11121
+ * last tile, whatever index you are at here. A host that reorders on every
11122
+ * speaker change makes the grid churn.
10931
11123
  */
10932
11124
  participants: F0MeetingParticipant[];
10933
11125
  localMedia: F0MeetingLocalMedia;
@@ -10992,6 +11184,16 @@ export declare type F0MeetingSidePanelTab = {
10992
11184
  export declare type F0MeetingSignal = {
10993
11185
  /** 0..1, smoothed by the host. LiveKit `Participant.audioLevel`. */
10994
11186
  audioLevel: number;
11187
+ /**
11188
+ * Energy per frequency band, 0..1 each, low to high — LiveKit's
11189
+ * `useMultibandTrackVolume`, or an `AnalyserNode` the host already has.
11190
+ *
11191
+ * Optional, and the waveform is honest about it: with a single `audioLevel`
11192
+ * five bars can only be one number drawn five times, so they rise and fall
11193
+ * together. Give it bands and each bar moves on its own, because each one is
11194
+ * actually a different measurement.
11195
+ */
11196
+ bands?: readonly number[];
10995
11197
  isSpeaking: boolean;
10996
11198
  quality: F0MeetingConnectionQuality;
10997
11199
  };
@@ -14452,7 +14654,7 @@ declare type MeetingRoomChatProps = {
14452
14654
  };
14453
14655
 
14454
14656
  /**
14455
- * The in-call panel: chat, transcript and notes beside the grid.
14657
+ * The in-call panel: chat, transcript and notes, beside the grid in fullscreen.
14456
14658
  *
14457
14659
  * F0 owns the bar, the selection and the close button because the control that
14458
14660
  * opens the panel lives in F0's own action bar and needs the tab labels and
@@ -14462,15 +14664,23 @@ declare type MeetingRoomChatProps = {
14462
14664
  * particular: its transcript is virtualized, and measuring rows inside a
14463
14665
  * display:none subtree yields zero heights that the list then has to correct
14464
14666
  * on reveal.
14667
+ *
14668
+ * The width comes from `plan`, never from a class. It used to be a literal
14669
+ * `w-[420px]` paired with a `SIDE_PANEL_WIDTH` nothing read — Tailwind cannot
14670
+ * take a number, the two had to agree, and nothing checked that they did.
14465
14671
  */
14466
- export declare const MeetingSidePanel: ({ panel }: MeetingSidePanelProps) => JSX_2.Element | null;
14672
+ export declare const MeetingSidePanel: ({ panel, plan }: MeetingSidePanelProps) => JSX_2.Element | null;
14467
14673
 
14468
14674
  declare type MeetingSidePanelProps = {
14469
14675
  panel: F0MeetingSidePanel;
14676
+ /** Where it sits and how wide, decided by `planSidePanel` from the room. */
14677
+ plan: SidePanelPlan;
14470
14678
  };
14471
14679
 
14472
14680
  export declare type MeetingSignalStore = F0MeetingSignalStore & {
14473
14681
  setAudioLevel: (participantId: string, level: number) => void;
14682
+ /** Per-band energy for the waveform. See `F0MeetingSignal.bands`. */
14683
+ setAudioBands: (participantId: string, bands: readonly number[]) => void;
14474
14684
  setSpeaking: (participantIds: readonly string[]) => void;
14475
14685
  setQuality: (participantId: string, quality: F0MeetingConnectionQuality) => void;
14476
14686
  remove: (participantId: string) => void;
@@ -14492,9 +14702,11 @@ declare type MeetingSurfaceContextValue = {
14492
14702
  /** What the user chose. Never mutated by the environment. */
14493
14703
  mode: F0MeetingSurfaceDestination;
14494
14704
  /**
14495
- * What actually renders. A small viewport or an unmounted inline slot derives
14496
- * a different mode without destroying the user's preference; so does an open
14497
- * picture-in-picture window, which is `pip` for as long as it is open.
14705
+ * What actually renders. It differs from `mode` for exactly two reasons, and
14706
+ * neither is the size of the screen: a place that is not there (an inline
14707
+ * slot nobody registered, a panel no frame provides) derives to `floating`,
14708
+ * and an open picture-in-picture window is `pip` for as long as it is open.
14709
+ * The user's pick is never overwritten, only stood aside from.
14498
14710
  */
14499
14711
  effectiveMode: F0MeetingSurfaceMode;
14500
14712
  setMode: (mode: F0MeetingSurfaceDestination) => void;
@@ -14506,15 +14718,6 @@ declare type MeetingSurfaceContextValue = {
14506
14718
  settleRect: (rect: F0Rect) => void;
14507
14719
  /** Commit a resize, keeping the current anchor. */
14508
14720
  resizeRect: (rect: F0Rect) => void;
14509
- /** True below the md breakpoint: no dragging, pill instead of window. */
14510
- isCompactViewport: boolean;
14511
- /**
14512
- * The frame's content area. `panel` mode does NOT use it — there the room is
14513
- * the side panel's content and the panel places itself. It is what a window
14514
- * sizes itself against when it has to sit BESIDE the panel (see
14515
- * `fitToContent`), and the viewport when no frame published one.
14516
- */
14517
- panelArea: F0Rect;
14518
14721
  /**
14519
14722
  * Whether there is a side panel for the call to be the content of.
14520
14723
  *
@@ -14524,15 +14727,16 @@ declare type MeetingSurfaceContextValue = {
14524
14727
  * `floating` and the switch stops offering it.
14525
14728
  */
14526
14729
  hasPanelSlot: boolean;
14527
- setPanelSlot: (available: boolean) => void;
14528
- /** Registered by `F0MeetingSlot` so `inline` knows where to fly to. */
14529
- setInlineRect: (rect: F0Rect | null) => void;
14530
14730
  /**
14531
- * The application frame's content region, published by the frame itself. The
14532
- * side panel lives inside it — between the navigation and the content —
14533
- * rather than on top of the whole viewport.
14731
+ * WHICH EDGE the slot is on, or `null` when there is none. The mode switch
14732
+ * draws the panel with the side it actually docks to, so the control shows
14733
+ * where the call is going rather than a generic panel that could be either.
14534
14734
  */
14535
- setFrameRect: (rect: F0Rect | null) => void;
14735
+ panelSide: "left" | "right" | null;
14736
+ /** `null` retires the slot; a side registers one. */
14737
+ setPanelSlot: (side: "left" | "right" | null) => void;
14738
+ /** Registered by `F0MeetingSlot` so `inline` knows where to fly to. */
14739
+ setInlineRect: (rect: F0Rect | null) => void;
14536
14740
  /** What the user asked the spotlight to do, if anything. */
14537
14741
  focusIntent: F0MeetingFocusIntent;
14538
14742
  setFocusIntent: (intent: F0MeetingFocusIntent) => void;
@@ -14541,6 +14745,18 @@ declare type MeetingSurfaceContextValue = {
14541
14745
  setSidePanelOpen: (open: boolean) => void;
14542
14746
  activeTabId: string | null;
14543
14747
  setActiveTabId: (id: string) => void;
14748
+ /**
14749
+ * The width the panel was last dragged to — a PREFERENCE, not the width it
14750
+ * draws at. `planSidePanel` clamps it against the room on every render and
14751
+ * the clamp is never written back, so shrinking the window does not destroy
14752
+ * a deliberate choice: widen it again and the panel returns to where it was.
14753
+ *
14754
+ * Not keyed by `roomId`, unlike the mode: how wide you like your chat is a
14755
+ * fact about you, not about this call.
14756
+ */
14757
+ sidePanelWidth: number;
14758
+ setSidePanelWidth: (width: number) => void;
14759
+ resetSidePanelWidth: () => void;
14544
14760
  announce: (message: string) => void;
14545
14761
  liveMessage: string;
14546
14762
  /** What the browser offers for picture-in-picture, after the host's opt-out. */
@@ -17019,6 +17235,24 @@ export declare type SidebarChat = {
17019
17235
  * chat resolves, flip this to false and pass the real `label`/`avatar`.
17020
17236
  */
17021
17237
  loading?: boolean;
17238
+ /**
17239
+ * Where the conversation lives. With it the row is a real link, rendered
17240
+ * through the host's router (`LinkProvider`), so cmd/middle-click, "open in
17241
+ * new tab" and Back all work, and the active row is resolved from the URL
17242
+ * rather than from `activeChatId`. Without it the row stays a button and
17243
+ * `onClick` is the only way in.
17244
+ *
17245
+ * The host must mount `LinkProvider` with a live `currentPath` for the
17246
+ * selection to follow the URL; if it does not, the row falls back to
17247
+ * `activeChatId` rather than going dead.
17248
+ */
17249
+ href?: string;
17250
+ /**
17251
+ * Match `href` exactly when resolving the active state. Leave it off for a
17252
+ * conversation with sub-routes (a thread, say) so the parent row stays lit.
17253
+ * @default false
17254
+ */
17255
+ exactMatch?: boolean;
17022
17256
  onClick?: () => void;
17023
17257
  /** When > 0, the chat is rendered as unread (darker, bolder name). */
17024
17258
  unreadCount?: number;
@@ -17199,6 +17433,18 @@ export declare type SidebarChatProviderProps = {
17199
17433
  export declare type SidebarChatStatus = {
17200
17434
  icon: IconType;
17201
17435
  label: string;
17436
+ /**
17437
+ * THE STATUS IS LIVE, so the whole row wears it: the glyph takes the selected
17438
+ * colour and the row takes the selected background — the same one the control
17439
+ * that started it wears in the conversation's own header. A call in progress
17440
+ * is the case this exists for, and it has to be findable from the list
17441
+ * without opening anything.
17442
+ *
17443
+ * At most one status per row should carry it. An accent that several things
17444
+ * share stops pointing at any of them, which is the whole job here: the row
17445
+ * is coloured because ONE thing about it is happening right now.
17446
+ */
17447
+ accent?: boolean;
17202
17448
  };
17203
17449
 
17204
17450
  /**
@@ -17209,9 +17455,13 @@ export declare type SidebarChatStatus = {
17209
17455
  export declare type SidebarChatStore = {
17210
17456
  groups: SidebarChatGroup[];
17211
17457
  /**
17212
- * Id of the currently active chat. Chats are not navigation links — you can
17213
- * be on any page (e.g. the dashboard) with a chat active — so the active
17214
- * state is driven from here, not from the router.
17458
+ * Id of the currently active chat, for rows with no `href`: you can be on any
17459
+ * page (e.g. the dashboard) with such a chat active, so its active state is
17460
+ * driven from here rather than from the router.
17461
+ *
17462
+ * A ROUTED row (one carrying `href`) takes its active state from the URL
17463
+ * instead. This stays the source for unrouted rows, and the fallback for
17464
+ * routed ones when no `LinkProvider` is mounted.
17215
17465
  */
17216
17466
  activeChatId?: string;
17217
17467
  /** Number of conversations with unread messages (across all groups). */
@@ -17386,6 +17636,18 @@ export declare type SidebarTab = {
17386
17636
  * tab (transparent background; the icon darkens on hover).
17387
17637
  */
17388
17638
  variant?: "default" | "ai";
17639
+ /**
17640
+ * Where this tab lives. With it the tab is a real link: cmd-click opens the
17641
+ * section in a new tab, and switching sections is a navigation rather than a
17642
+ * state change the host has to translate into one. The selection stays
17643
+ * controlled — `activeTab` is still the host's, derived from its own route.
17644
+ *
17645
+ * Declaring `href` on ANY tab also turns off the mount-time restore of
17646
+ * `persistKey` — see {@link usePersistedTab}.
17647
+ */
17648
+ href?: string;
17649
+ /** Match `href` exactly when resolving the active state. @default false */
17650
+ exactMatch?: boolean;
17389
17651
  };
17390
17652
 
17391
17653
  /**
@@ -17591,6 +17853,29 @@ declare type SidePanelContextValue = {
17591
17853
  */
17592
17854
  export declare type SidePanelLayout = "sidepanel" | "fullscreen";
17593
17855
 
17856
+ /**
17857
+ * Where the in-call panel sits, which is a question about the ROOM'S width and
17858
+ * never about the viewport's — the same rule the grid, the density table and
17859
+ * the control bar already follow.
17860
+ *
17861
+ * - `beside` the panel is a column in the row and the grid shrinks for it.
17862
+ * - `over` the panel floats on the grid's right edge; the grid keeps its
17863
+ * full width and never re-solves.
17864
+ * - `full` the panel takes the whole video area. The control bar is outside
17865
+ * the row, so leaving and muting are still there.
17866
+ */
17867
+ declare type SidePanelLayout_2 = "beside" | "over" | "full";
17868
+
17869
+ declare type SidePanelPlan = {
17870
+ layout: SidePanelLayout_2;
17871
+ /** The width to draw, already clamped. `full` reports the room's own. */
17872
+ width: number;
17873
+ min: number;
17874
+ max: number;
17875
+ /** A handle that cannot travel is worse than no handle. */
17876
+ canResize: boolean;
17877
+ };
17878
+
17594
17879
  /**
17595
17880
  * A product's claim on the panel.
17596
17881
  *
@@ -17612,6 +17897,20 @@ export declare type SidePanelViewDefinition = {
17612
17897
  available?: boolean;
17613
17898
  /** Edge this view docks to. Falls back to the panel's `side`. */
17614
17899
  side?: "left" | "right";
17900
+ /**
17901
+ * Can this view re-mount content persisted from a previous session? Only a
17902
+ * view whose host actually answers `restoringViewId` — by calling `present`
17903
+ * or `cancelRestore` — should say true.
17904
+ *
17905
+ * Default `false`, and deliberately so. With no restorer the panel holds a
17906
+ * skeleton for the full safety timeout on every reload, including — after a
17907
+ * product moves its content OUT of the panel — for an id nothing will ever
17908
+ * claim again. The safe default is that the panel does not hold itself
17909
+ * hostage for a host that never opted in; the host who wants the restore is
17910
+ * also the host in a position to notice this field.
17911
+ * @default false
17912
+ */
17913
+ restoresContent?: boolean;
17615
17914
  };
17616
17915
 
17617
17916
  /**
@@ -18757,6 +19056,54 @@ export declare type UpsellActionDefinition = {
18757
19056
  /** Returns the upsell action, or undefined to hide it. */
18758
19057
  export declare type UpsellActionDefinitionFn = () => UpsellActionDefinition | undefined;
18759
19058
 
19059
+ declare interface UpsellingButtonProps extends Omit<F0ButtonProps, "icon"> {
19060
+ variant?: "promote" | "outlinePromote";
19061
+ /**
19062
+ * The text to be displayed in the button
19063
+ */
19064
+ label: string;
19065
+ /**
19066
+ * Whether to show the Upsell icon. Defaults to true.
19067
+ */
19068
+ showIcon?: boolean;
19069
+ /**
19070
+ * Function to be executed when the button is clicked
19071
+ */
19072
+ onRequest?: () => Promise<void> | void;
19073
+ /**
19074
+ * Whether to show the confirmation dialog after the request
19075
+ */
19076
+ showConfirmation?: boolean;
19077
+ /**
19078
+ * The error message to be displayed in the confirmation dialog
19079
+ */
19080
+ errorMessage: ErrorMessageProps;
19081
+ /**
19082
+ * The success message to be displayed in the confirmation dialog
19083
+ */
19084
+ successMessage: SuccessMessageProps;
19085
+ /**
19086
+ * The label to be displayed in the button when the request is being processed
19087
+ */
19088
+ loadingState: LoadingStateProps;
19089
+ /**
19090
+ * The next steps to be displayed in the confirmation dialog
19091
+ */
19092
+ nextSteps: NextStepsProps;
19093
+ /**
19094
+ * The label to be displayed in the close button of the confirmation dialog
19095
+ */
19096
+ closeLabel: string;
19097
+ /**
19098
+ * Callback to notify when the modal state changes (open/closed)
19099
+ */
19100
+ onModalStateChange?: (isOpen: boolean) => void;
19101
+ /**
19102
+ * Portal container for the confirmation dialog
19103
+ */
19104
+ portalContainer?: HTMLElement | null;
19105
+ }
19106
+
18760
19107
  export declare function useAiPromotionChat(): AiPromotionChatProviderReturnValue;
18761
19108
 
18762
19109
  /**
@@ -20127,9 +20474,11 @@ declare module "@tiptap/core" {
20127
20474
 
20128
20475
  declare module "@tiptap/core" {
20129
20476
  interface Commands<ReturnType> {
20130
- fontSize: {
20131
- setFontSize: (fontSize: string) => ReturnType;
20132
- unsetFontSize: () => ReturnType;
20477
+ enhanceHighlight: {
20478
+ setEnhanceHighlight: (from: number, to: number, options?: {
20479
+ placeholder?: string;
20480
+ }) => ReturnType;
20481
+ clearEnhanceHighlight: () => ReturnType;
20133
20482
  };
20134
20483
  }
20135
20484
  }
@@ -20137,11 +20486,9 @@ declare module "@tiptap/core" {
20137
20486
 
20138
20487
  declare module "@tiptap/core" {
20139
20488
  interface Commands<ReturnType> {
20140
- enhanceHighlight: {
20141
- setEnhanceHighlight: (from: number, to: number, options?: {
20142
- placeholder?: string;
20143
- }) => ReturnType;
20144
- clearEnhanceHighlight: () => ReturnType;
20489
+ fontSize: {
20490
+ setFontSize: (fontSize: string) => ReturnType;
20491
+ unsetFontSize: () => ReturnType;
20145
20492
  };
20146
20493
  }
20147
20494
  }