@jobber/components 4.58.5 → 4.59.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,16 +1,11 @@
1
1
  /// <reference types="react" />
2
2
  import { ComboboxProps } from "./Combobox.types";
3
- import { ComboboxContent } from "./components/ComboboxContent";
4
3
  import { ComboboxAction } from "./components/ComboboxAction";
5
- import { ComboboxTriggerButton, ComboboxTriggerChip } from "./components/ComboboxTrigger";
6
- import { ComboboxOption } from "./components/ComboboxOption";
4
+ import { ComboboxOption as ComboboxOptionComponent } from "./components/ComboboxOption/ComboboxOption";
7
5
  import { ComboboxActivator } from "./components/ComboboxActivator";
8
- export declare function Combobox({ multiSelect, label, selected, ...props }: ComboboxProps): JSX.Element;
6
+ export declare function Combobox(props: ComboboxProps): JSX.Element;
9
7
  export declare namespace Combobox {
10
- var TriggerButton: typeof ComboboxTriggerButton;
11
- var TriggerChip: typeof ComboboxTriggerChip;
12
8
  var Activator: typeof ComboboxActivator;
13
- var Content: typeof ComboboxContent;
14
9
  var Action: typeof ComboboxAction;
15
- var Option: typeof ComboboxOption;
10
+ var Option: typeof ComboboxOptionComponent;
16
11
  }
@@ -1,8 +1,8 @@
1
1
  import { Dispatch, ReactElement, SetStateAction } from "react";
2
- import { XOR } from "ts-xor";
3
- import { ButtonProps } from "../Button";
4
- export interface ComboboxProps extends Partial<Omit<ComboboxContentBaseProps, "options">> {
5
- readonly children: ReactElement | ReactElement[];
2
+ type ComboboxFragment = Iterable<ComboboxNode>;
3
+ type ComboboxNode = ReactElement | ComboboxFragment;
4
+ export interface ComboboxProps {
5
+ readonly children?: ComboboxNode;
6
6
  /**
7
7
  * When `true`, `Combobox` will allow for multiple selections
8
8
  *
@@ -10,52 +10,48 @@ export interface ComboboxProps extends Partial<Omit<ComboboxContentBaseProps, "o
10
10
  */
11
11
  readonly multiSelect?: boolean;
12
12
  /**
13
- * The label for the Combobox trigger
14
- */
15
- readonly label?: string;
16
- readonly onSelect?: (selection: ComboboxOption[]) => void;
17
- readonly onClose?: (selection: ComboboxOption[]) => void;
18
- }
19
- export interface ComboboxTriggerProps {
20
- /**
21
- * The label text of the trigger.
13
+ * Placeholder text to display in the search input. Defaults to "Search".
22
14
  */
23
- readonly label: string;
24
- }
25
- export interface ComboboxTriggerButtonProps extends ComboboxTriggerProps, Pick<ButtonProps, "type" | "variation" | "icon" | "iconOnRight"> {
26
- }
27
- export type ComboboxTriggerChipProps = ComboboxTriggerProps;
28
- export interface ComboboxOption {
15
+ readonly searchPlaceholder?: string;
29
16
  /**
30
- * A unique identifier for the option.
17
+ * The selected options of the Combobox.
31
18
  */
32
- id: string | number;
19
+ readonly selected: ComboboxOption[];
33
20
  /**
34
- * The value to be visually displayed in the Combobox options list.
21
+ * The encapsulating noun for the content of the combobox. Used
22
+ * in the empty state, and search placeholder. Should be pluralized.
35
23
  */
36
- label: string;
37
- }
38
- interface ComboboxCloseProps {
24
+ readonly subjectNoun?: string;
39
25
  /**
40
26
  * Callback function invoked upon the selection of an option. Provides the selected option(s) as an argument.
41
27
  */
42
28
  readonly onSelect: (selection: ComboboxOption[]) => void;
43
- }
44
- interface ComboboxSelectProps {
45
29
  /**
46
- * Callback function invoked upon the Combobox menu closing. Provides the selected option(s) as an argument.
30
+ * Callback function invoked upon the Combobox menu closing.
31
+ */
32
+ readonly onClose?: () => void;
33
+ /**
34
+ * The Chip heading for the trigger
47
35
  */
48
- readonly onClose: (selection: ComboboxOption[]) => void;
36
+ readonly label?: string;
37
+ }
38
+ export interface ComboboxActivatorProps {
39
+ readonly children: React.ReactElement;
40
+ }
41
+ export interface ComboboxTriggerProps extends Pick<ComboboxContentProps, "selected"> {
42
+ readonly label?: string;
49
43
  }
50
- interface ComboboxContentBaseProps {
44
+ export interface ComboboxOption {
51
45
  /**
52
- * List of selectable options to display.
46
+ * A unique identifier for the option.
53
47
  */
54
- readonly options: ComboboxOption[];
48
+ id: string | number;
55
49
  /**
56
- * Optional action button(s) to display at the bottom of the list.
50
+ * The value to be visually displayed in the Combobox options list.
57
51
  */
58
- readonly children?: ReactElement | ReactElement[];
52
+ label: string;
53
+ }
54
+ export interface ComboboxContentProps {
59
55
  /**
60
56
  * Placeholder text to display in the search input. Defaults to "Search".
61
57
  */
@@ -69,8 +65,47 @@ interface ComboboxContentBaseProps {
69
65
  * in the empty state, and search placeholder. Should be pluralized.
70
66
  */
71
67
  readonly subjectNoun?: string;
68
+ /**
69
+ * Action elements to be displayed at the bottom of the list.
70
+ */
71
+ readonly actionElements?: ReactElement[];
72
+ /**
73
+ * State setter for the selected options.
74
+ */
75
+ readonly selectedStateSetter: (selection: ComboboxOption[]) => void;
76
+ /**
77
+ * Callback function to be called when an option is selected.
78
+ */
79
+ readonly handleSelection: (option: ComboboxOption) => void;
80
+ /**
81
+ * Are multiple selections permitted.
82
+ */
83
+ readonly multiselect?: boolean;
84
+ /**
85
+ * The current search term.
86
+ */
87
+ readonly searchValue: string;
88
+ /**
89
+ * Setter for the current search term.
90
+ */
91
+ readonly setSearchValue: Dispatch<SetStateAction<string>>;
92
+ /**
93
+ * Reference to the wrapping div element of all the Combobox pieces
94
+ */
95
+ readonly wrapperRef: React.RefObject<HTMLDivElement>;
96
+ /**
97
+ * Is the Combobox open
98
+ */
99
+ readonly open: boolean;
100
+ /**
101
+ * Setter for the open state of the Combobox.
102
+ */
103
+ readonly setOpen: (open: boolean) => void;
104
+ /**
105
+ * The full set of options for the Combobox in the shape of data, not elements.
106
+ */
107
+ readonly options: ComboboxOption[];
72
108
  }
73
- export type ComboboxContentProps = ComboboxContentBaseProps & XOR<ComboboxCloseProps, ComboboxSelectProps>;
74
109
  export interface ComboboxSearchProps {
75
110
  /**
76
111
  * The placeholder for the search input.
@@ -128,14 +163,6 @@ export interface ComboboxListProps {
128
163
  * A ref to the list element.
129
164
  */
130
165
  readonly optionsListRef: React.RefObject<HTMLUListElement>;
131
- /**
132
- * Setter for the first selected element, which is used to scroll the list to the first selected element on re-opening.
133
- */
134
- readonly setFirstSelectedElement: React.Dispatch<SetStateAction<HTMLElement | null>>;
135
- /**
136
- * The callback function to call when an option is selected.
137
- */
138
- readonly selectionHandler: (option: ComboboxOption) => void;
139
166
  /**
140
167
  * The current search term. Used in the no results message.
141
168
  */
@@ -143,7 +170,7 @@ export interface ComboboxListProps {
143
170
  /**
144
171
  * Determines if it is a single selection or multi selection Combobox.
145
172
  */
146
- readonly multiselect: boolean;
173
+ readonly multiselect?: boolean;
147
174
  /**
148
175
  * The noun to be used in the empty state message.
149
176
  */
@@ -1,12 +1,20 @@
1
- import React, { RefObject } from "react";
1
+ import React, { Dispatch, MutableRefObject, SetStateAction } from "react";
2
+ import { ComboboxOption } from "./Combobox.types";
2
3
  export declare const ComboboxContext: React.Context<{
3
- multiselect: boolean;
4
4
  open: boolean;
5
5
  setOpen: (open: boolean) => void;
6
- wrapperRef: RefObject<HTMLDivElement>;
6
+ selected: ComboboxOption[];
7
+ selectionHandler: (option: ComboboxOption) => void;
8
+ handleClose: () => void;
9
+ shouldScroll: MutableRefObject<boolean>;
7
10
  }>;
8
11
  export interface ComboboxProviderProps {
9
12
  readonly children: React.ReactNode;
10
- readonly multiselect?: boolean;
13
+ readonly selected: ComboboxOption[];
14
+ readonly selectionHandler: (option: ComboboxOption) => void;
15
+ readonly open: boolean;
16
+ readonly setOpen: Dispatch<SetStateAction<boolean>>;
17
+ readonly handleClose: () => void;
18
+ readonly shouldScroll: MutableRefObject<boolean>;
11
19
  }
12
20
  export declare function ComboboxContextProvider(props: ComboboxProviderProps): JSX.Element;
@@ -1,6 +1,3 @@
1
1
  import React from "react";
2
- interface ComboboxActivatorProps {
3
- readonly children: React.ReactElement;
4
- }
2
+ import { ComboboxActivatorProps } from "../../Combobox.types";
5
3
  export declare function ComboboxActivator(props: ComboboxActivatorProps): React.ReactElement<any, string | React.JSXElementConstructor<any>>;
6
- export {};
@@ -1,2 +1,6 @@
1
- import { ComboboxOption as ComboboxOptionType } from "../../Combobox.types";
2
- export declare function ComboboxOption(_: ComboboxOptionType): null;
1
+ /// <reference types="react" />
2
+ export interface ComboboxOptionProps {
3
+ readonly id: string | number;
4
+ readonly label: string;
5
+ }
6
+ export declare function ComboboxOption(props: ComboboxOptionProps): JSX.Element;
@@ -1,7 +1,3 @@
1
1
  /// <reference types="react" />
2
- import { ComboboxContentProps } from "../../Combobox.types";
3
- interface ComboboxTriggerProps extends Pick<ComboboxContentProps, "selected"> {
4
- readonly label: string;
5
- }
6
- export declare function ComboboxTrigger({ selected, ...props }: ComboboxTriggerProps): JSX.Element;
7
- export {};
2
+ import { ComboboxTriggerProps } from "../../Combobox.types";
3
+ export declare function ComboboxTrigger({ label, selected, }: ComboboxTriggerProps): JSX.Element;
@@ -1,3 +1 @@
1
- export { ComboboxTriggerButton } from "./ComboboxTriggerButton/ComboboxTriggerButton";
2
- export { ComboboxTriggerChip } from "./ComboboxTriggerChip/ComboboxTriggerChip";
3
1
  export { ComboboxTrigger } from "./ComboboxTrigger";
@@ -0,0 +1,15 @@
1
+ import React, { Dispatch, MutableRefObject } from "react";
2
+ import { UseMakeComboboxHandlersReturn } from "./useMakeComboboxHandlers";
3
+ import { ComboboxOption } from "../Combobox.types";
4
+ type UseComboboxReturn = {
5
+ wrapperRef: React.RefObject<HTMLDivElement>;
6
+ searchValue: string;
7
+ setSearchValue: Dispatch<React.SetStateAction<string>>;
8
+ open: boolean;
9
+ setOpen: Dispatch<React.SetStateAction<boolean>>;
10
+ selectedOptions: ComboboxOption[];
11
+ selectedStateSetter: (selection: ComboboxOption[]) => void;
12
+ shouldScroll: MutableRefObject<boolean>;
13
+ } & UseMakeComboboxHandlersReturn;
14
+ export declare function useCombobox(selected: ComboboxOption[], onSelect: (selection: ComboboxOption[]) => void, onClose?: () => void, multiSelect?: boolean): UseComboboxReturn;
15
+ export {};
@@ -1,6 +1,6 @@
1
1
  /// <reference types="react" />
2
2
  import { ComboboxOption } from "../Combobox.types";
3
- export declare function useComboboxAccessibility(selectionCallback: (selection: ComboboxOption) => void, filteredOptions: ComboboxOption[], optionsListRef: React.RefObject<HTMLUListElement>, open: boolean, setOpen: (open: boolean) => void, wrapperRef: React.RefObject<HTMLDivElement>): {
3
+ export declare function useComboboxAccessibility(selectionCallback: (selection: ComboboxOption) => void, filteredOptions: ComboboxOption[], optionsListRef: React.RefObject<HTMLUListElement>, open: boolean, wrapperRef: React.RefObject<HTMLDivElement>): {
4
4
  popperRef: React.RefObject<HTMLDivElement>;
5
5
  popperStyles: {
6
6
  [key: string]: React.CSSProperties;
@@ -1,13 +1,8 @@
1
1
  /// <reference types="react" />
2
2
  import { ComboboxOption } from "../Combobox.types";
3
3
  interface useComboboxContent {
4
- searchValue: string;
5
- setSearchValue: React.Dispatch<React.SetStateAction<string>>;
6
- setFirstSelectedElement: React.Dispatch<React.SetStateAction<HTMLElement | null>>;
7
4
  filteredOptions: ComboboxOption[];
8
5
  optionsListRef: React.RefObject<HTMLUListElement>;
9
- selectedOptions: ComboboxOption[];
10
- optionsSelectionHandler: (selected: ComboboxOption[]) => void;
11
6
  }
12
- export declare function useComboboxContent(options: ComboboxOption[], open: boolean, selected: ComboboxOption[], onClose: ((selection: ComboboxOption[]) => void) | undefined, onSelect: ((selection: ComboboxOption[]) => void) | undefined): useComboboxContent;
7
+ export declare function useComboboxContent(options: ComboboxOption[], open: boolean, selected: ComboboxOption[], searchValue: string): useComboboxContent;
13
8
  export {};
@@ -1,10 +1,12 @@
1
- import { ReactElement, ReactNode } from "react";
2
- import { ComboboxActionProps, ComboboxOption as ComboboxOptionProps } from "../Combobox.types";
3
- export declare const COMBOBOX_TRIGGER_COUNT_ERROR_MESSAGE = "Combobox can only have one Trigger or Activator element";
4
- export declare const COMBOBOX_OPTION_AND_CONTENT_EXISTS_ERROR = "Combobox prefers using Combobox.Option and Combobox.Action as the direct child of Combobox instead of Combobox.Content";
5
- export declare function useComboboxValidation(children: ReactNode): {
6
- triggerElement: ReactNode;
7
- contentElement: ReactNode | undefined;
8
- optionElements: ReactElement<ComboboxOptionProps>[];
9
- actionElements: ReactElement<ComboboxActionProps>[];
1
+ import { ReactElement } from "react";
2
+ import { ComboboxProps } from "../Combobox.types";
3
+ export declare const COMBOBOX_TRIGGER_COUNT_ERROR_MESSAGE = "Combobox must have exactly one Trigger element";
4
+ export declare function useComboboxValidation(children?: ComboboxProps["children"]): {
5
+ triggerElement?: ReactElement;
6
+ optionElements?: ReactElement[];
7
+ actionElements?: ReactElement[];
10
8
  };
9
+ /**
10
+ * Return all instances child component that matches the `type` provided
11
+ */
12
+ export declare function getCompoundComponents<T>(type: ReactElement<T>["type"], children?: ComboboxProps["children"]): ReactElement<T>[];
@@ -0,0 +1,7 @@
1
+ import React from "react";
2
+ import { ComboboxOption } from "../Combobox.types";
3
+ export interface UseMakeComboboxHandlersReturn {
4
+ handleClose: () => void;
5
+ handleSelection: (selection: ComboboxOption) => void;
6
+ }
7
+ export declare function useMakeComboboxHandlers(setOpen: (open: boolean) => void, setSearchValue: (searchValue: string) => void, selectedOptions: ComboboxOption[], shouldScroll: React.MutableRefObject<boolean>, selectedStateSetter: (selected: ComboboxOption[]) => void, multiSelect?: boolean, onClose?: () => void): UseMakeComboboxHandlersReturn;
@@ -2,7 +2,6 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var tslib_es6 = require('../tslib.es6-5b8768b7.js');
6
5
  var React = require('react');
7
6
  var classnames = require('classnames');
8
7
  var ReactDOM = require('react-dom');
@@ -16,8 +15,8 @@ var useFocusTrap = require('@jobber/hooks/useFocusTrap');
16
15
  var reactPopper = require('react-popper');
17
16
  var useOnKeyDown = require('@jobber/hooks/useOnKeyDown');
18
17
  var Chip = require('../Chip-f8b8fd89.js');
19
- var useAssert = require('@jobber/hooks/useAssert');
20
18
  require('@jobber/design');
19
+ var useAssert = require('@jobber/hooks/useAssert');
21
20
  require('react-router-dom');
22
21
  require('@jobber/hooks/useInView');
23
22
  require('../Avatar-1aa30ee1.js');
@@ -63,24 +62,40 @@ function ComboboxContentSearch(props) {
63
62
  }
64
63
  }
65
64
 
66
- var css_248z$4 = ".SgMzjOcdE-E- {\n position: relative;\n padding: calc(16px / 2) 0;\n padding: var(--space-small) 0;\n}\n\n.TwoTCjgcssc- {\n display: -ms-flexbox;\n display: flex;\n max-height: calc((16px / 2) * 33.33);\n max-height: calc(calc(16px / 2) * 33.33);\n max-height: calc(var(--space-small) * 33.33);\n margin: 0;\n padding: 0;\n overflow: scroll;\n list-style: none;\n -ms-flex-direction: column;\n flex-direction: column;\n gap: calc(16px / 4);\n gap: var(--space-smaller);\n}\n\n._2LVD-wjMRfQ- {\n display: -ms-flexbox;\n display: flex;\n min-height: calc((calc(16px * 3) - calc(16px / 4)));\n min-height: calc((var(--space-largest) - var(--space-smaller)));\n box-sizing: border-box;\n margin: 0 calc(16px / 2);\n margin: 0 var(--space-small);\n padding: calc(16px / 2);\n padding: var(--space-small);\n border-radius: calc(16px / 4);\n border-radius: var(--radius-large);\n color: rgb(1, 41, 57);\n color: var(--color-heading);\n font-weight: 500;\n cursor: pointer;\n transition: all 200ms;\n transition: all var(--timing-base);\n -ms-flex-pack: justify;\n justify-content: space-between;\n -ms-flex-align: center;\n align-items: center;\n}\n\n._2LVD-wjMRfQ-:hover,\n._2LVD-wjMRfQ-:focus {\n background-color: rgb(244, 244, 244);\n background-color: var(--color-surface--background);\n}\n\n._2LVD-wjMRfQ-:focus {\n box-shadow: 0px 0px calc(16px / 4) calc(16px / 8)\n rgb(231, 213, 87);\n box-shadow: var(--shadow-focus);\n}\n\n._8T5M7MGwCRE-,\n._4y5NXkNeIQM- {\n padding: calc(16px / 2) calc(16px * 1);\n padding: var(--space-small) var(--space-base);\n}\n\n.SgMzjOcdE-E-::after {\n content: \"\";\n display: block;\n position: absolute;\n right: 0;\n bottom: calc(16px / 2);\n bottom: var(--space-small);\n left: 0;\n height: calc(16px * 1);\n height: var(--space-base);\n background: linear-gradient(\n 180deg,\n rgba(255, 255, 255, 0) 0%,\n rgb(255, 255, 255) 100%\n );\n}\n\n.SgMzjOcdE-E-::before {\n content: \"\";\n display: block;\n position: absolute;\n top: calc(16px / 2);\n top: var(--space-small);\n right: 0;\n left: 0;\n height: calc(16px * 1);\n height: var(--space-base);\n background: linear-gradient(\n to bottom,\n rgba(255, 255, 255, 1),\n rgba(255, 255, 255, 0)\n );\n}\n";
67
- var styles$4 = {"container":"SgMzjOcdE-E-","optionsList":"TwoTCjgcssc-","option":"_2LVD-wjMRfQ-","filterMessage":"_8T5M7MGwCRE-","emptyStateMessage":"_4y5NXkNeIQM-"};
65
+ var css_248z$4 = ".SgMzjOcdE-E- {\n position: relative;\n padding: calc(16px / 2) 0;\n padding: var(--space-small) 0;\n}\n\n.TwoTCjgcssc- {\n display: -ms-flexbox;\n display: flex;\n max-height: calc((16px / 2) * 33.33);\n max-height: calc(calc(16px / 2) * 33.33);\n max-height: calc(var(--space-small) * 33.33);\n margin: 0;\n padding: 0;\n overflow: scroll;\n list-style: none;\n -ms-flex-direction: column;\n flex-direction: column;\n gap: calc(16px / 4);\n gap: var(--space-smaller);\n}\n\n._8T5M7MGwCRE-,\n._4y5NXkNeIQM- {\n padding: calc(16px / 2) calc(16px * 1);\n padding: var(--space-small) var(--space-base);\n}\n\n.SgMzjOcdE-E-::after {\n content: \"\";\n display: block;\n position: absolute;\n right: 0;\n bottom: calc(16px / 2);\n bottom: var(--space-small);\n left: 0;\n height: calc(16px * 1);\n height: var(--space-base);\n background: linear-gradient(\n 180deg,\n rgba(255, 255, 255, 0) 0%,\n rgb(255, 255, 255) 100%\n );\n}\n\n.SgMzjOcdE-E-::before {\n content: \"\";\n display: block;\n position: absolute;\n top: calc(16px / 2);\n top: var(--space-small);\n right: 0;\n left: 0;\n height: calc(16px * 1);\n height: var(--space-base);\n background: linear-gradient(\n to bottom,\n rgba(255, 255, 255, 1),\n rgba(255, 255, 255, 0)\n );\n}\n";
66
+ var styles$4 = {"container":"SgMzjOcdE-E-","optionsList":"TwoTCjgcssc-","filterMessage":"_8T5M7MGwCRE-","emptyStateMessage":"_4y5NXkNeIQM-"};
68
67
  styleInject_es.styleInject(css_248z$4);
69
68
 
69
+ var css_248z$3 = "._5QdRGmaNHvc- {\n display: -ms-flexbox;\n display: flex;\n min-height: calc((calc(16px * 3) - calc(16px / 4)));\n min-height: calc((var(--space-largest) - var(--space-smaller)));\n box-sizing: border-box;\n margin: 0 calc(16px / 2);\n margin: 0 var(--space-small);\n padding: calc(16px / 2);\n padding: var(--space-small);\n border-radius: calc(16px / 4);\n border-radius: var(--radius-large);\n color: rgb(1, 41, 57);\n color: var(--color-heading);\n font-weight: 500;\n cursor: pointer;\n transition: all 200ms;\n transition: all var(--timing-base);\n -ms-flex-pack: justify;\n justify-content: space-between;\n -ms-flex-align: center;\n align-items: center;\n}\n\n._5QdRGmaNHvc-:hover,\n._5QdRGmaNHvc-:focus {\n background-color: rgb(244, 244, 244);\n background-color: var(--color-surface--background);\n}\n\n._5QdRGmaNHvc-:focus {\n box-shadow: 0px 0px calc(16px / 4) calc(16px / 8)\n rgb(231, 213, 87);\n box-shadow: var(--shadow-focus);\n}\n";
70
+ var styles$3 = {"option":"_5QdRGmaNHvc-"};
71
+ styleInject_es.styleInject(css_248z$3);
72
+
73
+ const ComboboxContext = React__default["default"].createContext({});
74
+ function ComboboxContextProvider(props) {
75
+ return (React__default["default"].createElement(ComboboxContext.Provider, { value: {
76
+ open: props.open,
77
+ setOpen: props.setOpen,
78
+ selected: props.selected,
79
+ selectionHandler: props.selectionHandler,
80
+ handleClose: props.handleClose,
81
+ shouldScroll: props.shouldScroll,
82
+ } }, props.children));
83
+ }
84
+
85
+ function ComboboxOption(props) {
86
+ const { selected, selectionHandler } = React.useContext(ComboboxContext);
87
+ const isSelected = selected.some(selection => selection.id.toString() === props.id.toString());
88
+ return (React__default["default"].createElement("li", { key: props.id, tabIndex: -1, "data-selected": isSelected, role: "option", "aria-selected": isSelected, onClick: () => selectionHandler &&
89
+ selectionHandler({ id: props.id, label: props.label }), className: classnames__default["default"](styles$3.option) },
90
+ props.label,
91
+ isSelected && React__default["default"].createElement(Icon.Icon, { name: "checkmark", color: "blue" })));
92
+ }
93
+
70
94
  function ComboboxContentList(props) {
71
- let hasSeenFirstSelected = false;
72
95
  return (React__default["default"].createElement("div", { className: styles$4.container },
73
96
  !props.showEmptyState && props.options.length > 0 && (React__default["default"].createElement("ul", { className: styles$4.optionsList, role: "listbox", "aria-multiselectable": props.multiselect, ref: props.optionsListRef }, !props.showEmptyState &&
74
97
  props.options.map(option => {
75
- const isSelected = props.selected.some(selection => selection.id.toString() === option.id.toString());
76
- return (React__default["default"].createElement("li", { ref: listItem => {
77
- if (isSelected && !hasSeenFirstSelected) {
78
- props.setFirstSelectedElement(listItem);
79
- hasSeenFirstSelected = true;
80
- }
81
- }, key: option.id, tabIndex: -1, role: "option", "aria-selected": isSelected, onClick: () => props.selectionHandler(option), className: classnames__default["default"](styles$4.option) },
82
- option.label,
83
- isSelected && React__default["default"].createElement(Icon.Icon, { name: "checkmark", color: "blue" })));
98
+ return (React__default["default"].createElement(ComboboxOption, { key: option.id, id: option.id, label: option.label }));
84
99
  }))),
85
100
  !props.showEmptyState && props.options.length === 0 && (React__default["default"].createElement("div", { className: styles$4.filterMessage },
86
101
  React__default["default"].createElement(Text.Text, { variation: "subdued" },
@@ -96,9 +111,9 @@ function getZeroIndexStateText(subjectNoun) {
96
111
  return "No options yet";
97
112
  }
98
113
 
99
- var css_248z$3 = ".Q-mwo-g5Fi8- {\n display: -ms-flexbox;\n display: flex;\n padding: calc(16px * 1) calc(16px / 2) 0 calc(16px * 1);\n padding: var(--space-base) var(--space-small) 0 var(--space-base);\n -ms-flex-pack: justify;\n justify-content: space-between;\n gap: calc(16px / 4);\n gap: var(--space-smaller);\n}\n";
100
- var styles$3 = {"header":"Q-mwo-g5Fi8-"};
101
- styleInject_es.styleInject(css_248z$3);
114
+ var css_248z$2 = ".Q-mwo-g5Fi8- {\n display: -ms-flexbox;\n display: flex;\n padding: calc(16px * 1) calc(16px / 2) 0 calc(16px * 1);\n padding: var(--space-base) var(--space-small) 0 var(--space-base);\n -ms-flex-pack: justify;\n justify-content: space-between;\n gap: calc(16px / 4);\n gap: var(--space-smaller);\n}\n";
115
+ var styles$2 = {"header":"Q-mwo-g5Fi8-"};
116
+ styleInject_es.styleInject(css_248z$2);
102
117
 
103
118
  function ComboboxContentHeader(props) {
104
119
  const hasSelected = props.selectedCount > 0;
@@ -106,7 +121,7 @@ function ComboboxContentHeader(props) {
106
121
  const label = getLabel(hasSelected, props.selectedCount, props.subjectNoun);
107
122
  const handleSelectAll = hasSelected ? props.onClearAll : props.onSelectAll;
108
123
  const showAction = hasSelected || props.hasOptionsVisible;
109
- return (React__default["default"].createElement("div", { className: styles$3.header, "data-testid": "ATL-Combobox-Header" },
124
+ return (React__default["default"].createElement("div", { className: styles$2.header, "data-testid": "ATL-Combobox-Header" },
110
125
  React__default["default"].createElement(Typography.Typography, { textColor: "heading", fontWeight: "semiBold" }, label),
111
126
  showAction && (React__default["default"].createElement(Button.Button, { size: "small", label: actionLabel, type: "tertiary", onClick: handleSelectAll }))));
112
127
  }
@@ -120,58 +135,38 @@ function getLabel(hasSelected, count, subjectNoun) {
120
135
  return "Select";
121
136
  }
122
137
 
123
- var css_248z$2 = ".W8qMZnORYxI- {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 6;\n z-index: var(--elevation-menu);\n background-color: transparent;\n}\n";
124
- var styles$2 = {"overlay":"W8qMZnORYxI-"};
125
- styleInject_es.styleInject(css_248z$2);
126
-
127
- const ComboboxContext = React__default["default"].createContext({});
128
- function ComboboxContextProvider(props) {
129
- const multiselect = props.multiselect || false;
130
- const [open, setOpen] = React.useState(false);
131
- const wrapperRef = React.useRef(null);
132
- return (React__default["default"].createElement(ComboboxContext.Provider, { value: { multiselect, open, setOpen, wrapperRef } },
133
- React__default["default"].createElement("div", { ref: wrapperRef },
134
- open && (React__default["default"].createElement("div", { className: styles$2.overlay, onClick: () => setOpen(false), "data-testid": "ATL-Combobox-Overlay" })),
135
- props.children)));
136
- }
137
-
138
- function useComboboxContent(options, open, selected, onClose, onSelect) {
139
- const [searchValue, setSearchValue] = React.useState("");
140
- const [firstSelectedElement, setFirstSelectedElement] = React.useState(null);
138
+ function useComboboxContent(options, open, selected, searchValue) {
139
+ const { shouldScroll } = React.useContext(ComboboxContext);
141
140
  const optionsListRef = React.useRef(null);
142
141
  const filteredOptions = options.filter(option => option.label.toLowerCase().includes(searchValue.toLowerCase()));
143
- const [internalSelected, setInternalSelected] = React.useState(selected);
144
- const selectedOptions = onClose ? internalSelected : selected;
145
- const optionsSelectionHandler = onSelect ? onSelect : setInternalSelected;
146
- React.useEffect(() => {
147
- if (!open && onClose) {
148
- onClose(selectedOptions);
149
- }
150
- }, [open, onClose, selectedOptions]);
151
142
  React.useEffect(() => {
152
- if (open && firstSelectedElement) {
153
- firstSelectedElement === null || firstSelectedElement === void 0 ? void 0 : firstSelectedElement.scrollIntoView({
154
- block: "nearest",
143
+ var _a;
144
+ if (open && shouldScroll.current && optionsListRef.current) {
145
+ const firstSelected = Array.from((_a = optionsListRef === null || optionsListRef === void 0 ? void 0 : optionsListRef.current) === null || _a === void 0 ? void 0 : _a.children).find(child => {
146
+ if (child instanceof HTMLElement) {
147
+ return child.dataset.selected === "true";
148
+ }
155
149
  });
150
+ scrollToFirstSelected(firstSelected, shouldScroll);
156
151
  }
157
- }, [open, firstSelectedElement]);
158
- React.useEffect(() => {
159
- if (selectedOptions.length === 0) {
160
- setFirstSelectedElement(null);
161
- }
162
- }, [selectedOptions]);
152
+ }, [open, selected]);
163
153
  return {
164
- searchValue,
165
- setSearchValue,
166
- setFirstSelectedElement,
167
154
  filteredOptions,
168
155
  optionsListRef,
169
- selectedOptions,
170
- optionsSelectionHandler,
171
156
  };
172
157
  }
158
+ function scrollToFirstSelected(firstSelected, shouldScroll) {
159
+ if (firstSelected) {
160
+ firstSelected.scrollIntoView({
161
+ block: "nearest",
162
+ });
163
+ shouldScroll.current = false;
164
+ }
165
+ }
173
166
 
174
- function useComboboxAccessibility(selectionCallback, filteredOptions, optionsListRef, open, setOpen, wrapperRef) {
167
+ // eslint-disable-next-line max-statements
168
+ function useComboboxAccessibility(selectionCallback, filteredOptions, optionsListRef, open, wrapperRef) {
169
+ const { handleClose } = React.useContext(ComboboxContext);
175
170
  const hasOptionsVisible = open && filteredOptions.length > 0;
176
171
  const focusedIndex = React.useRef(null);
177
172
  useRefocusOnActivator.useRefocusOnActivator(open);
@@ -202,7 +197,7 @@ function useComboboxAccessibility(selectionCallback, filteredOptions, optionsLis
202
197
  }, [open, optionsListRef, filteredOptions]);
203
198
  useOnKeyDown.useOnKeyDown(() => {
204
199
  if (open) {
205
- setOpen(false);
200
+ handleClose();
206
201
  }
207
202
  }, "Escape");
208
203
  function handleContentKeydown(event) {
@@ -248,43 +243,21 @@ function useComboboxAccessibility(selectionCallback, filteredOptions, optionsLis
248
243
  }
249
244
 
250
245
  function ComboboxContent(props) {
251
- const { open, setOpen, wrapperRef, multiselect } = React__default["default"].useContext(ComboboxContext);
252
246
  const optionsExist = props.options.length > 0;
253
- const { searchValue, setSearchValue, setFirstSelectedElement, filteredOptions, optionsListRef, selectedOptions, optionsSelectionHandler, } = useComboboxContent(props.options, open, props.selected, props.onClose, props.onSelect);
254
- const { popperRef, popperStyles, attributes } = useComboboxAccessibility(handleSelection, filteredOptions, optionsListRef, open, setOpen, wrapperRef);
255
- const template = (React__default["default"].createElement("div", Object.assign({ ref: popperRef, id: "ATL-Combobox-Content", "data-testid": "ATL-Combobox-Content", tabIndex: 0, className: classnames__default["default"](styles$6.content, { [styles$6.hidden]: !open }), style: popperStyles.popper }, attributes.popper),
256
- React__default["default"].createElement(ComboboxContentSearch, { open: open, placeholder: props.subjectNoun, searchValue: searchValue, setSearchValue: setSearchValue }),
257
- multiselect && optionsExist && (React__default["default"].createElement(ComboboxContentHeader, { hasOptionsVisible: filteredOptions.length > 0, subjectNoun: props.subjectNoun, selectedCount: selectedOptions.length, onClearAll: () => {
258
- optionsSelectionHandler([]);
247
+ const { filteredOptions, optionsListRef } = useComboboxContent(props.options, props.open, props.selected, props.searchValue);
248
+ const { popperRef, popperStyles, attributes } = useComboboxAccessibility(props.handleSelection, filteredOptions, optionsListRef, props.open, props.wrapperRef);
249
+ const template = (React__default["default"].createElement("div", Object.assign({ ref: popperRef, id: "ATL-Combobox-Content", "data-testid": "ATL-Combobox-Content", tabIndex: 0, className: classnames__default["default"](styles$6.content, { [styles$6.hidden]: !props.open }), style: popperStyles.popper }, attributes.popper),
250
+ React__default["default"].createElement(ComboboxContentSearch, { open: props.open, placeholder: props.subjectNoun, searchValue: props.searchValue, setSearchValue: props.setSearchValue }),
251
+ props.multiselect && optionsExist && (React__default["default"].createElement(ComboboxContentHeader, { hasOptionsVisible: filteredOptions.length > 0, subjectNoun: props.subjectNoun, selectedCount: props.selected.length, onClearAll: () => {
252
+ props.selectedStateSetter([]);
259
253
  }, onSelectAll: () => {
260
- optionsSelectionHandler(filteredOptions);
254
+ props.selectedStateSetter(filteredOptions);
261
255
  } })),
262
- React__default["default"].createElement(ComboboxContentList, { multiselect: multiselect, showEmptyState: !optionsExist, options: filteredOptions, selected: selectedOptions, optionsListRef: optionsListRef, setFirstSelectedElement: setFirstSelectedElement, selectionHandler: handleSelection, searchValue: searchValue, subjectNoun: props.subjectNoun }),
263
- props.children && (React__default["default"].createElement("div", { className: styles$6.actions, role: "group" }, React__default["default"].Children.toArray(props.children).map((child, index, childrenArray) => (React__default["default"].createElement("div", { key: index, className: classnames__default["default"]({
256
+ React__default["default"].createElement(ComboboxContentList, { multiselect: props.multiselect, showEmptyState: !optionsExist, options: filteredOptions, selected: props.selected, optionsListRef: optionsListRef, searchValue: props.searchValue, subjectNoun: props.subjectNoun }),
257
+ props.actionElements && (React__default["default"].createElement("div", { className: styles$6.actions, role: "group" }, props.actionElements.map((child, index, childrenArray) => (React__default["default"].createElement("div", { key: index, className: classnames__default["default"]({
264
258
  [styles$6.actionPadding]: index === childrenArray.length - 1,
265
259
  }) }, child)))))));
266
260
  return ReactDOM__default["default"].createPortal(template, document.body);
267
- function handleSelection(selection) {
268
- if (multiselect) {
269
- handleMultiSelect(optionsSelectionHandler, selectedOptions, selection);
270
- }
271
- else {
272
- handleSingleSelect(optionsSelectionHandler, selection);
273
- }
274
- }
275
- function handleSingleSelect(selectCallback, selection) {
276
- selectCallback([selection]);
277
- setSearchValue("");
278
- setOpen(false);
279
- }
280
- }
281
- function handleMultiSelect(selectCallback, selected, selection) {
282
- if (selected.some(s => s.id === selection.id)) {
283
- selectCallback(selected.filter(s => s.id !== selection.id));
284
- }
285
- else {
286
- selectCallback([...selected, selection]);
287
- }
288
261
  }
289
262
 
290
263
  var css_248z$1 = ".Ow9wSNnGP-g- {\n width: 100%;\n box-sizing: border-box;\n padding: 0 calc(16px / 2);\n padding: 0 var(--space-small);\n background-color: rgba(255, 255, 255, 1);\n background-color: var(--color-surface);\n}\n\n.ncp0nKHQ7d8- {\n position: relative;\n width: 100%;\n min-height: calc((calc(16px * 3) - calc(16px / 2)));\n min-height: calc((var(--space-largest) - var(--space-small)));\n padding: calc(16px / 2) 0;\n padding: var(--space-small) 0;\n border: none;\n border-radius: calc(16px / 4);\n border-radius: var(--radius-large);\n text-align: left;\n background-color: rgba(255, 255, 255, 1);\n background-color: var(--color-surface);\n cursor: pointer;\n transition: all 200ms;\n transition: all var(--timing-base);\n}\n\n.ncp0nKHQ7d8-:focus {\n box-shadow: 0px 0px calc(16px / 4) calc(16px / 8)\n rgb(231, 213, 87);\n box-shadow: var(--shadow-focus);\n background-color: rgb(244, 244, 244);\n background-color: var(--color-surface--background);\n}\n\n.ncp0nKHQ7d8-:hover {\n background-color: rgb(244, 244, 244);\n background-color: var(--color-surface--background);\n}\n\n.ncp0nKHQ7d8- span {\n margin-left: calc(16px / 2);\n margin-left: var(--space-small);\n}\n";
@@ -297,127 +270,137 @@ function ComboboxAction(props) {
297
270
  React__default["default"].createElement(Typography.Typography, { element: "span", size: "base", textColor: "green", fontWeight: "semiBold" }, props.label))));
298
271
  }
299
272
 
300
- function ComboboxTriggerButton(props) {
301
- const { open, setOpen } = React__default["default"].useContext(ComboboxContext);
302
- return (React__default["default"].createElement(Button.Button, { role: "combobox", "aria-expanded": open, "aria-haspopup": "listbox", "aria-controls": "ATL-Combobox-Content", "aria-autocomplete": "list", label: props.label, variation: props.variation, type: props.type, onClick: () => setOpen(!open), icon: props.icon, iconOnRight: props.iconOnRight }));
273
+ function ComboboxTrigger({ label = "Select", selected, }) {
274
+ const { handleClose, open, setOpen } = React__default["default"].useContext(ComboboxContext);
275
+ const hasSelection = selected.length;
276
+ const selectedLabel = selected.map(option => option.label).join(", ");
277
+ return (React__default["default"].createElement(Chip.Chip, { variation: hasSelection ? "base" : "subtle", label: hasSelection ? selectedLabel : "", heading: label, onClick: () => {
278
+ if (open) {
279
+ handleClose();
280
+ }
281
+ else {
282
+ setOpen(true);
283
+ }
284
+ }, role: "combobox" }, !hasSelection && (React__default["default"].createElement(Chip.Chip.Suffix, null,
285
+ React__default["default"].createElement(Icon.Icon, { name: "add", size: "small" })))));
303
286
  }
304
287
 
305
- var css_248z = ".NtYpU6bZMtM- {\n display: -ms-inline-flexbox;\n display: inline-flex;\n padding: calc(16px / 2) calc(16px * 1);\n padding: var(--space-small) var(--space-base);\n border: calc(16px / 16) solid rgb(225, 225, 225);\n border: var(--border-base) solid var(--color-border);\n border-radius: calc((16px / 4) * 5);\n border-radius: calc(calc(16px / 4) * 5);\n border-radius: calc(var(--radius-large) * 5);\n font-size: calc((16px * 1) * 0.875);\n font-size: calc(calc(16px * 1) * 0.875);\n font-size: var(--typography--fontSize-base);\n background-color: rgba(255, 255, 255, 1);\n background-color: var(--color-surface);\n gap: calc(16px / 2);\n gap: var(--space-small);\n}\n\n.NtYpU6bZMtM-:focus {\n box-shadow: 0px 0px calc(16px / 4) calc(16px / 8)\n rgb(231, 213, 87);\n box-shadow: var(--shadow-focus);\n}\n\n.ftceU-6iBO0- {\n display: -ms-flexbox;\n display: flex;\n -ms-flex-pack: center;\n justify-content: center;\n -ms-flex-align: center;\n align-items: center;\n}\n";
306
- var styles = {"trigger":"NtYpU6bZMtM-","triggerIcon":"ftceU-6iBO0-"};
288
+ var css_248z = ".W8qMZnORYxI- {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 6;\n z-index: var(--elevation-menu);\n background-color: transparent;\n}\n\n._-0dkolvLF-Y- {\n display: inline-block;\n}\n";
289
+ var styles = {"overlay":"W8qMZnORYxI-","wrapper":"_-0dkolvLF-Y-"};
307
290
  styleInject_es.styleInject(css_248z);
308
291
 
309
- function ComboboxTriggerChip(props) {
310
- const { open, setOpen } = React__default["default"].useContext(ComboboxContext);
311
- return (React__default["default"].createElement("button", { className: styles.trigger, role: "combobox", type: "button", "aria-expanded": open, "aria-haspopup": "listbox", "aria-controls": "ATL-Combobox-Content", "aria-autocomplete": "list", onClick: () => {
312
- setOpen(!open);
313
- } },
314
- React__default["default"].createElement(Typography.Typography, { fontWeight: "semiBold", textColor: "heading" }, props.label),
315
- React__default["default"].createElement("div", { className: styles.triggerIcon },
316
- React__default["default"].createElement(Icon.Icon, { color: "surfaceReverse", name: "add", size: "small" }))));
292
+ function useMakeComboboxHandlers(setOpen, setSearchValue, selectedOptions, shouldScroll, selectedStateSetter, multiSelect, onClose) {
293
+ const handleClose = React.useCallback(() => {
294
+ setOpen(false);
295
+ setSearchValue("");
296
+ onClose && onClose();
297
+ if (selectedOptions.length > 0) {
298
+ shouldScroll.current = true;
299
+ }
300
+ }, [setOpen, setSearchValue, onClose, selectedOptions.length]);
301
+ const handleSelection = React.useCallback((selection) => {
302
+ if (multiSelect) {
303
+ handleMultiSelect(selectedStateSetter, selectedOptions, selection);
304
+ }
305
+ else {
306
+ handleSingleSelect(selectedStateSetter, selection);
307
+ }
308
+ }, [multiSelect, selectedStateSetter, selectedOptions]);
309
+ const handleSingleSelect = React.useCallback((selectCallback, selection) => {
310
+ selectCallback([selection]);
311
+ handleClose();
312
+ }, []);
313
+ return {
314
+ handleClose,
315
+ handleSelection,
316
+ };
317
+ }
318
+ function handleMultiSelect(selectCallback, selected, selection) {
319
+ if (selected.some(s => s.id === selection.id)) {
320
+ selectCallback(selected.filter(s => s.id !== selection.id));
321
+ }
322
+ else {
323
+ selectCallback([...selected, selection]);
324
+ }
317
325
  }
318
326
 
319
- function ComboboxTrigger(_a) {
320
- var { selected } = _a, props = tslib_es6.__rest(_a, ["selected"]);
321
- const { open, setOpen, multiselect } = React__default["default"].useContext(ComboboxContext);
322
- const hasSelection = selected.length;
323
- const selectedLabel = selected.map(option => option.label).join(", ");
324
- const renderHeading = multiselect || !hasSelection;
325
- return (React__default["default"].createElement(Chip.Chip, { variation: hasSelection ? "base" : "subtle", label: hasSelection ? selectedLabel : "", heading: renderHeading ? props.label : "", onClick: () => setOpen(!open), role: "combobox" }, !hasSelection && (React__default["default"].createElement(Chip.Chip.Suffix, null,
326
- React__default["default"].createElement(Icon.Icon, { name: "add", size: "small" })))));
327
+ function useCombobox(selected, onSelect, onClose, multiSelect) {
328
+ const wrapperRef = React.useRef(null);
329
+ const shouldScroll = React.useRef(false);
330
+ const [open, setOpen] = React.useState(false);
331
+ const [searchValue, setSearchValue] = React.useState("");
332
+ const { handleClose, handleSelection } = useMakeComboboxHandlers(setOpen, setSearchValue, selected, shouldScroll, onSelect, multiSelect, onClose);
333
+ return {
334
+ wrapperRef,
335
+ searchValue,
336
+ setSearchValue,
337
+ open,
338
+ setOpen,
339
+ selectedOptions: selected,
340
+ selectedStateSetter: onSelect,
341
+ shouldScroll,
342
+ handleClose,
343
+ handleSelection,
344
+ };
327
345
  }
328
346
 
329
347
  function ComboboxActivator(props) {
330
- const { open, setOpen } = React__default["default"].useContext(ComboboxContext);
348
+ const { handleClose, open, setOpen } = React__default["default"].useContext(ComboboxContext);
331
349
  if (props.children.type === Button.Button || props.children.type === Chip.Chip) {
332
350
  return React__default["default"].cloneElement(props.children, {
333
351
  role: "combobox",
334
- onClick: () => setOpen(!open),
352
+ onClick: () => {
353
+ if (open) {
354
+ handleClose();
355
+ }
356
+ else {
357
+ setOpen(true);
358
+ }
359
+ },
335
360
  });
336
361
  }
337
362
  return props.children;
338
363
  }
339
364
 
340
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
341
- function ComboboxOption(_) {
342
- useAssert.useAssert(true, "Combobox.Option can only be used inside a Combobox component");
343
- return null;
344
- }
345
-
346
- const COMBOBOX_TRIGGER_COUNT_ERROR_MESSAGE = "Combobox can only have one Trigger or Activator element";
347
- const COMBOBOX_OPTION_AND_CONTENT_EXISTS_ERROR = "Combobox prefers using Combobox.Option and Combobox.Action as the direct child of Combobox instead of Combobox.Content";
365
+ const COMBOBOX_TRIGGER_COUNT_ERROR_MESSAGE = "Combobox must have exactly one Trigger element";
348
366
  function useComboboxValidation(children) {
349
- const childrenArray = React__default["default"].Children.toArray(children);
350
- let triggerElement, contentElement, multipleTriggersFound = false;
351
- const optionElements = [];
352
- const actionElements = [];
353
- childrenArray.forEach(child => {
354
- if (isTriggerElement(child)) {
355
- if (triggerElement) {
356
- multipleTriggersFound = true;
357
- }
358
- triggerElement = child;
359
- }
360
- if (isContentElement(child)) {
361
- contentElement = child;
362
- }
363
- if (isOptionElement(child)) {
364
- optionElements.push(child);
365
- }
366
- if (isActionElement(child)) {
367
- actionElements.push(child);
368
- }
369
- });
370
- useAssert.useAssert(multipleTriggersFound, COMBOBOX_TRIGGER_COUNT_ERROR_MESSAGE);
371
- useAssert.useAssert(Boolean((optionElements.length || actionElements.length) && contentElement), COMBOBOX_OPTION_AND_CONTENT_EXISTS_ERROR);
367
+ const optionElements = getCompoundComponents(ComboboxOption, children);
368
+ const actionElements = getCompoundComponents(ComboboxAction, children);
369
+ const activatorElements = getCompoundComponents(ComboboxActivator, children);
370
+ const shouldThrowTriggerError = isInvalid(activatorElements);
371
+ useAssert.useAssert(shouldThrowTriggerError, COMBOBOX_TRIGGER_COUNT_ERROR_MESSAGE);
372
372
  return {
373
- contentElement,
374
- triggerElement,
375
373
  optionElements,
374
+ triggerElement: activatorElements[0],
376
375
  actionElements,
377
376
  };
378
377
  }
379
- function isTriggerElement(child) {
380
- return (React__default["default"].isValidElement(child) &&
381
- (child.type === ComboboxTriggerButton ||
382
- child.type === ComboboxTriggerChip ||
383
- child.type === ComboboxActivator));
384
- }
385
- function isContentElement(child) {
386
- return React__default["default"].isValidElement(child) && child.type === ComboboxContent;
378
+ function isInvalid(activators) {
379
+ return activators.length > 1 ? true : false;
387
380
  }
388
- function isOptionElement(child) {
389
- return React__default["default"].isValidElement(child) && child.type === ComboboxOption;
390
- }
391
- function isActionElement(child) {
392
- return React__default["default"].isValidElement(child) && child.type === ComboboxAction;
381
+ /**
382
+ * Return all instances child component that matches the `type` provided
383
+ */
384
+ function getCompoundComponents(type, children) {
385
+ const childrenArray = React.Children.toArray(children);
386
+ const elements = childrenArray.filter((child) => React.isValidElement(child) && child.type === type);
387
+ return elements;
393
388
  }
394
389
 
395
- function Combobox(_a) {
396
- var { multiSelect = false, label = "Select", selected = [] } = _a, props = tslib_es6.__rest(_a, ["multiSelect", "label", "selected"]);
397
- const { contentElement, triggerElement, optionElements, actionElements } = useComboboxValidation(props.children);
398
- const buildOptions = optionElements.map(option => ({
390
+ function Combobox(props) {
391
+ const { optionElements, triggerElement, actionElements } = useComboboxValidation(props.children);
392
+ const options = React.useMemo(() => (optionElements === null || optionElements === void 0 ? void 0 : optionElements.map(option => ({
399
393
  id: option.props.id,
400
394
  label: option.props.label,
401
- }));
402
- return (React__default["default"].createElement(ComboboxContextProvider, { multiselect: multiSelect },
403
- triggerElement || React__default["default"].createElement(ComboboxTrigger, { label: label, selected: selected }),
404
- contentElement || (
405
- // @ts-expect-error - Suppress the XOR error with onClose|onSelect until we finish the refactor on JOB-81416
406
- React__default["default"].createElement(ComboboxContent, Object.assign({ options: buildOptions, selected: selected }, props), actionElements))));
395
+ }))) || [], [optionElements]);
396
+ const { selectedOptions, selectedStateSetter, shouldScroll, wrapperRef, searchValue, setSearchValue, open, setOpen, handleClose, handleSelection, } = useCombobox(props.selected, props.onSelect, props.onClose, props.multiSelect);
397
+ return (React__default["default"].createElement(ComboboxContextProvider, { selected: selectedOptions, selectionHandler: handleSelection, open: open, setOpen: setOpen, handleClose: handleClose, shouldScroll: shouldScroll },
398
+ React__default["default"].createElement("div", { ref: wrapperRef, className: styles.wrapper },
399
+ open && (React__default["default"].createElement("div", { className: styles.overlay, onClick: () => handleClose(), "data-testid": "ATL-Combobox-Overlay" })),
400
+ triggerElement || (React__default["default"].createElement(ComboboxTrigger, { label: props.label, selected: props.selected })),
401
+ React__default["default"].createElement(ComboboxContent, { multiselect: props.multiSelect, searchPlaceholder: props.searchPlaceholder, subjectNoun: props.subjectNoun, selected: selectedOptions, actionElements: actionElements, selectedStateSetter: selectedStateSetter, handleSelection: handleSelection, searchValue: searchValue, setSearchValue: setSearchValue, wrapperRef: wrapperRef, open: open, setOpen: setOpen, options: options }))));
407
402
  }
408
- /**
409
- * @deprecated Use Combobox.Activator instead
410
- */
411
- Combobox.TriggerButton = ComboboxTriggerButton;
412
- /**
413
- * @deprecated Use Combobox.Activator instead
414
- */
415
- Combobox.TriggerChip = ComboboxTriggerChip;
416
403
  Combobox.Activator = ComboboxActivator;
417
- /**
418
- * @deprecated Use individual Combobox.Option instead
419
- */
420
- Combobox.Content = ComboboxContent;
421
404
  Combobox.Action = ComboboxAction;
422
405
  Combobox.Option = ComboboxOption;
423
406
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jobber/components",
3
- "version": "4.58.5",
3
+ "version": "4.59.0",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -84,5 +84,5 @@
84
84
  "> 1%",
85
85
  "IE 10"
86
86
  ],
87
- "gitHead": "e7ff430888d3261c08b96521ad414e1ad63c1cb5"
87
+ "gitHead": "6727b0e5428d011ebeec1f3b9bd642144964d977"
88
88
  }
@@ -1,3 +0,0 @@
1
- /// <reference types="react" />
2
- import { ComboboxTriggerButtonProps } from "../../../Combobox.types";
3
- export declare function ComboboxTriggerButton(props: ComboboxTriggerButtonProps): JSX.Element;
@@ -1,3 +0,0 @@
1
- /// <reference types="react" />
2
- import { ComboboxTriggerChipProps } from "../../../Combobox.types";
3
- export declare function ComboboxTriggerChip(props: ComboboxTriggerChipProps): JSX.Element;