@telus-uds/components-base 3.21.0 → 3.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +31 -1
- package/lib/cjs/Button/Button.js +12 -3
- package/lib/cjs/Button/ButtonBase.js +63 -10
- package/lib/cjs/Button/ButtonDropdown.js +2 -0
- package/lib/cjs/Button/ButtonGroup.js +45 -38
- package/lib/cjs/Button/propTypes.js +6 -0
- package/lib/cjs/Card/PressableCardBase.js +3 -1
- package/lib/cjs/Carousel/Carousel.js +63 -22
- package/lib/cjs/Carousel/CarouselItem/CarouselItem.js +23 -3
- package/lib/cjs/Icon/Icon.js +8 -11
- package/lib/cjs/Icon/IconText.js +0 -1
- package/lib/cjs/Listbox/GroupControl.js +33 -39
- package/lib/cjs/Listbox/Listbox.js +22 -13
- package/lib/cjs/Listbox/ListboxGroup.js +2 -1
- package/lib/cjs/Listbox/ListboxOverlay.js +5 -2
- package/lib/cjs/Listbox/PressableItem.js +8 -4
- package/lib/cjs/TextInput/TextInputBase.js +5 -1
- package/lib/cjs/ThemeProvider/index.js +9 -1
- package/lib/cjs/ThemeProvider/useResponsiveThemeTokensCallback.js +124 -0
- package/lib/cjs/Validator/Validator.js +171 -135
- package/lib/cjs/index.js +7 -0
- package/lib/esm/Button/Button.js +13 -4
- package/lib/esm/Button/ButtonBase.js +64 -11
- package/lib/esm/Button/ButtonDropdown.js +2 -0
- package/lib/esm/Button/ButtonGroup.js +44 -39
- package/lib/esm/Button/propTypes.js +6 -0
- package/lib/esm/Card/PressableCardBase.js +3 -1
- package/lib/esm/Carousel/Carousel.js +63 -22
- package/lib/esm/Carousel/CarouselItem/CarouselItem.js +23 -3
- package/lib/esm/Icon/Icon.js +8 -11
- package/lib/esm/Icon/IconText.js +0 -1
- package/lib/esm/Listbox/GroupControl.js +33 -39
- package/lib/esm/Listbox/Listbox.js +23 -14
- package/lib/esm/Listbox/ListboxGroup.js +2 -1
- package/lib/esm/Listbox/ListboxOverlay.js +5 -2
- package/lib/esm/Listbox/PressableItem.js +8 -4
- package/lib/esm/TextInput/TextInputBase.js +5 -1
- package/lib/esm/ThemeProvider/index.js +1 -0
- package/lib/esm/ThemeProvider/useResponsiveThemeTokensCallback.js +117 -0
- package/lib/esm/Validator/Validator.js +171 -135
- package/lib/esm/index.js +1 -1
- package/lib/package.json +2 -2
- package/package.json +2 -2
- package/src/Button/Button.jsx +26 -5
- package/src/Button/ButtonBase.jsx +79 -16
- package/src/Button/ButtonDropdown.jsx +2 -0
- package/src/Button/ButtonGroup.jsx +62 -45
- package/src/Button/propTypes.js +6 -0
- package/src/Card/PressableCardBase.jsx +3 -1
- package/src/Carousel/Carousel.jsx +71 -7
- package/src/Carousel/CarouselItem/CarouselItem.jsx +31 -3
- package/src/Icon/Icon.jsx +11 -14
- package/src/Icon/IconText.jsx +0 -1
- package/src/Listbox/GroupControl.jsx +41 -47
- package/src/Listbox/Listbox.jsx +26 -9
- package/src/Listbox/ListboxGroup.jsx +2 -1
- package/src/Listbox/ListboxOverlay.jsx +7 -2
- package/src/Listbox/PressableItem.jsx +8 -4
- package/src/PriceLockup/utils/renderPrice.jsx +15 -17
- package/src/TextInput/TextInputBase.jsx +5 -1
- package/src/ThemeProvider/index.js +1 -0
- package/src/ThemeProvider/useResponsiveThemeTokensCallback.js +129 -0
- package/src/Validator/Validator.jsx +180 -159
- package/src/index.js +2 -1
|
@@ -44,11 +44,10 @@ const Validator = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
|
|
|
44
44
|
supportsProps
|
|
45
45
|
} = selectProps(rest);
|
|
46
46
|
const strValidation = supportsProps.validation;
|
|
47
|
-
const [, setIndividualCodes] = _react.default.useState({});
|
|
48
|
-
const [text, setText] = _react.default.useState(value);
|
|
49
47
|
const validatorsLength = 6;
|
|
50
48
|
const prefix = 'code';
|
|
51
49
|
const sufixValidation = 'Validation';
|
|
50
|
+
const [codes, setCodes] = _react.default.useState(() => Array(validatorsLength).fill(''));
|
|
52
51
|
const [isHover, setIsHover] = _react.default.useState(false);
|
|
53
52
|
const handleMouseOver = () => {
|
|
54
53
|
setIsHover(true);
|
|
@@ -59,84 +58,87 @@ const Validator = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
|
|
|
59
58
|
const themeTokens = (0, _ThemeProvider.useThemeTokens)('TextInput', tokens, variant, {
|
|
60
59
|
hover: isHover
|
|
61
60
|
});
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
Array.from({
|
|
61
|
+
|
|
62
|
+
// Create refs for input elements
|
|
63
|
+
const codeReferences = _react.default.useMemo(() => {
|
|
64
|
+
return Array.from({
|
|
66
65
|
length: validatorsLength
|
|
67
|
-
}, (
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
66
|
+
}, () => /*#__PURE__*/_react.default.createRef());
|
|
67
|
+
}, [validatorsLength]);
|
|
68
|
+
|
|
69
|
+
// Keep onChange and mask in refs to avoid re-creating event listeners
|
|
70
|
+
const onChangeRef = _react.default.useRef(onChange);
|
|
71
|
+
const maskRef = _react.default.useRef(mask);
|
|
72
|
+
_react.default.useEffect(() => {
|
|
73
|
+
onChangeRef.current = onChange;
|
|
74
|
+
maskRef.current = mask;
|
|
75
|
+
}, [onChange, mask]);
|
|
76
|
+
|
|
77
|
+
// Update a single code digit
|
|
78
|
+
const updateCode = _react.default.useCallback((index, digit) => {
|
|
79
|
+
setCodes(prevCodes => {
|
|
80
|
+
const newCodes = [...prevCodes];
|
|
81
|
+
newCodes[index] = digit;
|
|
82
|
+
if (onChangeRef.current) {
|
|
83
|
+
const codeString = newCodes.join('');
|
|
84
|
+
const singleCodesObj = {};
|
|
85
|
+
newCodes.forEach((code, i) => {
|
|
86
|
+
singleCodesObj[prefix + i] = code;
|
|
87
|
+
singleCodesObj[prefix + i + sufixValidation] = code ? 'success' : '';
|
|
88
|
+
});
|
|
89
|
+
onChangeRef.current(codeString, singleCodesObj);
|
|
90
|
+
}
|
|
91
|
+
return newCodes;
|
|
72
92
|
});
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
singleCodes[codeId + sufixValidation] = validation;
|
|
78
|
-
setIndividualCodes(prev => ({
|
|
79
|
-
...prev,
|
|
80
|
-
[codeId]: val
|
|
81
|
-
}));
|
|
82
|
-
}, [singleCodes, sufixValidation]);
|
|
83
|
-
const changeDataMasking = _react.default.useCallback(boxElement => {
|
|
84
|
-
let charMasking = '';
|
|
85
|
-
const element = boxElement;
|
|
86
|
-
if (mask && mask.length === 1) {
|
|
87
|
-
charMasking = mask;
|
|
88
|
-
} else if (mask && mask.length > 1) {
|
|
89
|
-
charMasking = mask.substring(0, 1);
|
|
90
|
-
}
|
|
91
|
-
if (charMasking && element) {
|
|
92
|
-
element.value = charMasking;
|
|
93
|
-
}
|
|
94
|
-
}, [mask]);
|
|
95
|
-
const handleChangeCode = _react.default.useCallback(() => {
|
|
96
|
-
const code = Array.from({
|
|
97
|
-
length: validatorsLength
|
|
98
|
-
}, (_, i) => singleCodes[prefix + i] || '').join('');
|
|
99
|
-
if (typeof onChange === 'function') {
|
|
100
|
-
onChange(code, singleCodes);
|
|
101
|
-
}
|
|
102
|
-
}, [validatorsLength, singleCodes, prefix, onChange]);
|
|
103
|
-
const handleChangeCodeValues = _react.default.useCallback((event, codeId, nextIndex) => {
|
|
104
|
-
const codeElement = codeReferences[codeId]?.current;
|
|
93
|
+
}, [prefix, sufixValidation]);
|
|
94
|
+
|
|
95
|
+
// Handle input change
|
|
96
|
+
const handleInputChange = _react.default.useCallback((index, event) => {
|
|
105
97
|
const val = event.nativeEvent?.value || event.target?.value;
|
|
106
98
|
|
|
107
|
-
//
|
|
108
|
-
|
|
109
|
-
if (codeElement && codeElement.value) {
|
|
110
|
-
codeElement.value = numericOnly;
|
|
111
|
-
}
|
|
112
|
-
handleSingleCodes(codeId, numericOnly, numericOnly ? 'success' : '');
|
|
113
|
-
handleChangeCode();
|
|
114
|
-
if (nextIndex === validatorsLength) {
|
|
115
|
-
codeElement?.blur();
|
|
116
|
-
changeDataMasking(codeElement);
|
|
99
|
+
// This prevents the infinite loop where setting element.value triggers another input event
|
|
100
|
+
if (maskRef.current && val === maskRef.current.substring(0, 1)) {
|
|
117
101
|
return;
|
|
118
102
|
}
|
|
119
|
-
|
|
120
|
-
|
|
103
|
+
const numericOnly = val.replace(/\D/g, '').substring(0, 1);
|
|
104
|
+
|
|
105
|
+
// Update state
|
|
106
|
+
updateCode(index, numericOnly);
|
|
107
|
+
|
|
108
|
+
// Update DOM element
|
|
109
|
+
const element = codeReferences[index]?.current;
|
|
110
|
+
if (element) {
|
|
111
|
+
if (maskRef.current && numericOnly) {
|
|
112
|
+
element.value = maskRef.current.substring(0, 1);
|
|
113
|
+
} else {
|
|
114
|
+
element.value = numericOnly;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Move to next field if digit entered
|
|
119
|
+
if (numericOnly && index < validatorsLength - 1) {
|
|
120
|
+
const nextElement = codeReferences[index + 1]?.current;
|
|
121
121
|
nextElement?.focus();
|
|
122
|
-
|
|
122
|
+
} else if (index === validatorsLength - 1) {
|
|
123
|
+
element?.blur();
|
|
123
124
|
}
|
|
124
|
-
}, [codeReferences,
|
|
125
|
-
|
|
125
|
+
}, [codeReferences, updateCode, validatorsLength]);
|
|
126
|
+
|
|
127
|
+
// Handle backspace
|
|
128
|
+
const handleKeyPress = _react.default.useCallback((index, event) => {
|
|
126
129
|
if (!(event.keyCode === 8 || event.code === 'Backspace')) {
|
|
127
130
|
return;
|
|
128
131
|
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
132
|
+
const currentElement = codeReferences[index]?.current;
|
|
133
|
+
if (currentElement) {
|
|
134
|
+
currentElement.value = '';
|
|
135
|
+
}
|
|
136
|
+
updateCode(index, '');
|
|
137
|
+
if (index > 0) {
|
|
138
|
+
const previousElement = codeReferences[index - 1]?.current;
|
|
135
139
|
previousElement?.focus();
|
|
136
140
|
}
|
|
137
|
-
|
|
138
|
-
handleChangeCode();
|
|
139
|
-
};
|
|
141
|
+
}, [codeReferences, updateCode]);
|
|
140
142
|
const getCodeComponents = () => {
|
|
141
143
|
return Array.from({
|
|
142
144
|
length: validatorsLength
|
|
@@ -145,11 +147,14 @@ const Validator = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
|
|
|
145
147
|
const codeInputProps = {
|
|
146
148
|
nativeID: codeId,
|
|
147
149
|
keyboardType: 'numeric',
|
|
148
|
-
ref: codeReferences[
|
|
149
|
-
validation: strValidation ||
|
|
150
|
+
ref: codeReferences[i] ?? null,
|
|
151
|
+
validation: strValidation || (codes[i] ? 'success' : ''),
|
|
150
152
|
tokens: selectCodeTextInputTokens(themeTokens),
|
|
153
|
+
// Only use secureTextEntry in React Native, web handles mask differently
|
|
154
|
+
secureTextEntry: !!(_Platform.default.OS !== 'web' && mask),
|
|
155
|
+
selectTextOnFocus: _Platform.default.OS !== 'web',
|
|
151
156
|
onFocus: () => {
|
|
152
|
-
const element = codeReferences[
|
|
157
|
+
const element = codeReferences[i]?.current;
|
|
153
158
|
if (_Platform.default.OS === 'web' && element?.select) {
|
|
154
159
|
return element.select() ?? null;
|
|
155
160
|
}
|
|
@@ -158,11 +163,35 @@ const Validator = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
|
|
|
158
163
|
}
|
|
159
164
|
return null;
|
|
160
165
|
},
|
|
161
|
-
onKeyPress: event => handleKeyPress(
|
|
166
|
+
onKeyPress: event => handleKeyPress(i, event),
|
|
162
167
|
onMouseOver: handleMouseOver,
|
|
163
168
|
onMouseOut: handleMouseOut,
|
|
164
169
|
inactive
|
|
165
170
|
};
|
|
171
|
+
|
|
172
|
+
// For React Native, use onChangeText and maxLength
|
|
173
|
+
if (_Platform.default.OS !== 'web') {
|
|
174
|
+
codeInputProps.maxLength = 1;
|
|
175
|
+
codeInputProps.value = codes[i];
|
|
176
|
+
codeInputProps.onChange = () => {};
|
|
177
|
+
codeInputProps.onChangeText = text => {
|
|
178
|
+
if (text) {
|
|
179
|
+
updateCode(i, text);
|
|
180
|
+
if (i < validatorsLength - 1) {
|
|
181
|
+
setTimeout(() => {
|
|
182
|
+
codeReferences[i + 1]?.current?.focus();
|
|
183
|
+
}, 50);
|
|
184
|
+
}
|
|
185
|
+
} else {
|
|
186
|
+
updateCode(i, '');
|
|
187
|
+
if (i > 0) {
|
|
188
|
+
setTimeout(() => {
|
|
189
|
+
codeReferences[i - 1]?.current?.focus();
|
|
190
|
+
}, 50);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
}
|
|
166
195
|
if (!codeInputProps.validation) {
|
|
167
196
|
delete codeInputProps.validation;
|
|
168
197
|
}
|
|
@@ -174,89 +203,96 @@ const Validator = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
|
|
|
174
203
|
}, codeId);
|
|
175
204
|
});
|
|
176
205
|
};
|
|
206
|
+
|
|
207
|
+
// Sync external value prop to internal state
|
|
177
208
|
_react.default.useEffect(() => {
|
|
178
|
-
if (Number(value).toString() !== 'NaN') {
|
|
179
|
-
|
|
209
|
+
if (value && Number(value).toString() !== 'NaN') {
|
|
210
|
+
const digits = value.split('').slice(0, validatorsLength);
|
|
211
|
+
const newCodes = Array(validatorsLength).fill('');
|
|
212
|
+
digits.forEach((digit, i) => {
|
|
213
|
+
if (/\d/.test(digit)) {
|
|
214
|
+
newCodes[i] = digit;
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
setCodes(newCodes);
|
|
180
218
|
}
|
|
181
|
-
}, [value]);
|
|
219
|
+
}, [value, validatorsLength]);
|
|
220
|
+
|
|
221
|
+
// Sync codes state to DOM elements
|
|
182
222
|
_react.default.useEffect(() => {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
}, (_, i) => {
|
|
186
|
-
const element = codeReferences[prefix + i]?.current;
|
|
223
|
+
codes.forEach((code, i) => {
|
|
224
|
+
const element = codeReferences[i]?.current;
|
|
187
225
|
if (element && element.value !== undefined) {
|
|
188
|
-
if (mask &&
|
|
189
|
-
element.value = mask;
|
|
226
|
+
if (mask && code) {
|
|
227
|
+
element.value = mask.substring(0, 1);
|
|
190
228
|
} else {
|
|
191
|
-
element.value =
|
|
229
|
+
element.value = code;
|
|
192
230
|
}
|
|
193
231
|
}
|
|
194
|
-
handleSingleCodes(prefix + i, text[i] ?? '', text[i] ? 'success' : '');
|
|
195
|
-
return null;
|
|
196
232
|
});
|
|
197
|
-
}, [
|
|
233
|
+
}, [codes, codeReferences, mask]);
|
|
234
|
+
|
|
235
|
+
// Setup event listeners - only runs once on mount
|
|
198
236
|
_react.default.useEffect(() => {
|
|
199
|
-
|
|
237
|
+
if (_Platform.default.OS !== 'web') {
|
|
238
|
+
return undefined;
|
|
239
|
+
}
|
|
240
|
+
const handlePaste = event => {
|
|
200
241
|
event.preventDefault();
|
|
201
|
-
|
|
202
|
-
// Clear current state first
|
|
203
|
-
setText('');
|
|
204
|
-
|
|
205
|
-
// Clear all individual input fields and their state
|
|
206
|
-
Array.from({
|
|
207
|
-
length: validatorsLength
|
|
208
|
-
}, (_, i) => {
|
|
209
|
-
const element = codeReferences[prefix + i]?.current;
|
|
210
|
-
if (element && element.value !== undefined) {
|
|
211
|
-
element.value = '';
|
|
212
|
-
}
|
|
213
|
-
handleSingleCodes(prefix + i, '', '');
|
|
214
|
-
return null;
|
|
215
|
-
});
|
|
216
242
|
const clipBoardText = event.clipboardData.getData('text');
|
|
217
|
-
|
|
218
|
-
// Validate that input contains only digits and truncate to 6 characters
|
|
219
243
|
const numericOnly = clipBoardText.replace(/\D/g, '').substring(0, validatorsLength);
|
|
220
|
-
|
|
221
|
-
|
|
244
|
+
const newCodes = Array(validatorsLength).fill('');
|
|
245
|
+
numericOnly.split('').forEach((digit, i) => {
|
|
246
|
+
newCodes[i] = digit;
|
|
247
|
+
});
|
|
248
|
+
setCodes(newCodes);
|
|
249
|
+
if (onChangeRef.current) {
|
|
250
|
+
const singleCodesObj = {};
|
|
251
|
+
newCodes.forEach((code, i) => {
|
|
252
|
+
singleCodesObj[prefix + i] = code;
|
|
253
|
+
singleCodesObj[prefix + i + sufixValidation] = code ? 'success' : '';
|
|
254
|
+
});
|
|
255
|
+
onChangeRef.current(numericOnly, singleCodesObj);
|
|
222
256
|
}
|
|
223
257
|
};
|
|
224
258
|
const handleCopy = event => {
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
259
|
+
setCodes(currentCodes => {
|
|
260
|
+
const clipBoardText = currentCodes.join('');
|
|
261
|
+
event.clipboardData.setData('text/plain', clipBoardText);
|
|
262
|
+
event.preventDefault();
|
|
263
|
+
return currentCodes;
|
|
264
|
+
});
|
|
230
265
|
};
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
266
|
+
|
|
267
|
+
// Add event listeners to each input
|
|
268
|
+
codeReferences.forEach((inputRef, i) => {
|
|
269
|
+
const element = inputRef?.current;
|
|
270
|
+
if (element && typeof element.addEventListener === 'function') {
|
|
271
|
+
element.addEventListener('paste', handlePaste);
|
|
272
|
+
element.addEventListener('copy', handleCopy);
|
|
273
|
+
element.addEventListener('input', event => handleInputChange(i, event));
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
// Cleanup
|
|
278
|
+
return () => {
|
|
279
|
+
codeReferences.forEach(inputRef => {
|
|
280
|
+
const element = inputRef?.current;
|
|
281
|
+
if (element && typeof element.removeEventListener === 'function') {
|
|
282
|
+
element.removeEventListener('paste', handlePaste);
|
|
283
|
+
element.removeEventListener('copy', handleCopy);
|
|
284
|
+
element.removeEventListener('input', event => handleInputChange(event.target.dataset.index, event));
|
|
240
285
|
}
|
|
241
|
-
return null;
|
|
242
286
|
});
|
|
243
|
-
}
|
|
244
|
-
return () => {
|
|
245
|
-
if (_Platform.default.OS === 'web') {
|
|
246
|
-
Array.from({
|
|
247
|
-
length: validatorsLength
|
|
248
|
-
}, (_, i) => {
|
|
249
|
-
const element = codeReferences[prefix + i]?.current;
|
|
250
|
-
if (element && typeof element.removeEventListener === 'function') {
|
|
251
|
-
element.removeEventListener('paste', handlePasteCode);
|
|
252
|
-
element.removeEventListener('copy', handleCopy);
|
|
253
|
-
element.removeEventListener('input', event => handleChangeCodeValues(event, prefix + i, i + 1));
|
|
254
|
-
}
|
|
255
|
-
return null;
|
|
256
|
-
});
|
|
257
|
-
}
|
|
258
287
|
};
|
|
259
|
-
|
|
288
|
+
/*
|
|
289
|
+
* codeReferences and handleInputChange are intentionally omitted from dependencies
|
|
290
|
+
* because we want event listeners to be registered ONLY ONCE when the component mounts.
|
|
291
|
+
* codeReferences is stable (created with useMemo) and handleInputChange is stable (useCallback).
|
|
292
|
+
* Including them would cause unnecessary re-registration of listeners on each render.
|
|
293
|
+
*/
|
|
294
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
295
|
+
}, []);
|
|
260
296
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_InputSupports.default, {
|
|
261
297
|
...supportsProps,
|
|
262
298
|
feedbackProps: {
|
package/lib/cjs/index.js
CHANGED
|
@@ -93,6 +93,7 @@ var _exportNames = {
|
|
|
93
93
|
applyTextStyles: true,
|
|
94
94
|
applyShadowToken: true,
|
|
95
95
|
useResponsiveThemeTokens: true,
|
|
96
|
+
useResponsiveThemeTokensCallback: true,
|
|
96
97
|
Portal: true
|
|
97
98
|
};
|
|
98
99
|
Object.defineProperty(exports, "A11yInfoProvider", {
|
|
@@ -605,6 +606,12 @@ Object.defineProperty(exports, "useResponsiveThemeTokens", {
|
|
|
605
606
|
return _ThemeProvider.useResponsiveThemeTokens;
|
|
606
607
|
}
|
|
607
608
|
});
|
|
609
|
+
Object.defineProperty(exports, "useResponsiveThemeTokensCallback", {
|
|
610
|
+
enumerable: true,
|
|
611
|
+
get: function () {
|
|
612
|
+
return _ThemeProvider.useResponsiveThemeTokensCallback;
|
|
613
|
+
}
|
|
614
|
+
});
|
|
608
615
|
Object.defineProperty(exports, "useSetTheme", {
|
|
609
616
|
enumerable: true,
|
|
610
617
|
get: function () {
|
package/lib/esm/Button/Button.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import ButtonBase from './ButtonBase';
|
|
3
3
|
import buttonPropTypes, { textAndA11yText } from './propTypes';
|
|
4
|
-
import { useThemeTokensCallback } from '../ThemeProvider';
|
|
4
|
+
import { useThemeTokensCallback, useResponsiveThemeTokensCallback, useTheme } from '../ThemeProvider';
|
|
5
5
|
import { a11yProps } from '../utils/props';
|
|
6
6
|
import { useViewport } from '../ViewportProvider';
|
|
7
7
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
@@ -10,19 +10,28 @@ const Button = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
10
10
|
accessibilityRole = 'button',
|
|
11
11
|
tokens,
|
|
12
12
|
variant,
|
|
13
|
+
heightFull = true,
|
|
13
14
|
...props
|
|
14
15
|
} = _ref;
|
|
15
16
|
const viewport = useViewport();
|
|
16
|
-
const
|
|
17
|
+
const {
|
|
18
|
+
themeOptions: {
|
|
19
|
+
enableMediaQueryStyleSheet
|
|
20
|
+
}
|
|
21
|
+
} = useTheme();
|
|
22
|
+
const buttonVariant = enableMediaQueryStyleSheet ? variant : {
|
|
17
23
|
viewport,
|
|
18
24
|
...variant
|
|
19
25
|
};
|
|
20
|
-
const
|
|
26
|
+
const useTokens = enableMediaQueryStyleSheet ? useResponsiveThemeTokensCallback : useThemeTokensCallback;
|
|
27
|
+
const getTokens = useTokens('Button', tokens, buttonVariant);
|
|
21
28
|
return /*#__PURE__*/_jsx(ButtonBase, {
|
|
22
29
|
...props,
|
|
23
30
|
tokens: getTokens,
|
|
31
|
+
heightFull: heightFull,
|
|
24
32
|
accessibilityRole: accessibilityRole,
|
|
25
|
-
ref: ref
|
|
33
|
+
ref: ref,
|
|
34
|
+
viewport: viewport
|
|
26
35
|
});
|
|
27
36
|
});
|
|
28
37
|
Button.displayName = 'Button';
|
|
@@ -6,7 +6,7 @@ import StyleSheet from "react-native-web/dist/exports/StyleSheet";
|
|
|
6
6
|
import Platform from "react-native-web/dist/exports/Platform";
|
|
7
7
|
import { applyTextStyles, applyShadowToken, applyOuterBorder, useTheme } from '../ThemeProvider';
|
|
8
8
|
import buttonPropTypes from './propTypes';
|
|
9
|
-
import { a11yProps, clickProps, focusHandlerProps, getCursorStyle, linkProps, resolvePressableState, resolvePressableTokens, selectSystemProps, viewProps, wrapStringsInText, withLinkRouter, contentfulProps } from '../utils';
|
|
9
|
+
import { a11yProps, clickProps, focusHandlerProps, getCursorStyle, linkProps, resolvePressableState, resolvePressableTokens, selectSystemProps, viewProps, wrapStringsInText, withLinkRouter, contentfulProps, createMediaQueryStyles, StyleSheet as StyleSheetUtils } from '../utils';
|
|
10
10
|
import { IconText } from '../Icon';
|
|
11
11
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
12
12
|
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, focusHandlerProps, linkProps, viewProps, contentfulProps]);
|
|
@@ -33,23 +33,27 @@ const selectFlexAndWidthStyles = _ref2 => {
|
|
|
33
33
|
}
|
|
34
34
|
return styles;
|
|
35
35
|
};
|
|
36
|
-
const selectOuterContainerStyles = _ref3 => {
|
|
36
|
+
const selectOuterContainerStyles = (_ref3, heightFull) => {
|
|
37
37
|
let {
|
|
38
38
|
opacity,
|
|
39
39
|
outerBorderColor,
|
|
40
40
|
outerBorderWidth,
|
|
41
41
|
outerBorderGap,
|
|
42
42
|
borderRadius,
|
|
43
|
-
outerBackgroundColor
|
|
43
|
+
outerBackgroundColor,
|
|
44
|
+
alignSelf
|
|
44
45
|
} = _ref3;
|
|
45
46
|
return {
|
|
47
|
+
backgroundColor: outerBackgroundColor,
|
|
48
|
+
opacity,
|
|
46
49
|
...Platform.select({
|
|
47
50
|
native: {
|
|
51
|
+
alignSelf: alignSelf !== undefined ? alignSelf : 'flex-start'
|
|
52
|
+
},
|
|
53
|
+
web: heightFull ? {} : {
|
|
48
54
|
alignSelf: 'flex-start'
|
|
49
55
|
}
|
|
50
56
|
}),
|
|
51
|
-
backgroundColor: outerBackgroundColor,
|
|
52
|
-
opacity,
|
|
53
57
|
...applyOuterBorder({
|
|
54
58
|
outerBorderGap,
|
|
55
59
|
outerBorderWidth,
|
|
@@ -248,8 +252,16 @@ const ButtonBase = /*#__PURE__*/React.forwardRef((_ref12, ref) => {
|
|
|
248
252
|
icon,
|
|
249
253
|
iconPosition = icon ? 'left' : undefined,
|
|
250
254
|
iconProps,
|
|
255
|
+
heightFull = true,
|
|
251
256
|
...rawRest
|
|
252
257
|
} = _ref12;
|
|
258
|
+
const {
|
|
259
|
+
themeOptions
|
|
260
|
+
} = useTheme();
|
|
261
|
+
const {
|
|
262
|
+
viewport
|
|
263
|
+
} = rawRest;
|
|
264
|
+
const enableMediaQueryStyleSheet = themeOptions.enableMediaQueryStyleSheet && viewport;
|
|
253
265
|
const {
|
|
254
266
|
onPress,
|
|
255
267
|
...rest
|
|
@@ -261,15 +273,55 @@ const ButtonBase = /*#__PURE__*/React.forwardRef((_ref12, ref) => {
|
|
|
261
273
|
};
|
|
262
274
|
const resolveButtonTokens = pressableState => resolvePressableTokens(tokens, pressableState, extraButtonState);
|
|
263
275
|
const systemProps = selectProps(rest);
|
|
276
|
+
let layoutMediaQueryStyles;
|
|
277
|
+
let flexAndWidthStylesIds;
|
|
278
|
+
if (enableMediaQueryStyleSheet) {
|
|
279
|
+
const defaultPressableState = {
|
|
280
|
+
pressed: false,
|
|
281
|
+
hovered: false,
|
|
282
|
+
focused: false
|
|
283
|
+
};
|
|
284
|
+
const defaultTokensByViewport = resolveButtonTokens(defaultPressableState);
|
|
285
|
+
const layoutTokensByViewport = Object.entries(defaultTokensByViewport).reduce((acc, _ref13) => {
|
|
286
|
+
let [vp, viewportTokens] = _ref13;
|
|
287
|
+
const flexAndWidthStyles = viewportTokens.width === '100%' && viewportTokens.flex === 1 ? selectFlexAndWidthStyles(viewportTokens) : {};
|
|
288
|
+
acc[vp] = {
|
|
289
|
+
...staticStyles.row,
|
|
290
|
+
...selectWebOnlyStyles(inactive, viewportTokens, systemProps),
|
|
291
|
+
...(Object.keys(flexAndWidthStyles).length > 0 ? flexAndWidthStyles : {}),
|
|
292
|
+
...selectOuterSizeStyles(viewportTokens)
|
|
293
|
+
};
|
|
294
|
+
return acc;
|
|
295
|
+
}, {});
|
|
296
|
+
const mediaQueryStyles = createMediaQueryStyles(layoutTokensByViewport);
|
|
297
|
+
const {
|
|
298
|
+
ids,
|
|
299
|
+
styles
|
|
300
|
+
} = StyleSheetUtils.create({
|
|
301
|
+
layout: {
|
|
302
|
+
...mediaQueryStyles
|
|
303
|
+
}
|
|
304
|
+
});
|
|
305
|
+
layoutMediaQueryStyles = styles.layout;
|
|
306
|
+
flexAndWidthStylesIds = ids.layout;
|
|
307
|
+
}
|
|
264
308
|
const getPressableStyle = pressableState => {
|
|
309
|
+
if (enableMediaQueryStyleSheet) {
|
|
310
|
+
const themeTokens = resolveButtonTokens(pressableState)[viewport];
|
|
311
|
+
return [layoutMediaQueryStyles, selectOuterContainerStyles(themeTokens)];
|
|
312
|
+
}
|
|
265
313
|
const themeTokens = resolveButtonTokens(pressableState);
|
|
266
|
-
// Only apply flex and width styles when they are explicitly set (e.g., from ButtonGroup with width: 'equal') to not to affect other use cases
|
|
267
314
|
const flexAndWidthStyles = themeTokens.width === '100%' && themeTokens.flex === 1 ? selectFlexAndWidthStyles(themeTokens) : {};
|
|
268
|
-
return [staticStyles.row, selectWebOnlyStyles(inactive, themeTokens, systemProps), selectOuterContainerStyles(themeTokens), ...(Object.keys(flexAndWidthStyles).length > 0 ? [flexAndWidthStyles] : []), selectOuterSizeStyles(themeTokens)];
|
|
315
|
+
return [staticStyles.row, selectWebOnlyStyles(inactive, themeTokens, systemProps), selectOuterContainerStyles(themeTokens, heightFull), ...(Object.keys(flexAndWidthStyles).length > 0 ? [flexAndWidthStyles] : []), selectOuterSizeStyles(themeTokens)];
|
|
269
316
|
};
|
|
270
|
-
const {
|
|
271
|
-
|
|
272
|
-
|
|
317
|
+
const dataSetProp = flexAndWidthStylesIds || rawRest.dataSet ? {
|
|
318
|
+
dataSet: {
|
|
319
|
+
...(flexAndWidthStylesIds ? {
|
|
320
|
+
media: flexAndWidthStylesIds
|
|
321
|
+
} : {}),
|
|
322
|
+
...rawRest.dataSet
|
|
323
|
+
}
|
|
324
|
+
} : {};
|
|
273
325
|
return /*#__PURE__*/_jsx(Pressable, {
|
|
274
326
|
ref: ref,
|
|
275
327
|
href: href,
|
|
@@ -281,8 +333,9 @@ const ButtonBase = /*#__PURE__*/React.forwardRef((_ref12, ref) => {
|
|
|
281
333
|
disabled: inactive,
|
|
282
334
|
hrefAttrs: hrefAttrs,
|
|
283
335
|
...systemProps,
|
|
336
|
+
...dataSetProp,
|
|
284
337
|
children: pressableState => {
|
|
285
|
-
const themeTokens = resolveButtonTokens(pressableState);
|
|
338
|
+
const themeTokens = enableMediaQueryStyleSheet ? resolveButtonTokens(pressableState)[viewport] : resolveButtonTokens(pressableState);
|
|
286
339
|
const containerStyles = selectInnerContainerStyles(themeTokens);
|
|
287
340
|
const borderStyles = selectBorderStyles(themeTokens);
|
|
288
341
|
const textStyles = [selectTextStyles(themeTokens, themeOptions), staticStyles.text, Platform.select({
|
|
@@ -103,6 +103,7 @@ const ButtonDropdown = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
|
103
103
|
accessibilityRole = 'radio',
|
|
104
104
|
description,
|
|
105
105
|
singleOption,
|
|
106
|
+
heightFull = true,
|
|
106
107
|
...props
|
|
107
108
|
} = _ref2;
|
|
108
109
|
const isFullWidth = variant?.width === FULL_WIDTH_STYLE;
|
|
@@ -145,6 +146,7 @@ const ButtonDropdown = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
|
145
146
|
...pressHandlers,
|
|
146
147
|
onPress: handlePress,
|
|
147
148
|
tokens: getButtonTokens,
|
|
149
|
+
heightFull: heightFull,
|
|
148
150
|
inactive: singleOption || inactive,
|
|
149
151
|
icon: () => null,
|
|
150
152
|
accessibilityRole: accessibilityRole,
|