@factorialco/f0-react 6.8.4 → 6.9.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.
@@ -766,6 +766,8 @@ declare const alertAvatarVariants: (props?: ({
766
766
 
767
767
  declare type AlertTagProps = ComponentProps<typeof F0TagAlert>;
768
768
 
769
+ declare type AlertType = Parameters<typeof F0AvatarAlert>[0]["type"];
770
+
769
771
  declare type AlertVariant = (typeof alertVariantOptions)[number];
770
772
 
771
773
  declare const alertVariantOptions: readonly ["info", "warning", "critical", "neutral", "positive"];
@@ -867,6 +869,10 @@ declare type AvatarBadge = ({
867
869
  tooltip?: string;
868
870
  };
869
871
 
872
+ declare type AvatarData<T extends AvatarVariant["type"]> = Omit<Extract<AvatarVariant, {
873
+ type: T;
874
+ }>, "type">;
875
+
870
876
  declare const avatarEmojiSizes: readonly ["sm", "md", "lg", "xl"];
871
877
 
872
878
  declare type AvatarFileSize = (typeof avatarFileSizes)[number];
@@ -3180,6 +3186,15 @@ declare const daytimePageVariants: (props?: ({
3180
3186
  className?: ClassValue;
3181
3187
  })) | undefined) => string;
3182
3188
 
3189
+ /**
3190
+ * Built-in renderers for the standard visualizations. `list` covers every
3191
+ * row-based slot through its schema; `event-list` and `indicators` spread
3192
+ * their params onto the matching f0 content component. Bespoke visualizations
3193
+ * (e.g. `clock-in`, `carousel`) are intentionally absent — supply them via
3194
+ * `slotRenderers`.
3195
+ */
3196
+ export declare const defaultSlotRenderers: SlotRenderers;
3197
+
3183
3198
  declare const defaultTranslations: {
3184
3199
  readonly common: {
3185
3200
  readonly selectPlaceholder: "Select";
@@ -4890,6 +4905,15 @@ declare interface ErrorMessageProps {
4890
4905
  description: string;
4891
4906
  }
4892
4907
 
4908
+ /** The gap between rows of the `event-list` slot. */
4909
+ export declare const EVENT_LIST_GAP = "gap-2";
4910
+
4911
+ /** `event-list` params: f0 calendar-event rows (color band + date avatars). */
4912
+ export declare interface EventListParams {
4913
+ events: CalendarEventProps[];
4914
+ showAllItems?: boolean;
4915
+ }
4916
+
4893
4917
  /**
4894
4918
  * Profile data for an expense entity, resolved asynchronously
4895
4919
  * and displayed in the entity reference hover card.
@@ -7296,6 +7320,16 @@ export declare const getSecondaryActions: (secondaryActions: SecondaryActionsDef
7296
7320
 
7297
7321
  export declare const getUpsellAction: (upsellAction: UpsellActionDefinitionFn | undefined) => UpsellActionDefinition | undefined;
7298
7322
 
7323
+ /**
7324
+ * The DaytimePage gradient wash, by period — the same stops and the same 8%
7325
+ * opacity, so Home and the daytime header read as one surface.
7326
+ */
7327
+ declare const GRADIENTS: {
7328
+ readonly morning: "bg-gradient-to-bl from-[#E51943] from-20% via-[#F97316] via-35% to-transparent to-50%";
7329
+ readonly afternoon: "bg-gradient-to-bl from-[#5596F6] from-20% via-[#10B881] via-35% to-transparent to-50%";
7330
+ readonly evening: "bg-gradient-to-bl from-[#3739A8] from-20% via-[#CB6687] via-35% to-transparent to-50%";
7331
+ };
7332
+
7299
7333
  export declare interface GranularityDefinition {
7300
7334
  calendarMode?: CalendarMode;
7301
7335
  calendarView: CalendarView;
@@ -7675,6 +7709,83 @@ declare type HighlightBannerProps = {
7675
7709
  onClick?: () => void;
7676
7710
  };
7677
7711
 
7712
+ export declare type HomePeriod = keyof typeof GRADIENTS;
7713
+
7714
+ /**
7715
+ * The Home kit's slot vocabulary and how each slot is drawn. `SlotWidget`
7716
+ * renders a widget from these; the layout (`NewHomeLayout`) stays pure
7717
+ * placement.
7718
+ */
7719
+ /** Context threaded into every slot renderer. */
7720
+ export declare interface HomeRenderCtx {
7721
+ /**
7722
+ * Whether this slot is the LAST one in its widget. `SlotWidget` sets it per
7723
+ * slot; row-based slots use it to keep their bottom bleed (see
7724
+ * { slotRowBleed}).
7725
+ */
7726
+ isLastSlot?: boolean;
7727
+ }
7728
+
7729
+ /**
7730
+ * Builds a slot with its params CHECKED against its visualization.
7731
+ * `HomeWidgetSlot`'s `params` is `unknown` (bespoke slots need it to be), so a
7732
+ * plain `{ visualization, params }` literal gets no checking — use this for
7733
+ * the built-in vocabulary (and {@link listSlot} for `list` slots), keeping
7734
+ * literals for bespoke visualizations.
7735
+ */
7736
+ export declare const homeSlot: <V extends keyof HomeSlotParamsMap>(visualization: V, params: HomeSlotParamsMap[V]) => HomeWidgetSlot;
7737
+
7738
+ /** The built-in slot vocabulary: each visualization and its params shape. */
7739
+ export declare interface HomeSlotParamsMap {
7740
+ "event-list": EventListParams;
7741
+ indicators: IndicatorsListProps;
7742
+ }
7743
+
7744
+ /**
7745
+ * The `Widget` chrome a Home widget may carry beyond its header, passed straight
7746
+ * through to the frame.
7747
+ *
7748
+ * `alert` and `status` are EXCLUSIVE — `Widget` throws when given both — so the
7749
+ * type says so rather than leaving it to blow up at runtime.
7750
+ */
7751
+ export declare type HomeWidgetChrome = Pick<WidgetProps, "action" | "summaries"> & ({
7752
+ alert?: WidgetProps["alert"];
7753
+ status?: never;
7754
+ } | {
7755
+ status?: WidgetProps["status"];
7756
+ alert?: never;
7757
+ });
7758
+
7759
+ /** A widget as handed to the layout: header + an ordered list of slots. */
7760
+ export declare type HomeWidgetItem = HomeWidgetChrome & {
7761
+ id: string;
7762
+ header?: WidgetProps["header"];
7763
+ fullHeight?: boolean;
7764
+ /**
7765
+ * The widget's catalog glyph — shown for it in the collapsed rail and in the
7766
+ * "Add widget" picker, so the strip can never drift from the catalog.
7767
+ */
7768
+ icon?: IconType;
7769
+ /**
7770
+ * PINNED: the widget stays put. In edit mode it shows no remove control and
7771
+ * does not wiggle (nor drag, once dragging lands) — for widgets a user must
7772
+ * always have, like Clock in.
7773
+ */
7774
+ locked?: boolean;
7775
+ /**
7776
+ * Something new since the user last looked (unread messages, a pending
7777
+ * request). The collapsed rail badges the widget's glyph with an accent dot.
7778
+ */
7779
+ hasUpdates?: boolean;
7780
+ slots: HomeWidgetSlot[];
7781
+ };
7782
+
7783
+ /** One slot of a widget: a visualization tag + its params (opaque to the layout). */
7784
+ export declare interface HomeWidgetSlot {
7785
+ visualization: string;
7786
+ params: unknown;
7787
+ }
7788
+
7678
7789
  declare type HTMLString = string;
7679
7790
 
7680
7791
  declare type I18nContextType = TranslationsType & {
@@ -8130,13 +8241,118 @@ declare type LinkProps = AnchorHTMLAttributes<HTMLAnchorElement> & {
8130
8241
  disabled?: boolean;
8131
8242
  };
8132
8243
 
8244
+ /**
8245
+ * Past this many rows a list auto-compacts: every row's second line folds into
8246
+ * a tooltip on the row, and the glyphs drop to `sm`.
8247
+ */
8248
+ export declare const LIST_COMPACT_AFTER = 6;
8249
+
8250
+ declare type ListClickData<C> = C extends "link" ? {
8251
+ href: string;
8252
+ } : object;
8253
+
8133
8254
  /**
8134
8255
  * Group List: Renders the list for a group
8135
8256
  */
8136
8257
  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>>;
8137
8258
 
8259
+ /** One row of a `list` slot — its shape FOLLOWS from the slot's schema. */
8260
+ export declare type ListItem<S extends ListSchema = ListSchema> = {
8261
+ id: string | number;
8262
+ /** An accent dot on the left glyph — unseen/pending. */
8263
+ unread?: boolean;
8264
+ } & ListTextData<S> & ListLeftData<S["left"]> & ListRightData<S["right"]> & ListClickData<S["clickBehavior"]>;
8265
+
8266
+ declare type ListLeftData<L> = L extends "module" ? {
8267
+ module: ModuleId;
8268
+ } : L extends "alert" ? {
8269
+ alert: AlertType;
8270
+ } : L extends AvatarVariant["type"] ? {
8271
+ avatar: AvatarData<L>;
8272
+ } : object;
8273
+
8274
+ /** What every row of a `list` slot draws on its LEFT. */
8275
+ export declare type ListLeftKind = AvatarVariant["type"] | "module" | "alert";
8276
+
8277
+ /** `list` params: the schema, then items shaped by it. Build with {@link listSlot}. */
8278
+ export declare interface ListParams<S extends ListSchema = ListSchema> {
8279
+ schema: S;
8280
+ items: Array<ListItem<S>>;
8281
+ }
8282
+
8138
8283
  declare type ListPropertyDefinition<R, Sortings extends SortingsDefinition> = WithOptionalSorting_2<R, Sortings> & PropertyDefinition_2<R>;
8139
8284
 
8285
+ declare type ListRightData<R> = R extends "counter" ? {
8286
+ count: number;
8287
+ } : R extends `${infer T extends F0AvatarListProps["type"]}-list` ? {
8288
+ avatars: Array<AvatarData<T>>;
8289
+ remainingCount?: number;
8290
+ } : R extends AvatarVariant["type"] ? {
8291
+ rightAvatar: AvatarData<R>;
8292
+ } : object;
8293
+
8294
+ /**
8295
+ * What every row draws on its RIGHT: a counter, one avatar (e.g. the sender),
8296
+ * or a compact strip of avatars with an optional `remainingCount`.
8297
+ */
8298
+ export declare type ListRightKind = "counter" | AvatarVariant["type"] | `${F0AvatarListProps["type"]}-list`;
8299
+
8300
+ /**
8301
+ * A `list` slot's SCHEMA: declared once for the whole slot, it decides what
8302
+ * every row looks like — the rows are CONSISTENT by construction, and the item
8303
+ * type follows from it (see {@link ListItem}). Sizing is prescriptive, not
8304
+ * configurable: two text lines (a required `description`) draw an `md` glyph,
8305
+ * one line draws `sm`.
8306
+ */
8307
+ export declare interface ListSchema {
8308
+ /** The one left treatment every row draws. Omit for plain text rows. */
8309
+ left?: ListLeftKind;
8310
+ /** The one right treatment every row draws. Omit for none. */
8311
+ right?: ListRightKind;
8312
+ /** Every row carries an inline subtitle (on the title's line, after a dot). */
8313
+ subtitleRequired?: boolean;
8314
+ /** Every row carries a second line — this is what makes rows two-line. */
8315
+ descriptionRequired?: boolean;
8316
+ /**
8317
+ * `"link"` rows each carry an `href` and render as REAL anchors (role
8318
+ * `link`, routed through the app's `LinkProvider`) — never an onClick;
8319
+ * that's the only click behavior rows have. Omit for inert rows.
8320
+ * Same-tab for relative and `#` hrefs, `target="_blank"` for other domains.
8321
+ */
8322
+ clickBehavior?: "link";
8323
+ /**
8324
+ * How many rows show before the rest fold behind a "View more (n)" button at
8325
+ * the list's bottom (which turns into "View less" once expanded). Omit to
8326
+ * always show every row.
8327
+ */
8328
+ maxVisibleItems?: number;
8329
+ /**
8330
+ * Forces the COMPACT presentation at any count: every row's `description`
8331
+ * folds into a tooltip on the row and the glyphs draw `sm`. Without it,
8332
+ * lists compact on their own past `LIST_COMPACT_AFTER` visible rows.
8333
+ */
8334
+ compact?: boolean;
8335
+ }
8336
+
8337
+ /**
8338
+ * Builds a `list` slot: the schema is declared once, and the items' shape is
8339
+ * CHECKED against it — a `left: "person"` slot only takes person data, a
8340
+ * `clickBehavior: "link"` slot demands an `href` on every row.
8341
+ */
8342
+ export declare const listSlot: <const S extends ListSchema>(schema: S, items: Array<ListItem<S>>) => HomeWidgetSlot;
8343
+
8344
+ declare type ListTextData<S extends ListSchema> = {
8345
+ title: string;
8346
+ } & (S["subtitleRequired"] extends true ? {
8347
+ subtitle: string;
8348
+ } : {
8349
+ subtitle?: never;
8350
+ }) & (S["descriptionRequired"] extends true ? {
8351
+ description: string;
8352
+ } : {
8353
+ description?: never;
8354
+ });
8355
+
8140
8356
  declare type ListVisualizationOptions<R extends RecordType, _Filters extends FiltersDefinition, Sortings extends SortingsDefinition> = {
8141
8357
  itemDefinition: (record: R) => ItemDefinition;
8142
8358
  fields: ReadonlyArray<ListPropertyDefinition<R, Sortings>>;
@@ -8555,6 +8771,77 @@ declare type NestedVariant = "basic" | "detailed";
8555
8771
 
8556
8772
  declare type NewColor = Extract<BaseColor, (typeof tagDotColors)[number]>;
8557
8773
 
8774
+ /**
8775
+ * NewHomeLayout — the shell for the redesigned Home, modelled on the custom-home
8776
+ * prototype's Feed page.
8777
+ *
8778
+ * A growing MAIN column (content capped to a centered `mainWidth`) next to a
8779
+ * FIXED-width side rail, separated only by a gap — no divider. The WHOLE page
8780
+ * sits on one full-bleed DaytimePage gradient (`period`): neither column paints
8781
+ * a background, so the wash runs under both and across the gap, out to the
8782
+ * window's edges. Below `md` everything stacks into one column, main first.
8783
+ *
8784
+ * WHEN THE LAYOUT IS TOO NARROW for both columns at full width (but still two
8785
+ * columns), the rail COLLAPSES: one `lg` avatar per widget carrying that
8786
+ * widget's own catalog `icon`. Hovering (or clicking) an avatar floats the SAME
8787
+ * widget render out over the feed at the rail's expanded width — one render,
8788
+ * two states, exactly like the prototype.
8789
+ */
8790
+ export declare const NewHomeLayout: ForwardRefExoticComponent<NewHomeLayoutProps & RefAttributes<HTMLDivElement>>;
8791
+
8792
+ export declare interface NewHomeLayoutProps {
8793
+ /** Freeform main-column content on top (greeting, shortcut cards, ranked feed…). */
8794
+ children?: ReactNode;
8795
+ /** Main column: widget slots stacked below `children`. */
8796
+ leftWidgets?: HomeWidgetItem[];
8797
+ /** Side rail: spec-conforming widgets. */
8798
+ rightWidgets?: HomeWidgetItem[];
8799
+ /** Freeform side-rail content, rendered above `rightWidgets` (expanded rail only). */
8800
+ aside?: ReactNode;
8801
+ /** Per-visualization renderers, MERGED OVER the kit's `defaultSlotRenderers`. */
8802
+ slotRenderers?: SlotRenderers;
8803
+ /** Full override of how a whole widget is drawn. Defaults to `SlotWidget`. */
8804
+ renderWidget?: (widget: HomeWidgetItem, ctx: HomeRenderCtx) => ReactNode;
8805
+ /**
8806
+ * Edit mode. Omit it and the layout owns the state itself, toggled by its own
8807
+ * edit button; pass it to drive edit mode from outside.
8808
+ */
8809
+ editing?: boolean;
8810
+ /** Called when the layout's edit button is pressed. */
8811
+ onEditingChange?: (editing: boolean) => void;
8812
+ /**
8813
+ * Which containers a user may actually edit. In edit mode only these show
8814
+ * remove controls and the add placeholder; the others stay put. Both by default.
8815
+ */
8816
+ editableWidgetContainers?: WidgetContainerSide[];
8817
+ /** Called with a widget id when its remove control is clicked (edit mode only). */
8818
+ onRemoveWidget?: (id: string) => void;
8819
+ /** When set, renders a "+ Add widget" affordance at the bottom of each column. */
8820
+ onClickAddNewWidget?: (side: WidgetContainerSide) => void;
8821
+ /** Called with a side and its widget ids in their new order after a drag. */
8822
+ onReorderWidgets?: (side: WidgetContainerSide, ids: string[]) => void;
8823
+ /** The daytime gradient period for the page surface. */
8824
+ period?: HomePeriod;
8825
+ /** Fixed px width of the side rail. */
8826
+ asideWidth?: number;
8827
+ /** Max px width of the (centered) main-column content. */
8828
+ mainWidth?: number;
8829
+ /**
8830
+ * How far the page surface reaches past this layout's box, in px — set it to
8831
+ * the page's own gutter so the gradient runs to the window's edges instead of
8832
+ * stopping at that padding.
8833
+ */
8834
+ bleed?: number;
8835
+ /**
8836
+ * When the layout stacks (below `md` there is no rail), how many leading
8837
+ * blocks of `children` come before the pinned widgets folded in from it.
8838
+ * Defaults to 2 — a greeting and the shortcuts under it.
8839
+ */
8840
+ stackedPinsAfter?: number;
8841
+ ctx?: HomeRenderCtx;
8842
+ className?: string;
8843
+ }
8844
+
8558
8845
  declare type NextDepth<T> = T extends 1 ? 2 : T extends 2 ? 3 : T extends 3 ? 4 : never;
8559
8846
 
8560
8847
  declare interface NextStepsProps {
@@ -10560,6 +10847,26 @@ declare const skeletonVariants: (props?: ({
10560
10847
  className?: ClassValue;
10561
10848
  })) | undefined) => string;
10562
10849
 
10850
+ /**
10851
+ * Row-based slots cancel their rows' own padding so the rows sit flush with the
10852
+ * widget's content box — every list-like slot carries this. `indicators`
10853
+ * doesn't: it isn't rows and has no padding to cancel.
10854
+ */
10855
+ export declare const SLOT_ROW_BLEED = "-m-2";
10856
+
10857
+ /** Draws ONE slot from its params. Keyed by `visualization` in a renderer map. */
10858
+ export declare type SlotRenderer<P = unknown> = (params: P, ctx: HomeRenderCtx) => ReactNode;
10859
+
10860
+ export declare type SlotRenderers = Record<string, SlotRenderer>;
10861
+
10862
+ /**
10863
+ * The bleed a row-based slot applies to itself: `SLOT_ROW_BLEED` with its
10864
+ * VERTICAL halves put back — `mt-0` always (the widget header already spaces
10865
+ * the first slot, and a divider spaces the rest), and `mb-0` unless this is the
10866
+ * widget's last slot, where the bleed should reach the card's bottom edge.
10867
+ */
10868
+ export declare const slotRowBleed: (ctx: HomeRenderCtx) => string;
10869
+
10563
10870
  /**
10564
10871
  * Type helper to extract keys from a SortingsDefinition
10565
10872
  */
@@ -12007,6 +12314,49 @@ export declare type WidgetAvatarsListItemProps = {
12007
12314
  alert: ComponentProps<typeof F0AvatarAlert>["type"];
12008
12315
  });
12009
12316
 
12317
+ /**
12318
+ * WidgetCatalog — the "Add widget" dialog, mirroring the custom-home prototype:
12319
+ * a searchable picker on the left (icon + title rows, the selected row tinted),
12320
+ * a LIVE preview of the highlighted widget on the right at the width it will
12321
+ * really get, and the "Add widget" CTA in the dialog footer. `width="xl"`
12322
+ * rather than fullscreen.
12323
+ *
12324
+ * Selection follows the filter: if the selected row is filtered out, the first
12325
+ * remaining row takes over, so the preview always shows something the CTA can
12326
+ * actually add.
12327
+ */
12328
+ export declare function WidgetCatalog({ isOpen, onClose, widgets, onAdd, previewWidth, title, }: WidgetCatalogProps): JSX_2.Element;
12329
+
12330
+ /** One entry in the widget catalog dialog. */
12331
+ export declare interface WidgetCatalogItem {
12332
+ id: string;
12333
+ title: string;
12334
+ icon: IconType;
12335
+ /**
12336
+ * The LIVE PREVIEW of the widget — the same node the Home renders (e.g. a
12337
+ * `SlotWidget`), so the preview can't drift from what gets added.
12338
+ */
12339
+ preview: ReactNode;
12340
+ }
12341
+
12342
+ export declare interface WidgetCatalogProps {
12343
+ isOpen: boolean;
12344
+ onClose: () => void;
12345
+ /** The widgets that can be added, in the order to list them. */
12346
+ widgets: WidgetCatalogItem[];
12347
+ /** Called with the chosen widget id when the CTA is pressed. */
12348
+ onAdd: (id: string) => void;
12349
+ /**
12350
+ * Content width of the column this was opened from — the preview is capped
12351
+ * to it, so a rail-bound widget previews at rail width.
12352
+ */
12353
+ previewWidth?: number;
12354
+ title?: string;
12355
+ }
12356
+
12357
+ /** Which column a container is: the growing main one, or the fixed side rail. */
12358
+ export declare type WidgetContainerSide = "main" | "right";
12359
+
12010
12360
  /**
12011
12361
  * @experimental This is an experimental component use it at your own risk
12012
12362
  */
@@ -12059,6 +12409,21 @@ export declare interface WidgetProps {
12059
12409
  variant: StatusVariant;
12060
12410
  };
12061
12411
  fullHeight?: boolean;
12412
+ /**
12413
+ * Shows a drag handle to the left of the title. The handle carries
12414
+ * `data-gs-handle`, so a gridstack board picks it up as its handle.
12415
+ */
12416
+ draggable?: boolean;
12417
+ onDragStart?: () => void;
12418
+ onDragEnd?: () => void;
12419
+ /** Lifts the card while it is being dragged. */
12420
+ isDragging?: boolean;
12421
+ /** Marks the card as picked out — a selected tile on an editable board. */
12422
+ selected?: boolean;
12423
+ /** An "Ask One" AI button in the header. */
12424
+ AIButton?: () => void;
12425
+ /** An overflow menu at the header's right, beside `link`. */
12426
+ actions?: DropdownItem[];
12062
12427
  }
12063
12428
 
12064
12429
  /**