@factorialco/f0-react 6.24.0 → 6.26.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.
@@ -4781,6 +4781,9 @@ export declare interface DeleteBlockNotesTextEditorPageDocumentPatch {
4781
4781
  targetId: string;
4782
4782
  }
4783
4783
 
4784
+ /** The row data a schema field demands, or merely allows under `rightOptional`. */
4785
+ declare type Demanded<T, Optional> = Optional extends true ? Partial<T> : T;
4786
+
4784
4787
  /**
4785
4788
  * @experimental This is an experimental component use it at your own risk
4786
4789
  */
@@ -8184,6 +8187,46 @@ declare type HighlightBannerProps = {
8184
8187
  onClick?: () => void;
8185
8188
  };
8186
8189
 
8190
+ /**
8191
+ * One of a row's hover actions: a button at the row's right that acts on THAT
8192
+ * row.
8193
+ *
8194
+ * ICON-ONLY BY DEFAULT, because a row is a dense line of text and a strip of
8195
+ * labelled buttons beside it would outweigh what it is about — `label` is then
8196
+ * the accessible name and the tooltip rather than visible text.
8197
+ *
8198
+ * A row's PRIMARY action can say what it is (`showLabel`), and usually should
8199
+ * when the glyph alone would be a guess: "Clock out" is a clock, and so is
8200
+ * "Snooze". Keep it to ONE per row, leading, with the rest as glyphs — a strip
8201
+ * of labelled buttons is a toolbar, not a row.
8202
+ */
8203
+ declare type HomeListItemAction = {
8204
+ /** What it DOES, in words: "Clock out", "Dismiss". Never "OK" or "Go". */
8205
+ label: string;
8206
+ /** Omit for a text-only button — then the label always shows. */
8207
+ icon?: IconType;
8208
+ /** A destructive one — it draws as the critical button. */
8209
+ critical?: boolean;
8210
+ /** Show the `label` beside the glyph instead of only in the tooltip. */
8211
+ showLabel?: boolean;
8212
+ } & ({
8213
+ onClick: () => void;
8214
+ items?: never;
8215
+ } | {
8216
+ /**
8217
+ * The action OPENS A MENU instead of doing one thing — "Remind me" over
8218
+ * Later today / Tomorrow / Next Monday. Ordinary `DropdownItem`s, so a
8219
+ * `{ type: "label", text }` heads the group and `{ type: "separator" }`
8220
+ * divides it.
8221
+ *
8222
+ * The button is the same button either way, glyph or label: what changes
8223
+ * is that pressing it opens the menu, and the strip STAYS OPEN while the
8224
+ * menu is (the pointer has to leave the row to reach it).
8225
+ */
8226
+ items: DropdownItem[];
8227
+ onClick?: never;
8228
+ });
8229
+
8187
8230
  export declare type HomePeriod = keyof typeof GRADIENTS;
8188
8231
 
8189
8232
  /**
@@ -8218,6 +8261,39 @@ export declare type HomeSkeletonCtx = HomeRenderCtx & {
8218
8261
  */
8219
8262
  export declare const homeSlot: <V extends keyof HomeSlotParamsMap>(visualization: V, params: HomeSlotParamsMap[V], options?: SlotOptions) => HomeWidgetSlot;
8220
8263
 
8264
+ /**
8265
+ * One item inside a {@link HomeSlotItems}. MUST carry the item's stable id as
8266
+ * its `key` — that key is the only thing telling the list which items are the
8267
+ * same ones between two renders, and a positional key would animate every row
8268
+ * below a removal as though it had been replaced.
8269
+ */
8270
+ export declare const HomeSlotItem: ({ className, animated, children, }: HomeSlotItemProps) => JSX_2.Element;
8271
+
8272
+ declare interface HomeSlotItemProps {
8273
+ className?: string;
8274
+ /**
8275
+ * `false` puts the item straight where it belongs, with no enter or exit —
8276
+ * for a render that is replacing the list rather than changing one item of it
8277
+ * (see {@link useIsBulkChange}).
8278
+ */
8279
+ animated?: boolean;
8280
+ children: ReactNode;
8281
+ }
8282
+
8283
+ /**
8284
+ * The list an item's arrival and departure is animated in. Wrap the items of
8285
+ * ANY slot in it — `list` rows, `event-list` events, a bespoke renderer's own —
8286
+ * and give each {@link HomeSlotItem} the item's stable id as its key.
8287
+ *
8288
+ * `initial={false}`: the items already there when the widget mounts have not
8289
+ * arrived, they simply are. The widget's own entrance (`HomeEntrance`) is what
8290
+ * brings the whole card in; without this every list would replay a row-by-row
8291
+ * arrival inside it.
8292
+ */
8293
+ export declare const HomeSlotItems: ({ children }: {
8294
+ children: ReactNode;
8295
+ }) => JSX_2.Element;
8296
+
8221
8297
  /** The built-in slot vocabulary: each visualization and its params shape. */
8222
8298
  export declare interface HomeSlotParamsMap {
8223
8299
  "event-list": EventListParams;
@@ -8788,17 +8864,55 @@ declare type ListClickData<C> = C extends "link" ? {
8788
8864
  */
8789
8865
  declare type ListCollectionProps<Record extends RecordType, Filters extends FiltersDefinition, Sortings extends SortingsDefinition, Summaries extends SummariesDefinition, ItemActions extends ItemActionsDefinition<Record>, NavigationFilters extends NavigationFiltersDefinition, Grouping extends GroupingDefinition<Record>> = CollectionProps<Record, Filters, Sortings, Summaries, ItemActions, NavigationFilters, Grouping, ListVisualizationOptions<Record, Filters, Sortings>>;
8790
8866
 
8867
+ /**
8868
+ * A row's glyph tint: one of {@link listIconColors}, or a HEX of your own.
8869
+ *
8870
+ * Prefer a palette name. Those eleven hues were picked to sit beside each other
8871
+ * in one column and to hold up in both themes, which is the whole job here — a
8872
+ * feed's glyphs are read as a SET, and a colour chosen per row without seeing
8873
+ * the others is how a card ends up with two greens that mean different things.
8874
+ *
8875
+ * The hex is for the case the palette genuinely cannot serve: a colour that is
8876
+ * already data — a calendar's own colour, a module's brand, a category a user
8877
+ * picked themselves. It is treated exactly like a palette hue (a tenth of it as
8878
+ * the tile, the hue itself as the icon), so a bespoke colour and a named one
8879
+ * still draw the same glyph. `#RGB` and `#RRGGBB` both parse; anything else
8880
+ * falls back to the plain, untinted glyph rather than drawing nothing.
8881
+ */
8882
+ export declare type ListIconColor = ListIconPaletteColor | `#${string}`;
8883
+
8884
+ /**
8885
+ * The tint a row's ICON glyph can carry. f0's NAMED palette — the same hues
8886
+ * `ui/Avatar` colours initials with — deliberately, rather than the semantic
8887
+ * families (`critical`, `warning`, `positive`): a colour here says which KIND
8888
+ * of thing the row is, so a feed can give every category its own without any of
8889
+ * them reading as an alert. For "this is urgent", the left kind is `alert`.
8890
+ */
8891
+ export declare const listIconColors: readonly ["viridian", "malibu", "yellow", "purple", "lilac", "barbie", "smoke", "army", "flubber", "indigo", "camel"];
8892
+
8893
+ export declare type ListIconPaletteColor = (typeof listIconColors)[number];
8894
+
8791
8895
  /** One row of a `list` slot — its shape FOLLOWS from the slot's schema. */
8792
8896
  export declare type ListItem<S extends ListSchema = ListSchema> = {
8793
8897
  id: string | number;
8794
8898
  /** An accent dot on the left glyph — unseen/pending. */
8795
8899
  unread?: boolean;
8796
- } & ListTextData<S> & ListLeftData<S["left"]> & ListRightData<S["right"]> & ListClickData<S["clickBehavior"]>;
8900
+ /**
8901
+ * What can be DONE to this row, revealed on hover (and on focus, so they are
8902
+ * reachable by keyboard) behind a fade over whatever the row trails. Keep it
8903
+ * to two: the strip covers the row's right-hand side while it shows.
8904
+ */
8905
+ actions?: ListRowAction[];
8906
+ } & ListTextData<S> & ListLeftData<S["left"]> & ListRightData<S["right"], S["rightOptional"]> & ListClickData<S["clickBehavior"]>;
8797
8907
 
8798
8908
  declare type ListLeftData<L> = L extends "module" ? {
8799
8909
  module: ModuleId;
8800
8910
  } : L extends "alert" ? {
8801
8911
  alert: AlertType;
8912
+ } : L extends "icon" ? {
8913
+ avatar: AvatarData<"icon"> & {
8914
+ color?: ListIconColor;
8915
+ };
8802
8916
  } : L extends AvatarVariant["type"] ? {
8803
8917
  avatar: AvatarData<L>;
8804
8918
  } : object;
@@ -8814,14 +8928,15 @@ export declare interface ListParams<S extends ListSchema = ListSchema> {
8814
8928
 
8815
8929
  declare type ListPropertyDefinition<R, Sortings extends SortingsDefinition> = WithOptionalSorting_2<R, Sortings> & PropertyDefinition_2<R>;
8816
8930
 
8817
- declare type ListRightData<R> = R extends "counter" ? {
8931
+ declare type ListRightData<R, Optional> = R extends "counter" ? Demanded<{
8818
8932
  count: number;
8819
- } : R extends `${infer T extends F0AvatarListProps["type"]}-list` ? {
8933
+ }, Optional> : R extends `${infer T extends F0AvatarListProps["type"]}-list` ? Demanded<{
8820
8934
  avatars: Array<AvatarData<T>>;
8935
+ }, Optional> & {
8821
8936
  remainingCount?: number;
8822
- } : R extends AvatarVariant["type"] ? {
8937
+ } : R extends AvatarVariant["type"] ? Demanded<{
8823
8938
  rightAvatar: AvatarData<R>;
8824
- } : object;
8939
+ }, Optional> : object;
8825
8940
 
8826
8941
  /**
8827
8942
  * What every row draws on its RIGHT: a counter, one avatar (e.g. the sender),
@@ -8829,6 +8944,14 @@ declare type ListRightData<R> = R extends "counter" ? {
8829
8944
  */
8830
8945
  export declare type ListRightKind = "counter" | AvatarVariant["type"] | `${F0AvatarListProps["type"]}-list`;
8831
8946
 
8947
+ /**
8948
+ * One HOVER ACTION on a `list` row: an icon button over the row's right edge
8949
+ * that acts on that row alone — "Clock out", "Dismiss". Per ROW rather than per
8950
+ * schema, because unlike everything else about a row what you can do to it is
8951
+ * genuinely its own: a feed mixes items you can dismiss with items you can't.
8952
+ */
8953
+ export declare type ListRowAction = HomeListItemAction;
8954
+
8832
8955
  /**
8833
8956
  * A `list` slot's SCHEMA: declared once for the whole slot, it decides what
8834
8957
  * every row looks like — the rows are CONSISTENT by construction, and the item
@@ -8841,10 +8964,29 @@ export declare interface ListSchema {
8841
8964
  left?: ListLeftKind;
8842
8965
  /** The one right treatment every row draws. Omit for none. */
8843
8966
  right?: ListRightKind;
8967
+ /**
8968
+ * The `right` treatment is ALLOWED but not demanded: rows that carry its data
8969
+ * draw it and the rest trail nothing — a feed where only some items came from
8970
+ * a person. Without this every row must supply it, which is what keeps an
8971
+ * ordinary list even.
8972
+ */
8973
+ rightOptional?: boolean;
8844
8974
  /** Every row carries an inline subtitle (on the title's line, after a dot). */
8845
8975
  subtitleRequired?: boolean;
8846
8976
  /** Every row carries a second line — this is what makes rows two-line. */
8847
8977
  descriptionRequired?: boolean;
8978
+ /**
8979
+ * A second line is ALLOWED but not demanded: some rows carry a `description`
8980
+ * and others don't — a feed where only a few items have a due date or a
8981
+ * sender. The list is still a two-line list (the glyphs stay `md`, so the
8982
+ * column of them lines up); the rows without one are simply shorter.
8983
+ *
8984
+ * `descriptionRequired` wins when both are set: demanding it already allows it.
8985
+ *
8986
+ * Such a list does NOT auto-compact past {@link LIST_COMPACT_AFTER} rows —
8987
+ * see {@link listCompacts}. `compact: true` still forces it.
8988
+ */
8989
+ descriptionOptional?: boolean;
8848
8990
  /**
8849
8991
  * `"link"` rows each carry an `href` and render as REAL anchors (role
8850
8992
  * `link`, routed through the app's `LinkProvider`) — never an onClick;
@@ -8882,6 +9024,8 @@ declare type ListTextData<S extends ListSchema> = {
8882
9024
  subtitle?: never;
8883
9025
  }) & (S["descriptionRequired"] extends true ? {
8884
9026
  description: string;
9027
+ } : S["descriptionOptional"] extends true ? {
9028
+ description?: string;
8885
9029
  } : {
8886
9030
  description?: never;
8887
9031
  });
@@ -9340,6 +9484,30 @@ export declare interface NewHomeLayoutProps {
9340
9484
  * dragging and the add placeholder; the others stay put. Both by default.
9341
9485
  */
9342
9486
  editableWidgetContainers?: WidgetContainerSide[];
9487
+ /**
9488
+ * Which containers keep ONLY THE WIDGETS YOU CAN SEE in the DOM. None by
9489
+ * default: for a Home of a dozen widgets, mounting them all is what keeps a
9490
+ * card's data, clock and animation alive across everything this layout does to
9491
+ * it, and virtualizing would trade that away for nothing.
9492
+ *
9493
+ * Name a side once its widgets can outnumber a screen — a hundred cards is a
9494
+ * hundred fetches and a hundred charts, and all but the three in view are work
9495
+ * nobody asked for. Below `virtualization.threshold` widgets (12 by default) the
9496
+ * column still renders them all, so naming a side here is a CEILING rather than
9497
+ * a switch. What it costs is on `WidgetVirtualization`; in short, a widget that
9498
+ * scrolls out is unmounted and comes back new, and only the cards in view get
9499
+ * out of a dragged one's way.
9500
+ *
9501
+ * STACKED (below `md`) the rail's widgets belong to the main column, so "main"
9502
+ * is what virtualizes them there.
9503
+ */
9504
+ virtualizedWidgetContainers?: WidgetContainerSide[];
9505
+ /**
9506
+ * Tuning for the above — the height a card is guessed at before it is measured,
9507
+ * how many are kept past each edge, and the count it starts at. The scroll
9508
+ * region is this layout's own, per side, and is not yours to set.
9509
+ */
9510
+ virtualization?: Omit<WidgetVirtualization, "scrollElement">;
9343
9511
  /**
9344
9512
  * Called with a widget id when its "Remove widget" menu item is used — the
9345
9513
  * three-dots menu in the widget's own header.
@@ -12520,6 +12688,13 @@ export declare const useInfiniteScrollPagination: (paginationInfo: PaginationInf
12520
12688
  loadingIndicatorRef: RefObject<HTMLTableCellElement>;
12521
12689
  };
12522
12690
 
12691
+ /**
12692
+ * Whether the item count changed by more than {@link ITEM_CHURN_BULK_AFTER}
12693
+ * since the last render — i.e. whether THIS render is a bulk replacement rather
12694
+ * than an item coming or going. Feed it to {@link HomeSlotItem}'s `animated`.
12695
+ */
12696
+ export declare const useIsBulkChange: (count: number, threshold?: number) => boolean;
12697
+
12523
12698
  /**
12524
12699
  * Converts an item-navigation result into the `NavigationProps` shape that
12525
12700
  * `PageHeader` and `F0Dialog` accept (directly or via
@@ -12583,6 +12758,8 @@ export declare const useSidebarChatActions: () => SidebarChatActions;
12583
12758
  /** Read the chat state (groups, active chat) and the imperative store API. */
12584
12759
  export declare const useSidebarChats: () => SidebarChatStore;
12585
12760
 
12761
+ export declare const useWidgetIsWide: () => boolean;
12762
+
12586
12763
  /**
12587
12764
  * Profile data for a vacancy entity (ATS vacancy/position), resolved asynchronously
12588
12765
  * and displayed in the entity reference hover card.
@@ -13210,6 +13387,45 @@ export declare const widgetTitle: (widget: {
13210
13387
  params?: WidgetParams;
13211
13388
  }) => string;
13212
13389
 
13390
+ /**
13391
+ * VIRTUALIZATION — what a column does when it has more widgets than a screen.
13392
+ *
13393
+ * A widget is not a row: it is a card with its own data, its own chart, its own
13394
+ * list of rows inside it. A hundred of them mounted is a hundred fetches, a
13395
+ * hundred charts laid out and a DOM the browser spends every frame on, and all
13396
+ * but the three you can see are work nobody asked for. So a virtualized column
13397
+ * mounts ONLY the widgets in view (plus `overscan` past each edge) and holds the
13398
+ * space of the rest open, so the scrollbar still describes the whole column.
13399
+ *
13400
+ * WHAT IT COSTS, and why it is opt-in rather than the default:
13401
+ *
13402
+ * - A widget that scrolls out is UNMOUNTED. Whatever it had loaded, timed or
13403
+ * animated is gone, and it starts again when it comes back — the opposite of
13404
+ * what the collapsed rail is built to guarantee. For a column of a few widgets
13405
+ * that trade is a bad one, which is what `threshold` is for.
13406
+ * - Dragging still reorders correctly, but only the widgets that are MOUNTED
13407
+ * shuffle out of the way as you go: dnd-kit can't move a card that isn't
13408
+ * there. The dragged card itself is pinned into the DOM for the whole gesture.
13409
+ * - `fullHeight` means nothing here. A virtualized column's height is the sum of
13410
+ * its cards, so there is no column height for a card to fill.
13411
+ */
13412
+ export declare interface WidgetVirtualization {
13413
+ /**
13414
+ * Below this many widgets the column simply renders them all. Defaults to 12.
13415
+ */
13416
+ threshold?: number;
13417
+ /** First guess at a card's height in px, before it is measured. */
13418
+ estimateHeight?: number;
13419
+ /** How many cards stay mounted past each edge of the viewport. */
13420
+ overscan?: number;
13421
+ /**
13422
+ * The scroll region to virtualize against. Defaults to the column's nearest
13423
+ * scrollable ancestor — pass it when you already have the element (it saves
13424
+ * the walk, and it is exact).
13425
+ */
13426
+ scrollElement?: HTMLElement | null;
13427
+ }
13428
+
13213
13429
  declare type WidgetWidth = "sm" | "md" | "lg";
13214
13430
 
13215
13431
  declare interface WiggleOptions {
@@ -13382,10 +13598,8 @@ declare module "@tiptap/core" {
13382
13598
 
13383
13599
  declare module "@tiptap/core" {
13384
13600
  interface Commands<ReturnType> {
13385
- indent: {
13386
- setIndent: (level: number) => ReturnType;
13387
- unsetIndent: () => ReturnType;
13388
- outdent: () => ReturnType;
13601
+ moodTracker: {
13602
+ insertMoodTracker: (data: MoodTrackerData) => ReturnType;
13389
13603
  };
13390
13604
  }
13391
13605
  }
@@ -13393,8 +13607,10 @@ declare module "@tiptap/core" {
13393
13607
 
13394
13608
  declare module "@tiptap/core" {
13395
13609
  interface Commands<ReturnType> {
13396
- moodTracker: {
13397
- insertMoodTracker: (data: MoodTrackerData) => ReturnType;
13610
+ indent: {
13611
+ setIndent: (level: number) => ReturnType;
13612
+ unsetIndent: () => ReturnType;
13613
+ outdent: () => ReturnType;
13398
13614
  };
13399
13615
  }
13400
13616
  }