@react-aria/utils 3.8.1 → 3.11.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/dist/main.js +219 -42
- package/dist/main.js.map +1 -1
- package/dist/module.js +205 -40
- package/dist/module.js.map +1 -1
- package/dist/types.d.ts +22 -2
- package/dist/types.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/index.ts +4 -0
- package/src/mergeProps.ts +24 -27
- package/src/scrollIntoView.ts +65 -0
- package/src/useDescription.ts +2 -1
- package/src/useEvent.ts +39 -0
- package/src/useGlobalListeners.ts +8 -2
- package/src/useId.ts +28 -13
- package/src/useObjectRef.ts +46 -0
- package/src/useValueEffect.ts +65 -0
package/dist/main.js
CHANGED
|
@@ -8,6 +8,8 @@ exports.clamp = clamp;
|
|
|
8
8
|
|
|
9
9
|
var _clsx = $parcel$interopDefault(require("clsx"));
|
|
10
10
|
|
|
11
|
+
var _babelRuntimeHelpersExtends = $parcel$interopDefault(require("@babel/runtime/helpers/extends"));
|
|
12
|
+
|
|
11
13
|
var {
|
|
12
14
|
useSSRSafeId
|
|
13
15
|
} = require("@react-aria/ssr");
|
|
@@ -17,11 +19,10 @@ var _react2 = require("react");
|
|
|
17
19
|
var _react = $parcel$interopDefault(_react2);
|
|
18
20
|
|
|
19
21
|
var {
|
|
22
|
+
useCallback,
|
|
20
23
|
useEffect,
|
|
21
24
|
useRef,
|
|
22
|
-
useState
|
|
23
|
-
useCallback,
|
|
24
|
-
useLayoutEffect: _useLayoutEffect
|
|
25
|
+
useState
|
|
25
26
|
} = _react2;
|
|
26
27
|
|
|
27
28
|
function $parcel$interopDefault(a) {
|
|
@@ -43,7 +44,8 @@ function useId(defaultId) {
|
|
|
43
44
|
let isRendering = useRef(true);
|
|
44
45
|
isRendering.current = true;
|
|
45
46
|
let [value, setValue] = useState(defaultId);
|
|
46
|
-
let nextId = useRef(null);
|
|
47
|
+
let nextId = useRef(null);
|
|
48
|
+
let res = useSSRSafeId(value); // don't memo this, we want it new each render so that the Effects always run
|
|
47
49
|
|
|
48
50
|
let updateValue = val => {
|
|
49
51
|
if (!isRendering.current) {
|
|
@@ -53,9 +55,16 @@ function useId(defaultId) {
|
|
|
53
55
|
}
|
|
54
56
|
};
|
|
55
57
|
|
|
58
|
+
$f09fcd7f5f367fc80aacfeac62ed2$var$idsUpdaterMap.set(res, updateValue);
|
|
56
59
|
useLayoutEffect(() => {
|
|
57
60
|
isRendering.current = false;
|
|
58
61
|
}, [updateValue]);
|
|
62
|
+
useLayoutEffect(() => {
|
|
63
|
+
let r = res;
|
|
64
|
+
return () => {
|
|
65
|
+
$f09fcd7f5f367fc80aacfeac62ed2$var$idsUpdaterMap.delete(r);
|
|
66
|
+
};
|
|
67
|
+
}, [res]);
|
|
59
68
|
useEffect(() => {
|
|
60
69
|
let newId = nextId.current;
|
|
61
70
|
|
|
@@ -64,8 +73,6 @@ function useId(defaultId) {
|
|
|
64
73
|
nextId.current = null;
|
|
65
74
|
}
|
|
66
75
|
}, [setValue, updateValue]);
|
|
67
|
-
let res = useSSRSafeId(value);
|
|
68
|
-
$f09fcd7f5f367fc80aacfeac62ed2$var$idsUpdaterMap.set(res, updateValue);
|
|
69
76
|
return res;
|
|
70
77
|
}
|
|
71
78
|
/**
|
|
@@ -100,21 +107,27 @@ function mergeIds(idA, idB) {
|
|
|
100
107
|
/**
|
|
101
108
|
* Used to generate an id, and after render, check if that id is rendered so we know
|
|
102
109
|
* if we can use it in places such as labelledby.
|
|
110
|
+
* @param depArray - When to recalculate if the id is in the DOM.
|
|
103
111
|
*/
|
|
104
112
|
|
|
105
113
|
|
|
106
114
|
exports.mergeIds = mergeIds;
|
|
107
115
|
|
|
108
|
-
function useSlotId() {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
116
|
+
function useSlotId(depArray) {
|
|
117
|
+
if (depArray === void 0) {
|
|
118
|
+
depArray = [];
|
|
119
|
+
}
|
|
112
120
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
121
|
+
let id = useId();
|
|
122
|
+
let [resolvedId, setResolvedId] = useValueEffect(id);
|
|
123
|
+
let updateId = useCallback(() => {
|
|
124
|
+
setResolvedId(function* () {
|
|
125
|
+
yield id;
|
|
126
|
+
yield document.getElementById(id) ? id : null;
|
|
127
|
+
});
|
|
128
|
+
}, [id, setResolvedId]);
|
|
129
|
+
useLayoutEffect(updateId, [id, updateId, ...depArray]);
|
|
130
|
+
return resolvedId;
|
|
118
131
|
}
|
|
119
132
|
|
|
120
133
|
exports.useSlotId = useSlotId;
|
|
@@ -158,32 +171,30 @@ exports.chain = chain;
|
|
|
158
171
|
* @param args - Multiple sets of props to merge together.
|
|
159
172
|
*/
|
|
160
173
|
function mergeProps() {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
args[_key] = arguments[_key];
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
for (let props of args) {
|
|
168
|
-
for (let key in result) {
|
|
169
|
-
// Chain events
|
|
170
|
-
if (/^on[A-Z]/.test(key) && typeof result[key] === 'function' && typeof props[key] === 'function') {
|
|
171
|
-
result[key] = chain(result[key], props[key]); // Merge classnames, sometimes classNames are empty string which eval to false, so we just need to do a type check
|
|
172
|
-
} else if (key === 'className' && typeof result.className === 'string' && typeof props.className === 'string') {
|
|
173
|
-
result[key] = _clsx(result.className, props.className);
|
|
174
|
-
} else if (key === 'UNSAFE_className' && typeof result.UNSAFE_className === 'string' && typeof props.UNSAFE_className === 'string') {
|
|
175
|
-
result[key] = _clsx(result.UNSAFE_className, props.UNSAFE_className);
|
|
176
|
-
} else if (key === 'id' && result.id && props.id) {
|
|
177
|
-
result.id = mergeIds(result.id, props.id); // Override others
|
|
178
|
-
} else {
|
|
179
|
-
result[key] = props[key] !== undefined ? props[key] : result[key];
|
|
180
|
-
}
|
|
181
|
-
} // Add props from b that are not in a
|
|
174
|
+
// Start with a base clone of the first argument. This is a lot faster than starting
|
|
175
|
+
// with an empty object and adding properties as we go.
|
|
176
|
+
let result = _babelRuntimeHelpersExtends({}, arguments.length <= 0 ? undefined : arguments[0]);
|
|
182
177
|
|
|
178
|
+
for (let i = 1; i < arguments.length; i++) {
|
|
179
|
+
let props = i < 0 || arguments.length <= i ? undefined : arguments[i];
|
|
183
180
|
|
|
184
181
|
for (let key in props) {
|
|
185
|
-
|
|
186
|
-
|
|
182
|
+
let a = result[key];
|
|
183
|
+
let b = props[key]; // Chain events
|
|
184
|
+
|
|
185
|
+
if (typeof a === 'function' && typeof b === 'function' && // This is a lot faster than a regex.
|
|
186
|
+
key[0] === 'o' && key[1] === 'n' && key.charCodeAt(2) >=
|
|
187
|
+
/* 'A' */
|
|
188
|
+
65 && key.charCodeAt(2) <=
|
|
189
|
+
/* 'Z' */
|
|
190
|
+
90) {
|
|
191
|
+
result[key] = chain(a, b); // Merge classnames, sometimes classNames are empty string which eval to false, so we just need to do a type check
|
|
192
|
+
} else if ((key === 'className' || key === 'UNSAFE_className') && typeof a === 'string' && typeof b === 'string') {
|
|
193
|
+
result[key] = _clsx(a, b);
|
|
194
|
+
} else if (key === 'id' && a && b) {
|
|
195
|
+
result.id = mergeIds(a, b); // Override others
|
|
196
|
+
} else {
|
|
197
|
+
result[key] = b !== undefined ? b : a;
|
|
187
198
|
}
|
|
188
199
|
}
|
|
189
200
|
}
|
|
@@ -613,15 +624,24 @@ exports.useDrag1D = useDrag1D;
|
|
|
613
624
|
function useGlobalListeners() {
|
|
614
625
|
let globalListeners = useRef(new Map());
|
|
615
626
|
let addGlobalListener = useCallback((eventTarget, type, listener, options) => {
|
|
627
|
+
// Make sure we remove the listener after it is called with the `once` option.
|
|
628
|
+
let fn = options != null && options.once ? function () {
|
|
629
|
+
globalListeners.current.delete(listener);
|
|
630
|
+
listener(...arguments);
|
|
631
|
+
} : listener;
|
|
616
632
|
globalListeners.current.set(listener, {
|
|
617
633
|
type,
|
|
618
634
|
eventTarget,
|
|
635
|
+
fn,
|
|
619
636
|
options
|
|
620
637
|
});
|
|
621
638
|
eventTarget.addEventListener(type, listener, options);
|
|
622
639
|
}, []);
|
|
623
640
|
let removeGlobalListener = useCallback((eventTarget, type, listener, options) => {
|
|
624
|
-
|
|
641
|
+
var _globalListeners$curr;
|
|
642
|
+
|
|
643
|
+
let fn = ((_globalListeners$curr = globalListeners.current.get(listener)) == null ? void 0 : _globalListeners$curr.fn) || listener;
|
|
644
|
+
eventTarget.removeEventListener(type, fn, options);
|
|
625
645
|
globalListeners.current.delete(listener);
|
|
626
646
|
}, []);
|
|
627
647
|
let removeAllGlobalListeners = useCallback(() => {
|
|
@@ -678,6 +698,39 @@ function useLabels(props, defaultLabel) {
|
|
|
678
698
|
|
|
679
699
|
exports.useLabels = useLabels;
|
|
680
700
|
|
|
701
|
+
/**
|
|
702
|
+
* Offers an object ref for a given callback ref or an object ref. Especially
|
|
703
|
+
* helfpul when passing forwarded refs (created using `React.forwardRef`) to
|
|
704
|
+
* React Aria Hooks.
|
|
705
|
+
*
|
|
706
|
+
* @param forwardedRef The original ref intended to be used.
|
|
707
|
+
* @returns An object ref that updates the given ref.
|
|
708
|
+
* @see https://reactjs.org/docs/forwarding-refs.html
|
|
709
|
+
*/
|
|
710
|
+
function useObjectRef(forwardedRef) {
|
|
711
|
+
const objRef = useRef();
|
|
712
|
+
/**
|
|
713
|
+
* We're using `useLayoutEffect` here instead of `useEffect` because we want
|
|
714
|
+
* to make sure that the `ref` value is up to date before other places in the
|
|
715
|
+
* the execution cycle try to read it.
|
|
716
|
+
*/
|
|
717
|
+
|
|
718
|
+
useLayoutEffect(() => {
|
|
719
|
+
if (!forwardedRef) {
|
|
720
|
+
return;
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
if (typeof forwardedRef === 'function') {
|
|
724
|
+
forwardedRef(objRef.current);
|
|
725
|
+
} else {
|
|
726
|
+
forwardedRef.current = objRef.current;
|
|
727
|
+
}
|
|
728
|
+
}, [forwardedRef]);
|
|
729
|
+
return objRef;
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
exports.useObjectRef = useObjectRef;
|
|
733
|
+
|
|
681
734
|
// Like useEffect, but only called for updates after the initial render.
|
|
682
735
|
function useUpdateEffect(effect, dependencies) {
|
|
683
736
|
const isInitialMount = useRef(true);
|
|
@@ -813,8 +866,7 @@ const $bd5928122fc632cc7302c36df9f$var$descriptionNodes = new Map();
|
|
|
813
866
|
|
|
814
867
|
function useDescription(description) {
|
|
815
868
|
let [id, setId] = useState(null);
|
|
816
|
-
|
|
817
|
-
_useLayoutEffect(() => {
|
|
869
|
+
useLayoutEffect(() => {
|
|
818
870
|
if (!description) {
|
|
819
871
|
return;
|
|
820
872
|
}
|
|
@@ -846,7 +898,6 @@ function useDescription(description) {
|
|
|
846
898
|
}
|
|
847
899
|
};
|
|
848
900
|
}, [description]);
|
|
849
|
-
|
|
850
901
|
return {
|
|
851
902
|
'aria-describedby': description ? id : undefined
|
|
852
903
|
};
|
|
@@ -910,4 +961,130 @@ function isAndroid() {
|
|
|
910
961
|
}
|
|
911
962
|
|
|
912
963
|
exports.isAndroid = isAndroid;
|
|
964
|
+
|
|
965
|
+
function useEvent(ref, event, handler, options) {
|
|
966
|
+
let handlerRef = useRef(handler);
|
|
967
|
+
handlerRef.current = handler;
|
|
968
|
+
let isDisabled = handler == null;
|
|
969
|
+
useEffect(() => {
|
|
970
|
+
if (isDisabled) {
|
|
971
|
+
return;
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
let element = ref.current;
|
|
975
|
+
|
|
976
|
+
let handler = e => handlerRef.current.call(this, e);
|
|
977
|
+
|
|
978
|
+
element.addEventListener(event, handler, options);
|
|
979
|
+
return () => {
|
|
980
|
+
element.removeEventListener(event, handler, options);
|
|
981
|
+
};
|
|
982
|
+
}, [ref, event, options, isDisabled]);
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
exports.useEvent = useEvent;
|
|
986
|
+
|
|
987
|
+
// This hook works like `useState`, but when setting the value, you pass a generator function
|
|
988
|
+
// that can yield multiple values. Each yielded value updates the state and waits for the next
|
|
989
|
+
// layout effect, then continues the generator. This allows sequential updates to state to be
|
|
990
|
+
// written linearly.
|
|
991
|
+
function useValueEffect(defaultValue) {
|
|
992
|
+
let [value, setValue] = useState(defaultValue);
|
|
993
|
+
let valueRef = useRef(value);
|
|
994
|
+
let effect = useRef(null);
|
|
995
|
+
valueRef.current = value; // Store the function in a ref so we can always access the current version
|
|
996
|
+
// which has the proper `value` in scope.
|
|
997
|
+
|
|
998
|
+
let nextRef = useRef(null);
|
|
999
|
+
|
|
1000
|
+
nextRef.current = () => {
|
|
1001
|
+
// Run the generator to the next yield.
|
|
1002
|
+
let newValue = effect.current.next(); // If the generator is done, reset the effect.
|
|
1003
|
+
|
|
1004
|
+
if (newValue.done) {
|
|
1005
|
+
effect.current = null;
|
|
1006
|
+
return;
|
|
1007
|
+
} // If the value is the same as the current value,
|
|
1008
|
+
// then continue to the next yield. Otherwise,
|
|
1009
|
+
// set the value in state and wait for the next layout effect.
|
|
1010
|
+
|
|
1011
|
+
|
|
1012
|
+
if (value === newValue.value) {
|
|
1013
|
+
nextRef.current();
|
|
1014
|
+
} else {
|
|
1015
|
+
setValue(newValue.value);
|
|
1016
|
+
}
|
|
1017
|
+
};
|
|
1018
|
+
|
|
1019
|
+
useLayoutEffect(() => {
|
|
1020
|
+
// If there is an effect currently running, continue to the next yield.
|
|
1021
|
+
if (effect.current) {
|
|
1022
|
+
nextRef.current();
|
|
1023
|
+
}
|
|
1024
|
+
});
|
|
1025
|
+
let queue = useCallback(fn => {
|
|
1026
|
+
effect.current = fn(valueRef.current);
|
|
1027
|
+
nextRef.current();
|
|
1028
|
+
}, [effect, nextRef]);
|
|
1029
|
+
return [value, queue];
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1032
|
+
exports.useValueEffect = useValueEffect;
|
|
1033
|
+
|
|
1034
|
+
function scrollIntoView(scrollView, element) {
|
|
1035
|
+
let offsetX = $cbd55f9ce27bf074ec65b15e6f24531$var$relativeOffset(scrollView, element, 'left');
|
|
1036
|
+
let offsetY = $cbd55f9ce27bf074ec65b15e6f24531$var$relativeOffset(scrollView, element, 'top');
|
|
1037
|
+
let width = element.offsetWidth;
|
|
1038
|
+
let height = element.offsetHeight;
|
|
1039
|
+
let x = scrollView.scrollLeft;
|
|
1040
|
+
let y = scrollView.scrollTop;
|
|
1041
|
+
let maxX = x + scrollView.offsetWidth;
|
|
1042
|
+
let maxY = y + scrollView.offsetHeight;
|
|
1043
|
+
|
|
1044
|
+
if (offsetX <= x) {
|
|
1045
|
+
x = offsetX;
|
|
1046
|
+
} else if (offsetX + width > maxX) {
|
|
1047
|
+
x += offsetX + width - maxX;
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
if (offsetY <= y) {
|
|
1051
|
+
y = offsetY;
|
|
1052
|
+
} else if (offsetY + height > maxY) {
|
|
1053
|
+
y += offsetY + height - maxY;
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
scrollView.scrollLeft = x;
|
|
1057
|
+
scrollView.scrollTop = y;
|
|
1058
|
+
}
|
|
1059
|
+
/**
|
|
1060
|
+
* Computes the offset left or top from child to ancestor by accumulating
|
|
1061
|
+
* offsetLeft or offsetTop through intervening offsetParents.
|
|
1062
|
+
*/
|
|
1063
|
+
|
|
1064
|
+
|
|
1065
|
+
exports.scrollIntoView = scrollIntoView;
|
|
1066
|
+
|
|
1067
|
+
function $cbd55f9ce27bf074ec65b15e6f24531$var$relativeOffset(ancestor, child, axis) {
|
|
1068
|
+
const prop = axis === 'left' ? 'offsetLeft' : 'offsetTop';
|
|
1069
|
+
let sum = 0;
|
|
1070
|
+
|
|
1071
|
+
while (child.offsetParent) {
|
|
1072
|
+
sum += child[prop];
|
|
1073
|
+
|
|
1074
|
+
if (child.offsetParent === ancestor) {
|
|
1075
|
+
// Stop once we have found the ancestor we are interested in.
|
|
1076
|
+
break;
|
|
1077
|
+
} else if (child.offsetParent.contains(ancestor)) {
|
|
1078
|
+
// If the ancestor is not `position:relative`, then we stop at
|
|
1079
|
+
// _its_ offset parent, and we subtract off _its_ offset, so that
|
|
1080
|
+
// we end up with the proper offset from child to ancestor.
|
|
1081
|
+
sum -= ancestor[prop];
|
|
1082
|
+
break;
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
child = child.offsetParent;
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
return sum;
|
|
1089
|
+
}
|
|
913
1090
|
//# sourceMappingURL=main.js.map
|