@jobber/components 6.112.1 → 6.113.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.
@@ -230,11 +230,12 @@ export type MenuFooter<Extra extends object = ExtraProps> = Extra & {
230
230
  };
231
231
  export type MenuItem<T extends OptionLike, SectionExtra extends object = ExtraProps, ActionExtra extends object = ExtraProps> = MenuSection<T, SectionExtra, ActionExtra> | MenuOptions<T, ActionExtra> | MenuHeader<ActionExtra> | MenuFooter<ActionExtra>;
232
232
  export type AutocompleteValue<Value extends OptionLike, Multiple extends boolean> = Multiple extends true ? Value[] : Value | undefined;
233
- interface AutocompleteRebuiltBaseProps<Value extends OptionLike, Multiple extends boolean, SectionExtra extends object, ActionExtra extends object> extends AriaInputPropsManaged, Pick<HTMLInputBaseProps, "name" | "disabled" | "readOnly" | "autoFocus">, Pick<RebuiltInputCommonProps, "placeholder" | "error" | "invalid" | "loading" | "description" | "size" | "prefix" | "suffix" | "version">, FocusEvents<HTMLInputElement | HTMLTextAreaElement> {
233
+ interface AutocompleteRebuiltBaseProps<Value extends OptionLike, Multiple extends boolean, SectionExtra extends object, ActionExtra extends object> extends AriaInputPropsManaged, Pick<HTMLInputBaseProps, "name" | "disabled" | "readOnly" | "autoFocus">, Pick<RebuiltInputCommonProps, "placeholder" | "error" | "invalid" | "loading" | "clearable" | "description" | "size" | "prefix" | "suffix" | "version">, FocusEvents<HTMLInputElement | HTMLTextAreaElement> {
234
234
  /**
235
235
  * Whether the autocomplete allows multiple selections.
236
- * WARNING: This is currently incomplete and will not display selections, only data is returned.
237
- * Do not use this prop unless you are sure you know what you are doing.
236
+ * When true, selected values are displayed as dismissible chips above the input.
237
+ * The menu stays open after each selection so the user can pick additional options.
238
+ * Pressing Backspace on an empty input removes the most recently added selection.
238
239
  */
239
240
  readonly multiple?: Multiple;
240
241
  /**
@@ -322,6 +323,21 @@ interface AutocompleteRebuiltBaseProps<Value extends OptionLike, Multiple extend
322
323
  value: MenuFooter<ActionExtra>;
323
324
  isActive?: boolean;
324
325
  }) => React.ReactNode;
326
+ /**
327
+ * Render prop to customize the content inside each selection chip.
328
+ * Only applicable in `multiple` mode. The Autocomplete handles the chip container,
329
+ * padding, dismiss button, hover/focus states, and disabled/readOnly behavior.
330
+ * You only provide the content that appears to the left of the dismiss button.
331
+ *
332
+ * When not provided, the chip content defaults to `getOptionLabel(option)`.
333
+ *
334
+ * @param args.value - The selected option this chip represents
335
+ * @param args.getOptionLabel - Function to get the display text for an option
336
+ */
337
+ readonly customRenderValue?: (args: {
338
+ value: Value;
339
+ getOptionLabel: (option: Value) => string;
340
+ }) => React.ReactNode;
325
341
  /**
326
342
  * Render prop to customize the rendering of the input.
327
343
  * @param props.inputRef - The ref to the input element
@@ -345,6 +361,7 @@ interface AutocompleteRebuiltBaseProps<Value extends OptionLike, Multiple extend
345
361
  input?: string;
346
362
  header?: string;
347
363
  footer?: string;
364
+ selection?: string;
348
365
  };
349
366
  /**
350
367
  * **Use at your own risk:** Custom style for specific elements. This should only be used as a
@@ -359,6 +376,7 @@ interface AutocompleteRebuiltBaseProps<Value extends OptionLike, Multiple extend
359
376
  input?: CSSProperties;
360
377
  header?: CSSProperties;
361
378
  footer?: CSSProperties;
379
+ selection?: CSSProperties;
362
380
  };
363
381
  /**
364
382
  * Render a custom empty state when the menu is empty.
@@ -377,6 +395,26 @@ interface AutocompleteRebuiltBaseProps<Value extends OptionLike, Multiple extend
377
395
  readonly emptyActions?: MenuAction<ActionExtra>[] | ((args: {
378
396
  inputValue: string;
379
397
  }) => MenuAction<ActionExtra>[]);
398
+ /**
399
+ * Maximum number of selection chips visible when the input is not focused.
400
+ * When the input gains focus, all selections are shown regardless of this value.
401
+ * Set to `-1` to always show all selections.
402
+ *
403
+ * Only applicable when `multiple` is `true`. Ignored for single-select.
404
+ *
405
+ * @default 6
406
+ */
407
+ readonly limitVisibleSelections?: number;
408
+ /**
409
+ * Function to generate the label displayed when selections are truncated
410
+ * by `limitVisibleSelections`. Receives the number of hidden selections.
411
+ * The final returned content must be Phrasing Content eg. string, span, etc.
412
+ *
413
+ * Only applicable when `multiple` is `true`. Ignored for single-select.
414
+ *
415
+ * @default (count) => `+${count}`
416
+ */
417
+ readonly limitSelectionText?: (truncatedCount: number) => React.ReactNode;
380
418
  /**
381
419
  * Whether the menu should open when the input gains focus.
382
420
  * Note: Clicking on the input will always open the menu.
@@ -0,0 +1,61 @@
1
+ import React from "react";
2
+ import type { UseFloatingReturn, UseInteractionsReturn } from "@floating-ui/react";
3
+ import type { ActionConfig, AutocompleteRebuiltProps, MenuFooter, MenuHeader, OptionLike } from "../Autocomplete.types";
4
+ import type { RenderItem } from "../useAutocomplete";
5
+ interface FloatingMenuProps<Value extends OptionLike> {
6
+ readonly context: UseFloatingReturn["context"];
7
+ readonly getFloatingProps: UseInteractionsReturn["getFloatingProps"];
8
+ readonly refs: UseFloatingReturn["refs"];
9
+ readonly listboxId: string;
10
+ readonly className: string;
11
+ readonly floatingStyles: React.CSSProperties;
12
+ readonly transitionStyles: React.CSSProperties;
13
+ readonly menuWidth?: number;
14
+ readonly menuStyle?: React.CSSProperties;
15
+ readonly renderable: Array<RenderItem<Value>>;
16
+ readonly persistentsHeaders: Array<MenuHeader<Record<string, unknown>>>;
17
+ readonly persistentsFooters: Array<MenuFooter<Record<string, unknown>>>;
18
+ readonly activeIndex: number | null;
19
+ readonly headerInteractiveCount: number;
20
+ readonly middleNavigableCount: number;
21
+ readonly getItemProps: UseInteractionsReturn["getItemProps"];
22
+ readonly listRef: React.RefObject<Array<HTMLElement | null>>;
23
+ readonly onSelection: (option: Value) => void;
24
+ readonly onAction: (action: ActionConfig) => void;
25
+ readonly onInteractionPointerDown: (e: React.PointerEvent) => void;
26
+ readonly getOptionLabel: (option: Value) => string;
27
+ readonly isOptionSelected: (option: Value) => boolean;
28
+ readonly loading: boolean;
29
+ readonly showEmptyStateMessage: boolean;
30
+ readonly emptyStateMessage?: React.ReactNode;
31
+ readonly customRenderLoading?: React.ReactNode;
32
+ readonly customRenderOption?: AutocompleteRebuiltProps<Value, false>["customRenderOption"];
33
+ readonly customRenderSection?: AutocompleteRebuiltProps<Value, false>["customRenderSection"];
34
+ readonly customRenderAction?: AutocompleteRebuiltProps<Value, false>["customRenderAction"];
35
+ readonly customRenderHeader?: AutocompleteRebuiltProps<Value, false>["customRenderHeader"];
36
+ readonly customRenderFooter?: AutocompleteRebuiltProps<Value, false>["customRenderFooter"];
37
+ readonly slotOverrides?: {
38
+ option?: {
39
+ className?: string;
40
+ style?: React.CSSProperties;
41
+ };
42
+ action?: {
43
+ className?: string;
44
+ style?: React.CSSProperties;
45
+ };
46
+ section?: {
47
+ className?: string;
48
+ style?: React.CSSProperties;
49
+ };
50
+ header?: {
51
+ className?: string;
52
+ style?: React.CSSProperties;
53
+ };
54
+ footer?: {
55
+ className?: string;
56
+ style?: React.CSSProperties;
57
+ };
58
+ };
59
+ }
60
+ export declare function FloatingMenu<Value extends OptionLike>({ context, getFloatingProps, refs, listboxId, className, floatingStyles, transitionStyles, menuWidth, menuStyle, renderable, persistentsHeaders, persistentsFooters, activeIndex, headerInteractiveCount, middleNavigableCount, getItemProps, listRef, onSelection, onAction, onInteractionPointerDown, getOptionLabel, isOptionSelected, loading, showEmptyStateMessage, emptyStateMessage, customRenderLoading, customRenderOption, customRenderSection, customRenderAction, customRenderHeader, customRenderFooter, slotOverrides, }: FloatingMenuProps<Value>): React.JSX.Element;
61
+ export {};
@@ -1 +1,4 @@
1
+ import type { OptionLike } from "./Autocomplete.types";
1
2
  export declare const AUTOCOMPLETE_MAX_HEIGHT = 300;
3
+ /** Stable empty array for cleared/empty selection state. Reuse to avoid reference churn. */
4
+ export declare const EMPTY_SELECTED_VALUES: readonly OptionLike[];
@@ -16,8 +16,15 @@ export interface UseAutocompleteListNavReturn {
16
16
  export interface UseAutocompleteListNavProps {
17
17
  navigableCount: number;
18
18
  shouldResetActiveIndexOnClose?: () => boolean;
19
+ onMenuOpen?: () => void;
19
20
  onMenuClose?: (reason?: string) => void;
20
21
  selectedIndex?: number | null;
21
22
  readOnly?: boolean;
23
+ disabled?: boolean;
24
+ /**
25
+ * When the reference is smaller than the clickable area (e.g. input inside chip area),
26
+ * pass a selector for the extended zone. Clicks inside it won't trigger outsidePress dismiss.
27
+ */
28
+ outsidePressExcludeSelector?: string;
22
29
  }
23
- export declare function useAutocompleteListNav({ navigableCount, shouldResetActiveIndexOnClose, onMenuClose, selectedIndex, readOnly, }: UseAutocompleteListNavProps): UseAutocompleteListNavReturn;
30
+ export declare function useAutocompleteListNav({ navigableCount, shouldResetActiveIndexOnClose, onMenuOpen, onMenuClose, selectedIndex, readOnly, disabled, outsidePressExcludeSelector, }: UseAutocompleteListNavProps): UseAutocompleteListNavReturn;
@@ -0,0 +1,17 @@
1
+ import type React from "react";
2
+ import type { OptionLike } from "../Autocomplete.types";
3
+ interface UseChipNavigationProps<Value extends OptionLike> {
4
+ readonly selectedValues: Value[];
5
+ readonly inputValue: string;
6
+ readonly readOnly?: boolean;
7
+ readonly removeSelection: (option: Value) => void;
8
+ readonly onInputKeyDown: (event: React.KeyboardEvent) => void;
9
+ readonly onInputBlur: (event: React.FocusEvent<HTMLInputElement | HTMLTextAreaElement>) => void;
10
+ }
11
+ interface UseChipNavigationReturn {
12
+ readonly activeChipIndex: number | null;
13
+ readonly onKeyDown: (event: React.KeyboardEvent) => void;
14
+ readonly onBlur: (event: React.FocusEvent<HTMLInputElement | HTMLTextAreaElement>) => void;
15
+ }
16
+ export declare function useChipNavigation<Value extends OptionLike>({ selectedValues, inputValue, readOnly, removeSelection, onInputKeyDown, onInputBlur, }: UseChipNavigationProps<Value>): UseChipNavigationReturn;
17
+ export {};