@udecode/react-utils 49.0.15 → 52.0.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/index.d.ts +88 -58
- package/dist/index.js +275 -360
- package/package.json +9 -12
- package/dist/index.d.mts +0 -155
- package/dist/index.js.map +0 -1
- package/dist/index.mjs +0 -340
- package/dist/index.mjs.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,397 +1,312 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __export = (target, all) => {
|
|
9
|
-
for (var name in all)
|
|
10
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
-
};
|
|
12
|
-
var __copyProps = (to, from, except, desc) => {
|
|
13
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
-
for (let key of __getOwnPropNames(from))
|
|
15
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
-
}
|
|
18
|
-
return to;
|
|
19
|
-
};
|
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
-
mod
|
|
27
|
-
));
|
|
28
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
1
|
+
import { Slot } from "@radix-ui/react-slot";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import ReactDOM from "react-dom";
|
|
4
|
+
import { isDefined } from "@udecode/utils";
|
|
5
|
+
import { clsx } from "clsx";
|
|
29
6
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
PortalBody: () => PortalBody,
|
|
38
|
-
Text: () => Text,
|
|
39
|
-
composeEventHandlers: () => composeEventHandlers,
|
|
40
|
-
composeRefs: () => composeRefs,
|
|
41
|
-
createPrimitiveComponent: () => createPrimitiveComponent,
|
|
42
|
-
createPrimitiveElement: () => createPrimitiveElement,
|
|
43
|
-
createSlotComponent: () => createSlotComponent,
|
|
44
|
-
useComposedRef: () => useComposedRef,
|
|
45
|
-
useEffectOnce: () => useEffectOnce,
|
|
46
|
-
useIsomorphicLayoutEffect: () => useIsomorphicLayoutEffect,
|
|
47
|
-
useMemoOnce: () => useMemoOnce,
|
|
48
|
-
useMemoizedSelector: () => useMemoizedSelector,
|
|
49
|
-
useOnClickOutside: () => useOnClickOutside,
|
|
50
|
-
useStableFn: () => useStableFn,
|
|
51
|
-
useStableMemo: () => useStableMemo,
|
|
52
|
-
withProviders: () => withProviders,
|
|
53
|
-
withRef: () => withRef
|
|
7
|
+
//#region src/createSlotComponent.tsx
|
|
8
|
+
const createSlotComponent = (element) => React.forwardRef(({ as, asChild = false, ...props }, ref) => {
|
|
9
|
+
const Comp = asChild ? Slot : as || element;
|
|
10
|
+
return /* @__PURE__ */ React.createElement(Comp, {
|
|
11
|
+
ref,
|
|
12
|
+
...props
|
|
13
|
+
});
|
|
54
14
|
});
|
|
55
|
-
module.exports = __toCommonJS(index_exports);
|
|
56
15
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
var createSlotComponent = (element) => import_react.default.forwardRef(({ as, asChild = false, ...props }, ref) => {
|
|
61
|
-
const Comp = asChild ? import_react_slot.Slot : as || element;
|
|
62
|
-
return /* @__PURE__ */ import_react.default.createElement(Comp, { ref, ...props });
|
|
63
|
-
});
|
|
16
|
+
//#endregion
|
|
17
|
+
//#region src/Box.tsx
|
|
18
|
+
const Box = createSlotComponent("div");
|
|
64
19
|
|
|
65
|
-
|
|
66
|
-
|
|
20
|
+
//#endregion
|
|
21
|
+
//#region src/MemoizedChildren.tsx
|
|
22
|
+
const MemoizedChildren = React.memo(({ children }) => /* @__PURE__ */ React.createElement(React.Fragment, null, children));
|
|
67
23
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
74
|
-
);
|
|
75
|
-
|
|
76
|
-
// src/PortalBody.tsx
|
|
77
|
-
var import_react3 = __toESM(require("react"));
|
|
78
|
-
var import_react_dom = __toESM(require("react-dom"));
|
|
79
|
-
var PortalBody = ({
|
|
80
|
-
children,
|
|
81
|
-
element
|
|
82
|
-
}) => {
|
|
83
|
-
const container = element || typeof window !== "undefined" ? document.body : void 0;
|
|
84
|
-
if (!container) return /* @__PURE__ */ import_react3.default.createElement(import_react3.default.Fragment, null, children);
|
|
85
|
-
return import_react_dom.default.createPortal(children, element || document.body);
|
|
24
|
+
//#endregion
|
|
25
|
+
//#region src/PortalBody.tsx
|
|
26
|
+
const PortalBody = ({ children, element }) => {
|
|
27
|
+
if (!(element || typeof window !== "undefined" ? document.body : void 0)) return children;
|
|
28
|
+
return ReactDOM.createPortal(children, element || document.body);
|
|
86
29
|
};
|
|
87
30
|
|
|
88
|
-
|
|
89
|
-
|
|
31
|
+
//#endregion
|
|
32
|
+
//#region src/Text.tsx
|
|
33
|
+
const Text = createSlotComponent("span");
|
|
90
34
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
35
|
+
//#endregion
|
|
36
|
+
//#region src/composeEventHandlers.ts
|
|
37
|
+
/** @see https://github.com/radix-ui/primitives/blob/b324ec2d7ddf13a2a115cb5b11478e24d2f45b87/packages/core/primitive/src/primitive.tsx#L1 */
|
|
38
|
+
const composeEventHandlers = (originalEventHandler, ourEventHandler, { checkForDefaultPrevented = true } = {}) => (event) => {
|
|
39
|
+
originalEventHandler?.(event);
|
|
40
|
+
if (checkForDefaultPrevented === false || !event.defaultPrevented) return ourEventHandler?.(event);
|
|
97
41
|
};
|
|
98
42
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
return ref(value);
|
|
109
|
-
} else if (ref !== null && ref !== void 0) {
|
|
110
|
-
ref.current = value;
|
|
111
|
-
}
|
|
43
|
+
//#endregion
|
|
44
|
+
//#region src/useComposedRef.ts
|
|
45
|
+
/**
|
|
46
|
+
* Set a given ref to a given value This utility takes care of different types
|
|
47
|
+
* of refs: callback refs and React.RefObject(s)
|
|
48
|
+
*/
|
|
49
|
+
const setRef = (ref, value) => {
|
|
50
|
+
if (typeof ref === "function") return ref(value);
|
|
51
|
+
if (ref !== null && ref !== void 0) ref.current = value;
|
|
112
52
|
};
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
53
|
+
/**
|
|
54
|
+
* A utility to compose multiple refs together Accepts callback refs and
|
|
55
|
+
* React.RefObject(s)
|
|
56
|
+
*/
|
|
57
|
+
const composeRefs = (...refs) => (node) => {
|
|
58
|
+
const cleanups = [];
|
|
59
|
+
refs.forEach((ref) => {
|
|
60
|
+
const cleanup = setRef(ref, node);
|
|
61
|
+
if (typeof cleanup === "function") cleanups.push(cleanup);
|
|
62
|
+
});
|
|
63
|
+
if (cleanups.length > 0) return () => {
|
|
64
|
+
for (const cleanup of cleanups) cleanup?.();
|
|
65
|
+
};
|
|
126
66
|
};
|
|
127
|
-
|
|
128
|
-
|
|
67
|
+
/**
|
|
68
|
+
* A custom hook that composes multiple refs Accepts callback refs and
|
|
69
|
+
* React.RefObject(s)
|
|
70
|
+
*/
|
|
71
|
+
const useComposedRef = (...refs) => {
|
|
72
|
+
return React.useCallback(composeRefs(...refs), refs);
|
|
129
73
|
};
|
|
130
74
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
75
|
+
//#endregion
|
|
76
|
+
//#region src/createPrimitiveComponent.tsx
|
|
77
|
+
/**
|
|
78
|
+
* Primitive component factory. It uses hooks for managing state and props, and
|
|
79
|
+
* forwards references to child components. Component props:
|
|
80
|
+
*
|
|
81
|
+
* - `asChild`: If true, the component will be rendered as a `Slot`
|
|
82
|
+
* {@link https://www.radix-ui.com/docs/primitives/utilities/slot}.
|
|
83
|
+
* - `options`: Options passed to the state hook.
|
|
84
|
+
* - `state`: Provide your state instead of using the state hook.
|
|
85
|
+
* - `className`: Class name to be merged to the component.
|
|
86
|
+
* - `style`: Style object to be merged to the component.
|
|
87
|
+
* - `setProps`: Function to set props from the props hook.
|
|
88
|
+
* - `...props`: Props to be passed to the component. Props hook return value:
|
|
89
|
+
* - `ref`: Reference to be forwarded to the component.
|
|
90
|
+
* - `props`: Props to be passed to the component.
|
|
91
|
+
* - `hidden`: If true, the component will not be rendered.
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* const MyButton = createPrimitiveComponent(Button)({
|
|
95
|
+
* stateHook: useButtonState,
|
|
96
|
+
* propsHook: useButton,
|
|
97
|
+
* });
|
|
98
|
+
*
|
|
99
|
+
* @param {React.ElementType} element The base component or native HTML element.
|
|
100
|
+
* @returns {function} A primitive component.
|
|
101
|
+
*/
|
|
102
|
+
const createPrimitiveComponent = (element) => {
|
|
103
|
+
const Comp = createSlotComponent(element);
|
|
104
|
+
return ({ propsHook, stateHook } = {}) => React.forwardRef(({ asChild, className: classNameProp, getClassName, options, state: stateProp, ...props }, ref) => {
|
|
105
|
+
const state = isDefined(stateProp) ? stateProp : stateHook ? stateHook(options) : void 0;
|
|
106
|
+
const { hidden, props: hookProps, ref: hookRef } = propsHook ? propsHook(state) : {
|
|
107
|
+
hidden: false,
|
|
108
|
+
props: {},
|
|
109
|
+
ref: null
|
|
110
|
+
};
|
|
111
|
+
const _ref = useComposedRef(ref, hookRef);
|
|
112
|
+
const className = isDefined(hookProps?.className) || isDefined(classNameProp) ? clsx(hookProps?.className, classNameProp) : void 0;
|
|
113
|
+
const style = hookProps?.style || props.style ? {
|
|
114
|
+
...hookProps?.style,
|
|
115
|
+
...props.style
|
|
116
|
+
} : void 0;
|
|
117
|
+
if (!asChild && hidden) return null;
|
|
118
|
+
return /* @__PURE__ */ React.createElement(Comp, {
|
|
119
|
+
asChild,
|
|
120
|
+
ref: _ref,
|
|
121
|
+
...hookProps,
|
|
122
|
+
className,
|
|
123
|
+
style,
|
|
124
|
+
...props,
|
|
125
|
+
...props.setProps?.(hookProps ?? {}) ?? {}
|
|
126
|
+
});
|
|
127
|
+
});
|
|
172
128
|
};
|
|
173
129
|
|
|
174
|
-
|
|
175
|
-
|
|
130
|
+
//#endregion
|
|
131
|
+
//#region src/createPrimitiveElement.tsx
|
|
176
132
|
function createPrimitiveElement(tag) {
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
133
|
+
return React.forwardRef(function CreateComponent(props, ref) {
|
|
134
|
+
return React.createElement(tag, {
|
|
135
|
+
...props,
|
|
136
|
+
ref
|
|
137
|
+
});
|
|
138
|
+
});
|
|
182
139
|
}
|
|
183
140
|
|
|
184
|
-
|
|
185
|
-
|
|
141
|
+
//#endregion
|
|
142
|
+
//#region src/useEffectOnce.ts
|
|
186
143
|
function useEffectOnce(effect, deps) {
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
144
|
+
const initialized = React.useRef(false);
|
|
145
|
+
const prevDepsRef = React.useRef(deps);
|
|
146
|
+
React.useEffect(() => {
|
|
147
|
+
const depsChanged = deps.some((dep, i) => dep !== prevDepsRef.current[i]);
|
|
148
|
+
if (!initialized.current || depsChanged) {
|
|
149
|
+
initialized.current = true;
|
|
150
|
+
prevDepsRef.current = deps;
|
|
151
|
+
effect();
|
|
152
|
+
}
|
|
153
|
+
}, deps);
|
|
197
154
|
}
|
|
198
155
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
156
|
+
//#endregion
|
|
157
|
+
//#region src/useIsomorphicLayoutEffect.ts
|
|
158
|
+
const CAN_USE_DOM = typeof window !== "undefined" && window.document?.createElement !== void 0;
|
|
159
|
+
/**
|
|
160
|
+
* Prevent warning on SSR by falling back to React.useEffect when DOM isn't
|
|
161
|
+
* available
|
|
162
|
+
*/
|
|
163
|
+
const useIsomorphicLayoutEffect = CAN_USE_DOM ? React.useLayoutEffect : React.useEffect;
|
|
203
164
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
}
|
|
215
|
-
return memoizedValueRef.current;
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
// src/useMemoizedSelector.ts
|
|
219
|
-
var import_react10 = __toESM(require("react"));
|
|
165
|
+
//#endregion
|
|
166
|
+
//#region src/useMemoizedSelector.ts
|
|
167
|
+
/**
|
|
168
|
+
* Re-render only when the selector result changes.
|
|
169
|
+
*
|
|
170
|
+
* @param selector A function that derives a value from deps
|
|
171
|
+
* @param deps Dependencies on which to run the selector
|
|
172
|
+
* @param equalityFn Optional comparison function to detect changes in the
|
|
173
|
+
* derived value
|
|
174
|
+
*/
|
|
220
175
|
function useMemoizedSelector(selector, deps, equalityFn = (a, b) => a === b) {
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
176
|
+
const [memoizedValue, setMemoizedValue] = React.useState(() => selector());
|
|
177
|
+
const previousValueRef = React.useRef(memoizedValue);
|
|
178
|
+
React.useEffect(() => {
|
|
179
|
+
const newValue = selector();
|
|
180
|
+
if (!equalityFn(previousValueRef.current, newValue)) {
|
|
181
|
+
setMemoizedValue(newValue);
|
|
182
|
+
previousValueRef.current = newValue;
|
|
183
|
+
}
|
|
184
|
+
}, deps);
|
|
185
|
+
return memoizedValue;
|
|
231
186
|
}
|
|
232
187
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
window.addEventListener("test", noop, options);
|
|
246
|
-
window.removeEventListener("test", noop, options);
|
|
247
|
-
return passive;
|
|
188
|
+
//#endregion
|
|
189
|
+
//#region src/useOnClickOutside.ts
|
|
190
|
+
const canUsePassiveEvents = () => {
|
|
191
|
+
if (typeof window === "undefined" || typeof window.addEventListener !== "function") return false;
|
|
192
|
+
let passive = false;
|
|
193
|
+
const options = Object.defineProperty({}, "passive", { get() {
|
|
194
|
+
passive = true;
|
|
195
|
+
} });
|
|
196
|
+
const noop = () => null;
|
|
197
|
+
window.addEventListener("test", noop, options);
|
|
198
|
+
window.removeEventListener("test", noop, options);
|
|
199
|
+
return passive;
|
|
248
200
|
};
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
}
|
|
261
|
-
return false;
|
|
201
|
+
const DEFAULT_IGNORE_CLASS = "ignore-onclickoutside";
|
|
202
|
+
const checkClass = (el, cl) => el.classList?.contains(cl);
|
|
203
|
+
const hasIgnoreClass = (e, ignoreClass) => {
|
|
204
|
+
let el = e.target || e;
|
|
205
|
+
while (el) {
|
|
206
|
+
if (Array.isArray(ignoreClass)) {
|
|
207
|
+
if (ignoreClass.some((c) => checkClass(el, c))) return true;
|
|
208
|
+
} else if (checkClass(el, ignoreClass)) return true;
|
|
209
|
+
el = el.parentElement;
|
|
210
|
+
}
|
|
211
|
+
return false;
|
|
262
212
|
};
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
(type) => document.removeEventListener(
|
|
305
|
-
type,
|
|
306
|
-
handler,
|
|
307
|
-
getEventOptions(type)
|
|
308
|
-
)
|
|
309
|
-
);
|
|
310
|
-
if (detectIFrame) window.removeEventListener("blur", blurHandler);
|
|
311
|
-
};
|
|
312
|
-
if (disabled) {
|
|
313
|
-
removeEventListener();
|
|
314
|
-
return;
|
|
315
|
-
}
|
|
316
|
-
eventTypes.forEach(
|
|
317
|
-
(type) => document.addEventListener(type, handler, getEventOptions(type))
|
|
318
|
-
);
|
|
319
|
-
if (detectIFrame) window.addEventListener("blur", blurHandler);
|
|
320
|
-
return () => removeEventListener();
|
|
321
|
-
},
|
|
322
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
323
|
-
[
|
|
324
|
-
refsState,
|
|
325
|
-
ignoreClass,
|
|
326
|
-
excludeScrollbar,
|
|
327
|
-
disabled,
|
|
328
|
-
detectIFrame,
|
|
329
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
330
|
-
JSON.stringify(eventTypes)
|
|
331
|
-
]
|
|
332
|
-
);
|
|
333
|
-
return ref;
|
|
213
|
+
const clickedOnScrollbar = (e) => document.documentElement.clientWidth <= e.clientX || document.documentElement.clientHeight <= e.clientY;
|
|
214
|
+
const getEventOptions = (type) => type.includes("touch") && canUsePassiveEvents() ? { passive: true } : false;
|
|
215
|
+
const useOnClickOutside = (callback, { detectIFrame = true, disabled, eventTypes = ["mousedown", "touchstart"], excludeScrollbar, ignoreClass = DEFAULT_IGNORE_CLASS, refs: refsOpt } = {}) => {
|
|
216
|
+
const [refsState, setRefsState] = React.useState([]);
|
|
217
|
+
const callbackRef = React.useRef(callback);
|
|
218
|
+
callbackRef.current = callback;
|
|
219
|
+
const ref = React.useCallback((el) => setRefsState((prevState) => [...prevState, { current: el }]), []);
|
|
220
|
+
React.useEffect(() => {
|
|
221
|
+
if (!refsOpt?.length && refsState.length === 0) return;
|
|
222
|
+
const getEls = () => {
|
|
223
|
+
const els = [];
|
|
224
|
+
for (const { current } of refsOpt || refsState) if (current) els.push(current);
|
|
225
|
+
return els;
|
|
226
|
+
};
|
|
227
|
+
const handler = (e) => {
|
|
228
|
+
if (!hasIgnoreClass(e, ignoreClass) && !(excludeScrollbar && clickedOnScrollbar(e)) && getEls().every((el) => !el.contains(e.target))) callbackRef.current(e);
|
|
229
|
+
};
|
|
230
|
+
const blurHandler = (e) => setTimeout(() => {
|
|
231
|
+
const { activeElement } = document;
|
|
232
|
+
if (activeElement?.tagName === "IFRAME" && !hasIgnoreClass(activeElement, ignoreClass) && !getEls().includes(activeElement)) callbackRef.current(e);
|
|
233
|
+
}, 0);
|
|
234
|
+
const removeEventListener = () => {
|
|
235
|
+
for (const type of eventTypes) document.removeEventListener(type, handler, getEventOptions(type));
|
|
236
|
+
if (detectIFrame) window.removeEventListener("blur", blurHandler);
|
|
237
|
+
};
|
|
238
|
+
if (disabled) {
|
|
239
|
+
removeEventListener();
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
for (const type of eventTypes) document.addEventListener(type, handler, getEventOptions(type));
|
|
243
|
+
if (detectIFrame) window.addEventListener("blur", blurHandler);
|
|
244
|
+
return () => removeEventListener();
|
|
245
|
+
}, [
|
|
246
|
+
refsState,
|
|
247
|
+
ignoreClass,
|
|
248
|
+
excludeScrollbar,
|
|
249
|
+
disabled,
|
|
250
|
+
detectIFrame,
|
|
251
|
+
JSON.stringify(eventTypes)
|
|
252
|
+
]);
|
|
253
|
+
return ref;
|
|
334
254
|
};
|
|
335
255
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
256
|
+
//#endregion
|
|
257
|
+
//#region src/useStableFn.ts
|
|
258
|
+
/**
|
|
259
|
+
* Create a stable version of a function that can be used in dependency arrays
|
|
260
|
+
* without causing hooks like useEffect to re-run if the function changes.
|
|
261
|
+
* Calling the returned function always calls the most recent version of the
|
|
262
|
+
* function that was passed to useStableFn.
|
|
263
|
+
*
|
|
264
|
+
* If you do want the function to be replaced when certain dependency values
|
|
265
|
+
* change, include those values in the dependency array of useStableFn.
|
|
266
|
+
*/
|
|
267
|
+
const useStableFn = (fn, deps = []) => {
|
|
268
|
+
const fnRef = React.useRef(fn);
|
|
269
|
+
fnRef.current = fn;
|
|
270
|
+
return React.useCallback((...args) => fnRef.current(...args), deps);
|
|
342
271
|
};
|
|
343
272
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
273
|
+
//#endregion
|
|
274
|
+
//#region src/useStableMemo.ts
|
|
275
|
+
const useStableMemo = (producer, deps) => {
|
|
276
|
+
const [value, setValue] = React.useState(producer);
|
|
277
|
+
React.useLayoutEffect(() => {
|
|
278
|
+
setValue(producer);
|
|
279
|
+
}, deps);
|
|
280
|
+
return value;
|
|
352
281
|
};
|
|
353
282
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
283
|
+
//#endregion
|
|
284
|
+
//#region src/withProviders.tsx
|
|
285
|
+
/** biome-ignore-all lint/correctness/useJsxKeyInIterable: biome */
|
|
286
|
+
/**
|
|
287
|
+
* Wrap a component into multiple providers. If there are any props that you
|
|
288
|
+
* want a provider to receive, you can simply pass an array.
|
|
289
|
+
*/
|
|
290
|
+
const withProviders = (...providers) => (WrappedComponent) => (props) => providers.reduceRight((acc, prov) => {
|
|
291
|
+
let Provider = prov;
|
|
292
|
+
if (Array.isArray(prov)) {
|
|
293
|
+
[Provider] = prov;
|
|
294
|
+
return /* @__PURE__ */ React.createElement(Provider, prov[1], acc);
|
|
295
|
+
}
|
|
296
|
+
return /* @__PURE__ */ React.createElement(Provider, null, acc);
|
|
297
|
+
}, /* @__PURE__ */ React.createElement(WrappedComponent, props));
|
|
367
298
|
|
|
368
|
-
|
|
369
|
-
|
|
299
|
+
//#endregion
|
|
300
|
+
//#region src/withRef.tsx
|
|
301
|
+
/**
|
|
302
|
+
* Shorter alternative to `React.forwardRef`.
|
|
303
|
+
*
|
|
304
|
+
* @generic1 Component type or element type
|
|
305
|
+
* @generic2 Extended prop types
|
|
306
|
+
*/
|
|
370
307
|
function withRef(renderFunction) {
|
|
371
|
-
|
|
308
|
+
return React.forwardRef(renderFunction);
|
|
372
309
|
}
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
CAN_USE_DOM,
|
|
377
|
-
DEFAULT_IGNORE_CLASS,
|
|
378
|
-
MemoizedChildren,
|
|
379
|
-
PortalBody,
|
|
380
|
-
Text,
|
|
381
|
-
composeEventHandlers,
|
|
382
|
-
composeRefs,
|
|
383
|
-
createPrimitiveComponent,
|
|
384
|
-
createPrimitiveElement,
|
|
385
|
-
createSlotComponent,
|
|
386
|
-
useComposedRef,
|
|
387
|
-
useEffectOnce,
|
|
388
|
-
useIsomorphicLayoutEffect,
|
|
389
|
-
useMemoOnce,
|
|
390
|
-
useMemoizedSelector,
|
|
391
|
-
useOnClickOutside,
|
|
392
|
-
useStableFn,
|
|
393
|
-
useStableMemo,
|
|
394
|
-
withProviders,
|
|
395
|
-
withRef
|
|
396
|
-
});
|
|
397
|
-
//# sourceMappingURL=index.js.map
|
|
310
|
+
|
|
311
|
+
//#endregion
|
|
312
|
+
export { Box, CAN_USE_DOM, DEFAULT_IGNORE_CLASS, MemoizedChildren, PortalBody, Text, composeEventHandlers, composeRefs, createPrimitiveComponent, createPrimitiveElement, createSlotComponent, useComposedRef, useEffectOnce, useIsomorphicLayoutEffect, useMemoizedSelector, useOnClickOutside, useStableFn, useStableMemo, withProviders, withRef };
|