@drivy/cobalt 0.51.1 → 1.0.0-beta.2
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/cjs/tokens/zIndexes.js +2 -1
- package/cjs/tokens/zIndexes.js.map +1 -1
- package/components/Accordion/index.js +16 -32
- package/components/Accordion/index.js.map +1 -1
- package/components/Alerter/index.js +45 -77
- package/components/Alerter/index.js.map +1 -1
- package/components/Form/Autocomplete/index.js +177 -155
- package/components/Form/Autocomplete/index.js.map +1 -1
- package/components/Form/Slider.js +40 -19
- package/components/Form/Slider.js.map +1 -1
- package/components/Form/field.js +9 -1
- package/components/Form/field.js.map +1 -1
- package/components/Modal/ModalHeader.js +10 -7
- package/components/Modal/ModalHeader.js.map +1 -1
- package/components/Modal/index.js +33 -97
- package/components/Modal/index.js.map +1 -1
- package/components/PhotoDropzone/index.js +2 -5
- package/components/PhotoDropzone/index.js.map +1 -1
- package/components/Tabs/index.js +19 -118
- package/components/Tabs/index.js.map +1 -1
- package/index.js +3 -3
- package/package.json +3 -10
- package/src/tokens/zIndexes.js +2 -1
- package/src/tokens/zIndexes.js.map +1 -1
- package/styles/components/Accordion/index.scss +40 -19
- package/styles/components/Alerter/index.scss +42 -42
- package/styles/components/Form/Autocomplete/index.scss +52 -74
- package/styles/components/Form/RadioWithDetails.scss +2 -12
- package/styles/components/Form/Slider.scss +46 -55
- package/styles/components/Form/TextInput.scss +4 -0
- package/styles/components/Form/field.scss +2 -2
- package/styles/components/Modal/index.scss +82 -63
- package/styles/components/PhotoDropzone/index.scss +4 -0
- package/styles/components/Tabs/index.scss +18 -120
- package/styles/core/z-index.scss +1 -0
- package/tokens/zIndexes.js +2 -1
- package/tokens/zIndexes.js.map +1 -1
- package/types/src/components/Accordion/index.d.ts +15 -66
- package/types/src/components/Alerter/index.d.ts +8 -19
- package/types/src/components/Form/Autocomplete/index.d.ts +38 -37
- package/types/src/components/Form/Slider.d.ts +12 -77
- package/types/src/components/Form/field.d.ts +16 -1
- package/types/src/components/Modal/ModalHeader.d.ts +1 -1
- package/types/src/components/Modal/index.d.ts +2 -2
- package/types/src/components/Tabs/index.d.ts +9 -6
- package/types/src/index.d.ts +1 -1
- package/types/src/tokens/index.d.ts +1 -0
- package/utilities.css +59 -0
- package/utils/getCobaltTailwindcssConfig.js.map +1 -1
- package/components/Alerter/Alert.js +0 -47
- package/components/Alerter/Alert.js.map +0 -1
- package/components/Modal/ModalBody.js +0 -11
- package/components/Modal/ModalBody.js.map +0 -1
- package/components/utils/Timer.js +0 -24
- package/components/utils/Timer.js.map +0 -1
- package/components/utils/dom.js +0 -8
- package/components/utils/dom.js.map +0 -1
- package/components/utils/px.js +0 -5
- package/components/utils/px.js.map +0 -1
- package/hooks/useElementHeight.js +0 -34
- package/hooks/useElementHeight.js.map +0 -1
- package/types/src/components/Alerter/Alert.d.ts +0 -9
- package/types/src/components/Modal/ModalBody.d.ts +0 -8
|
@@ -1,168 +1,190 @@
|
|
|
1
|
-
import React, { useState, useRef, useEffect } from 'react';
|
|
1
|
+
import React, { forwardRef, useState, useRef, useMemo, useEffect, useImperativeHandle } from 'react';
|
|
2
2
|
import cx from 'classnames';
|
|
3
|
-
import { Combobox, ComboboxPopover, ComboboxList, ComboboxOption, ComboboxOptionText, ComboboxInput } from '@reach/combobox';
|
|
4
3
|
import { Icon } from '../../Icon/index.js';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
4
|
+
import { createListCollection, useCombobox, Combobox, Portal } from '@ark-ui/react';
|
|
5
|
+
import { Hint } from '../Hint.js';
|
|
6
|
+
import { nanoid } from 'nanoid';
|
|
7
|
+
import CheckIcon from '../../Icon/__generated__/CheckIcon.js';
|
|
7
8
|
|
|
8
|
-
function
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
9
|
+
function sanitizeItem(item) {
|
|
10
|
+
if (typeof item === "string") {
|
|
11
|
+
// If the item is a string, create an object with label and value being the string
|
|
12
|
+
return { label: item, value: item };
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
// If the item is an object, ensure it has a label property
|
|
16
|
+
const { value, label } = item;
|
|
17
|
+
return { ...item, label: label !== null && label !== void 0 ? label : value };
|
|
18
|
+
}
|
|
18
19
|
}
|
|
19
|
-
function sanitizeItems(items
|
|
20
|
-
|
|
21
|
-
useEffect(() => {
|
|
22
|
-
setSanitizedItems(items.map((item) => typeof item === "string" ? { [valueKey]: item } : item));
|
|
23
|
-
}, [items]);
|
|
24
|
-
return sanitizedItems;
|
|
20
|
+
function sanitizeItems(items) {
|
|
21
|
+
return items.map((item) => sanitizeItem(item));
|
|
25
22
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const
|
|
34
|
-
const
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
23
|
+
const KEY_CODE_ENTER = 13;
|
|
24
|
+
const ignoreItemValue = nanoid();
|
|
25
|
+
const Autocomplete = forwardRef(({ id, className, label, hint, fullWidth, icon, status, focusOnInit = false, popoverClassName, minQueryLength = 1, onQueryChange, onSelectItem, renderItem, items, onKeyDown, disabled, defaultValue, onClearValue, allowCustomValue = true, ...inputProps }, ref) => {
|
|
26
|
+
const [defaultInputValue, setDefaultInputValue] = useState(defaultValue);
|
|
27
|
+
const [autocompleteKey, setAutocompleteKey] = useState(true);
|
|
28
|
+
const isInputValidChangedProgrammatically = useRef(false);
|
|
29
|
+
const sanitizedInitialItems = useMemo(() => sanitizeItems(items), [items]);
|
|
30
|
+
const [value, setValue] = useState(defaultValue || "");
|
|
31
|
+
const [popoverItems, setPopoverItems] = useState(sanitizedInitialItems);
|
|
32
|
+
const collection = useMemo(() => createListCollection({
|
|
33
|
+
items: popoverItems.length
|
|
34
|
+
? popoverItems
|
|
35
|
+
: sanitizeItems([{ value: ignoreItemValue }]), // having an empty collection makes the component buggy. Best practice is to always have an "instruction" item when empty. This dummy item will not be displayed
|
|
36
|
+
}), [popoverItems]);
|
|
37
|
+
const handleInputChange = (details) => {
|
|
38
|
+
if (isInputValidChangedProgrammatically.current) {
|
|
39
|
+
isInputValidChangedProgrammatically.current = false;
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
onQueryChange
|
|
43
|
+
? onQueryChange(details.inputValue)
|
|
44
|
+
: setPopoverItems(sanitizedInitialItems.filter((item) => item.label
|
|
45
|
+
.toLowerCase()
|
|
46
|
+
.includes(details.inputValue.toLowerCase())));
|
|
38
47
|
};
|
|
39
|
-
const isMounted = useRef(true);
|
|
40
|
-
const forceIdTimer = useRef();
|
|
41
|
-
const focusTimer = useRef();
|
|
42
|
-
const blurTimer = useRef();
|
|
43
|
-
const clearInputTimer = useRef();
|
|
44
|
-
function forceId() {
|
|
45
|
-
// id is overriden by Reach ui Combobox
|
|
46
|
-
forceIdTimer.current = setTimeout(() => {
|
|
47
|
-
id && inputEl.current && inputEl.current.setAttribute("id", id);
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
48
|
useEffect(() => {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
49
|
+
setPopoverItems(sanitizeItems(items));
|
|
50
|
+
}, [items]);
|
|
51
|
+
const inputRef = useRef(null);
|
|
52
|
+
const combobox = useCombobox({
|
|
53
|
+
...(id ? { id } : {}),
|
|
54
|
+
allowCustomValue: allowCustomValue,
|
|
55
|
+
autoFocus: focusOnInit,
|
|
56
|
+
value: [value],
|
|
57
|
+
collection: collection,
|
|
58
|
+
onInputValueChange: handleInputChange,
|
|
59
|
+
openOnClick: minQueryLength === 0 && collection.items.length > 0,
|
|
60
|
+
onValueChange: (details) => {
|
|
61
|
+
isInputValidChangedProgrammatically.current = true;
|
|
62
|
+
details.items[0]
|
|
63
|
+
? setValue(details.items[0].value)
|
|
64
|
+
: setValue("");
|
|
65
|
+
details.items[0] &&
|
|
66
|
+
onSelectItem &&
|
|
67
|
+
onSelectItem(details.items[0], combobox.inputValue);
|
|
68
|
+
},
|
|
69
|
+
onInteractOutside: () => {
|
|
70
|
+
setTimeout(() => { var _a; return (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.blur(); }, 30);
|
|
71
|
+
},
|
|
72
|
+
positioning: {
|
|
73
|
+
gutter: -3,
|
|
74
|
+
flip: false,
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
useImperativeHandle(ref, () => {
|
|
78
|
+
return {
|
|
79
|
+
query: combobox.inputValue,
|
|
80
|
+
input: inputRef.current,
|
|
81
|
+
open: () => {
|
|
82
|
+
combobox.setOpen(true);
|
|
83
|
+
},
|
|
84
|
+
focus: () => {
|
|
85
|
+
combobox.focus();
|
|
86
|
+
},
|
|
87
|
+
clearValue: () => {
|
|
88
|
+
combobox.clearValue();
|
|
89
|
+
setValue("");
|
|
90
|
+
setDefaultInputValue("");
|
|
91
|
+
onClearValue && onClearValue();
|
|
92
|
+
onQueryChange && onQueryChange("");
|
|
93
|
+
},
|
|
94
|
+
setSelectedItem: (selectedItem) => {
|
|
95
|
+
isInputValidChangedProgrammatically.current = true;
|
|
96
|
+
const sanitizedItem = sanitizeItem(selectedItem);
|
|
97
|
+
const existingItem = popoverItems.find((item) => item.value === sanitizedItem.value);
|
|
98
|
+
if (!existingItem) {
|
|
99
|
+
combobox.setOpen(false);
|
|
100
|
+
setPopoverItems([]);
|
|
101
|
+
setDefaultInputValue(sanitizedItem.value);
|
|
102
|
+
setValue(sanitizedItem.value);
|
|
103
|
+
setAutocompleteKey(!autocompleteKey);
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
setValue(sanitizedItem.value);
|
|
107
|
+
combobox.setOpen(false);
|
|
108
|
+
}
|
|
109
|
+
},
|
|
59
110
|
};
|
|
60
|
-
}, []);
|
|
111
|
+
}, [combobox]);
|
|
61
112
|
useEffect(() => {
|
|
62
|
-
|
|
63
|
-
}, [
|
|
113
|
+
focusOnInit && combobox.setOpen(collection.items.length > 0);
|
|
114
|
+
}, []);
|
|
115
|
+
const validItems = collection.items.filter((item) => item.value !== ignoreItemValue);
|
|
64
116
|
useEffect(() => {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
},
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
onQueryChange && onQueryChange("");
|
|
93
|
-
clearInputTimer.current = setTimeout(giveInputFocus); //timeout to trigger openOnFocus
|
|
94
|
-
};
|
|
95
|
-
const handleSelectItem = (item, e) => {
|
|
96
|
-
// item click interceptor to enable custom select cancellation
|
|
97
|
-
const processSelection = onSelectItem
|
|
98
|
-
? onSelectItem(item, term) !== false
|
|
99
|
-
: true;
|
|
100
|
-
if (processSelection) {
|
|
101
|
-
setTerm(item[valueKey]);
|
|
102
|
-
}
|
|
103
|
-
else if (e) {
|
|
104
|
-
e.preventDefault();
|
|
105
|
-
ignoreFocus = true;
|
|
106
|
-
giveInputFocus();
|
|
107
|
-
}
|
|
108
|
-
};
|
|
109
|
-
const handleKeyDown = (e) => {
|
|
110
|
-
onKeyDown && onKeyDown(e);
|
|
111
|
-
// ENTER key down interceptor to enable custom select cancellation
|
|
112
|
-
const KEY_CODE_ENTER = 13;
|
|
113
|
-
// BACKSPACE key down interceptor to synchonize react input value and dom input value in some edge case (Comnbobox autocomplete = true)
|
|
114
|
-
const KEY_CODE_BACKSPACE = 8;
|
|
115
|
-
if (e.keyCode === KEY_CODE_ENTER) {
|
|
116
|
-
if (!popoverEl.current)
|
|
117
|
-
return;
|
|
118
|
-
const options = Array.from(popoverEl.current.querySelectorAll("[data-reach-combobox-option]"));
|
|
119
|
-
const selectedItemIndex = options.findIndex((el) => el.getAttribute("aria-selected") === "true");
|
|
120
|
-
selectedItemIndex >= 0 && handleSelectItem(results[selectedItemIndex], e);
|
|
121
|
-
}
|
|
122
|
-
else if (e.keyCode === KEY_CODE_BACKSPACE) {
|
|
123
|
-
if (!inputEl.current)
|
|
124
|
-
return;
|
|
125
|
-
if (inputEl.current.value.slice(0, -1) === term) {
|
|
126
|
-
setTerm(inputEl.current.value);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
};
|
|
130
|
-
const shouldDisplayItemsOnEmptyQuery = () => {
|
|
131
|
-
return !autoFilter && results.length > 0 && term.length === 0 && hasFocus;
|
|
132
|
-
};
|
|
133
|
-
const handleMouseDown = (item, e) => {
|
|
134
|
-
// In a specific case, we force the popover to display (results available, empty input using backspace)
|
|
135
|
-
// But doing so, reach ui component is not ready for this case and will raise an error
|
|
136
|
-
// We need to prevent the error and to force the selection
|
|
137
|
-
if (shouldDisplayItemsOnEmptyQuery() &&
|
|
138
|
-
popoverEl.current &&
|
|
139
|
-
popoverEl.current.getAttribute("hidden") != null) {
|
|
140
|
-
e.preventDefault(); // it will prevent reach ui combobox to raise an error
|
|
141
|
-
handleSelectItem(item, e); // we force the selection to be processed
|
|
142
|
-
}
|
|
143
|
-
};
|
|
144
|
-
return (React.createElement(Combobox, { className: cx("cobalt-Autocomplete", {
|
|
145
|
-
"cobalt-Autocomplete--forceDisplayResults": shouldDisplayItemsOnEmptyQuery(), // Combobox Component, by design, hide the popover when the input is empty (on change) even if there are some results.
|
|
146
|
-
}), as: "div", openOnFocus: true, ref: comboboxEl },
|
|
147
|
-
results.length > 0 && (React.createElement(ComboboxPopover, { className: "cobalt-Autocomplete__popover", portal: false, ref: popoverEl },
|
|
148
|
-
React.createElement(ComboboxList, { className: "cobalt-Autocomplete__list", "aria-label": "Autocomplete option" }, results.map((item, index) => (React.createElement(ComboboxOption, { className: "cobalt-Autocomplete__item", key: index, value: item[valueKey], onMouseDown: (e) => {
|
|
149
|
-
handleMouseDown(item, e);
|
|
150
|
-
}, onClick: (e) => {
|
|
151
|
-
handleSelectItem(item, e);
|
|
152
|
-
} }, renderItem ? (renderItem(item, term)) : (React.createElement("span", { className: "cobalt-Autocomplete__item-wrapper" },
|
|
153
|
-
icon && (React.createElement("span", { className: "cobalt-Autocomplete__item-icon" },
|
|
154
|
-
React.createElement(Icon, { source: icon, color: "accent" }))),
|
|
155
|
-
React.createElement("span", { className: "cobalt-Autocomplete__item-value" },
|
|
156
|
-
React.createElement(ComboboxOptionText, null)))))))))),
|
|
157
|
-
React.createElement("div", { className: "cobalt-Autocomplete__input-wrapper" },
|
|
158
|
-
React.createElement(TextInputWrapper, { icon: icon, status: status, render: (className) => {
|
|
159
|
-
return (React.createElement(ComboboxInput, { ...inputProps, autoComplete: "off", autoCorrect: "off", autoCapitalize: "off", spellCheck: false, "aria-label": "autocomplete input", type: "text", value: term, onChange: handleChange, onBlur: handleBlur, onFocus: handleFocus, onKeyDown: handleKeyDown, ref: inputEl, className: className }));
|
|
117
|
+
validItems.length === 0 && combobox.setOpen(false);
|
|
118
|
+
combobox.focused &&
|
|
119
|
+
collection.items.length > 0 &&
|
|
120
|
+
!combobox.open &&
|
|
121
|
+
combobox.setOpen(true);
|
|
122
|
+
}, [collection.items.length]);
|
|
123
|
+
const autocomplete = (React.createElement(Combobox.RootProvider, { value: combobox, className: cx("cobalt-Autocomplete", className, {
|
|
124
|
+
"cobalt-Autocomplete--empty": validItems.length === 0,
|
|
125
|
+
}), key: "" + autocompleteKey },
|
|
126
|
+
label && (React.createElement(Combobox.Label, { className: "cobalt-FormField__Label" }, label)),
|
|
127
|
+
React.createElement(Combobox.Control, { className: cx("cobalt-TextField", {
|
|
128
|
+
"cobalt-TextField--error": status === "error",
|
|
129
|
+
"cobalt-TextField--success": status === "success",
|
|
130
|
+
"cobalt-TextField--withIcon": icon,
|
|
131
|
+
"cobalt-TextField--withValue": inputRef.current && inputRef.current.value.length > 0,
|
|
132
|
+
}) },
|
|
133
|
+
React.createElement(Combobox.Input, { className: "cobalt-TextField__Input", ref: inputRef, disabled: disabled, defaultValue: defaultInputValue, ...inputProps, onKeyDown: (e) => {
|
|
134
|
+
onKeyDown && onKeyDown(e);
|
|
135
|
+
if (onSelectItem &&
|
|
136
|
+
e.keyCode === KEY_CODE_ENTER &&
|
|
137
|
+
combobox.highlightedItem) {
|
|
138
|
+
const processSelection = onSelectItem(combobox.highlightedItem, combobox.inputValue);
|
|
139
|
+
if (!processSelection) {
|
|
140
|
+
e.preventDefault();
|
|
141
|
+
e.stopPropagation();
|
|
142
|
+
}
|
|
143
|
+
}
|
|
160
144
|
} }),
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
145
|
+
icon && (React.createElement(Icon, { source: icon, color: "accent", className: "cobalt-TextField__Icon" })),
|
|
146
|
+
value.length > 0 && !disabled && (React.createElement(Combobox.ClearTrigger, { className: "cobalt-Autocomplete__clear-button", role: "clear", onClick: () => {
|
|
147
|
+
setDefaultInputValue("");
|
|
148
|
+
setValue("");
|
|
149
|
+
setAutocompleteKey(!autocompleteKey);
|
|
150
|
+
minQueryLength === 0 &&
|
|
151
|
+
setTimeout(() => {
|
|
152
|
+
var _a;
|
|
153
|
+
(_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.click();
|
|
154
|
+
}, 0);
|
|
155
|
+
onClearValue && onClearValue();
|
|
156
|
+
onQueryChange && onQueryChange("");
|
|
157
|
+
} },
|
|
158
|
+
React.createElement(Icon, { source: "close", size: 16 })))),
|
|
159
|
+
React.createElement(Portal, null,
|
|
160
|
+
React.createElement(Combobox.Positioner, { className: "cobalt-Autocomplete__positioner" },
|
|
161
|
+
React.createElement(Combobox.Content, { className: cx("cobalt-Autocomplete__content", popoverClassName, {
|
|
162
|
+
"cobalt-Autocomplete__content--empty": validItems.length === 0,
|
|
163
|
+
}) }, validItems.map((item, index) => (React.createElement(Combobox.Item, { key: index, item: item, className: "cobalt-Autocomplete__item" }, renderItem ? (React.createElement("div", { onClick: (e) => {
|
|
164
|
+
if (onSelectItem) {
|
|
165
|
+
const processSelection = onSelectItem(combobox.highlightedItem, combobox.inputValue);
|
|
166
|
+
if (!processSelection) {
|
|
167
|
+
e.preventDefault();
|
|
168
|
+
e.stopPropagation();
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
} }, renderItem(item, combobox.inputValue))) : (React.createElement("div", { className: cx("cobalt-Autocomplete__item-wrapper", {
|
|
172
|
+
"cobalt-Autocomplete__item-wrapper--disabled": item.disabled,
|
|
173
|
+
}) },
|
|
174
|
+
icon && (React.createElement("span", { className: "cobalt-Autocomplete__item-icon" },
|
|
175
|
+
React.createElement(Icon, { source: icon, color: "accent" }))),
|
|
176
|
+
React.createElement(Combobox.ItemText, { className: "cobalt-Autocomplete__item-label" }, item.label),
|
|
177
|
+
React.createElement(Combobox.ItemIndicator, { className: "cobalt-Autocomplete_selected-item-indicator" },
|
|
178
|
+
React.createElement(CheckIcon, { size: 16 }))))))))))));
|
|
179
|
+
return label || hint ? (React.createElement("div", { className: cx("cobalt-FormField", {
|
|
180
|
+
"cobalt-FormField--withHint": hint,
|
|
181
|
+
"cobalt-FormField--fullWidth": fullWidth,
|
|
182
|
+
}) },
|
|
183
|
+
autocomplete,
|
|
184
|
+
hint && (React.createElement(Hint, { status: status },
|
|
185
|
+
React.createElement("span", { dangerouslySetInnerHTML: { __html: hint } }))))) : (React.createElement(React.Fragment, null, autocomplete));
|
|
186
|
+
});
|
|
187
|
+
Autocomplete.displayName = "Autocomplete";
|
|
166
188
|
|
|
167
|
-
export {
|
|
189
|
+
export { Autocomplete };
|
|
168
190
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../../src/components/Form/Autocomplete/index.tsx"],"sourcesContent":["import React, { useEffect, useRef, ElementType } from \"react\"\nimport { useState } from \"react\"\nimport classNames from \"classnames\"\n\nimport {\n Combobox,\n ComboboxInput,\n ComboboxPopover,\n ComboboxList,\n ComboboxOption,\n ComboboxOptionText,\n} from \"@reach/combobox\"\n\nimport { Icon, IconSources } from \"../../Icon\"\n\nimport { withFieldLabelAndHint } from \"../field\"\nimport { TextInputWrapper } from \"../TextInput\"\nimport { FormElement } from \"../form\"\n\nexport interface AutocompleteItem {\n [x: string]: any\n}\n\ntype ComboboxPopoverType = ElementType<\"div\"> & HTMLDivElement\ntype ComboboxOptionType = HTMLLIElement & React.ElementType<\"li\">\ntype ComboboxOptionMouseEventType = React.MouseEvent<\n ComboboxOptionType,\n MouseEvent\n>\n\ntype Props = {\n icon?: IconSources\n items: (AutocompleteItem | string)[]\n minQueryLength?: number\n autoFilter?: boolean\n selectedItem?: AutocompleteItem\n focusOnInit?: boolean\n autocomplete?: boolean\n valueKey?: string\n inputRef?: React.RefObject<HTMLInputElement>\n autocompleteRef?: React.RefObject<HTMLDivElement>\n onKeyDown?: (event: React.KeyboardEvent<HTMLElement>) => void\n onBlur?: (event: React.FocusEvent<HTMLInputElement>) => void\n onFocus?: (event: React.FocusEvent<HTMLInputElement>) => void\n onQueryChange?: (term: string) => void\n onSelectItem?: (item: AutocompleteItem, term: string) => boolean\n renderItem?: (item: AutocompleteItem, term: string) => React.ReactNode\n} & FormElement &\n React.InputHTMLAttributes<HTMLInputElement>\n\nfunction filterMatchingItems(\n items: AutocompleteItem[],\n term: string,\n minLength: number,\n valueKey: string\n) {\n const [matchingItems, setMatchingItems] = useState<AutocompleteItem[]>([])\n\n useEffect(() => {\n term.length >= minLength\n ? setMatchingItems(\n items.filter((item: AutocompleteItem) => {\n return item[valueKey].toLowerCase().indexOf(term.toLowerCase()) > -1\n })\n )\n : setMatchingItems([])\n }, [items, term, valueKey])\n\n return matchingItems\n}\n\nfunction sanitizeItems(items: (AutocompleteItem | string)[], valueKey: string) {\n const [sanitizedItems, setSanitizedItems] = useState<AutocompleteItem[]>([])\n useEffect(() => {\n setSanitizedItems(\n items.map((item) =>\n typeof item === \"string\" ? { [valueKey]: item } : item\n )\n )\n }, [items])\n return sanitizedItems\n}\n\nfunction Autocomplete({\n id,\n icon,\n status,\n items,\n selectedItem,\n autoFilter = true,\n minQueryLength = 1,\n focusOnInit = false,\n onKeyDown,\n onFocus,\n onBlur,\n onQueryChange,\n onSelectItem,\n renderItem,\n inputRef,\n autocompleteRef,\n valueKey = \"value\",\n ...inputProps\n}: Props) {\n const [term, setTerm] = useState(\"\")\n\n const [hasFocus, setHasFocus] = useState(false)\n\n let ignoreFocus = false // extra flag to ignore programmatical focus triggered by click on item\n\n const results = autoFilter\n ? filterMatchingItems(\n sanitizeItems(items, valueKey),\n term,\n minQueryLength,\n valueKey\n )\n : sanitizeItems(items, valueKey)\n\n const comboboxEl = autocompleteRef || useRef<HTMLDivElement>(null)\n\n const inputEl = inputRef || useRef<HTMLInputElement>(null)\n\n const popoverEl = useRef<ComboboxPopoverType>(null)\n\n const giveInputFocus = () => {\n inputEl.current && inputEl.current.focus()\n }\n\n const isMounted = useRef(true)\n const forceIdTimer = useRef<any>()\n const focusTimer = useRef<any>()\n const blurTimer = useRef<any>()\n const clearInputTimer = useRef<any>()\n\n function forceId() {\n // id is overriden by Reach ui Combobox\n forceIdTimer.current = setTimeout(() => {\n id && inputEl.current && inputEl.current.setAttribute(\"id\", id)\n })\n }\n\n useEffect(() => {\n // on mount ...\n focusOnInit && giveInputFocus()\n\n return () => {\n isMounted.current = false\n forceIdTimer.current && clearTimeout(forceIdTimer.current)\n focusTimer.current && clearTimeout(focusTimer.current)\n blurTimer.current && clearTimeout(blurTimer.current)\n clearInputTimer.current && clearTimeout(clearInputTimer.current)\n }\n }, [])\n\n useEffect(() => {\n forceId()\n }, [id])\n\n useEffect(() => {\n setTerm(selectedItem ? \"\" + selectedItem[valueKey] : \"\")\n }, [selectedItem])\n\n const handleFocus = (event: React.FocusEvent<HTMLInputElement>) => {\n !ignoreFocus && onFocus && onFocus(event)\n ignoreFocus = false\n focusTimer.current = setTimeout(() => {\n // required by \"forceDisplayResults\" mechanism\n isMounted.current && setHasFocus(true)\n }, 100)\n }\n\n const handleBlur = (event: React.FocusEvent<HTMLInputElement>) => {\n // blur interceptor required by \"forceDisplayResults\" mechanism\n onBlur && onBlur(event)\n blurTimer.current = setTimeout(() => {\n isMounted.current && setHasFocus(false)\n }, 100)\n }\n\n const handleChange = (event: React.FocusEvent<HTMLInputElement>) => {\n const inputValue = (event.target as HTMLInputElement).value\n if (inputValue.trim().length || term.length) {\n // to prevent starting with a space character\n setTerm(inputValue)\n onQueryChange && onQueryChange(inputValue)\n }\n }\n\n const handleClearInput = () => {\n setTerm(\"\")\n onQueryChange && onQueryChange(\"\")\n\n clearInputTimer.current = setTimeout(giveInputFocus) //timeout to trigger openOnFocus\n }\n\n const handleSelectItem = (\n item: AutocompleteItem,\n e: ComboboxOptionMouseEventType | React.KeyboardEvent<HTMLElement>\n ) => {\n // item click interceptor to enable custom select cancellation\n const processSelection = onSelectItem\n ? onSelectItem(item, term) !== false\n : true\n\n if (processSelection) {\n setTerm(item[valueKey])\n } else if (e) {\n e.preventDefault()\n ignoreFocus = true\n giveInputFocus()\n }\n }\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLElement>) => {\n onKeyDown && onKeyDown(e)\n\n // ENTER key down interceptor to enable custom select cancellation\n const KEY_CODE_ENTER = 13\n\n // BACKSPACE key down interceptor to synchonize react input value and dom input value in some edge case (Comnbobox autocomplete = true)\n const KEY_CODE_BACKSPACE = 8\n\n if (e.keyCode === KEY_CODE_ENTER) {\n if (!popoverEl.current) return\n\n const options = Array.from(\n popoverEl.current.querySelectorAll(\"[data-reach-combobox-option]\")\n )\n\n const selectedItemIndex = options.findIndex(\n (el) => el.getAttribute(\"aria-selected\") === \"true\"\n )\n\n selectedItemIndex >= 0 && handleSelectItem(results[selectedItemIndex], e)\n } else if (e.keyCode === KEY_CODE_BACKSPACE) {\n if (!inputEl.current) return\n if (inputEl.current.value.slice(0, -1) === term) {\n setTerm(inputEl.current.value)\n }\n }\n }\n\n const shouldDisplayItemsOnEmptyQuery = () => {\n return !autoFilter && results.length > 0 && term.length === 0 && hasFocus\n }\n\n const handleMouseDown = (\n item: AutocompleteItem,\n e: ComboboxOptionMouseEventType\n ) => {\n // In a specific case, we force the popover to display (results available, empty input using backspace)\n // But doing so, reach ui component is not ready for this case and will raise an error\n // We need to prevent the error and to force the selection\n if (\n shouldDisplayItemsOnEmptyQuery() &&\n popoverEl.current &&\n popoverEl.current.getAttribute(\"hidden\") != null\n ) {\n e.preventDefault() // it will prevent reach ui combobox to raise an error\n handleSelectItem(item, e) // we force the selection to be processed\n }\n }\n\n return (\n <Combobox\n className={classNames(\"cobalt-Autocomplete\", {\n \"cobalt-Autocomplete--forceDisplayResults\":\n shouldDisplayItemsOnEmptyQuery(), // Combobox Component, by design, hide the popover when the input is empty (on change) even if there are some results.\n })}\n as=\"div\"\n openOnFocus={true}\n ref={comboboxEl}\n >\n {results.length > 0 && (\n <ComboboxPopover\n className=\"cobalt-Autocomplete__popover\"\n portal={false}\n ref={popoverEl}\n >\n <ComboboxList\n className=\"cobalt-Autocomplete__list\"\n aria-label=\"Autocomplete option\"\n >\n {results.map((item, index) => (\n <ComboboxOption\n className=\"cobalt-Autocomplete__item\"\n key={index}\n value={item[valueKey]}\n onMouseDown={(e: ComboboxOptionMouseEventType) => {\n handleMouseDown(item, e)\n }}\n onClick={(e: ComboboxOptionMouseEventType) => {\n handleSelectItem(item, e)\n }}\n >\n {renderItem ? (\n renderItem(item, term)\n ) : (\n <span className=\"cobalt-Autocomplete__item-wrapper\">\n {icon && (\n <span className=\"cobalt-Autocomplete__item-icon\">\n <Icon source={icon} color=\"accent\" />\n </span>\n )}\n\n <span className=\"cobalt-Autocomplete__item-value\">\n <ComboboxOptionText />\n </span>\n </span>\n )}\n </ComboboxOption>\n ))}\n </ComboboxList>\n </ComboboxPopover>\n )}\n <div className=\"cobalt-Autocomplete__input-wrapper\">\n <TextInputWrapper\n icon={icon}\n status={status}\n render={(className) => {\n return (\n <ComboboxInput\n {...inputProps}\n autoComplete=\"off\"\n autoCorrect=\"off\"\n autoCapitalize=\"off\"\n spellCheck={false}\n aria-label=\"autocomplete input\"\n type=\"text\"\n value={term}\n onChange={handleChange}\n onBlur={handleBlur}\n onFocus={handleFocus}\n onKeyDown={handleKeyDown}\n ref={inputEl}\n className={className}\n />\n )\n }}\n />\n\n {term && (\n <div\n className=\"cobalt-Autocomplete__clear-button\"\n role=\"clear\"\n onClick={handleClearInput}\n >\n <Icon source=\"close\" size={16} />\n </div>\n )}\n </div>\n </Combobox>\n )\n}\n\nconst wrappedComponent = withFieldLabelAndHint(Autocomplete)\nwrappedComponent.displayName = \"Autocomplete\"\n\nexport { wrappedComponent as Autocomplete }\n"],"names":["classNames"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/components/Form/Autocomplete/index.tsx"],"sourcesContent":["import React, {\n useEffect,\n useRef,\n useMemo,\n useImperativeHandle,\n forwardRef,\n} from \"react\"\nimport { useState } from \"react\"\nimport cx from \"classnames\"\n\nimport { CheckIcon, Icon, IconSources } from \"../../Icon\"\n\nimport { FormElement } from \"../form\"\nimport {\n Combobox,\n createListCollection,\n Portal,\n useCombobox,\n} from \"@ark-ui/react\"\nimport { Hint } from \"../Hint\"\nimport { nanoid } from \"nanoid\"\n\nexport type AutocompleteItemInput =\n | string\n | {\n [x: string]: any\n icon?: IconSources\n label?: string\n value: string\n disabled?: boolean\n }\n\nexport type AutocompleteItem = {\n [x: string]: any\n icon?: IconSources\n label: string\n value: string\n disabled?: boolean\n}\n\nexport type AutocompleteRefType = {\n query: string\n input: HTMLInputElement\n open: () => void\n focus: () => void\n clearValue: () => void\n setSelectedItem: (item: AutocompleteItemInput) => void\n}\n\ntype Props = {\n className?: string\n label?: string\n hint?: string\n fullWidth?: boolean\n icon?: IconSources\n items: AutocompleteItemInput[]\n popoverClassName?: string\n minQueryLength?: number\n autoFilter?: boolean\n focusOnInit?: boolean\n autocomplete?: boolean\n autocompleteRef?: React.RefObject<HTMLDivElement>\n onClearValue?: () => void\n onKeyDown?: (event: React.KeyboardEvent<HTMLElement>) => void\n onQueryChange?: (term: string) => void\n onSelectItem?: (item: AutocompleteItem, term: string) => boolean\n renderItem?: (item: AutocompleteItem, term: string) => React.ReactNode\n allowCustomValue?: boolean\n} & FormElement &\n React.InputHTMLAttributes<HTMLInputElement>\n\nfunction sanitizeItem(item: AutocompleteItemInput) {\n if (typeof item === \"string\") {\n // If the item is a string, create an object with label and value being the string\n return { label: item, value: item }\n } else {\n // If the item is an object, ensure it has a label property\n const { value, label } = item\n return { ...item, label: label ?? value }\n }\n}\n\nfunction sanitizeItems(items: AutocompleteItemInput[]) {\n return items.map((item) => sanitizeItem(item))\n}\n\nconst HIGHLIGHT_CLASSNAME = \"autocomplete_matching_query\"\nconst regExpEscape = (s: string) => s.replace(/[-\\\\^$*+?.()|[\\]{}]/g, \"\\\\$&\")\n\ntype AutocompleteMatchHighlightPropsType = {\n label: string\n query: string\n matchClassName?: string\n}\n\nexport const AutocompleteMatchHighlight = ({\n label,\n query,\n matchClassName = HIGHLIGHT_CLASSNAME,\n}: AutocompleteMatchHighlightPropsType) => {\n if (query.trim().length === 0) return label\n\n const queryRX = RegExp(`(${regExpEscape(query)})`, \"gi\")\n\n return (\n <>\n {label.split(queryRX).map((part, i) =>\n part.match(queryRX) ? (\n <span className={cx(matchClassName)} key={i}>\n {part}\n </span>\n ) : (\n part\n )\n )}\n </>\n )\n}\n\nconst KEY_CODE_ENTER = 13\n\nconst ignoreItemValue = nanoid()\n\nconst Autocomplete = forwardRef(\n (\n {\n id,\n className,\n label,\n hint,\n fullWidth,\n icon,\n status,\n focusOnInit = false,\n popoverClassName,\n minQueryLength = 1,\n onQueryChange,\n onSelectItem,\n renderItem,\n items,\n onKeyDown,\n disabled,\n defaultValue,\n onClearValue,\n allowCustomValue = true,\n ...inputProps\n }: Props,\n ref\n ) => {\n const [defaultInputValue, setDefaultInputValue] = useState(defaultValue)\n const [autocompleteKey, setAutocompleteKey] = useState(true)\n\n const isInputValidChangedProgrammatically = useRef(false)\n const sanitizedInitialItems = useMemo(() => sanitizeItems(items), [items])\n\n const [value, setValue] = useState<string>((defaultValue as string) || \"\")\n const [popoverItems, setPopoverItems] = useState(sanitizedInitialItems)\n\n const collection = useMemo(\n () =>\n createListCollection({\n items: popoverItems.length\n ? popoverItems\n : sanitizeItems([{ value: ignoreItemValue }]), // having an empty collection makes the component buggy. Best practice is to always have an \"instruction\" item when empty. This dummy item will not be displayed\n }),\n [popoverItems]\n )\n\n const handleInputChange = (details: Combobox.InputValueChangeDetails) => {\n if (isInputValidChangedProgrammatically.current) {\n isInputValidChangedProgrammatically.current = false\n return\n }\n\n onQueryChange\n ? onQueryChange(details.inputValue)\n : setPopoverItems(\n sanitizedInitialItems.filter((item) =>\n item.label\n .toLowerCase()\n .includes(details.inputValue.toLowerCase())\n )\n )\n }\n\n useEffect(() => {\n setPopoverItems(sanitizeItems(items))\n }, [items])\n\n const inputRef = useRef<HTMLInputElement>(null)\n\n const combobox = useCombobox({\n ...(id ? { id } : {}),\n allowCustomValue: allowCustomValue,\n autoFocus: focusOnInit,\n value: [value],\n collection: collection,\n onInputValueChange: handleInputChange,\n openOnClick: minQueryLength === 0 && collection.items.length > 0,\n onValueChange: (details) => {\n isInputValidChangedProgrammatically.current = true\n details.items[0]\n ? setValue((details.items[0] as AutocompleteItem).value)\n : setValue(\"\")\n details.items[0] &&\n onSelectItem &&\n onSelectItem(\n details.items[0] as AutocompleteItem,\n combobox.inputValue\n )\n },\n onInteractOutside: () => {\n setTimeout(() => inputRef.current?.blur(), 30)\n },\n positioning: {\n gutter: -3,\n flip: false,\n },\n })\n\n useImperativeHandle(ref, (): AutocompleteRefType => {\n return {\n query: combobox.inputValue,\n input: inputRef.current as HTMLInputElement,\n open: () => {\n combobox.setOpen(true)\n },\n focus: () => {\n combobox.focus()\n },\n clearValue: () => {\n combobox.clearValue()\n setValue(\"\")\n setDefaultInputValue(\"\")\n onClearValue && onClearValue()\n onQueryChange && onQueryChange(\"\")\n },\n setSelectedItem: (selectedItem: AutocompleteItemInput) => {\n isInputValidChangedProgrammatically.current = true\n const sanitizedItem = sanitizeItem(selectedItem)\n const existingItem = popoverItems.find(\n (item) => item.value === sanitizedItem.value\n )\n\n if (!existingItem) {\n combobox.setOpen(false)\n setPopoverItems([])\n setDefaultInputValue(sanitizedItem.value)\n setValue(sanitizedItem.value)\n setAutocompleteKey(!autocompleteKey)\n } else {\n setValue(sanitizedItem.value)\n combobox.setOpen(false)\n }\n },\n }\n }, [combobox])\n\n useEffect(() => {\n focusOnInit && combobox.setOpen(collection.items.length > 0)\n }, [])\n\n const validItems = collection.items.filter(\n (item) => item.value !== ignoreItemValue\n )\n\n useEffect(() => {\n validItems.length === 0 && combobox.setOpen(false)\n\n combobox.focused &&\n collection.items.length > 0 &&\n !combobox.open &&\n combobox.setOpen(true)\n }, [collection.items.length])\n\n const autocomplete = (\n <Combobox.RootProvider\n value={combobox}\n className={cx(\"cobalt-Autocomplete\", className, {\n \"cobalt-Autocomplete--empty\": validItems.length === 0,\n })}\n key={\"\" + autocompleteKey}\n >\n {label && (\n <Combobox.Label className=\"cobalt-FormField__Label\">\n {label}\n </Combobox.Label>\n )}\n <Combobox.Control\n className={cx(\"cobalt-TextField\", {\n \"cobalt-TextField--error\": status === \"error\",\n \"cobalt-TextField--success\": status === \"success\",\n \"cobalt-TextField--withIcon\": icon,\n \"cobalt-TextField--withValue\":\n inputRef.current && inputRef.current.value.length > 0,\n })}\n >\n <Combobox.Input\n className=\"cobalt-TextField__Input\"\n ref={inputRef}\n disabled={disabled}\n defaultValue={defaultInputValue}\n {...inputProps}\n onKeyDown={(e) => {\n onKeyDown && onKeyDown(e)\n if (\n onSelectItem &&\n e.keyCode === KEY_CODE_ENTER &&\n combobox.highlightedItem\n ) {\n const processSelection = onSelectItem(\n combobox.highlightedItem as AutocompleteItem,\n combobox.inputValue\n )\n\n if (!processSelection) {\n e.preventDefault()\n e.stopPropagation()\n }\n }\n }}\n />\n {icon && (\n <Icon\n source={icon}\n color=\"accent\"\n className=\"cobalt-TextField__Icon\"\n />\n )}\n {value.length > 0 && !disabled && (\n <Combobox.ClearTrigger\n className=\"cobalt-Autocomplete__clear-button\"\n role=\"clear\"\n onClick={() => {\n setDefaultInputValue(\"\")\n setValue(\"\")\n setAutocompleteKey(!autocompleteKey)\n minQueryLength === 0 &&\n setTimeout(() => {\n inputRef.current?.click()\n }, 0)\n onClearValue && onClearValue()\n onQueryChange && onQueryChange(\"\")\n }}\n >\n <Icon source=\"close\" size={16} />\n </Combobox.ClearTrigger>\n )}\n </Combobox.Control>\n <Portal>\n <Combobox.Positioner className=\"cobalt-Autocomplete__positioner\">\n <Combobox.Content\n className={cx(\"cobalt-Autocomplete__content\", popoverClassName, {\n \"cobalt-Autocomplete__content--empty\": validItems.length === 0,\n })}\n >\n {validItems.map((item: AutocompleteItem, index: number) => (\n <Combobox.Item\n key={index}\n item={item}\n className=\"cobalt-Autocomplete__item\"\n >\n {renderItem ? (\n <div\n onClick={(e) => {\n if (onSelectItem) {\n const processSelection = onSelectItem(\n combobox.highlightedItem as AutocompleteItem,\n combobox.inputValue\n )\n\n if (!processSelection) {\n e.preventDefault()\n e.stopPropagation()\n }\n }\n }}\n >\n {renderItem(item, combobox.inputValue)}\n </div>\n ) : (\n <div\n className={cx(\"cobalt-Autocomplete__item-wrapper\", {\n \"cobalt-Autocomplete__item-wrapper--disabled\":\n item.disabled,\n })}\n >\n {icon && (\n <span className=\"cobalt-Autocomplete__item-icon\">\n <Icon source={icon} color=\"accent\" />\n </span>\n )}\n <Combobox.ItemText className=\"cobalt-Autocomplete__item-label\">\n {item.label}\n </Combobox.ItemText>\n <Combobox.ItemIndicator className=\"cobalt-Autocomplete_selected-item-indicator\">\n <CheckIcon size={16} />\n </Combobox.ItemIndicator>\n </div>\n )}\n </Combobox.Item>\n ))}\n </Combobox.Content>\n </Combobox.Positioner>\n </Portal>\n </Combobox.RootProvider>\n )\n\n return label || hint ? (\n <div\n className={cx(\"cobalt-FormField\", {\n \"cobalt-FormField--withHint\": hint,\n \"cobalt-FormField--fullWidth\": fullWidth,\n })}\n >\n {autocomplete}\n {hint && (\n <Hint status={status}>\n <span dangerouslySetInnerHTML={{ __html: hint }} />\n </Hint>\n )}\n </div>\n ) : (\n <>{autocomplete}</>\n )\n }\n)\n\nAutocomplete.displayName = \"Autocomplete\"\n\nexport { Autocomplete }\n"],"names":[],"mappings":"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"}
|
|
@@ -1,33 +1,54 @@
|
|
|
1
1
|
import React, { useState } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import { Slider as Slider$1 } from '@reach/slider';
|
|
2
|
+
import { Slider as Slider$1 } from '@ark-ui/react';
|
|
4
3
|
import cx from 'classnames';
|
|
4
|
+
import { FieldWrapper } from './field.js';
|
|
5
5
|
|
|
6
|
-
const Slider = ({ defaultValue, value, min, max,
|
|
6
|
+
const Slider = ({ defaultValue: _defaultValue, value: _value, min, max, disabled, onValueChange, renderValue, ariaLabel, hint, label, status, ...restProps }) => {
|
|
7
|
+
const value = Array.isArray(_value)
|
|
8
|
+
? _value
|
|
9
|
+
: _value !== undefined && !isNaN(_value)
|
|
10
|
+
? [_value]
|
|
11
|
+
: undefined;
|
|
12
|
+
const defaultValue = Array.isArray(_defaultValue)
|
|
13
|
+
? _defaultValue
|
|
14
|
+
: _defaultValue !== undefined && !isNaN(_defaultValue)
|
|
15
|
+
? [_defaultValue]
|
|
16
|
+
: undefined;
|
|
7
17
|
function initValue() {
|
|
8
|
-
if (value
|
|
18
|
+
if (value !== undefined)
|
|
9
19
|
return value;
|
|
10
|
-
if (defaultValue
|
|
20
|
+
if (defaultValue !== undefined)
|
|
11
21
|
return defaultValue;
|
|
12
|
-
if (min
|
|
13
|
-
return min;
|
|
14
|
-
return 0;
|
|
22
|
+
if (min !== undefined)
|
|
23
|
+
return [min];
|
|
24
|
+
return [0];
|
|
15
25
|
}
|
|
16
26
|
const [sliderValue, setSliderValue] = useState(() => initValue());
|
|
17
|
-
return (React.createElement(
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
27
|
+
return (React.createElement(FieldWrapper, { ...restProps, status: status, label: label, hint: hint },
|
|
28
|
+
React.createElement(Slider$1.Root, { ...restProps, className: cx("cobalt-slider", {
|
|
29
|
+
"cobalt-slider--disabled": disabled,
|
|
30
|
+
"cobalt-slider--withHint": hint,
|
|
31
|
+
}), thumbAlignment: "contain", disabled: disabled, "aria-label": [ariaLabel], value: sliderValue, min: min, max: max,
|
|
32
|
+
// Need to force disbplaying in smaller spaces like popovers
|
|
33
|
+
thumbSize: {
|
|
34
|
+
width: 24,
|
|
35
|
+
height: 24,
|
|
36
|
+
}, onValueChange: ({ value: newValueArr }) => {
|
|
37
|
+
setSliderValue(newValueArr);
|
|
38
|
+
const newValue = newValueArr.length === 1 ? newValueArr[0] : newValueArr;
|
|
39
|
+
onValueChange && onValueChange(newValue);
|
|
40
|
+
} },
|
|
41
|
+
React.createElement(Slider$1.Label, { className: FieldWrapper.labelClassName }, label),
|
|
42
|
+
renderValue && (React.createElement("div", { className: "cobalt-slider__value-container" }, renderValue((sliderValue.length === 1 ? sliderValue[0] : sliderValue), status))),
|
|
43
|
+
React.createElement(Slider$1.Control, null,
|
|
44
|
+
React.createElement(Slider$1.Track, null,
|
|
45
|
+
React.createElement(Slider$1.Range, null)),
|
|
46
|
+
sliderValue.map((_v, i) => (React.createElement(Slider$1.Thumb, { key: i, index: i },
|
|
47
|
+
React.createElement(Slider$1.HiddenInput, null))))))));
|
|
25
48
|
};
|
|
26
|
-
const wrappedComponent = withFieldLabelAndHint(Slider);
|
|
27
|
-
wrappedComponent.displayName = "Slider";
|
|
28
49
|
const SliderValueMeta = ({ children }) => {
|
|
29
50
|
return React.createElement("span", { className: "cobalt-slider__value-meta" }, children);
|
|
30
51
|
};
|
|
31
52
|
|
|
32
|
-
export { SliderValueMeta,
|
|
53
|
+
export { SliderValueMeta, Slider as default };
|
|
33
54
|
//# sourceMappingURL=Slider.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Slider.js","sources":["../../../src/components/Form/Slider.tsx"],"sourcesContent":["import React, { useState } from \"react\"\nimport {
|
|
1
|
+
{"version":3,"file":"Slider.js","sources":["../../../src/components/Form/Slider.tsx"],"sourcesContent":["import React, { PropsWithChildren, useState } from \"react\"\nimport { Slider as ArkSlider, SliderRootProps } from \"@ark-ui/react\"\nimport cx from \"classnames\"\nimport { FieldWrapper, FieldWrapperProps } from \"./field\"\n\nexport type SliderPropsType<T extends number | number[]> = {\n /**\n * mandatory for A11y\n */\n value?: T\n defaultValue?: T\n ariaLabel: string\n /**\n * values interval\n */\n step?: number\n disabled?: boolean\n /**\n * Listener called when the value is changed\n */\n onValueChange?: (newValue: T) => void\n /**\n * Function used to visually display the slider value\n */\n renderValue?: (\n value: T,\n status: FieldWrapperProps[\"status\"]\n ) => React.ReactElement\n\n onFocus?: (event: React.FocusEvent<HTMLInputElement>) => void\n} & FieldWrapperProps &\n Omit<SliderRootProps, \"value\" | \"defaultValue\" | \"onValueChange\">\n\nconst Slider = <T extends number | number[]>({\n defaultValue: _defaultValue,\n value: _value,\n min,\n max,\n disabled,\n onValueChange,\n renderValue,\n ariaLabel,\n hint,\n label,\n status,\n ...restProps\n}: SliderPropsType<T>) => {\n const value: number[] | undefined = Array.isArray(_value)\n ? _value\n : _value !== undefined && !isNaN(_value)\n ? [_value]\n : undefined\n const defaultValue: number[] | undefined = Array.isArray(_defaultValue)\n ? _defaultValue\n : _defaultValue !== undefined && !isNaN(_defaultValue)\n ? [_defaultValue]\n : undefined\n function initValue(): number[] {\n if (value !== undefined) return value\n if (defaultValue !== undefined) return defaultValue\n if (min !== undefined) return [min]\n return [0]\n }\n\n const [sliderValue, setSliderValue] = useState(() => initValue())\n\n return (\n <FieldWrapper {...restProps} status={status} label={label} hint={hint}>\n <ArkSlider.Root\n {...restProps}\n className={cx(\"cobalt-slider\", {\n \"cobalt-slider--disabled\": disabled,\n \"cobalt-slider--withHint\": hint,\n })}\n thumbAlignment=\"contain\"\n disabled={disabled}\n aria-label={[ariaLabel]}\n value={sliderValue}\n min={min}\n max={max}\n // Need to force disbplaying in smaller spaces like popovers\n thumbSize={{\n width: 24,\n height: 24,\n }}\n onValueChange={({ value: newValueArr }) => {\n setSliderValue(newValueArr)\n const newValue =\n newValueArr.length === 1 ? newValueArr[0] : newValueArr\n onValueChange && onValueChange(newValue as T)\n }}\n >\n <ArkSlider.Label className={FieldWrapper.labelClassName}>\n {label}\n </ArkSlider.Label>\n {renderValue && (\n <div className=\"cobalt-slider__value-container\">\n {renderValue(\n (sliderValue.length === 1 ? sliderValue[0] : sliderValue) as T,\n status\n )}\n </div>\n )}\n <ArkSlider.Control>\n <ArkSlider.Track>\n <ArkSlider.Range />\n </ArkSlider.Track>\n {sliderValue.map((_v, i) => (\n <ArkSlider.Thumb key={i} index={i}>\n <ArkSlider.HiddenInput />\n </ArkSlider.Thumb>\n ))}\n </ArkSlider.Control>\n </ArkSlider.Root>\n </FieldWrapper>\n )\n}\n\nexport default Slider\n\nexport const SliderValueMeta = ({ children }: PropsWithChildren) => {\n return <span className=\"cobalt-slider__value-meta\">{children}</span>\n}\n"],"names":["ArkSlider"],"mappings":"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"}
|
package/components/Form/field.js
CHANGED
|
@@ -25,6 +25,14 @@ const withFieldLabelAndHint = (WrappedComponent) => {
|
|
|
25
25
|
Wrapper.Raw = WrappedComponent;
|
|
26
26
|
return Wrapper;
|
|
27
27
|
};
|
|
28
|
+
const FieldWrapper = ({ label, hint, fullWidth, status, children, }) => label || hint ? (React.createElement("div", { className: cx("cobalt-FormField", {
|
|
29
|
+
"cobalt-FormField--withHint": hint,
|
|
30
|
+
"cobalt-FormField--fullWidth": fullWidth,
|
|
31
|
+
}) },
|
|
32
|
+
children,
|
|
33
|
+
hint && (React.createElement(Hint, { status: status },
|
|
34
|
+
React.createElement("span", { dangerouslySetInnerHTML: { __html: hint } }))))) : (React.createElement(React.Fragment, null, children));
|
|
35
|
+
FieldWrapper.labelClassName = "cobalt-FormField__Label";
|
|
28
36
|
|
|
29
|
-
export { withFieldLabelAndHint };
|
|
37
|
+
export { FieldWrapper, withFieldLabelAndHint };
|
|
30
38
|
//# sourceMappingURL=field.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"field.js","sources":["../../../src/components/Form/field.tsx"],"sourcesContent":["import React, { Component } from \"react\"\nimport { Hint } from \"./Hint\"\nimport { FormElement } from \"./form\"\nimport classNames from \"classnames\"\n\ntype InjectedProps = {\n id?: string\n label?: string\n hint?: string\n fieldClassName?: string\n fullWidth?: boolean\n} & FormElement\n\nlet singletonIdCounter = 0\nconst generateUniqueId = () => {\n singletonIdCounter = singletonIdCounter + 1\n return `cobaltFormField${singletonIdCounter}`\n}\n\nexport const withFieldLabelAndHint = <OriginalProps,>(\n WrappedComponent: React.ComponentType<OriginalProps>\n): React.ComponentClass<OriginalProps & InjectedProps> & {\n Raw: React.ComponentType<OriginalProps>\n} => {\n class Wrapper extends Component<OriginalProps & InjectedProps> {\n static Raw = WrappedComponent\n render() {\n const {\n id,\n label,\n hint,\n status,\n fieldClassName,\n fullWidth,\n ...originalProps\n }: OriginalProps & InjectedProps = this.props\n\n const consolidatedId = id ? id : generateUniqueId()\n\n return (\n <div\n className={classNames(\"cobalt-FormField\", fieldClassName, {\n \"cobalt-FormField--withHint\": !!hint,\n \"cobalt-FormField--fullWidth\": fullWidth,\n })}\n >\n {label && (\n <label className=\"cobalt-FormField__Label\" htmlFor={consolidatedId}>\n {label}\n </label>\n )}\n\n <WrappedComponent\n {...(originalProps as OriginalProps)}\n id={consolidatedId}\n status={status}\n />\n\n {hint && (\n <Hint status={status}>\n <span dangerouslySetInnerHTML={{ __html: hint }} />\n </Hint>\n )}\n </div>\n )\n }\n }\n\n return Wrapper\n}\n"],"names":["classNames"],"mappings":";;;;AAaA,IAAI,kBAAkB,GAAG,CAAC,CAAA;AAC1B,MAAM,gBAAgB,GAAG,MAAK;AAC5B,IAAA,kBAAkB,GAAG,kBAAkB,GAAG,CAAC,CAAA;IAC3C,OAAO,CAAA,eAAA,EAAkB,kBAAkB,CAAA,CAAE,CAAA;AAC/C,CAAC,CAAA;AAEY,MAAA,qBAAqB,GAAG,CACnC,gBAAoD,KAGlD;IACF,MAAM,OAAQ,SAAQ,SAAwC,CAAA;QAE5D,MAAM,GAAA;YACJ,MAAM,EACJ,EAAE,EACF,KAAK,EACL,IAAI,EACJ,MAAM,EACN,cAAc,EACd,SAAS,EACT,GAAG,aAAa,EACjB,GAAkC,IAAI,CAAC,KAAK,CAAA;AAE7C,YAAA,MAAM,cAAc,GAAG,EAAE,GAAG,EAAE,GAAG,gBAAgB,EAAE,CAAA;YAEnD,QACE,6BACE,SAAS,EAAEA,EAAU,CAAC,kBAAkB,EAAE,cAAc,EAAE;oBACxD,4BAA4B,EAAE,CAAC,CAAC,IAAI;AACpC,oBAAA,6BAA6B,EAAE,SAAS;iBACzC,CAAC,EAAA;AAED,gBAAA,KAAK,KACJ,KAAO,CAAA,aAAA,CAAA,OAAA,EAAA,EAAA,SAAS,EAAC,yBAAyB,EAAC,OAAO,EAAE,cAAc,EAC/D,EAAA,KAAK,CACA,CACT;gBAED,KAAC,CAAA,aAAA,CAAA,gBAAgB,EACV,EAAA,GAAA,aAA+B,EACpC,EAAE,EAAE,cAAc,EAClB,MAAM,EAAE,MAAM,EACd,CAAA;AAED,gBAAA,IAAI,KACH,KAAA,CAAA,aAAA,CAAC,IAAI,EAAC,EAAA,MAAM,EAAE,MAAM,EAAA;AAClB,oBAAA,KAAA,CAAA,aAAA,CAAA,MAAA,EAAA,EAAM,uBAAuB,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,EAAA,CAAI,CAC9C,CACR,CACG,EACP;SACF;;IAxCM,OAAG,CAAA,GAAA,GAAG,gBAAgB,CAAA;AA2C/B,IAAA,OAAO,OAAO,CAAA;AAChB;;;;"}
|
|
1
|
+
{"version":3,"file":"field.js","sources":["../../../src/components/Form/field.tsx"],"sourcesContent":["import React, { Component, PropsWithChildren } from \"react\"\nimport { Hint } from \"./Hint\"\nimport { FormElement } from \"./form\"\nimport classNames from \"classnames\"\n\ntype InjectedProps = {\n id?: string\n label?: string\n hint?: string\n fieldClassName?: string\n fullWidth?: boolean\n} & FormElement\n\nlet singletonIdCounter = 0\nconst generateUniqueId = () => {\n singletonIdCounter = singletonIdCounter + 1\n return `cobaltFormField${singletonIdCounter}`\n}\n\nexport const withFieldLabelAndHint = <OriginalProps,>(\n WrappedComponent: React.ComponentType<OriginalProps>\n): React.ComponentClass<OriginalProps & InjectedProps> & {\n Raw: React.ComponentType<OriginalProps>\n} => {\n class Wrapper extends Component<OriginalProps & InjectedProps> {\n static Raw = WrappedComponent\n render() {\n const {\n id,\n label,\n hint,\n status,\n fieldClassName,\n fullWidth,\n ...originalProps\n }: OriginalProps & InjectedProps = this.props\n\n const consolidatedId = id ? id : generateUniqueId()\n\n return (\n <div\n className={classNames(\"cobalt-FormField\", fieldClassName, {\n \"cobalt-FormField--withHint\": !!hint,\n \"cobalt-FormField--fullWidth\": fullWidth,\n })}\n >\n {label && (\n <label className=\"cobalt-FormField__Label\" htmlFor={consolidatedId}>\n {label}\n </label>\n )}\n\n <WrappedComponent\n {...(originalProps as OriginalProps)}\n id={consolidatedId}\n status={status}\n />\n\n {hint && (\n <Hint status={status}>\n <span dangerouslySetInnerHTML={{ __html: hint }} />\n </Hint>\n )}\n </div>\n )\n }\n }\n\n return Wrapper\n}\n\nexport type FieldWrapperProps = {\n label?: string\n hint?: string\n fullWidth?: boolean\n status?: FormElement[\"status\"]\n}\n\nexport const FieldWrapper = ({\n label,\n hint,\n fullWidth,\n status,\n children,\n}: PropsWithChildren<{\n label?: string\n fullWidth?: boolean\n status?: FormElement[\"status\"]\n hint?: string\n}>) =>\n label || hint ? (\n <div\n className={classNames(\"cobalt-FormField\", {\n \"cobalt-FormField--withHint\": hint,\n \"cobalt-FormField--fullWidth\": fullWidth,\n })}\n >\n {children}\n {hint && (\n <Hint status={status}>\n <span dangerouslySetInnerHTML={{ __html: hint }} />\n </Hint>\n )}\n </div>\n ) : (\n <>{children}</>\n )\n\nFieldWrapper.labelClassName = \"cobalt-FormField__Label\"\n"],"names":["classNames"],"mappings":";;;;AAaA,IAAI,kBAAkB,GAAG,CAAC,CAAA;AAC1B,MAAM,gBAAgB,GAAG,MAAK;AAC5B,IAAA,kBAAkB,GAAG,kBAAkB,GAAG,CAAC,CAAA;IAC3C,OAAO,CAAA,eAAA,EAAkB,kBAAkB,CAAA,CAAE,CAAA;AAC/C,CAAC,CAAA;AAEY,MAAA,qBAAqB,GAAG,CACnC,gBAAoD,KAGlD;IACF,MAAM,OAAQ,SAAQ,SAAwC,CAAA;QAE5D,MAAM,GAAA;YACJ,MAAM,EACJ,EAAE,EACF,KAAK,EACL,IAAI,EACJ,MAAM,EACN,cAAc,EACd,SAAS,EACT,GAAG,aAAa,EACjB,GAAkC,IAAI,CAAC,KAAK,CAAA;AAE7C,YAAA,MAAM,cAAc,GAAG,EAAE,GAAG,EAAE,GAAG,gBAAgB,EAAE,CAAA;YAEnD,QACE,6BACE,SAAS,EAAEA,EAAU,CAAC,kBAAkB,EAAE,cAAc,EAAE;oBACxD,4BAA4B,EAAE,CAAC,CAAC,IAAI;AACpC,oBAAA,6BAA6B,EAAE,SAAS;iBACzC,CAAC,EAAA;AAED,gBAAA,KAAK,KACJ,KAAO,CAAA,aAAA,CAAA,OAAA,EAAA,EAAA,SAAS,EAAC,yBAAyB,EAAC,OAAO,EAAE,cAAc,EAC/D,EAAA,KAAK,CACA,CACT;gBAED,KAAC,CAAA,aAAA,CAAA,gBAAgB,EACV,EAAA,GAAA,aAA+B,EACpC,EAAE,EAAE,cAAc,EAClB,MAAM,EAAE,MAAM,EACd,CAAA;AAED,gBAAA,IAAI,KACH,KAAA,CAAA,aAAA,CAAC,IAAI,EAAC,EAAA,MAAM,EAAE,MAAM,EAAA;AAClB,oBAAA,KAAA,CAAA,aAAA,CAAA,MAAA,EAAA,EAAM,uBAAuB,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,EAAA,CAAI,CAC9C,CACR,CACG,EACP;SACF;;IAxCM,OAAG,CAAA,GAAA,GAAG,gBAAgB,CAAA;AA2C/B,IAAA,OAAO,OAAO,CAAA;AAChB,EAAC;AASM,MAAM,YAAY,GAAG,CAAC,EAC3B,KAAK,EACL,IAAI,EACJ,SAAS,EACT,MAAM,EACN,QAAQ,GAMR,KACA,KAAK,IAAI,IAAI,IACX,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EACE,SAAS,EAAEA,EAAU,CAAC,kBAAkB,EAAE;AACxC,QAAA,4BAA4B,EAAE,IAAI;AAClC,QAAA,6BAA6B,EAAE,SAAS;KACzC,CAAC,EAAA;IAED,QAAQ;AACR,IAAA,IAAI,KACH,KAAA,CAAA,aAAA,CAAC,IAAI,EAAC,EAAA,MAAM,EAAE,MAAM,EAAA;QAClB,KAAM,CAAA,aAAA,CAAA,MAAA,EAAA,EAAA,uBAAuB,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,GAAI,CAC9C,CACR,CACG,KAEN,0CAAG,QAAQ,CAAI,EAChB;AAEH,YAAY,CAAC,cAAc,GAAG,yBAAyB;;;;"}
|