@jobber/components 6.66.0 → 6.67.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.
@@ -21,7 +21,17 @@ export interface ComboboxProps {
21
21
  /**
22
22
  * Callback function invoked upon the selection of an option. Provides the selected option(s) as an argument.
23
23
  */
24
- readonly onSelect: (selection: ComboboxOption[]) => void;
24
+ readonly onSelect: (selection: ComboboxSelection[]) => void;
25
+ /**
26
+ * Callback function invoked upon the selection of all options. Provides the selected option(s) as an argument.
27
+ * This is only available when `multiSelect` is `true`.
28
+ */
29
+ readonly onSelectAll?: (selection: ComboboxSelection[]) => void;
30
+ /**
31
+ * Callback function invoked upon the clearing of all options.
32
+ * This is only available when `multiSelect` is `true`.
33
+ */
34
+ readonly onClear?: () => void;
25
35
  /**
26
36
  * Callback function invoked upon the Combobox menu closing.
27
37
  */
@@ -102,8 +112,13 @@ export interface ComboboxOptionProps {
102
112
  readonly customRender?: (option: Omit<ComboboxOptionProps, "customRender"> & {
103
113
  isSelected: boolean;
104
114
  }) => React.ReactNode;
115
+ /**
116
+ * Callback function invoked when the option is clicked.
117
+ */
118
+ readonly onClick?: (option: ComboboxOption) => void;
105
119
  }
106
120
  export type ComboboxOption = ComboboxOptionProps;
121
+ export type ComboboxSelection = Pick<ComboboxOptionProps, "id" | "label">;
107
122
  export interface ComboboxContentProps {
108
123
  /**
109
124
  * The selected options of the Combobox.
@@ -10,6 +10,8 @@ export interface ComboboxProviderProps {
10
10
  readonly shouldScroll: MutableRefObject<boolean>;
11
11
  readonly searchValue: string;
12
12
  readonly label?: string;
13
+ readonly onClear?: () => void;
14
+ readonly onSelectAll?: (selection: ComboboxOption[]) => void;
13
15
  }
14
16
  export declare const ComboboxContext: React.Context<Omit<ComboboxProviderProps, "children">>;
15
17
  export declare function ComboboxContextProvider({ children, ...props }: ComboboxProviderProps): JSX.Element;
@@ -1,6 +1,8 @@
1
1
  import { ComboboxOption } from "../Combobox.types";
2
2
  interface useComboboxContent {
3
3
  optionsListRef: React.RefObject<HTMLUListElement>;
4
+ onClear?: () => void;
5
+ onSelectAll?: (selection: ComboboxOption[]) => void;
4
6
  }
5
7
  export declare function useComboboxContent(open: boolean, selected: ComboboxOption[]): useComboboxContent;
6
8
  export {};
@@ -1,10 +1,10 @@
1
1
  import { ReactElement } from "react";
2
- import { ComboboxProps } from "../Combobox.types";
2
+ import { ComboboxActionProps, ComboboxActivatorProps, ComboboxOptionProps, ComboboxProps } from "../Combobox.types";
3
3
  export declare const COMBOBOX_TRIGGER_COUNT_ERROR_MESSAGE = "Combobox must have exactly one Trigger element";
4
4
  export declare function useComboboxValidation(children?: ComboboxProps["children"]): {
5
- triggerElement?: ReactElement;
6
- optionElements?: ReactElement[];
7
- actionElements?: ReactElement[];
5
+ triggerElement?: ReactElement<ComboboxActivatorProps>;
6
+ optionElements?: ReactElement<ComboboxOptionProps>[];
7
+ actionElements?: ReactElement<ComboboxActionProps>[];
8
8
  };
9
9
  /**
10
10
  * Return all instances child component that matches the `type` provided
@@ -1,3 +1,3 @@
1
1
  export * from "./Combobox";
2
2
  export { ComboboxContextProvider } from "./ComboboxProvider";
3
- export { ComboboxOption, ComboboxCustomActivatorProps } from "./Combobox.types";
3
+ export { ComboboxOption, ComboboxCustomActivatorProps, ComboboxSelection, } from "./Combobox.types";
@@ -97,16 +97,11 @@ function getCompoundComponents(type, children) {
97
97
 
98
98
  function Combobox(props) {
99
99
  const { optionElements, triggerElement, actionElements } = useComboboxValidation(props.children);
100
- const options = React.useMemo(() => (optionElements === null || optionElements === void 0 ? void 0 : optionElements.map(option => ({
101
- id: option.props.id,
102
- label: option.props.label,
103
- prefix: option.props.prefix,
104
- customRender: option.props.customRender,
105
- }))) || [], [optionElements]);
100
+ const options = React.useMemo(() => (optionElements === null || optionElements === void 0 ? void 0 : optionElements.map(option => (Object.assign({}, option.props)))) || [], [optionElements]);
106
101
  const { selectedOptions, selectedStateSetter, shouldScroll, wrapperRef, searchValue, setSearchValue, open, handleClose, handleSelection, handleOpen, internalFilteredOptions, handleSearchChange, } = useCombobox(props.selected, props.onSelect, options, props.onClose, props.multiSelect, props.onSearch, props.onSearchDebounce);
107
- return (React.createElement(ComboboxProvider.ComboboxContextProvider, { selected: selectedOptions, selectionHandler: handleSelection, open: open, handleOpen: handleOpen, handleClose: handleClose, shouldScroll: shouldScroll, searchValue: searchValue, label: props.label },
102
+ return (React.createElement(ComboboxProvider.ComboboxContextProvider, { selected: selectedOptions, selectionHandler: handleSelection, open: open, handleOpen: handleOpen, handleClose: handleClose, shouldScroll: shouldScroll, searchValue: searchValue, label: props.label, onClear: props.onClear, onSelectAll: props.onSelectAll },
108
103
  React.createElement("div", { ref: wrapperRef, className: styles.wrapper },
109
- open && (React.createElement("div", { className: styles.overlay, onClick: () => handleClose(), "data-testid": "ATL-Combobox-Overlay" })),
104
+ open && (React.createElement("div", { className: styles.overlay, onClick: handleClose, "data-testid": "ATL-Combobox-Overlay" })),
110
105
  triggerElement || (React.createElement(ComboboxTrigger.ComboboxTrigger, { label: props.label, selected: props.selected, activatorRef: props.defaultActivatorRef })),
111
106
  React.createElement(ComboboxContent.ComboboxContent, { multiselect: props.multiSelect, subjectNoun: props.subjectNoun, selected: selectedOptions, actionElements: actionElements, selectedStateSetter: selectedStateSetter, handleSelection: handleSelection, searchValue: searchValue, setSearchValue: setSearchValue, wrapperRef: wrapperRef, open: open, options: props.onSearch ? options : internalFilteredOptions, loading: props.loading, handleSearchChange: handleSearchChange, onLoadMore: props.onLoadMore }))));
112
107
  }
@@ -95,16 +95,11 @@ function getCompoundComponents(type, children) {
95
95
 
96
96
  function Combobox(props) {
97
97
  const { optionElements, triggerElement, actionElements } = useComboboxValidation(props.children);
98
- const options = useMemo(() => (optionElements === null || optionElements === void 0 ? void 0 : optionElements.map(option => ({
99
- id: option.props.id,
100
- label: option.props.label,
101
- prefix: option.props.prefix,
102
- customRender: option.props.customRender,
103
- }))) || [], [optionElements]);
98
+ const options = useMemo(() => (optionElements === null || optionElements === void 0 ? void 0 : optionElements.map(option => (Object.assign({}, option.props)))) || [], [optionElements]);
104
99
  const { selectedOptions, selectedStateSetter, shouldScroll, wrapperRef, searchValue, setSearchValue, open, handleClose, handleSelection, handleOpen, internalFilteredOptions, handleSearchChange, } = useCombobox(props.selected, props.onSelect, options, props.onClose, props.multiSelect, props.onSearch, props.onSearchDebounce);
105
- return (React__default.createElement(ComboboxContextProvider, { selected: selectedOptions, selectionHandler: handleSelection, open: open, handleOpen: handleOpen, handleClose: handleClose, shouldScroll: shouldScroll, searchValue: searchValue, label: props.label },
100
+ return (React__default.createElement(ComboboxContextProvider, { selected: selectedOptions, selectionHandler: handleSelection, open: open, handleOpen: handleOpen, handleClose: handleClose, shouldScroll: shouldScroll, searchValue: searchValue, label: props.label, onClear: props.onClear, onSelectAll: props.onSelectAll },
106
101
  React__default.createElement("div", { ref: wrapperRef, className: styles.wrapper },
107
- open && (React__default.createElement("div", { className: styles.overlay, onClick: () => handleClose(), "data-testid": "ATL-Combobox-Overlay" })),
102
+ open && (React__default.createElement("div", { className: styles.overlay, onClick: handleClose, "data-testid": "ATL-Combobox-Overlay" })),
108
103
  triggerElement || (React__default.createElement(ComboboxTrigger, { label: props.label, selected: props.selected, activatorRef: props.defaultActivatorRef })),
109
104
  React__default.createElement(ComboboxContent, { multiselect: props.multiSelect, subjectNoun: props.subjectNoun, selected: selectedOptions, actionElements: actionElements, selectedStateSetter: selectedStateSetter, handleSelection: handleSelection, searchValue: searchValue, setSearchValue: setSearchValue, wrapperRef: wrapperRef, open: open, options: props.onSearch ? options : internalFilteredOptions, loading: props.loading, handleSearchChange: handleSearchChange, onLoadMore: props.onLoadMore }))));
110
105
  }
@@ -15,7 +15,7 @@ var constants = require('./constants-cjs.js');
15
15
  var styles = {"content":"QsRc49DHSgA-","hidden":"_7Fd5XGsPpUA-","actions":"yV8-0Hs43J0-","actionPadding":"g3Gdt8jXvFk-","spinning":"dJVYYOaf04E-"};
16
16
 
17
17
  function useComboboxContent(open, selected) {
18
- const { shouldScroll } = React.useContext(ComboboxProvider.ComboboxContext);
18
+ const { onClear, onSelectAll, shouldScroll } = React.useContext(ComboboxProvider.ComboboxContext);
19
19
  const optionsListRef = React.useRef(null);
20
20
  React.useEffect(() => {
21
21
  var _a;
@@ -29,6 +29,8 @@ function useComboboxContent(open, selected) {
29
29
  }
30
30
  }, [open, selected]);
31
31
  return {
32
+ onClear,
33
+ onSelectAll,
32
34
  optionsListRef,
33
35
  };
34
36
  }
@@ -134,7 +136,7 @@ function useComboboxAccessibility(selectionCallback, filteredOptions, optionsLis
134
136
 
135
137
  function ComboboxContent(props) {
136
138
  const optionsExist = props.options.length > 0;
137
- const { optionsListRef } = useComboboxContent(props.open, props.selected);
139
+ const { onClear, onSelectAll, optionsListRef } = useComboboxContent(props.open, props.selected);
138
140
  const { popperRef, popperStyles, floatingProps, nodeId, parentNodeId } = useComboboxAccessibility(props.handleSelection, props.options, optionsListRef, props.open, props.wrapperRef);
139
141
  const content = (React.createElement("div", Object.assign({ ref: popperRef, id: constants.COMBOBOX_MENU_ID, "data-testid": constants.COMBOBOX_MENU_ID, "data-elevation": "elevated", tabIndex: 0, className: classnames(styles.content, {
140
142
  [styles.hidden]: !props.open,
@@ -142,8 +144,10 @@ function ComboboxContent(props) {
142
144
  React.createElement(ComboboxContentSearch.ComboboxContentSearch, { open: props.open, placeholder: props.subjectNoun, searchValue: props.searchValue, setSearchValue: props.setSearchValue, handleSearchChange: props.handleSearchChange }),
143
145
  props.multiselect && (optionsExist || props.selected.length > 0) && (React.createElement(ComboboxContentHeader.ComboboxContentHeader, { hasOptionsVisible: optionsExist, subjectNoun: props.subjectNoun, selectedCount: props.selected.length, onClearAll: () => {
144
146
  props.selectedStateSetter([]);
147
+ onClear === null || onClear === void 0 ? void 0 : onClear();
145
148
  }, onSelectAll: () => {
146
149
  props.selectedStateSetter(props.options);
150
+ onSelectAll === null || onSelectAll === void 0 ? void 0 : onSelectAll(props.options);
147
151
  } })),
148
152
  React.createElement(ComboboxContentList.ComboboxContentList, { multiselect: props.multiselect, options: props.options, selected: props.selected, optionsListRef: optionsListRef, searchValue: props.searchValue, subjectNoun: props.subjectNoun, loading: props.loading, onLoadMore: props.onLoadMore }),
149
153
  props.actionElements && (React.createElement("div", { className: styles.actions, role: "group" }, props.actionElements.map((child, index, childrenArray) => (React.createElement("div", { key: index, className: classnames({
@@ -13,7 +13,7 @@ import { C as COMBOBOX_MENU_ID } from './constants-es.js';
13
13
  var styles = {"content":"QsRc49DHSgA-","hidden":"_7Fd5XGsPpUA-","actions":"yV8-0Hs43J0-","actionPadding":"g3Gdt8jXvFk-","spinning":"dJVYYOaf04E-"};
14
14
 
15
15
  function useComboboxContent(open, selected) {
16
- const { shouldScroll } = useContext(ComboboxContext);
16
+ const { onClear, onSelectAll, shouldScroll } = useContext(ComboboxContext);
17
17
  const optionsListRef = useRef(null);
18
18
  useEffect(() => {
19
19
  var _a;
@@ -27,6 +27,8 @@ function useComboboxContent(open, selected) {
27
27
  }
28
28
  }, [open, selected]);
29
29
  return {
30
+ onClear,
31
+ onSelectAll,
30
32
  optionsListRef,
31
33
  };
32
34
  }
@@ -132,7 +134,7 @@ function useComboboxAccessibility(selectionCallback, filteredOptions, optionsLis
132
134
 
133
135
  function ComboboxContent(props) {
134
136
  const optionsExist = props.options.length > 0;
135
- const { optionsListRef } = useComboboxContent(props.open, props.selected);
137
+ const { onClear, onSelectAll, optionsListRef } = useComboboxContent(props.open, props.selected);
136
138
  const { popperRef, popperStyles, floatingProps, nodeId, parentNodeId } = useComboboxAccessibility(props.handleSelection, props.options, optionsListRef, props.open, props.wrapperRef);
137
139
  const content = (React__default.createElement("div", Object.assign({ ref: popperRef, id: COMBOBOX_MENU_ID, "data-testid": COMBOBOX_MENU_ID, "data-elevation": "elevated", tabIndex: 0, className: classnames(styles.content, {
138
140
  [styles.hidden]: !props.open,
@@ -140,8 +142,10 @@ function ComboboxContent(props) {
140
142
  React__default.createElement(ComboboxContentSearch, { open: props.open, placeholder: props.subjectNoun, searchValue: props.searchValue, setSearchValue: props.setSearchValue, handleSearchChange: props.handleSearchChange }),
141
143
  props.multiselect && (optionsExist || props.selected.length > 0) && (React__default.createElement(ComboboxContentHeader, { hasOptionsVisible: optionsExist, subjectNoun: props.subjectNoun, selectedCount: props.selected.length, onClearAll: () => {
142
144
  props.selectedStateSetter([]);
145
+ onClear === null || onClear === void 0 ? void 0 : onClear();
143
146
  }, onSelectAll: () => {
144
147
  props.selectedStateSetter(props.options);
148
+ onSelectAll === null || onSelectAll === void 0 ? void 0 : onSelectAll(props.options);
145
149
  } })),
146
150
  React__default.createElement(ComboboxContentList, { multiselect: props.multiselect, options: props.options, selected: props.selected, optionsListRef: optionsListRef, searchValue: props.searchValue, subjectNoun: props.subjectNoun, loading: props.loading, onLoadMore: props.onLoadMore }),
147
151
  props.actionElements && (React__default.createElement("div", { className: styles.actions, role: "group" }, props.actionElements.map((child, index, childrenArray) => (React__default.createElement("div", { key: index, className: classnames({
@@ -18,7 +18,7 @@ function ComboboxContentList(props) {
18
18
  return (React.createElement("div", { className: classnames(styles.container, styles[listScrollState]) },
19
19
  optionsExist && (React.createElement("ul", { className: styles.optionsList, role: "listbox", "aria-multiselectable": props.multiselect, ref: props.optionsListRef },
20
20
  props.options.map(option => {
21
- return (React.createElement(ComboboxOption.ComboboxOption, { key: option.id, id: option.id, label: option.label, prefix: option.prefix, customRender: option.customRender }));
21
+ return (React.createElement(ComboboxOption.ComboboxOption, { key: option.id, id: option.id, label: option.label, prefix: option.prefix, customRender: option.customRender, onClick: option.onClick }));
22
22
  }),
23
23
  React.createElement("div", { className: classnames([styles.loadingContainer, styles.hasOptions]) },
24
24
  React.createElement(AnimatedPresence.AnimatedPresence, { transition: "fromBottom" }, Boolean(props.loading && optionsExist) && (React.createElement(Spinner.Spinner, { size: "small" })))),
@@ -16,7 +16,7 @@ function ComboboxContentList(props) {
16
16
  return (React__default.createElement("div", { className: classnames(styles.container, styles[listScrollState]) },
17
17
  optionsExist && (React__default.createElement("ul", { className: styles.optionsList, role: "listbox", "aria-multiselectable": props.multiselect, ref: props.optionsListRef },
18
18
  props.options.map(option => {
19
- return (React__default.createElement(ComboboxOption, { key: option.id, id: option.id, label: option.label, prefix: option.prefix, customRender: option.customRender }));
19
+ return (React__default.createElement(ComboboxOption, { key: option.id, id: option.id, label: option.label, prefix: option.prefix, customRender: option.customRender, onClick: option.onClick }));
20
20
  }),
21
21
  React__default.createElement("div", { className: classnames([styles.loadingContainer, styles.hasOptions]) },
22
22
  React__default.createElement(AnimatedPresence, { transition: "fromBottom" }, Boolean(props.loading && optionsExist) && (React__default.createElement(Spinner, { size: "small" })))),
@@ -10,11 +10,15 @@ var ComboboxProvider = require('./ComboboxProvider-cjs.js');
10
10
  var styles = {"option":"HowvTX8-pw4-","spinning":"iwgbuC2MqzI-"};
11
11
 
12
12
  function ComboboxOption(props) {
13
- const { customRender } = props, contentProps = tslib_es6.__rest(props, ["customRender"]);
13
+ const { customRender, onClick } = props, contentProps = tslib_es6.__rest(props, ["customRender", "onClick"]);
14
14
  const { selected, selectionHandler } = React.useContext(ComboboxProvider.ComboboxContext);
15
15
  const isSelected = selected.some(selection => selection.id.toString() === props.id.toString());
16
- return (React.createElement("li", { key: props.id, tabIndex: -1, "data-selected": isSelected, role: "option", "aria-selected": isSelected, onClick: () => selectionHandler &&
17
- selectionHandler({ id: props.id, label: props.label }), className: classnames(styles.option) }, customRender ? (customRender(Object.assign(Object.assign({}, contentProps), { isSelected }))) : (React.createElement(InternalDefaultContent, Object.assign({}, contentProps, { isSelected: isSelected })))));
16
+ const handleClick = () => {
17
+ const { id, label } = props;
18
+ selectionHandler === null || selectionHandler === void 0 ? void 0 : selectionHandler({ id, label });
19
+ onClick === null || onClick === void 0 ? void 0 : onClick({ id, label });
20
+ };
21
+ return (React.createElement("li", { key: props.id, tabIndex: -1, "data-selected": isSelected, role: "option", "aria-selected": isSelected, onClick: handleClick, className: classnames(styles.option) }, customRender ? (customRender(Object.assign(Object.assign({}, contentProps), { isSelected }))) : (React.createElement(InternalDefaultContent, Object.assign({}, contentProps, { isSelected: isSelected })))));
18
22
  }
19
23
  function InternalDefaultContent(props) {
20
24
  return (React.createElement(React.Fragment, null,
@@ -8,11 +8,15 @@ import { a as ComboboxContext } from './ComboboxProvider-es.js';
8
8
  var styles = {"option":"HowvTX8-pw4-","spinning":"iwgbuC2MqzI-"};
9
9
 
10
10
  function ComboboxOption(props) {
11
- const { customRender } = props, contentProps = __rest(props, ["customRender"]);
11
+ const { customRender, onClick } = props, contentProps = __rest(props, ["customRender", "onClick"]);
12
12
  const { selected, selectionHandler } = useContext(ComboboxContext);
13
13
  const isSelected = selected.some(selection => selection.id.toString() === props.id.toString());
14
- return (React__default.createElement("li", { key: props.id, tabIndex: -1, "data-selected": isSelected, role: "option", "aria-selected": isSelected, onClick: () => selectionHandler &&
15
- selectionHandler({ id: props.id, label: props.label }), className: classnames(styles.option) }, customRender ? (customRender(Object.assign(Object.assign({}, contentProps), { isSelected }))) : (React__default.createElement(InternalDefaultContent, Object.assign({}, contentProps, { isSelected: isSelected })))));
14
+ const handleClick = () => {
15
+ const { id, label } = props;
16
+ selectionHandler === null || selectionHandler === void 0 ? void 0 : selectionHandler({ id, label });
17
+ onClick === null || onClick === void 0 ? void 0 : onClick({ id, label });
18
+ };
19
+ return (React__default.createElement("li", { key: props.id, tabIndex: -1, "data-selected": isSelected, role: "option", "aria-selected": isSelected, onClick: handleClick, className: classnames(styles.option) }, customRender ? (customRender(Object.assign(Object.assign({}, contentProps), { isSelected }))) : (React__default.createElement(InternalDefaultContent, Object.assign({}, contentProps, { isSelected: isSelected })))));
16
20
  }
17
21
  function InternalDefaultContent(props) {
18
22
  return (React__default.createElement(React__default.Fragment, null,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jobber/components",
3
- "version": "6.66.0",
3
+ "version": "6.67.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -542,5 +542,5 @@
542
542
  "> 1%",
543
543
  "IE 10"
544
544
  ],
545
- "gitHead": "c4b9bf8f3dab846ea63b3f772f993a5232de10af"
545
+ "gitHead": "6246dedceb2a622533b0bb366c0a96b312eabc0e"
546
546
  }