@jobber/components 4.60.3-replace-da.7 → 4.60.3

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.
@@ -0,0 +1,53 @@
1
+ 'use strict';
2
+
3
+ var React = require('react');
4
+ var reactPopper = require('react-popper');
5
+ var useRefocusOnActivator = require('@jobber/hooks/useRefocusOnActivator');
6
+ var styleInject_es = require('./style-inject.es-9d2f5f4e.js');
7
+ var ButtonDismiss = require('./ButtonDismiss-1ccb84ec.js');
8
+
9
+ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
10
+
11
+ var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
12
+
13
+ var css_248z = ":root {\n --card--base-padding: var(--space-base);\n --popover--padding: var(--space-base);\n --popover--width: calc(var(--base-unit) * 21.875);\n --dismiss--button-padding: calc(var(--base-unit) / 4);\n}\n\n.oSlK4rLUvzE- {\n display: -ms-flexbox;\n display: flex;\n position: \"relative\";\n padding: calc(16px * 1);\n padding: var(--popover--padding);\n -ms-flex-pack: justify;\n justify-content: space-between;\n -ms-flex-align: center;\n align-items: center;\n}\n\n.XVPpPb-7e30- {\n float: right;\n padding: calc(16px / 4);\n padding: var(--dismiss--button-padding);\n text-align: right;\n}\n\n.TDuYbqXaLW0- {\n z-index: 1002;\n z-index: var(--elevation-tooltip);\n width: -webkit-max-content;\n width: max-content;\n max-width: calc(16px * 21.875);\n max-width: var(--popover--width);\n box-shadow: 0px calc(16px / 16) calc(16px / 4) 0px\n rgba(0, 0, 0, 0.1),\n 0px calc(16px / 4) 12px 0px rgba(0, 0, 0, 0.05);\n box-shadow: var(--shadow-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 / 8);\n border-radius: var(--radius-base);\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 line-height: normal;\n background: rgba(255, 255, 255, 1);\n background: var(--color-surface);\n}\n\n.TDuYbqXaLW0- > * {\n --public-content--padding: var(--card--base-padding);\n}\n\n.LJCpn0zf1e8- {\n visibility: hidden;\n}\n\n.LJCpn0zf1e8-,\n.LJCpn0zf1e8-::before {\n position: absolute;\n width: 16px;\n width: var(--base-unit);\n height: 16px;\n height: var(--base-unit);\n background: inherit;\n}\n\n.LJCpn0zf1e8-::before {\n content: \"\";\n visibility: visible;\n border: calc(16px / 16) solid rgb(225, 225, 225);\n border: var(--border-base) solid var(--color-border);\n -webkit-transform: rotate(45deg);\n transform: rotate(45deg);\n -webkit-transform-origin: center;\n transform-origin: center;\n -webkit-clip-path: polygon(-4px -4px, 15.3px 0, 0 15.3px);\n clip-path: polygon(-4px -4px, 15.3px 0, 0 15.3px);\n}\n\n.TDuYbqXaLW0-[data-popper-placement^=\"top\"] > .LJCpn0zf1e8- {\n bottom: -5px;\n}\n\n.TDuYbqXaLW0-[data-popper-placement^=\"top\"] > .LJCpn0zf1e8-::before {\n -webkit-transform: rotate(-135deg);\n transform: rotate(-135deg);\n}\n\n.TDuYbqXaLW0-[data-popper-placement^=\"bottom\"] > .LJCpn0zf1e8- {\n top: -7px;\n}\n\n.TDuYbqXaLW0-[data-popper-placement^=\"left\"] > .LJCpn0zf1e8- {\n right: -5px;\n}\n\n.TDuYbqXaLW0-[data-popper-placement^=\"left\"] > .LJCpn0zf1e8-::before {\n -webkit-transform: rotate(135deg);\n transform: rotate(135deg);\n}\n\n.TDuYbqXaLW0-[data-popper-placement^=\"right\"] > .LJCpn0zf1e8- {\n left: -7px;\n}\n\n.TDuYbqXaLW0-[data-popper-placement^=\"right\"] > .LJCpn0zf1e8-::before {\n -webkit-transform: rotate(-45deg);\n transform: rotate(-45deg);\n}\n";
14
+ var classes = {"header":"oSlK4rLUvzE-","dismissButton":"XVPpPb-7e30-","popover":"TDuYbqXaLW0-","arrow":"LJCpn0zf1e8-"};
15
+ styleInject_es.styleInject(css_248z);
16
+
17
+ function Popover({ onRequestClose, children, attachTo, open, preferredPlacement = "auto", }) {
18
+ const [popperElement, setPopperElement] = React.useState();
19
+ const [arrowElement, setArrowElement] = React.useState();
20
+ const { styles: popperStyles, attributes } = reactPopper.usePopper(attachTo instanceof Element ? attachTo : attachTo.current, popperElement, {
21
+ modifiers: buildModifiers(arrowElement),
22
+ placement: preferredPlacement,
23
+ });
24
+ useRefocusOnActivator.useRefocusOnActivator(open);
25
+ return (React__default["default"].createElement(React__default["default"].Fragment, null, open && (React__default["default"].createElement("div", Object.assign({ role: "dialog", ref: setPopperElement, style: popperStyles.popper, className: classes.popover }, attributes.popper),
26
+ React__default["default"].createElement("div", { className: classes.dismissButton },
27
+ React__default["default"].createElement(ButtonDismiss.ButtonDismiss, { onClick: onRequestClose, ariaLabel: "Close dialog" })),
28
+ children,
29
+ React__default["default"].createElement("div", { ref: setArrowElement, className: classes.arrow, style: popperStyles.arrow })))));
30
+ }
31
+ function buildModifiers(arrowElement) {
32
+ const modifiers = [
33
+ {
34
+ name: "arrow",
35
+ options: { element: arrowElement, padding: 10 },
36
+ },
37
+ {
38
+ name: "offset",
39
+ options: {
40
+ offset: [0, 10],
41
+ },
42
+ },
43
+ {
44
+ name: "flip",
45
+ options: {
46
+ fallbackPlacements: ["auto"],
47
+ },
48
+ },
49
+ ];
50
+ return modifiers;
51
+ }
52
+
53
+ exports.Popover = Popover;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jobber/components",
3
- "version": "4.60.3-replace-da.7+c1ace120",
3
+ "version": "4.60.3",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -20,7 +20,7 @@
20
20
  ],
21
21
  "dependencies": {
22
22
  "@jobber/design": "^0.47.0",
23
- "@jobber/formatters": "^0.2.2",
23
+ "@jobber/formatters": "*",
24
24
  "@jobber/hooks": "^2.7.0",
25
25
  "@popperjs/core": "^2.0.6",
26
26
  "@std-proposal/temporal": "0.0.1",
@@ -84,5 +84,5 @@
84
84
  "> 1%",
85
85
  "IE 10"
86
86
  ],
87
- "gitHead": "c1ace1204825dda6f1bcedf8aba8abf425b76d4e"
87
+ "gitHead": "3654473db6119c8489361d0a8797554bf0a21b7a"
88
88
  }
@@ -1,403 +0,0 @@
1
- 'use strict';
2
-
3
- var React = require('react');
4
- var classnames = require('classnames');
5
- var ReactDOM = require('react-dom');
6
- var styleInject_es = require('./style-inject.es-9d2f5f4e.js');
7
- var Icon = require('./Icon-405a216c.js');
8
- var Text = require('./Text-54334431.js');
9
- var Typography = require('./Typography-83915c54.js');
10
- var Button = require('./Button-db6114a6.js');
11
- var useRefocusOnActivator = require('@jobber/hooks/useRefocusOnActivator');
12
- var useFocusTrap = require('@jobber/hooks/useFocusTrap');
13
- var reactPopper = require('react-popper');
14
- var useOnKeyDown = require('@jobber/hooks/useOnKeyDown');
15
- var Chip = require('./Chip-f26246d1.js');
16
- require('@jobber/design');
17
- var useAssert = require('@jobber/hooks/useAssert');
18
-
19
- function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
20
-
21
- var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
22
- var classnames__default = /*#__PURE__*/_interopDefaultLegacy(classnames);
23
- var ReactDOM__default = /*#__PURE__*/_interopDefaultLegacy(ReactDOM);
24
-
25
- var css_248z$6 = ".m1w5vdUZ6rQ- {\n z-index: 1002;\n z-index: var(--elevation-tooltip);\n max-width: var(--popover--width);\n min-width: calc((16px * 4) * 3.75);\n min-width: calc(calc(16px * 4) * 3.75);\n min-width: calc(var(--space-extravagant) * 3.75);\n box-shadow: 0px calc(16px / 16) calc(16px / 4) 0px\n rgba(0, 0, 0, 0.1),\n 0px calc(16px / 4) 12px 0px rgba(0, 0, 0, 0.05);\n box-shadow: var(--shadow-base);\n margin-top: calc(16px / 2);\n margin-top: var(--space-small);\n border: calc(16px / 16) solid rgb(225, 225, 225);\n border: var(--border-base) solid var(--color-border);\n border-radius: calc(16px / 2);\n border-radius: var(--radius-larger);\n overflow: scroll;\n overflow-y: auto;\n background: rgba(255, 255, 255, 1);\n background: var(--color-surface);\n}\n\n/* CAUTION: Tests for content visibility assume this class' presence hides the content\n* so please be careful if you change this class name, or the css rules within.\n*/\n\n.m1w5vdUZ6rQ-.Zlkv2HA096A- {\n display: none;\n visibility: hidden;\n}\n\n.YQry-Rd6zfQ- {\n display: -ms-flexbox;\n display: flex;\n -ms-flex-direction: column;\n flex-direction: column;\n position: sticky;\n gap: calc(16px / 4);\n gap: var(--space-smaller);\n bottom: 0;\n width: 100%;\n background-color: rgba(255, 255, 255, 1);\n background-color: var(--color-surface);\n}\n\n.TcpqL34s4lI- {\n padding-bottom: calc(16px / 2);\n padding-bottom: var(--space-small);\n}\n";
26
- var styles$6 = {"content":"m1w5vdUZ6rQ-","hidden":"Zlkv2HA096A-","actions":"YQry-Rd6zfQ-","actionPadding":"TcpqL34s4lI-"};
27
- styleInject_es.styleInject(css_248z$6);
28
-
29
- var css_248z$5 = ".MIyb-oFZg9w- {\n position: relative;\n}\n\n.WZPK91I4aJs- {\n width: 100%;\n padding: calc(16px * 1);\n padding: var(--space-base);\n padding-right: calc((16px * 1.5) * 2.25);\n padding-right: calc(calc(16px * 1.5) * 2.25);\n padding-right: calc(var(--space-large) * 2.25);\n border: none;\n border-bottom: calc(16px / 16) solid rgb(225, 225, 225);\n border-bottom: var(--border-base) solid var(--color-border);\n font-family: \"Inter\", Helvetica, Arial, sans-serif;\n font-family: var(--typography--fontFamily-normal);\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}\n\n.WZPK91I4aJs-::-webkit-search-decoration,\n.WZPK91I4aJs-::-webkit-search-cancel-button,\n.WZPK91I4aJs-::-webkit-search-results-button,\n.WZPK91I4aJs-::-webkit-search-results-decoration {\n -webkit-appearance: none;\n}\n\n.WZPK91I4aJs-:focus {\n outline: none;\n}\n\n._7loHrVUe-Rk- {\n display: -ms-flexbox;\n display: flex;\n position: absolute;\n top: 50%;\n right: calc(16px * 1);\n right: var(--space-base);\n z-index: 1002;\n z-index: var(--elevation-tooltip);\n width: calc(16px * 1.5);\n width: var(--space-large);\n height: calc(16px * 1.5);\n height: var(--space-large);\n padding: 0;\n border: none;\n border-radius: 100%;\n border-radius: var(--radius-circle);\n background-color: rgb(244, 244, 244);\n background-color: var(--color-surface--background);\n cursor: pointer;\n -webkit-transform: translateY(-50%);\n transform: translateY(-50%);\n -ms-flex-pack: center;\n justify-content: center;\n -ms-flex-align: center;\n align-items: center;\n}\n\n._7loHrVUe-Rk-: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";
30
- var styles$5 = {"search":"MIyb-oFZg9w-","searchInput":"WZPK91I4aJs-","clearSearch":"_7loHrVUe-Rk-"};
31
- styleInject_es.styleInject(css_248z$5);
32
-
33
- function ComboboxContentSearch(props) {
34
- const searchRef = React.useRef(null);
35
- React.useEffect(() => {
36
- if (props.open) {
37
- setTimeout(() => {
38
- var _a;
39
- (_a = searchRef.current) === null || _a === void 0 ? void 0 : _a.focus();
40
- }, 0);
41
- }
42
- }, [props.open]);
43
- return (React__default["default"].createElement("div", { className: styles$5.search },
44
- React__default["default"].createElement("input", { type: "search", ref: searchRef, className: styles$5.searchInput, placeholder: props.placeholder ? `Search ${props.placeholder}` : "Search", onChange: (event) => handleSearch(event), value: props.searchValue }),
45
- props.searchValue && (React__default["default"].createElement("button", { className: styles$5.clearSearch, onClick: clearSearch, type: "button", "data-testid": "ATL-Combobox-Content-Search-Clear", "aria-label": "Clear search" },
46
- React__default["default"].createElement(Icon.Icon, { name: "remove", size: "small" })))));
47
- function clearSearch() {
48
- var _a;
49
- props.setSearchValue("");
50
- (_a = searchRef.current) === null || _a === void 0 ? void 0 : _a.focus();
51
- }
52
- function handleSearch(event) {
53
- props.setSearchValue(event.target.value);
54
- }
55
- }
56
-
57
- 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 pointer-events: none;\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 pointer-events: none;\n}\n";
58
- var styles$4 = {"container":"SgMzjOcdE-E-","optionsList":"TwoTCjgcssc-","filterMessage":"_8T5M7MGwCRE-","emptyStateMessage":"_4y5NXkNeIQM-"};
59
- styleInject_es.styleInject(css_248z$4);
60
-
61
- 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";
62
- var styles$3 = {"option":"_5QdRGmaNHvc-"};
63
- styleInject_es.styleInject(css_248z$3);
64
-
65
- const ComboboxContext = React__default["default"].createContext({});
66
- function ComboboxContextProvider(props) {
67
- return (React__default["default"].createElement(ComboboxContext.Provider, { value: {
68
- open: props.open,
69
- setOpen: props.setOpen,
70
- selected: props.selected,
71
- selectionHandler: props.selectionHandler,
72
- handleClose: props.handleClose,
73
- shouldScroll: props.shouldScroll,
74
- } }, props.children));
75
- }
76
-
77
- function ComboboxOption(props) {
78
- const { selected, selectionHandler } = React.useContext(ComboboxContext);
79
- const isSelected = selected.some(selection => selection.id.toString() === props.id.toString());
80
- return (React__default["default"].createElement("li", { key: props.id, tabIndex: -1, "data-selected": isSelected, role: "option", "aria-selected": isSelected, onClick: () => selectionHandler &&
81
- selectionHandler({ id: props.id, label: props.label }), className: classnames__default["default"](styles$3.option) },
82
- props.label,
83
- isSelected && React__default["default"].createElement(Icon.Icon, { name: "checkmark", color: "blue" })));
84
- }
85
-
86
- function ComboboxContentList(props) {
87
- return (React__default["default"].createElement("div", { className: styles$4.container },
88
- !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 &&
89
- props.options.map(option => {
90
- return (React__default["default"].createElement(ComboboxOption, { key: option.id, id: option.id, label: option.label }));
91
- }))),
92
- !props.showEmptyState && props.options.length === 0 && (React__default["default"].createElement("div", { className: styles$4.filterMessage },
93
- React__default["default"].createElement(Text.Text, { variation: "subdued" },
94
- "No results for ",
95
- `“${props.searchValue}”`))),
96
- props.showEmptyState && (React__default["default"].createElement("div", { className: styles$4.emptyStateMessage },
97
- React__default["default"].createElement(Text.Text, { variation: "subdued" }, getZeroIndexStateText(props.subjectNoun))))));
98
- }
99
- function getZeroIndexStateText(subjectNoun) {
100
- if (subjectNoun) {
101
- return `You don't have any ${subjectNoun} yet`;
102
- }
103
- return "No options yet";
104
- }
105
-
106
- 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";
107
- var styles$2 = {"header":"Q-mwo-g5Fi8-"};
108
- styleInject_es.styleInject(css_248z$2);
109
-
110
- function ComboboxContentHeader(props) {
111
- const hasSelected = props.selectedCount > 0;
112
- const actionLabel = hasSelected ? "Clear" : "Select all";
113
- const label = getLabel(hasSelected, props.selectedCount, props.subjectNoun);
114
- const handleSelectAll = hasSelected ? props.onClearAll : props.onSelectAll;
115
- const showAction = hasSelected || props.hasOptionsVisible;
116
- return (React__default["default"].createElement("div", { className: styles$2.header, "data-testid": "ATL-Combobox-Header" },
117
- React__default["default"].createElement(Typography.Typography, { textColor: "heading", fontWeight: "semiBold" }, label),
118
- showAction && (React__default["default"].createElement(Button.Button, { size: "small", label: actionLabel, type: "tertiary", onClick: handleSelectAll }))));
119
- }
120
- function getLabel(hasSelected, count, subjectNoun) {
121
- if (hasSelected) {
122
- return `${count} selected`;
123
- }
124
- if (subjectNoun) {
125
- return `Select ${subjectNoun}`;
126
- }
127
- return "Select";
128
- }
129
-
130
- function useComboboxContent(options, open, selected, searchValue) {
131
- const { shouldScroll } = React.useContext(ComboboxContext);
132
- const optionsListRef = React.useRef(null);
133
- const filteredOptions = options.filter(option => option.label.toLowerCase().includes(searchValue.toLowerCase()));
134
- React.useEffect(() => {
135
- var _a;
136
- if (open && shouldScroll.current && optionsListRef.current) {
137
- const firstSelected = Array.from((_a = optionsListRef === null || optionsListRef === void 0 ? void 0 : optionsListRef.current) === null || _a === void 0 ? void 0 : _a.children).find(child => {
138
- if (child instanceof HTMLElement) {
139
- return child.dataset.selected === "true";
140
- }
141
- });
142
- scrollToFirstSelected(firstSelected, shouldScroll);
143
- }
144
- }, [open, selected]);
145
- return {
146
- filteredOptions,
147
- optionsListRef,
148
- };
149
- }
150
- function scrollToFirstSelected(firstSelected, shouldScroll) {
151
- if (firstSelected) {
152
- firstSelected.scrollIntoView({
153
- block: "nearest",
154
- });
155
- shouldScroll.current = false;
156
- }
157
- }
158
-
159
- // eslint-disable-next-line max-statements
160
- function useComboboxAccessibility(selectionCallback, filteredOptions, optionsListRef, open, wrapperRef) {
161
- const { handleClose } = React.useContext(ComboboxContext);
162
- const hasOptionsVisible = open && filteredOptions.length > 0;
163
- const focusedIndex = React.useRef(null);
164
- useRefocusOnActivator.useRefocusOnActivator(open);
165
- const popperRef = useFocusTrap.useFocusTrap(open);
166
- const { styles: popperStyles, attributes, update, } = reactPopper.usePopper(wrapperRef.current, popperRef.current, {
167
- modifiers: [
168
- {
169
- name: "flip",
170
- options: {
171
- fallbackPlacements: ["top-start"],
172
- },
173
- },
174
- ],
175
- placement: "bottom-start",
176
- });
177
- React.useEffect(() => {
178
- focusedIndex.current = null;
179
- if (open) {
180
- update === null || update === void 0 ? void 0 : update();
181
- }
182
- }, [open, filteredOptions.length]);
183
- React.useEffect(() => {
184
- var _a;
185
- if (open) {
186
- (_a = popperRef.current) === null || _a === void 0 ? void 0 : _a.addEventListener("keydown", handleContentKeydown);
187
- }
188
- return () => {
189
- var _a;
190
- (_a = popperRef.current) === null || _a === void 0 ? void 0 : _a.removeEventListener("keydown", handleContentKeydown);
191
- };
192
- }, [open, optionsListRef, filteredOptions]);
193
- useOnKeyDown.useOnKeyDown(() => {
194
- if (open) {
195
- handleClose();
196
- }
197
- }, "Escape");
198
- function handleContentKeydown(event) {
199
- var _a;
200
- if (!hasOptionsVisible)
201
- return;
202
- if (event.key === "Enter" || event.key === " ") {
203
- const activeElementInList = (_a = optionsListRef.current) === null || _a === void 0 ? void 0 : _a.contains(document.activeElement);
204
- if (!activeElementInList)
205
- return;
206
- handleKeyboardSelection(event);
207
- }
208
- if (event.key === "ArrowDown") {
209
- handleKeyboardNavigation(event, 1);
210
- }
211
- if (event.key === "ArrowUp") {
212
- handleKeyboardNavigation(event, -1);
213
- }
214
- }
215
- function handleKeyboardNavigation(event, indexChange) {
216
- var _a;
217
- const newIndex = focusedIndex.current === null ? 0 : focusedIndex.current + indexChange;
218
- if (newIndex < 0 || newIndex >= filteredOptions.length)
219
- return;
220
- const optionElement = (_a = optionsListRef.current) === null || _a === void 0 ? void 0 : _a.children[newIndex];
221
- optionElement === null || optionElement === void 0 ? void 0 : optionElement.focus();
222
- focusedIndex.current = newIndex;
223
- event.preventDefault();
224
- event.stopPropagation();
225
- }
226
- function handleKeyboardSelection(event) {
227
- event.preventDefault();
228
- event.stopPropagation();
229
- if (focusedIndex.current !== null) {
230
- selectionCallback(filteredOptions[focusedIndex.current]);
231
- }
232
- }
233
- return {
234
- popperRef,
235
- popperStyles,
236
- attributes,
237
- };
238
- }
239
-
240
- function ComboboxContent(props) {
241
- const optionsExist = props.options.length > 0;
242
- const { filteredOptions, optionsListRef } = useComboboxContent(props.options, props.open, props.selected, props.searchValue);
243
- const { popperRef, popperStyles, attributes } = useComboboxAccessibility(props.handleSelection, filteredOptions, optionsListRef, props.open, props.wrapperRef);
244
- 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),
245
- React__default["default"].createElement(ComboboxContentSearch, { open: props.open, placeholder: props.subjectNoun, searchValue: props.searchValue, setSearchValue: props.setSearchValue }),
246
- props.multiselect && optionsExist && (React__default["default"].createElement(ComboboxContentHeader, { hasOptionsVisible: filteredOptions.length > 0, subjectNoun: props.subjectNoun, selectedCount: props.selected.length, onClearAll: () => {
247
- props.selectedStateSetter([]);
248
- }, onSelectAll: () => {
249
- props.selectedStateSetter(filteredOptions);
250
- } })),
251
- React__default["default"].createElement(ComboboxContentList, { multiselect: props.multiselect, showEmptyState: !optionsExist, options: filteredOptions, selected: props.selected, optionsListRef: optionsListRef, searchValue: props.searchValue, subjectNoun: props.subjectNoun }),
252
- 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"]({
253
- [styles$6.actionPadding]: index === childrenArray.length - 1,
254
- }) }, child)))))));
255
- return ReactDOM__default["default"].createPortal(template, document.body);
256
- }
257
-
258
- 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";
259
- var styles$1 = {"actionContainer":"Ow9wSNnGP-g-","actionButton":"ncp0nKHQ7d8-"};
260
- styleInject_es.styleInject(css_248z$1);
261
-
262
- function ComboboxAction(props) {
263
- return (React__default["default"].createElement("div", { className: styles$1.actionContainer },
264
- React__default["default"].createElement("button", { className: styles$1.actionButton, onClick: props.onClick, type: "button", "aria-label": props.label },
265
- React__default["default"].createElement(Typography.Typography, { element: "span", size: "base", textColor: "green", fontWeight: "semiBold" }, props.label))));
266
- }
267
-
268
- function ComboboxTrigger({ label = "Select", selected, }) {
269
- const { handleClose, open, setOpen } = React__default["default"].useContext(ComboboxContext);
270
- const hasSelection = selected.length;
271
- const selectedLabel = selected.map(option => option.label).join(", ");
272
- return (React__default["default"].createElement(Chip.Chip, { variation: hasSelection ? "base" : "subtle", label: hasSelection ? selectedLabel : "", heading: label, onClick: () => {
273
- if (open) {
274
- handleClose();
275
- }
276
- else {
277
- setOpen(true);
278
- }
279
- }, role: "combobox" }, !hasSelection && (React__default["default"].createElement(Chip.Chip.Suffix, null,
280
- React__default["default"].createElement(Icon.Icon, { name: "add", size: "small" })))));
281
- }
282
-
283
- 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";
284
- var styles = {"overlay":"W8qMZnORYxI-","wrapper":"_-0dkolvLF-Y-"};
285
- styleInject_es.styleInject(css_248z);
286
-
287
- function useMakeComboboxHandlers(setOpen, setSearchValue, selectedOptions, shouldScroll, selectedStateSetter, multiSelect, onClose) {
288
- const handleClose = React.useCallback(() => {
289
- setOpen(false);
290
- setSearchValue("");
291
- onClose && onClose();
292
- if (selectedOptions.length > 0) {
293
- shouldScroll.current = true;
294
- }
295
- }, [setOpen, setSearchValue, onClose, selectedOptions.length]);
296
- const handleSelection = React.useCallback((selection) => {
297
- if (multiSelect) {
298
- handleMultiSelect(selectedStateSetter, selectedOptions, selection);
299
- }
300
- else {
301
- handleSingleSelect(selectedStateSetter, selection);
302
- }
303
- }, [multiSelect, selectedStateSetter, selectedOptions]);
304
- const handleSingleSelect = React.useCallback((selectCallback, selection) => {
305
- selectCallback([selection]);
306
- handleClose();
307
- }, []);
308
- return {
309
- handleClose,
310
- handleSelection,
311
- };
312
- }
313
- function handleMultiSelect(selectCallback, selected, selection) {
314
- if (selected.some(s => s.id === selection.id)) {
315
- selectCallback(selected.filter(s => s.id !== selection.id));
316
- }
317
- else {
318
- selectCallback([...selected, selection]);
319
- }
320
- }
321
-
322
- function useCombobox(selected, onSelect, onClose, multiSelect) {
323
- const wrapperRef = React.useRef(null);
324
- const shouldScroll = React.useRef(false);
325
- const [open, setOpen] = React.useState(false);
326
- const [searchValue, setSearchValue] = React.useState("");
327
- const { handleClose, handleSelection } = useMakeComboboxHandlers(setOpen, setSearchValue, selected, shouldScroll, onSelect, multiSelect, onClose);
328
- return {
329
- wrapperRef,
330
- searchValue,
331
- setSearchValue,
332
- open,
333
- setOpen,
334
- selectedOptions: selected,
335
- selectedStateSetter: onSelect,
336
- shouldScroll,
337
- handleClose,
338
- handleSelection,
339
- };
340
- }
341
-
342
- function ComboboxActivator(props) {
343
- const { handleClose, open, setOpen } = React__default["default"].useContext(ComboboxContext);
344
- if (props.children.type === Button.Button || props.children.type === Chip.Chip) {
345
- return React__default["default"].cloneElement(props.children, {
346
- role: "combobox",
347
- onClick: () => {
348
- if (open) {
349
- handleClose();
350
- }
351
- else {
352
- setOpen(true);
353
- }
354
- },
355
- });
356
- }
357
- return props.children;
358
- }
359
-
360
- const COMBOBOX_TRIGGER_COUNT_ERROR_MESSAGE = "Combobox must have exactly one Trigger element";
361
- function useComboboxValidation(children) {
362
- const optionElements = getCompoundComponents(ComboboxOption, children);
363
- const actionElements = getCompoundComponents(ComboboxAction, children);
364
- const activatorElements = getCompoundComponents(ComboboxActivator, children);
365
- const shouldThrowTriggerError = isInvalid(activatorElements);
366
- useAssert.useAssert(shouldThrowTriggerError, COMBOBOX_TRIGGER_COUNT_ERROR_MESSAGE);
367
- return {
368
- optionElements,
369
- triggerElement: activatorElements[0],
370
- actionElements,
371
- };
372
- }
373
- function isInvalid(activators) {
374
- return activators.length > 1 ? true : false;
375
- }
376
- /**
377
- * Return all instances child component that matches the `type` provided
378
- */
379
- function getCompoundComponents(type, children) {
380
- const childrenArray = React.Children.toArray(children);
381
- const elements = childrenArray.filter((child) => React.isValidElement(child) && child.type === type);
382
- return elements;
383
- }
384
-
385
- function Combobox(props) {
386
- const { optionElements, triggerElement, actionElements } = useComboboxValidation(props.children);
387
- const options = React.useMemo(() => (optionElements === null || optionElements === void 0 ? void 0 : optionElements.map(option => ({
388
- id: option.props.id,
389
- label: option.props.label,
390
- }))) || [], [optionElements]);
391
- const { selectedOptions, selectedStateSetter, shouldScroll, wrapperRef, searchValue, setSearchValue, open, setOpen, handleClose, handleSelection, } = useCombobox(props.selected, props.onSelect, props.onClose, props.multiSelect);
392
- return (React__default["default"].createElement(ComboboxContextProvider, { selected: selectedOptions, selectionHandler: handleSelection, open: open, setOpen: setOpen, handleClose: handleClose, shouldScroll: shouldScroll },
393
- React__default["default"].createElement("div", { ref: wrapperRef, className: styles.wrapper },
394
- open && (React__default["default"].createElement("div", { className: styles.overlay, onClick: () => handleClose(), "data-testid": "ATL-Combobox-Overlay" })),
395
- triggerElement || (React__default["default"].createElement(ComboboxTrigger, { label: props.label, selected: props.selected })),
396
- 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 }))));
397
- }
398
- Combobox.Activator = ComboboxActivator;
399
- Combobox.Action = ComboboxAction;
400
- Combobox.Option = ComboboxOption;
401
-
402
- exports.Combobox = Combobox;
403
- exports.ComboboxContextProvider = ComboboxContextProvider;