@jobber/components 4.45.6 → 4.46.1-JOB-79340.27
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.
- package/Chip.d.ts +1 -0
- package/Chip.js +17 -0
- package/dist/Autocomplete/index.js +7 -7
- package/dist/Avatar/Avatar.d.ts +1 -1
- package/dist/Avatar/index.d.ts +1 -1
- package/dist/Banner/index.js +3 -3
- package/dist/Button/index.js +2 -2
- package/dist/{Button-d89f2271.js → Button-db6114a6.js} +1 -1
- package/dist/ButtonDismiss/index.js +3 -3
- package/dist/{ButtonDismiss-250840a4.js → ButtonDismiss-1ccb84ec.js} +1 -1
- package/dist/Card/index.js +5 -5
- package/dist/{Card-69304e99.js → Card-116af709.js} +3 -3
- package/dist/Checkbox/index.js +3 -3
- package/dist/{Checkbox-eac63b7f.js → Checkbox-bc4bc968.js} +1 -1
- package/dist/Chip/Chip.d.ts +8 -0
- package/dist/Chip/Chip.types.d.d.ts +64 -0
- package/dist/Chip/components/ChipDismissible/ChipDismissible.d.ts +3 -0
- package/dist/Chip/components/ChipPrefix/Chip.Prefix.d.ts +6 -0
- package/dist/Chip/components/ChipSelectable/ChipSelectable.d.ts +3 -0
- package/dist/Chip/components/ChipSuffix/Chip.Suffix.d.ts +7 -0
- package/dist/Chip/hooks/index.d.ts +1 -0
- package/dist/Chip/hooks/useChildComponent.d.ts +8 -0
- package/dist/Chip/index.d.ts +4 -0
- package/dist/Chip/index.js +28 -0
- package/dist/ChipSelectable-8e5509a1.js +74 -0
- package/dist/Chips/ChipsTypes.d.ts +12 -8
- package/dist/Chips/InternalChipDismissible/InternalChipDismissible.d.ts +2 -2
- package/dist/Chips/InternalChipDismissible/InternalChipDismissibleTypes.d.ts +1 -1
- package/dist/Chips/InternalChipDismissible/hooks/useInternalChipDismissible.d.ts +1 -1
- package/dist/Chips/InternalChipMultiSelect.d.ts +1 -1
- package/dist/Chips/InternalChipSingleSelect.d.ts +2 -2
- package/dist/Chips/index.d.ts +5 -1
- package/dist/Chips/index.js +24 -10
- package/dist/{Chip-4d8e6370.js → Chips-2daf43ea.js} +84 -78
- package/dist/Combobox/Combobox.d.ts +6 -0
- package/dist/Combobox/ComboboxProvider.d.ts +2 -0
- package/dist/Combobox/components/ComboboxContent/ComboboxContent.d.ts +17 -6
- package/dist/Combobox/components/ComboboxContent/ComboboxList.d.ts +9 -8
- package/dist/Combobox/components/ComboboxContent/ComboboxSearch.d.ts +4 -4
- package/dist/Combobox/hooks/useComboboxContent.d.ts +7 -3
- package/dist/Combobox/index.js +64 -30
- package/dist/ConfirmationModal/index.js +9 -9
- package/dist/{ConfirmationModal-92f07027.js → ConfirmationModal-285c3cbe.js} +2 -2
- package/dist/DataDump/index.js +6 -6
- package/dist/DataList/DataList.types.d.ts +9 -1
- package/dist/DataList/components/DataListSearch/DataListSearch.d.ts +1 -1
- package/dist/DataList/index.js +47 -24
- package/dist/DataTable/index.js +6 -6
- package/dist/DatePicker/index.js +3 -3
- package/dist/{DatePicker-39d2dc8b.js → DatePicker-49213434.js} +2 -2
- package/dist/DescriptionList/index.js +1 -1
- package/dist/Disclosure/index.js +1 -1
- package/dist/Drawer/index.js +4 -4
- package/dist/Emphasis/index.js +2 -2
- package/dist/{Emphasis-cc3456ac.js → Emphasis-e10dde65.js} +1 -1
- package/dist/FeatureSwitch/index.js +7 -7
- package/dist/FormField/index.js +5 -5
- package/dist/{FormField-bef41ec9.js → FormField-fa9254dc.js} +3 -3
- package/dist/FormatFile/index.js +10 -10
- package/dist/{FormatFile-a470c0f2.js → FormatFile-6423c3b5.js} +4 -4
- package/dist/Gallery/index.js +11 -11
- package/dist/Heading/index.js +2 -2
- package/dist/{Heading-4562900a.js → Heading-4cde9989.js} +1 -1
- package/dist/InlineLabel/index.js +2 -2
- package/dist/{InlineLabel-3d461632.js → InlineLabel-a24706c4.js} +1 -1
- package/dist/InputAvatar/index.js +3 -3
- package/dist/InputDate/index.js +6 -6
- package/dist/InputEmail/index.js +5 -5
- package/dist/InputFile/index.js +3 -3
- package/dist/{InputFile-d327dee3.js → InputFile-25c3369b.js} +2 -2
- package/dist/InputNumber/index.js +6 -6
- package/dist/{InputNumber-5640fb55.js → InputNumber-ea9fcee1.js} +1 -1
- package/dist/InputPassword/index.js +5 -5
- package/dist/InputPhoneNumber/index.js +5 -5
- package/dist/InputText/index.js +6 -6
- package/dist/{InputText-5ac5cfe0.js → InputText-ab237501.js} +1 -1
- package/dist/InputTime/index.js +5 -5
- package/dist/InputValidation/index.js +3 -3
- package/dist/{InputValidation-4e809bdd.js → InputValidation-377d6c62.js} +1 -1
- package/dist/LightBox/index.js +4 -4
- package/dist/{LightBox-02ca409e.js → LightBox-93ef99b9.js} +2 -2
- package/dist/List/index.js +5 -5
- package/dist/Markdown/index.js +5 -5
- package/dist/{Markdown-b37cf9ec.js → Markdown-d53b01bf.js} +3 -3
- package/dist/Menu/index.js +3 -3
- package/dist/{Menu-cec53b50.js → Menu-2e64307a.js} +2 -2
- package/dist/Modal/index.js +5 -5
- package/dist/{Modal-dcdc0032.js → Modal-c17cc105.js} +3 -3
- package/dist/MultiSelect/index.js +3 -3
- package/dist/{Option-9f4a65da.js → Option-07a24acd.js} +1 -1
- package/dist/Page/index.js +7 -7
- package/dist/Popover/index.js +4 -4
- package/dist/{Popover-d401fb54.js → Popover-7c966790.js} +1 -1
- package/dist/RadioGroup/index.js +3 -3
- package/dist/{RadioGroup-46833fac.js → RadioGroup-9bdd8a59.js} +1 -1
- package/dist/RecurringSelect/index.js +8 -8
- package/dist/Select/index.js +6 -6
- package/dist/StatusLabel/index.js +2 -2
- package/dist/Switch/index.js +2 -2
- package/dist/{Switch-165f01e3.js → Switch-cc9b645c.js} +1 -1
- package/dist/Tabs/index.js +1 -1
- package/dist/Text/index.js +2 -2
- package/dist/{Text-59bde58c.js → Text-54334431.js} +1 -1
- package/dist/Toast/index.js +2 -2
- package/dist/Tooltip/index.js +3 -3
- package/dist/{Tooltip-59dbab5b.js → Tooltip-d5257798.js} +1 -1
- package/dist/Typography/index.js +1 -1
- package/dist/{Typography-9bff9c91.js → Typography-83915c54.js} +2 -2
- package/package.json +5 -5
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var React = require('react');
|
|
4
|
-
var uuid = require('uuid');
|
|
5
4
|
var styleInject_es = require('./style-inject.es-9d2f5f4e.js');
|
|
6
5
|
var classnames = require('classnames');
|
|
7
6
|
var useAssert = require('@jobber/hooks/useAssert');
|
|
8
7
|
var Icon = require('./Icon-405a216c.js');
|
|
9
8
|
var Avatar = require('./Avatar-1aa30ee1.js');
|
|
10
|
-
var Typography = require('./Typography-
|
|
11
|
-
var Tooltip = require('./Tooltip-
|
|
9
|
+
var Typography = require('./Typography-83915c54.js');
|
|
10
|
+
var Tooltip = require('./Tooltip-d5257798.js');
|
|
11
|
+
var ChipSelectable = require('./ChipSelectable-8e5509a1.js');
|
|
12
|
+
require('@jobber/design');
|
|
12
13
|
var sortBy = require('lodash/sortBy');
|
|
13
14
|
var useLiveAnnounce = require('@jobber/hooks/useLiveAnnounce');
|
|
15
|
+
var uuid = require('uuid');
|
|
14
16
|
var debounce = require('lodash/debounce');
|
|
15
17
|
var reactPopper = require('react-popper');
|
|
16
|
-
var Text = require('./Text-
|
|
17
|
-
var Button = require('./Button-
|
|
18
|
+
var Text = require('./Text-54334431.js');
|
|
19
|
+
var Button = require('./Button-db6114a6.js');
|
|
18
20
|
var Spinner = require('./Spinner-9d8fc7ff.js');
|
|
19
21
|
|
|
20
22
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
@@ -118,14 +120,20 @@ function InternalChip({ label, active = false, disabled = false, invalid = false
|
|
|
118
120
|
}
|
|
119
121
|
}
|
|
120
122
|
|
|
121
|
-
function InternalChipSingleSelect({ children, selected,
|
|
123
|
+
function InternalChipSingleSelect({ children, selected, onChange, onClick, }) {
|
|
122
124
|
return (React__default["default"].createElement("div", { className: styles$1.wrapper, "data-testid": "singleselect-chips" }, React__default["default"].Children.map(children, child => {
|
|
123
|
-
const isSelected = child.props.value === selected;
|
|
124
|
-
return (React__default["default"].createElement("
|
|
125
|
-
React__default["default"].createElement("
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
125
|
+
const isSelected = (child === null || child === void 0 ? void 0 : child.props.value) === selected || (child === null || child === void 0 ? void 0 : child.props.label) === selected;
|
|
126
|
+
return (React__default["default"].createElement(React__default["default"].Fragment, null,
|
|
127
|
+
React__default["default"].createElement("label", { style: { display: "none" } },
|
|
128
|
+
React__default["default"].createElement("input", { type: "radio", checked: isSelected, className: styles$1.input, onClick: handleClick((child === null || child === void 0 ? void 0 : child.props.value) || ""), onKeyUp: handleKeyUp(isSelected, (child === null || child === void 0 ? void 0 : child.props.value) || ""), onChange: () => {
|
|
129
|
+
/* No op. onClick handles the change to allow deselecting. */
|
|
130
|
+
}, disabled: child === null || child === void 0 ? void 0 : child.props.disabled }),
|
|
131
|
+
React__default["default"].createElement(InternalChip, Object.assign({}, child === null || child === void 0 ? void 0 : child.props, { label: (child === null || child === void 0 ? void 0 : child.props.label) || "", active: isSelected }))),
|
|
132
|
+
React__default["default"].createElement(ChipSelectable.ChipSelectable, Object.assign({}, child === null || child === void 0 ? void 0 : child.props, { label: (child === null || child === void 0 ? void 0 : child.props.label) || "", selected: isSelected, onClick: clickedItem => {
|
|
133
|
+
onChange(clickedItem);
|
|
134
|
+
onClick &&
|
|
135
|
+
onClick({}, child === null || child === void 0 ? void 0 : child.props.value);
|
|
136
|
+
}, onKeyDown: handleKeyUp(isSelected, (child === null || child === void 0 ? void 0 : child.props.value) || "") }))));
|
|
129
137
|
})));
|
|
130
138
|
function handleKeyUp(active, value) {
|
|
131
139
|
if (!active)
|
|
@@ -150,47 +158,50 @@ function InternalChipSingleSelect({ children, selected, name = uuid.v1(), onChan
|
|
|
150
158
|
}
|
|
151
159
|
|
|
152
160
|
function InternalChipMultiSelect({ children, selected, onChange, onClick, }) {
|
|
161
|
+
const toggleSelectedChip = (val, ev) => {
|
|
162
|
+
const newChips = [...(selected || [])];
|
|
163
|
+
const indexOfItem = newChips.findIndex(d => d === val);
|
|
164
|
+
if (indexOfItem !== -1) {
|
|
165
|
+
newChips.splice(indexOfItem, 1);
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
newChips.push(val);
|
|
169
|
+
}
|
|
170
|
+
onChange(newChips);
|
|
171
|
+
onClick && onClick(ev, val);
|
|
172
|
+
};
|
|
153
173
|
return (React__default["default"].createElement("div", { className: styles$1.wrapper, "data-testid": "multiselect-chips" }, React__default["default"].Children.map(children, chip => {
|
|
154
|
-
const isChipActive =
|
|
155
|
-
return (React__default["default"].createElement("
|
|
156
|
-
React__default["default"].createElement("
|
|
157
|
-
|
|
174
|
+
const isChipActive = selected === null || selected === void 0 ? void 0 : selected.includes((chip === null || chip === void 0 ? void 0 : chip.props.value) || (chip === null || chip === void 0 ? void 0 : chip.props.label));
|
|
175
|
+
return (React__default["default"].createElement(React__default["default"].Fragment, null,
|
|
176
|
+
React__default["default"].createElement("label", { style: { display: "none" } },
|
|
177
|
+
React__default["default"].createElement("input", { type: "checkbox", checked: isChipActive, className: styles$1.input, onClick: chip && handleClick(chip.props.value), onChange: chip && handleChange(chip.props.value), disabled: chip === null || chip === void 0 ? void 0 : chip.props.disabled })),
|
|
178
|
+
chip && (React__default["default"].createElement(ChipSelectable.ChipSelectable, Object.assign({}, chip.props, { selected: isChipActive, onClick: toggleSelectedChip })))));
|
|
179
|
+
function isChipSelected(value) {
|
|
180
|
+
return selected === null || selected === void 0 ? void 0 : selected.includes(value);
|
|
181
|
+
}
|
|
182
|
+
function handleClick(value) {
|
|
183
|
+
return (event) => onClick === null || onClick === void 0 ? void 0 : onClick(event, value);
|
|
184
|
+
}
|
|
185
|
+
function handleChange(value) {
|
|
186
|
+
return () => {
|
|
187
|
+
if (isChipSelected(value)) {
|
|
188
|
+
handleDeselect(value);
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
handleSelect(value);
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
function handleSelect(value) {
|
|
196
|
+
const newVal = [...(selected || []), value];
|
|
197
|
+
onChange(newVal);
|
|
198
|
+
}
|
|
199
|
+
function handleDeselect(value) {
|
|
200
|
+
const values = selected;
|
|
201
|
+
const newVal = values === null || values === void 0 ? void 0 : values.filter(val => val !== value);
|
|
202
|
+
onChange(newVal || []);
|
|
203
|
+
}
|
|
158
204
|
})));
|
|
159
|
-
function isChipSelected(value) {
|
|
160
|
-
return selected.includes(value);
|
|
161
|
-
}
|
|
162
|
-
function handleClick(value) {
|
|
163
|
-
return (event) => onClick === null || onClick === void 0 ? void 0 : onClick(event, value);
|
|
164
|
-
}
|
|
165
|
-
function handleChange(value) {
|
|
166
|
-
return () => {
|
|
167
|
-
if (isChipSelected(value)) {
|
|
168
|
-
handleDeselect(value);
|
|
169
|
-
}
|
|
170
|
-
else {
|
|
171
|
-
handleSelect(value);
|
|
172
|
-
}
|
|
173
|
-
};
|
|
174
|
-
}
|
|
175
|
-
function handleSelect(value) {
|
|
176
|
-
const newVal = [...selected, value];
|
|
177
|
-
onChange(newVal);
|
|
178
|
-
}
|
|
179
|
-
function handleDeselect(value) {
|
|
180
|
-
const values = selected;
|
|
181
|
-
const newVal = values.filter(val => val !== value);
|
|
182
|
-
onChange(newVal);
|
|
183
|
-
}
|
|
184
|
-
function checkmarkIcon(show) {
|
|
185
|
-
// Ideally, we should be returning a fragment `<></>` when a function
|
|
186
|
-
// returns a component / element. However, this one needs to return nothing
|
|
187
|
-
// to prevent it from randomly rendering a suffix.
|
|
188
|
-
//
|
|
189
|
-
// DO NOT COPY!
|
|
190
|
-
if (!show)
|
|
191
|
-
return;
|
|
192
|
-
return React__default["default"].createElement(Icon.Icon, { name: "checkmark" });
|
|
193
|
-
}
|
|
194
205
|
}
|
|
195
206
|
|
|
196
207
|
var css_248z = ".sCNIjluCskc- {\n display: -ms-flexbox;\n display: flex;\n position: relative;\n box-sizing: border-box;\n border: calc(16px / 16) solid transparent;\n border: var(--border-base) solid transparent;\n border-radius: calc(16px / 8);\n border-radius: var(--radius-base);\n transition: all 200ms;\n transition: all var(--timing-base);\n gap: calc(16px / 2);\n gap: var(--space-small);\n -ms-flex-wrap: wrap;\n flex-wrap: wrap;\n -ms-flex-align: center;\n align-items: center;\n}\n\n.MFUlz1WQLdk- {\n -ms-flex: 1;\n flex: 1;\n min-width: 120px;\n padding: calc(16px / 2) 0;\n padding: var(--space-small) 0;\n border: none;\n border-radius: 0;\n color: inherit;\n font-family: inherit;\n font-size: inherit;\n font-size: calc(calc(16px * 1) * 0.875);\n font-size: var(--typography--fontSize-base);\n line-height: 1.25;\n line-height: var(--typography--lineHeight-base);\n background: transparent;\n -webkit-appearance: none;\n appearance: none;\n}\n\n.MFUlz1WQLdk-:focus {\n outline: none;\n}\n\n.V9eYJdjPAeY- {\n position: relative;\n z-index: 6;\n z-index: var(--elevation-menu);\n width: 100%;\n}\n\n.LdytkOeCU9c- {\n max-height: 320px;\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 padding: calc(16px / 2) 0;\n padding: var(--space-small) 0;\n border-radius: calc(16px / 8);\n border-radius: var(--radius-base);\n overflow-y: scroll;\n background-color: rgba(255, 255, 255, 1);\n background-color: var(--color-surface);\n}\n\n.y7Cz2u8BuNE-,\n._-7bmao8Q9As- {\n display: -ms-flexbox;\n display: flex;\n width: 100%;\n padding: calc(16px / 2);\n padding: var(--space-small);\n border: none;\n background-color: transparent;\n cursor: pointer;\n -webkit-appearance: none;\n appearance: none;\n -ms-flex-align: center;\n align-items: center;\n gap: calc(16px / 2);\n gap: var(--space-small);\n}\n\n.y7Cz2u8BuNE-: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.y7Cz2u8BuNE-:focus,\n.iCwWdcmtInc- {\n outline: none;\n background-color: rgb(250, 246, 219);\n background-color: var(--color-surface--hover);\n}\n\n._-7bmao8Q9As- {\n -ms-flex-pack: center;\n justify-content: center;\n}\n";
|
|
@@ -199,19 +210,20 @@ styleInject_es.styleInject(css_248z);
|
|
|
199
210
|
|
|
200
211
|
function useInternalChipDismissible({ children, selected, onChange, onClick, onCustomAdd, }) {
|
|
201
212
|
const ref = React.useRef(null);
|
|
202
|
-
const chipOptions = children.map(chip => chip.props);
|
|
203
|
-
const visibleChipOptions = chipOptions.filter(chip => selected.includes(chip.value));
|
|
204
|
-
const sortedVisibleChipOptions = sortBy__default["default"](visibleChipOptions, chip => selected.indexOf(chip.value));
|
|
205
|
-
const availableChipOptions = chipOptions.filter(chip => !selected.includes(chip.value));
|
|
213
|
+
const chipOptions = children === null || children === void 0 ? void 0 : children.map(chip => chip.props);
|
|
214
|
+
const visibleChipOptions = chipOptions === null || chipOptions === void 0 ? void 0 : chipOptions.filter(chip => selected === null || selected === void 0 ? void 0 : selected.includes(chip.value));
|
|
215
|
+
const sortedVisibleChipOptions = sortBy__default["default"](visibleChipOptions, chip => selected === null || selected === void 0 ? void 0 : selected.indexOf(chip.value));
|
|
216
|
+
const availableChipOptions = chipOptions === null || chipOptions === void 0 ? void 0 : chipOptions.filter(chip => !(selected === null || selected === void 0 ? void 0 : selected.includes(chip.value)));
|
|
206
217
|
const { liveAnnounce } = useLiveAnnounce.useLiveAnnounce();
|
|
207
218
|
const actions = {
|
|
208
219
|
handleChipRemove: (value) => {
|
|
209
220
|
return () => {
|
|
210
221
|
liveAnnounce(`${value} Removed`);
|
|
211
|
-
onChange(selected.filter(val => val !== value));
|
|
222
|
+
onChange((selected === null || selected === void 0 ? void 0 : selected.filter(val => val !== value)) || []);
|
|
223
|
+
onClick && onClick({}, value);
|
|
212
224
|
};
|
|
213
225
|
},
|
|
214
|
-
handleChipAdd: (value) => onChange([...selected, value]),
|
|
226
|
+
handleChipAdd: (value) => onChange([...(selected || []), value]),
|
|
215
227
|
handleCustomAdd: onCustomAdd,
|
|
216
228
|
handleChipClick: (value) => {
|
|
217
229
|
if (onClick === undefined)
|
|
@@ -268,7 +280,7 @@ function useInternalChipDismissibleInput({ options, isLoadingMore = false, onCus
|
|
|
268
280
|
const [shouldCancelBlur, setShouldCancelBlur] = React.useState(false);
|
|
269
281
|
const [shouldCancelEnter, setShouldCancelEnter] = React.useState(false);
|
|
270
282
|
const canAddCustomOption = onCustomOptionSelect !== undefined && !isLoadingMore;
|
|
271
|
-
const maxOptionIndex = allOptions.length - 1;
|
|
283
|
+
const maxOptionIndex = (allOptions === null || allOptions === void 0 ? void 0 : allOptions.length) - 1;
|
|
272
284
|
const { liveAnnounce } = useLiveAnnounce.useLiveAnnounce();
|
|
273
285
|
React.useEffect(() => {
|
|
274
286
|
setAllOptions(generateOptions(options, searchValue, canAddCustomOption));
|
|
@@ -276,8 +288,8 @@ function useInternalChipDismissibleInput({ options, isLoadingMore = false, onCus
|
|
|
276
288
|
const computed = {
|
|
277
289
|
menuId,
|
|
278
290
|
inputRef: React.useRef(null),
|
|
279
|
-
activeOption: allOptions[activeIndex],
|
|
280
|
-
hasAvailableOptions: allOptions.length > 0,
|
|
291
|
+
activeOption: allOptions === null || allOptions === void 0 ? void 0 : allOptions[activeIndex],
|
|
292
|
+
hasAvailableOptions: (allOptions === null || allOptions === void 0 ? void 0 : allOptions.length) > 0,
|
|
281
293
|
nextOptionIndex: activeIndex < maxOptionIndex ? activeIndex + 1 : 0,
|
|
282
294
|
previousOptionIndex: activeIndex > 0 ? activeIndex - 1 : maxOptionIndex,
|
|
283
295
|
};
|
|
@@ -365,16 +377,14 @@ function useInternalChipDismissibleInput({ options, isLoadingMore = false, onCus
|
|
|
365
377
|
shouldCancelBlur });
|
|
366
378
|
}
|
|
367
379
|
function generateOptions(options, searchValue, canAddCustomOption) {
|
|
368
|
-
const allOptions = options
|
|
369
|
-
.filter(option => option.label.toLowerCase().match(searchValue.trim().toLowerCase()))
|
|
370
|
-
.map(opt => (Object.assign(Object.assign({}, opt), { custom: false })));
|
|
380
|
+
const allOptions = options === null || options === void 0 ? void 0 : options.filter(option => option.label.toLowerCase().match(searchValue.trim().toLowerCase())).map(opt => (Object.assign(Object.assign({}, opt), { custom: false })));
|
|
371
381
|
const { shouldAddCustomOption, customOption } = generateCustomOption(allOptions, searchValue, canAddCustomOption);
|
|
372
382
|
shouldAddCustomOption && allOptions.push(customOption);
|
|
373
383
|
return allOptions;
|
|
374
384
|
}
|
|
375
385
|
function generateCustomOption(options, searchValue, canAddCustomOption) {
|
|
376
386
|
function shouldAddCustomOption() {
|
|
377
|
-
const isMatchingOption = options.some(option => option.label.toLowerCase() === searchValue.trim().toLowerCase());
|
|
387
|
+
const isMatchingOption = options === null || options === void 0 ? void 0 : options.some(option => option.label.toLowerCase() === searchValue.trim().toLowerCase());
|
|
378
388
|
return !!searchValue && !isMatchingOption;
|
|
379
389
|
}
|
|
380
390
|
return {
|
|
@@ -472,7 +482,7 @@ function InternalChipDismissibleInput(props) {
|
|
|
472
482
|
React__default["default"].createElement("input", { ref: inputRef, className: styles.input, type: "text", role: "combobox", "aria-label": "Press up and down arrow to cycle through the options or type to narrow down the results", "aria-autocomplete": "list", "aria-owns": menuId, "aria-expanded": hasAvailableOptions, "aria-activedescendant": generateDescendantId(activeIndex), value: searchValue, onChange: handleSearchChange, onKeyDown: handleKeyDown, onBlur: debounce__default["default"](handleBlur, 200), onFocus: handleOpenMenu, autoFocus: true }),
|
|
473
483
|
(hasAvailableOptions || isLoadingMore) && (React__default["default"].createElement("div", Object.assign({ ref: setPositionedElementRef, className: styles.menu, style: popperStyles.popper }, attributes.popper),
|
|
474
484
|
React__default["default"].createElement("div", { ref: menuRef, role: "listbox", id: menuId, className: styles.menuList, "data-testid": "chip-menu" },
|
|
475
|
-
allOptions.map((option, i) => (React__default["default"].createElement("button", { key: option.value, role: "option", id: generateDescendantId(i), className: classnames__default["default"](styles.menuListOption, {
|
|
485
|
+
allOptions.map((option, i) => (React__default["default"].createElement("button", { key: option.value, role: "option", type: "button", id: generateDescendantId(i), className: classnames__default["default"](styles.menuListOption, {
|
|
476
486
|
[styles.activeOption]: activeIndex === i,
|
|
477
487
|
}), onClick: () => handleSelectOption(option), onMouseEnter: handleSetActiveOnMouseOver(i), onMouseDown: handleCancelBlur, onMouseUp: handleEnableBlur },
|
|
478
488
|
React__default["default"].createElement("span", { "aria-hidden": true }, option.prefix),
|
|
@@ -483,10 +493,12 @@ function InternalChipDismissibleInput(props) {
|
|
|
483
493
|
}
|
|
484
494
|
|
|
485
495
|
function InternalChipDismissible(props) {
|
|
486
|
-
const { availableChipOptions, ref: wrapperRef, sortedVisibleChipOptions, handleChipAdd,
|
|
496
|
+
const { availableChipOptions, ref: wrapperRef, sortedVisibleChipOptions, handleChipAdd, handleChipKeyDown, handleChipRemove, handleCustomAdd, handleWrapperKeyDown, } = useInternalChipDismissible(props);
|
|
487
497
|
return (React__default["default"].createElement("div", { ref: wrapperRef, className: styles.wrapper, "data-testid": "dismissible-chips", onKeyDown: handleWrapperKeyDown, role: "listbox" },
|
|
488
|
-
sortedVisibleChipOptions.map(chip => (React__default["default"].createElement(
|
|
489
|
-
|
|
498
|
+
sortedVisibleChipOptions.map(chip => (React__default["default"].createElement(ChipSelectable.Chip, Object.assign({ key: chip.value }, chip, { value: chip.label, onKeyDown: handleChipKeyDown(chip.value), onClick: handleChipRemove(chip.value), role: "radio", "data-testid": props.dataTestId || "remove-chip-button", ariaLabel: `${chip.label}. Press delete or backspace to remove ${chip.label}`, tabIndex: 0 }),
|
|
499
|
+
React__default["default"].createElement(ChipSelectable.Chip.Suffix, null,
|
|
500
|
+
React__default["default"].createElement(Icon.Icon, { name: "cross", size: "small" }))))),
|
|
501
|
+
React__default["default"].createElement(InternalChipDismissibleInput, { activator: props.activator, type: props.type, attachTo: wrapperRef, isLoadingMore: props.isLoadingMore, options: availableChipOptions || [], onOptionSelect: handleChipAdd, onCustomOptionSelect: handleCustomAdd, onSearch: props.onSearch, onLoadMore: props.onLoadMore })));
|
|
490
502
|
}
|
|
491
503
|
|
|
492
504
|
function Chips(props) {
|
|
@@ -496,19 +508,13 @@ function Chips(props) {
|
|
|
496
508
|
case "multiselect":
|
|
497
509
|
return React__default["default"].createElement(InternalChipMultiSelect, Object.assign({}, props));
|
|
498
510
|
default:
|
|
499
|
-
return React__default["default"].createElement(InternalChipSingleSelect, Object.assign({}, props));
|
|
511
|
+
return (React__default["default"].createElement(InternalChipSingleSelect, Object.assign({}, props, { type: "singleselect", selected: props.selected })));
|
|
500
512
|
}
|
|
501
513
|
}
|
|
502
514
|
|
|
503
|
-
// Only need the component to pass in the data as a react children
|
|
504
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
505
|
-
function Chip(props) {
|
|
506
|
-
// Throw error when <Chip /> gets used outside of the <Chips />
|
|
507
|
-
useAssert.useAssert(true, "`<Chip>` component can only be used inside `<Chips>`");
|
|
508
|
-
return React__default["default"].createElement(React__default["default"].Fragment, null);
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
exports.Chip = Chip;
|
|
512
515
|
exports.Chips = Chips;
|
|
513
516
|
exports.InternalChip = InternalChip;
|
|
514
517
|
exports.InternalChipButton = InternalChipButton;
|
|
518
|
+
exports.InternalChipDismissible = InternalChipDismissible;
|
|
519
|
+
exports.InternalChipMultiSelect = InternalChipMultiSelect;
|
|
520
|
+
exports.InternalChipSingleSelect = InternalChipSingleSelect;
|
|
@@ -4,6 +4,12 @@ import { ComboboxAction } from "./components/ComboboxAction";
|
|
|
4
4
|
import { ComboboxTriggerButton, ComboboxTriggerChip } from "./components/ComboboxTrigger";
|
|
5
5
|
export interface ComboboxProps {
|
|
6
6
|
readonly children: ReactElement | ReactElement[];
|
|
7
|
+
/**
|
|
8
|
+
* When `true`, `Combobox` will allow for multiple selections
|
|
9
|
+
*
|
|
10
|
+
* @default false
|
|
11
|
+
*/
|
|
12
|
+
readonly multiSelect?: boolean;
|
|
7
13
|
}
|
|
8
14
|
export declare const COMBOBOX_TRIGGER_COUNT_ERROR_MESSAGE = "Combobox can only have one Trigger element";
|
|
9
15
|
export declare const COMBOBOX_REQUIRED_CHILDREN_ERROR_MESSAGE = "Combobox must have a Trigger and Combobox.Content element";
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import React, { RefObject } from "react";
|
|
2
2
|
export declare const ComboboxContext: React.Context<{
|
|
3
|
+
multiselect: boolean;
|
|
3
4
|
open: boolean;
|
|
4
5
|
setOpen: (open: boolean) => void;
|
|
5
6
|
wrapperRef: RefObject<HTMLDivElement>;
|
|
6
7
|
}>;
|
|
7
8
|
export interface ComboboxProviderProps {
|
|
8
9
|
readonly children: React.ReactNode;
|
|
10
|
+
readonly multiselect?: boolean;
|
|
9
11
|
}
|
|
10
12
|
export declare function ComboboxContextProvider(props: ComboboxProviderProps): JSX.Element;
|
|
@@ -1,14 +1,24 @@
|
|
|
1
1
|
import { ReactElement } from "react";
|
|
2
|
+
import { XOR } from "ts-xor";
|
|
2
3
|
import { ComboboxOption } from "../../Combobox.types";
|
|
3
|
-
interface
|
|
4
|
+
interface ComboboxCloseProps {
|
|
4
5
|
/**
|
|
5
|
-
*
|
|
6
|
+
* Callback function invoked upon the selection of an option. Provides the selected option(s) as an argument.
|
|
6
7
|
*/
|
|
7
|
-
readonly
|
|
8
|
+
readonly onSelect: (selection: ComboboxOption[]) => void;
|
|
9
|
+
}
|
|
10
|
+
interface ComoboboxSelectProps {
|
|
11
|
+
/**
|
|
12
|
+
*
|
|
13
|
+
* Callback function invoked upon the Combobox menu closing. Provides the selected option(s) as an argument.
|
|
14
|
+
*/
|
|
15
|
+
readonly onClose: (selection: ComboboxOption[]) => void;
|
|
16
|
+
}
|
|
17
|
+
interface ComboboxContentBaseProps {
|
|
8
18
|
/**
|
|
9
|
-
*
|
|
19
|
+
* List of selectable options to display.
|
|
10
20
|
*/
|
|
11
|
-
readonly
|
|
21
|
+
readonly options: ComboboxOption[];
|
|
12
22
|
/**
|
|
13
23
|
* Optional action button(s) to display at the bottom of the list.
|
|
14
24
|
*/
|
|
@@ -22,12 +32,13 @@ interface ComboboxContentProps {
|
|
|
22
32
|
* @default ""
|
|
23
33
|
* @type string
|
|
24
34
|
*/
|
|
25
|
-
readonly selected: ComboboxOption
|
|
35
|
+
readonly selected: ComboboxOption[];
|
|
26
36
|
/**
|
|
27
37
|
* The encapsulating noun for the content of the combobox. Used
|
|
28
38
|
* in the empty state, and search placeholder. Should be pluralized.
|
|
29
39
|
*/
|
|
30
40
|
readonly subjectNoun?: string;
|
|
31
41
|
}
|
|
42
|
+
type ComboboxContentProps = ComboboxContentBaseProps & XOR<ComboboxCloseProps, ComoboboxSelectProps>;
|
|
32
43
|
export declare function ComboboxContent(props: ComboboxContentProps): JSX.Element;
|
|
33
44
|
export {};
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import React, { SetStateAction } from "react";
|
|
2
2
|
import { ComboboxOption } from "../../Combobox.types";
|
|
3
3
|
interface ComboboxListProps {
|
|
4
|
-
options: ComboboxOption[];
|
|
5
|
-
showEmptyState: boolean;
|
|
6
|
-
selected: ComboboxOption
|
|
7
|
-
optionsListRef: React.RefObject<HTMLUListElement>;
|
|
8
|
-
|
|
9
|
-
selectionHandler: (option: ComboboxOption) => void;
|
|
10
|
-
searchValue: string;
|
|
11
|
-
|
|
4
|
+
readonly options: ComboboxOption[];
|
|
5
|
+
readonly showEmptyState: boolean;
|
|
6
|
+
readonly selected: ComboboxOption[];
|
|
7
|
+
readonly optionsListRef: React.RefObject<HTMLUListElement>;
|
|
8
|
+
readonly setFirstSelectedElement: React.Dispatch<SetStateAction<HTMLElement | null>>;
|
|
9
|
+
readonly selectionHandler: (option: ComboboxOption) => void;
|
|
10
|
+
readonly searchValue: string;
|
|
11
|
+
readonly multiselect: boolean;
|
|
12
|
+
readonly subjectNoun?: string;
|
|
12
13
|
}
|
|
13
14
|
export declare function ComboboxList(props: ComboboxListProps): JSX.Element;
|
|
14
15
|
export {};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Dispatch, SetStateAction } from "react";
|
|
2
2
|
export declare function ComboboxSearch(props: {
|
|
3
|
-
placeholder?: string;
|
|
4
|
-
searchValue: string;
|
|
5
|
-
open: boolean;
|
|
6
|
-
setSearchValue: Dispatch<SetStateAction<string>>;
|
|
3
|
+
readonly placeholder?: string;
|
|
4
|
+
readonly searchValue: string;
|
|
5
|
+
readonly open: boolean;
|
|
6
|
+
readonly setSearchValue: Dispatch<SetStateAction<string>>;
|
|
7
7
|
}): JSX.Element;
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
import { ComboboxOption } from "../Combobox.types";
|
|
3
|
-
|
|
3
|
+
interface useComboboxContent {
|
|
4
4
|
searchValue: string;
|
|
5
5
|
setSearchValue: React.Dispatch<React.SetStateAction<string>>;
|
|
6
|
-
|
|
6
|
+
setFirstSelectedElement: React.Dispatch<React.SetStateAction<HTMLElement | null>>;
|
|
7
7
|
filteredOptions: ComboboxOption[];
|
|
8
8
|
optionsListRef: React.RefObject<HTMLUListElement>;
|
|
9
|
-
|
|
9
|
+
selectedOptions: ComboboxOption[];
|
|
10
|
+
setInternalSelected: (selected: ComboboxOption[]) => void;
|
|
11
|
+
}
|
|
12
|
+
export declare function useComboboxContent(options: ComboboxOption[], open: boolean, selected: ComboboxOption[], onClose: ((selection: ComboboxOption[]) => void) | undefined): useComboboxContent;
|
|
13
|
+
export {};
|
package/dist/Combobox/index.js
CHANGED
|
@@ -8,13 +8,13 @@ var classnames = require('classnames');
|
|
|
8
8
|
var ReactDOM = require('react-dom');
|
|
9
9
|
var styleInject_es = require('../style-inject.es-9d2f5f4e.js');
|
|
10
10
|
var Icon = require('../Icon-405a216c.js');
|
|
11
|
-
var Text = require('../Text-
|
|
11
|
+
var Text = require('../Text-54334431.js');
|
|
12
12
|
var useRefocusOnActivator = require('@jobber/hooks/useRefocusOnActivator');
|
|
13
13
|
var useFocusTrap = require('@jobber/hooks/useFocusTrap');
|
|
14
14
|
var reactPopper = require('react-popper');
|
|
15
15
|
var useOnKeyDown = require('@jobber/hooks/useOnKeyDown');
|
|
16
|
-
var Typography = require('../Typography-
|
|
17
|
-
var Button = require('../Button-
|
|
16
|
+
var Typography = require('../Typography-83915c54.js');
|
|
17
|
+
var Button = require('../Button-db6114a6.js');
|
|
18
18
|
require('@jobber/design');
|
|
19
19
|
require('react-router-dom');
|
|
20
20
|
|
|
@@ -24,11 +24,11 @@ var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
|
|
|
24
24
|
var classnames__default = /*#__PURE__*/_interopDefaultLegacy(classnames);
|
|
25
25
|
var ReactDOM__default = /*#__PURE__*/_interopDefaultLegacy(ReactDOM);
|
|
26
26
|
|
|
27
|
-
var css_248z$5 = ".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
|
|
27
|
+
var css_248z$5 = ".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";
|
|
28
28
|
var styles$5 = {"content":"m1w5vdUZ6rQ-","hidden":"Zlkv2HA096A-","actions":"YQry-Rd6zfQ-","actionPadding":"TcpqL34s4lI-"};
|
|
29
29
|
styleInject_es.styleInject(css_248z$5);
|
|
30
30
|
|
|
31
|
-
var css_248z$4 = ".ifwwZOYTf8U- {\n position: relative;\n}\n\n.gIbHknFkZLI- {\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.dZmEG-amk2U- {\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}\n\n.dZmEG-amk2U-: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
|
|
31
|
+
var css_248z$4 = ".ifwwZOYTf8U- {\n position: relative;\n}\n\n.gIbHknFkZLI- {\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.dZmEG-amk2U- {\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}\n\n.dZmEG-amk2U-: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";
|
|
32
32
|
var styles$4 = {"search":"ifwwZOYTf8U-","searchInput":"gIbHknFkZLI-","clearSearch":"dZmEG-amk2U-"};
|
|
33
33
|
styleInject_es.styleInject(css_248z$4);
|
|
34
34
|
|
|
@@ -44,7 +44,7 @@ function ComboboxSearch(props) {
|
|
|
44
44
|
}, [props.open]);
|
|
45
45
|
return (React__default["default"].createElement("div", { className: styles$4.search },
|
|
46
46
|
React__default["default"].createElement("input", { type: "search", ref: searchRef, className: styles$4.searchInput, placeholder: props.placeholder ? `Search ${props.placeholder}` : "Search", onChange: (event) => handleSearch(event), value: props.searchValue }),
|
|
47
|
-
props.searchValue && (React__default["default"].createElement("button", { className: styles$4.clearSearch, onClick: clearSearch, "data-testid": "ATL-Combobox-Content-Search-Clear", "aria-label": "Clear search" },
|
|
47
|
+
props.searchValue && (React__default["default"].createElement("button", { className: styles$4.clearSearch, onClick: clearSearch, type: "button", "data-testid": "ATL-Combobox-Content-Search-Clear", "aria-label": "Clear search" },
|
|
48
48
|
React__default["default"].createElement(Icon.Icon, { name: "remove", size: "small" })))));
|
|
49
49
|
function clearSearch() {
|
|
50
50
|
var _a;
|
|
@@ -56,22 +56,22 @@ function ComboboxSearch(props) {
|
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
var css_248z$3 = "._5n7VvEn39-Y- {\n padding: calc(16px / 2);\n padding: var(--space-small);\n}\n\n.KhX5VfZjAog- {\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.NNCJVHYx6lc- {\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 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 -ms-flex-pack: justify;\n justify-content: space-between;\n -ms-flex-align: center;\n align-items: center;\n
|
|
60
|
-
var styles$3 = {"container":"_5n7VvEn39-Y-","optionsList":"KhX5VfZjAog-","option":"NNCJVHYx6lc-","
|
|
59
|
+
var css_248z$3 = "._5n7VvEn39-Y- {\n position: relative;\n padding: calc(16px / 2) 0;\n padding: var(--space-small) 0;\n}\n\n.KhX5VfZjAog- {\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.NNCJVHYx6lc- {\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.NNCJVHYx6lc-:hover,\n.NNCJVHYx6lc-:focus {\n background-color: rgb(244, 244, 244);\n background-color: var(--color-surface--background);\n}\n\n.NNCJVHYx6lc-: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._2IRm1sf-TUU-,\n.DTuoA8WPNzc- {\n padding: calc(16px / 2) calc(16px * 1);\n padding: var(--space-small) var(--space-base);\n}\n\n._5n7VvEn39-Y-::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._5n7VvEn39-Y-::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";
|
|
60
|
+
var styles$3 = {"container":"_5n7VvEn39-Y-","optionsList":"KhX5VfZjAog-","option":"NNCJVHYx6lc-","filterMessage":"_2IRm1sf-TUU-","emptyStateMessage":"DTuoA8WPNzc-"};
|
|
61
61
|
styleInject_es.styleInject(css_248z$3);
|
|
62
62
|
|
|
63
63
|
function ComboboxList(props) {
|
|
64
|
+
let hasSeenFirstSelected = false;
|
|
64
65
|
return (React__default["default"].createElement("div", { className: styles$3.container },
|
|
65
|
-
!props.showEmptyState && props.options.length > 0 && (React__default["default"].createElement("ul", { className: styles$3.optionsList, role: "listbox", ref: props.optionsListRef }, !props.showEmptyState &&
|
|
66
|
+
!props.showEmptyState && props.options.length > 0 && (React__default["default"].createElement("ul", { className: styles$3.optionsList, role: "listbox", "aria-multiselectable": props.multiselect, ref: props.optionsListRef }, !props.showEmptyState &&
|
|
66
67
|
props.options.map(option => {
|
|
67
|
-
|
|
68
|
-
const isSelected = option.id.toString() === ((_a = props.selected) === null || _a === void 0 ? void 0 : _a.id.toString());
|
|
68
|
+
const isSelected = props.selected.some(selection => selection.id.toString() === option.id.toString());
|
|
69
69
|
return (React__default["default"].createElement("li", { ref: listItem => {
|
|
70
|
-
if (isSelected)
|
|
71
|
-
props.
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}) },
|
|
70
|
+
if (isSelected && !hasSeenFirstSelected) {
|
|
71
|
+
props.setFirstSelectedElement(listItem);
|
|
72
|
+
hasSeenFirstSelected = true;
|
|
73
|
+
}
|
|
74
|
+
}, key: option.id, tabIndex: -1, role: "option", "aria-selected": isSelected, onClick: () => props.selectionHandler(option), className: classnames__default["default"](styles$3.option) },
|
|
75
75
|
option.label,
|
|
76
76
|
isSelected && React__default["default"].createElement(Icon.Icon, { name: "checkmark", color: "blue" })));
|
|
77
77
|
}))),
|
|
@@ -95,32 +95,47 @@ styleInject_es.styleInject(css_248z$2);
|
|
|
95
95
|
|
|
96
96
|
const ComboboxContext = React__default["default"].createContext({});
|
|
97
97
|
function ComboboxContextProvider(props) {
|
|
98
|
+
const multiselect = props.multiselect || false;
|
|
98
99
|
const [open, setOpen] = React.useState(false);
|
|
99
100
|
const wrapperRef = React.useRef(null);
|
|
100
|
-
return (React__default["default"].createElement(ComboboxContext.Provider, { value: { open, setOpen, wrapperRef } },
|
|
101
|
+
return (React__default["default"].createElement(ComboboxContext.Provider, { value: { multiselect, open, setOpen, wrapperRef } },
|
|
101
102
|
React__default["default"].createElement("div", { ref: wrapperRef },
|
|
102
103
|
open && (React__default["default"].createElement("div", { className: styles$2.overlay, onClick: () => setOpen(false), "data-testid": "ATL-Combobox-Overlay" })),
|
|
103
104
|
props.children)));
|
|
104
105
|
}
|
|
105
106
|
|
|
106
|
-
function useComboboxContent(options, open) {
|
|
107
|
+
function useComboboxContent(options, open, selected, onClose) {
|
|
107
108
|
const [searchValue, setSearchValue] = React.useState("");
|
|
108
|
-
const [
|
|
109
|
+
const [firstSelectedElement, setFirstSelectedElement] = React.useState(null);
|
|
109
110
|
const optionsListRef = React.useRef(null);
|
|
110
111
|
const filteredOptions = options.filter(option => option.label.toLowerCase().includes(searchValue.toLowerCase()));
|
|
112
|
+
const [internalSelected, setInternalSelected] = React.useState(selected);
|
|
113
|
+
const selectedOptions = onClose ? internalSelected : selected;
|
|
114
|
+
React.useEffect(() => {
|
|
115
|
+
if (!open && onClose) {
|
|
116
|
+
onClose(selectedOptions);
|
|
117
|
+
}
|
|
118
|
+
}, [open, onClose, selectedOptions]);
|
|
111
119
|
React.useEffect(() => {
|
|
112
|
-
if (open &&
|
|
113
|
-
|
|
120
|
+
if (open && firstSelectedElement) {
|
|
121
|
+
firstSelectedElement === null || firstSelectedElement === void 0 ? void 0 : firstSelectedElement.scrollIntoView({
|
|
114
122
|
block: "nearest",
|
|
115
123
|
});
|
|
116
124
|
}
|
|
117
|
-
}, [open,
|
|
125
|
+
}, [open, firstSelectedElement]);
|
|
126
|
+
React.useEffect(() => {
|
|
127
|
+
if (selectedOptions.length === 0) {
|
|
128
|
+
setFirstSelectedElement(null);
|
|
129
|
+
}
|
|
130
|
+
}, [selectedOptions]);
|
|
118
131
|
return {
|
|
119
132
|
searchValue,
|
|
120
133
|
setSearchValue,
|
|
121
|
-
|
|
134
|
+
setFirstSelectedElement,
|
|
122
135
|
filteredOptions,
|
|
123
136
|
optionsListRef,
|
|
137
|
+
selectedOptions,
|
|
138
|
+
setInternalSelected,
|
|
124
139
|
};
|
|
125
140
|
}
|
|
126
141
|
|
|
@@ -201,23 +216,42 @@ function useComboboxAccessibility(selectionCallback, filteredOptions, optionsLis
|
|
|
201
216
|
}
|
|
202
217
|
|
|
203
218
|
function ComboboxContent(props) {
|
|
204
|
-
const { open, setOpen, wrapperRef } = React__default["default"].useContext(ComboboxContext);
|
|
219
|
+
const { open, setOpen, wrapperRef, multiselect } = React__default["default"].useContext(ComboboxContext);
|
|
205
220
|
const optionsExist = props.options.length > 0;
|
|
206
|
-
const { searchValue, setSearchValue,
|
|
221
|
+
const { searchValue, setSearchValue, setFirstSelectedElement, filteredOptions, optionsListRef, selectedOptions, setInternalSelected, } = useComboboxContent(props.options, open, props.selected, props.onClose);
|
|
207
222
|
const { popperRef, popperStyles, attributes } = useComboboxAccessibility(handleSelection, filteredOptions, optionsListRef, open, setOpen, wrapperRef);
|
|
208
223
|
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$5.content, { [styles$5.hidden]: !open }), style: popperStyles.popper }, attributes.popper),
|
|
209
224
|
React__default["default"].createElement(ComboboxSearch, { open: open, placeholder: props.subjectNoun, searchValue: searchValue, setSearchValue: setSearchValue }),
|
|
210
|
-
React__default["default"].createElement(ComboboxList, { showEmptyState: !optionsExist, options: filteredOptions, selected:
|
|
225
|
+
React__default["default"].createElement(ComboboxList, { multiselect: multiselect, showEmptyState: !optionsExist, options: filteredOptions, selected: selectedOptions, optionsListRef: optionsListRef, setFirstSelectedElement: setFirstSelectedElement, selectionHandler: handleSelection, searchValue: searchValue, subjectNoun: props.subjectNoun }),
|
|
211
226
|
props.children && (React__default["default"].createElement("div", { className: styles$5.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"]({
|
|
212
227
|
[styles$5.actionPadding]: index === childrenArray.length - 1,
|
|
213
228
|
}) }, child)))))));
|
|
214
229
|
return ReactDOM__default["default"].createPortal(template, document.body);
|
|
215
230
|
function handleSelection(selection) {
|
|
216
|
-
props.onSelect
|
|
231
|
+
const callbackHandler = props.onSelect
|
|
232
|
+
? props.onSelect
|
|
233
|
+
: setInternalSelected;
|
|
234
|
+
if (multiselect) {
|
|
235
|
+
handleMultiSelect(callbackHandler, selectedOptions, selection);
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
handleSingleSelect(callbackHandler, selection);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
function handleSingleSelect(selectCallback, selection) {
|
|
242
|
+
selectCallback([selection]);
|
|
217
243
|
setSearchValue("");
|
|
218
244
|
setOpen(false);
|
|
219
245
|
}
|
|
220
246
|
}
|
|
247
|
+
function handleMultiSelect(selectCallback, selected, selection) {
|
|
248
|
+
if (selected.some(s => s.id === selection.id)) {
|
|
249
|
+
selectCallback(selected.filter(s => s.id !== selection.id));
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
selectCallback([...selected, selection]);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
221
255
|
|
|
222
256
|
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";
|
|
223
257
|
var styles$1 = {"actionContainer":"Ow9wSNnGP-g-","actionButton":"ncp0nKHQ7d8-"};
|
|
@@ -225,7 +259,7 @@ styleInject_es.styleInject(css_248z$1);
|
|
|
225
259
|
|
|
226
260
|
function ComboboxAction(props) {
|
|
227
261
|
return (React__default["default"].createElement("div", { className: styles$1.actionContainer },
|
|
228
|
-
React__default["default"].createElement("button", { className: styles$1.actionButton, onClick: props.onClick, "aria-label": props.label },
|
|
262
|
+
React__default["default"].createElement("button", { className: styles$1.actionButton, onClick: props.onClick, type: "button", "aria-label": props.label },
|
|
229
263
|
React__default["default"].createElement(Typography.Typography, { element: "span", size: "base", textColor: "green", fontWeight: "semiBold" }, props.label))));
|
|
230
264
|
}
|
|
231
265
|
|
|
@@ -240,7 +274,7 @@ styleInject_es.styleInject(css_248z);
|
|
|
240
274
|
|
|
241
275
|
function ComboboxTriggerChip(props) {
|
|
242
276
|
const { open, setOpen } = React__default["default"].useContext(ComboboxContext);
|
|
243
|
-
return (React__default["default"].createElement("button", { className: styles.trigger, role: "combobox", "aria-expanded": open, "aria-haspopup": "listbox", "aria-controls": "ATL-Combobox-Content", "aria-autocomplete": "list", onClick: () => {
|
|
277
|
+
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: () => {
|
|
244
278
|
setOpen(!open);
|
|
245
279
|
} },
|
|
246
280
|
React__default["default"].createElement(Typography.Typography, { fontWeight: "semiBold", textColor: "heading" }, props.label),
|
|
@@ -252,7 +286,7 @@ const COMBOBOX_TRIGGER_COUNT_ERROR_MESSAGE = "Combobox can only have one Trigger
|
|
|
252
286
|
const COMBOBOX_REQUIRED_CHILDREN_ERROR_MESSAGE = "Combobox must have a Trigger and Combobox.Content element";
|
|
253
287
|
const Combobox = (props) => {
|
|
254
288
|
const { contentElement, triggerElement } = useComboboxValidation(props.children);
|
|
255
|
-
return (React__default["default"].createElement(ComboboxContextProvider,
|
|
289
|
+
return (React__default["default"].createElement(ComboboxContextProvider, { multiselect: props.multiSelect },
|
|
256
290
|
triggerElement,
|
|
257
291
|
contentElement));
|
|
258
292
|
};
|