@deque/cauldron-react 7.5.0-canary.b12b7518 → 7.5.0-canary.f2185113
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/lib/index.js +28 -11
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -3787,6 +3787,20 @@ var Listbox = React.forwardRef(function (_a, ref) {
|
|
|
3787
3787
|
var listboxRef = useSharedRef(ref);
|
|
3788
3788
|
var isControlled = typeof value !== 'undefined';
|
|
3789
3789
|
var isActiveControlled = typeof controlledActiveOption !== 'undefined';
|
|
3790
|
+
var hasActiveChangeHandler = typeof onActiveChange === 'function';
|
|
3791
|
+
React.useEffect(function () {
|
|
3792
|
+
if (process.env.NODE_ENV !== 'production' &&
|
|
3793
|
+
isActiveControlled &&
|
|
3794
|
+
hasActiveChangeHandler) {
|
|
3795
|
+
console.warn('Listbox received both `activeOption` and `onActiveChange`. Do not ' +
|
|
3796
|
+
'write the option reported by `onActiveChange` back into ' +
|
|
3797
|
+
'`activeOption`: the two copies then race, and a stale downward ' +
|
|
3798
|
+
'sync can revert a newer value and re-render without settling. ' +
|
|
3799
|
+
'Let Listbox own the active option, or use `activeOption` only as ' +
|
|
3800
|
+
'a one-shot request. ' +
|
|
3801
|
+
'See https://github.com/dequelabs/cauldron/issues/2512');
|
|
3802
|
+
}
|
|
3803
|
+
}, [isActiveControlled, hasActiveChangeHandler]);
|
|
3790
3804
|
React.useLayoutEffect(function () {
|
|
3791
3805
|
if (!isControlled && selectedOptions.length > 0) {
|
|
3792
3806
|
return;
|
|
@@ -3928,7 +3942,7 @@ var Listbox = React.forwardRef(function (_a, ref) {
|
|
|
3928
3942
|
var firstOption = !focusDisabledOptions
|
|
3929
3943
|
? options.find(function (option) { return !isDisabledOption(option); })
|
|
3930
3944
|
: options[0];
|
|
3931
|
-
if (firstOption) {
|
|
3945
|
+
if (firstOption && firstOption.element !== (activeOption === null || activeOption === void 0 ? void 0 : activeOption.element)) {
|
|
3932
3946
|
setActiveOption(firstOption);
|
|
3933
3947
|
}
|
|
3934
3948
|
return;
|
|
@@ -3937,7 +3951,7 @@ var Listbox = React.forwardRef(function (_a, ref) {
|
|
|
3937
3951
|
var lastOption = !focusDisabledOptions
|
|
3938
3952
|
? tslib.__spreadArray([], tslib.__read(options), false).reverse().find(function (option) { return !isDisabledOption(option); })
|
|
3939
3953
|
: options[options.length - 1];
|
|
3940
|
-
if (lastOption) {
|
|
3954
|
+
if (lastOption && lastOption.element !== (activeOption === null || activeOption === void 0 ? void 0 : activeOption.element)) {
|
|
3941
3955
|
setActiveOption(lastOption);
|
|
3942
3956
|
}
|
|
3943
3957
|
return;
|
|
@@ -5158,21 +5172,24 @@ function useMnemonics(_a) {
|
|
|
5158
5172
|
|
|
5159
5173
|
var ActionList = React.forwardRef(function (_a, ref) {
|
|
5160
5174
|
var _b = _a.selectionType, selectionType = _b === void 0 ? null : _b, onAction = _a.onAction, className = _a.className, children = _a.children, props = tslib.__rest(_a, ["selectionType", "onAction", "className", "children"]);
|
|
5161
|
-
|
|
5175
|
+
// Listbox owns the active option. ActionList must not mirror it back down
|
|
5176
|
+
// as a controlled prop: the two copies then race, and a downward sync
|
|
5177
|
+
// carrying an already-stale value can revert a newer one and oscillate.
|
|
5178
|
+
// `activeOption` below is only a one-shot mnemonic request, never a
|
|
5179
|
+
// mirror. See cauldron#2512; cauldron#2522 tracks making `activeOption`
|
|
5180
|
+
// properly controlled so this constraint lives in the interface instead.
|
|
5162
5181
|
var _c = tslib.__read(React.useState(), 2), activeOption = _c[0], setActiveOption = _c[1];
|
|
5163
|
-
var handleActiveChange = React.useCallback(function (value) {
|
|
5164
|
-
activeElement.current = value === null || value === void 0 ? void 0 : value.element;
|
|
5165
|
-
setActiveOption(value);
|
|
5166
|
-
}, []);
|
|
5167
5182
|
var handleAction = React.useCallback(function (key, event) {
|
|
5168
5183
|
if (typeof onAction === 'function') {
|
|
5169
5184
|
onAction(key, event);
|
|
5170
5185
|
}
|
|
5171
5186
|
}, [onAction]);
|
|
5187
|
+
// A new object every match, even for the same element: this is a one-shot
|
|
5188
|
+
// request to Listbox rather than a mirror of its state, so re-using the
|
|
5189
|
+
// previous object would leave the controlled prop unchanged and the
|
|
5190
|
+
// request would never reach Listbox.
|
|
5172
5191
|
var handleMnemonicMatch = React.useCallback(function (element) {
|
|
5173
|
-
setActiveOption(
|
|
5174
|
-
return (prev === null || prev === void 0 ? void 0 : prev.element) === element ? prev : { element: element };
|
|
5175
|
-
});
|
|
5192
|
+
setActiveOption({ element: element });
|
|
5176
5193
|
}, []);
|
|
5177
5194
|
var containerRef = useMnemonics({
|
|
5178
5195
|
onMatch: handleMnemonicMatch,
|
|
@@ -5189,7 +5206,7 @@ var ActionList = React.forwardRef(function (_a, ref) {
|
|
|
5189
5206
|
/* Listbox comes with an explicit role of "listbox", but we want to either
|
|
5190
5207
|
* use the role from props, or default to the intrinsic role */
|
|
5191
5208
|
// eslint-disable-next-line jsx-a11y/aria-role
|
|
5192
|
-
role: undefined, "aria-multiselectable": undefined, className: classNames__default["default"]('ActionList', className), activeOption: activeOption }, props, {
|
|
5209
|
+
role: undefined, "aria-multiselectable": undefined, className: classNames__default["default"]('ActionList', className), activeOption: activeOption }, props, { navigation: "bound" }),
|
|
5193
5210
|
React__default["default"].createElement(ActionListProvider, { role: props.role || 'list', onAction: handleAction, selectionType: selectionType }, children)));
|
|
5194
5211
|
});
|
|
5195
5212
|
ActionList.displayName = 'ActionList';
|
package/package.json
CHANGED