@udecode/react-utils 51.1.2 → 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.js CHANGED
@@ -1,381 +1,312 @@
1
- "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
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);
29
-
30
- // src/index.ts
31
- var index_exports = {};
32
- __export(index_exports, {
33
- Box: () => Box,
34
- CAN_USE_DOM: () => CAN_USE_DOM,
35
- DEFAULT_IGNORE_CLASS: () => DEFAULT_IGNORE_CLASS,
36
- MemoizedChildren: () => MemoizedChildren,
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
- useMemoizedSelector: () => useMemoizedSelector,
48
- useOnClickOutside: () => useOnClickOutside,
49
- useStableFn: () => useStableFn,
50
- useStableMemo: () => useStableMemo,
51
- withProviders: () => withProviders,
52
- withRef: () => withRef
53
- });
54
- module.exports = __toCommonJS(index_exports);
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";
55
6
 
56
- // src/createSlotComponent.tsx
57
- var import_react_slot = require("@radix-ui/react-slot");
58
- var import_react = __toESM(require("react"));
59
- var createSlotComponent = (element) => import_react.default.forwardRef(({ as, asChild = false, ...props }, ref) => {
60
- const Comp = asChild ? import_react_slot.Slot : as || element;
61
- return /* @__PURE__ */ import_react.default.createElement(Comp, { ref, ...props });
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
+ });
62
14
  });
63
15
 
64
- // src/Box.tsx
65
- var Box = createSlotComponent("div");
16
+ //#endregion
17
+ //#region src/Box.tsx
18
+ const Box = createSlotComponent("div");
66
19
 
67
- // src/MemoizedChildren.tsx
68
- var import_react2 = __toESM(require("react"));
69
- var MemoizedChildren = import_react2.default.memo(
70
- ({ children }) => /* @__PURE__ */ import_react2.default.createElement(import_react2.default.Fragment, null, children)
71
- );
20
+ //#endregion
21
+ //#region src/MemoizedChildren.tsx
22
+ const MemoizedChildren = React.memo(({ children }) => /* @__PURE__ */ React.createElement(React.Fragment, null, children));
72
23
 
73
- // src/PortalBody.tsx
74
- var import_react_dom = __toESM(require("react-dom"));
75
- var PortalBody = ({
76
- children,
77
- element
78
- }) => {
79
- const container = element || typeof window !== "undefined" ? document.body : void 0;
80
- if (!container) return children;
81
- 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);
82
29
  };
83
30
 
84
- // src/Text.tsx
85
- var Text = createSlotComponent("span");
31
+ //#endregion
32
+ //#region src/Text.tsx
33
+ const Text = createSlotComponent("span");
86
34
 
87
- // src/composeEventHandlers.ts
88
- var composeEventHandlers = (originalEventHandler, ourEventHandler, { checkForDefaultPrevented = true } = {}) => (event) => {
89
- originalEventHandler?.(event);
90
- if (checkForDefaultPrevented === false || !event.defaultPrevented) {
91
- return ourEventHandler?.(event);
92
- }
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);
93
41
  };
94
42
 
95
- // src/createPrimitiveComponent.tsx
96
- var import_utils = require("@udecode/utils");
97
- var import_clsx = require("clsx");
98
- var import_react4 = __toESM(require("react"));
99
-
100
- // src/useComposedRef.ts
101
- var import_react3 = __toESM(require("react"));
102
- var setRef = (ref, value) => {
103
- if (typeof ref === "function") {
104
- return ref(value);
105
- }
106
- if (ref !== null && ref !== void 0) {
107
- ref.current = value;
108
- }
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;
109
52
  };
110
- var composeRefs = (...refs) => (node) => {
111
- const cleanups = [];
112
- refs.forEach((ref) => {
113
- const cleanup = setRef(ref, node);
114
- if (typeof cleanup === "function") {
115
- cleanups.push(cleanup);
116
- }
117
- });
118
- if (cleanups.length > 0) {
119
- return () => {
120
- for (const cleanup of cleanups) {
121
- cleanup?.();
122
- }
123
- };
124
- }
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
+ };
125
66
  };
126
- var useComposedRef = (...refs) => {
127
- return import_react3.default.useCallback(composeRefs(...refs), refs);
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);
128
73
  };
129
74
 
130
- // src/createPrimitiveComponent.tsx
131
- var createPrimitiveComponent = (element) => {
132
- const Comp = createSlotComponent(element);
133
- return ({
134
- propsHook,
135
- stateHook
136
- } = {}) => import_react4.default.forwardRef(
137
- ({
138
- asChild,
139
- className: classNameProp,
140
- getClassName,
141
- options,
142
- state: stateProp,
143
- ...props
144
- }, ref) => {
145
- const state = (0, import_utils.isDefined)(stateProp) ? stateProp : stateHook ? stateHook(options) : void 0;
146
- const {
147
- hidden,
148
- props: hookProps,
149
- ref: hookRef
150
- } = propsHook ? propsHook(state) : { hidden: false, props: {}, ref: null };
151
- const _ref = useComposedRef(ref, hookRef);
152
- const className = (0, import_utils.isDefined)(hookProps?.className) || (0, import_utils.isDefined)(classNameProp) ? (0, import_clsx.clsx)(hookProps?.className, classNameProp) : void 0;
153
- const style = hookProps?.style || props.style ? { ...hookProps?.style, ...props.style } : void 0;
154
- if (!asChild && hidden) return null;
155
- return /* @__PURE__ */ import_react4.default.createElement(
156
- Comp,
157
- {
158
- asChild,
159
- ref: _ref,
160
- ...hookProps,
161
- className,
162
- style,
163
- ...props,
164
- ...props.setProps?.(hookProps ?? {}) ?? {}
165
- }
166
- );
167
- }
168
- );
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
+ });
169
128
  };
170
129
 
171
- // src/createPrimitiveElement.tsx
172
- var import_react5 = __toESM(require("react"));
130
+ //#endregion
131
+ //#region src/createPrimitiveElement.tsx
173
132
  function createPrimitiveElement(tag) {
174
- return import_react5.default.forwardRef(
175
- function CreateComponent(props, ref) {
176
- return import_react5.default.createElement(tag, { ...props, ref });
177
- }
178
- );
133
+ return React.forwardRef(function CreateComponent(props, ref) {
134
+ return React.createElement(tag, {
135
+ ...props,
136
+ ref
137
+ });
138
+ });
179
139
  }
180
140
 
181
- // src/useEffectOnce.ts
182
- var import_react6 = __toESM(require("react"));
141
+ //#endregion
142
+ //#region src/useEffectOnce.ts
183
143
  function useEffectOnce(effect, deps) {
184
- const initialized = import_react6.default.useRef(false);
185
- const prevDepsRef = import_react6.default.useRef(deps);
186
- import_react6.default.useEffect(() => {
187
- const depsChanged = deps.some((dep, i) => dep !== prevDepsRef.current[i]);
188
- if (!initialized.current || depsChanged) {
189
- initialized.current = true;
190
- prevDepsRef.current = deps;
191
- effect();
192
- }
193
- }, deps);
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);
194
154
  }
195
155
 
196
- // src/useIsomorphicLayoutEffect.ts
197
- var import_react7 = __toESM(require("react"));
198
- var CAN_USE_DOM = typeof window !== "undefined" && window.document?.createElement !== void 0;
199
- var useIsomorphicLayoutEffect = CAN_USE_DOM ? import_react7.default.useLayoutEffect : import_react7.default.useEffect;
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;
200
164
 
201
- // src/useMemoizedSelector.ts
202
- var import_react8 = __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
+ */
203
175
  function useMemoizedSelector(selector, deps, equalityFn = (a, b) => a === b) {
204
- const [memoizedValue, setMemoizedValue] = import_react8.default.useState(() => selector());
205
- const previousValueRef = import_react8.default.useRef(memoizedValue);
206
- import_react8.default.useEffect(() => {
207
- const newValue = selector();
208
- if (!equalityFn(previousValueRef.current, newValue)) {
209
- setMemoizedValue(newValue);
210
- previousValueRef.current = newValue;
211
- }
212
- }, deps);
213
- return memoizedValue;
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;
214
186
  }
215
187
 
216
- // src/useOnClickOutside.ts
217
- var import_react9 = __toESM(require("react"));
218
- var canUsePassiveEvents = () => {
219
- if (typeof window === "undefined" || typeof window.addEventListener !== "function")
220
- return false;
221
- let passive = false;
222
- const options = Object.defineProperty({}, "passive", {
223
- get() {
224
- passive = true;
225
- }
226
- });
227
- const noop = () => null;
228
- window.addEventListener("test", noop, options);
229
- window.removeEventListener("test", noop, options);
230
- 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;
231
200
  };
232
- var DEFAULT_IGNORE_CLASS = "ignore-onclickoutside";
233
- var checkClass = (el, cl) => el.classList?.contains(cl);
234
- var hasIgnoreClass = (e, ignoreClass) => {
235
- let el = e.target || e;
236
- while (el) {
237
- if (Array.isArray(ignoreClass)) {
238
- if (ignoreClass.some((c) => checkClass(el, c))) return true;
239
- } else if (checkClass(el, ignoreClass)) {
240
- return true;
241
- }
242
- el = el.parentElement;
243
- }
244
- 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;
245
212
  };
246
- var clickedOnScrollbar = (e) => document.documentElement.clientWidth <= e.clientX || document.documentElement.clientHeight <= e.clientY;
247
- var getEventOptions = (type) => type.includes("touch") && canUsePassiveEvents() ? { passive: true } : false;
248
- var useOnClickOutside = (callback, {
249
- detectIFrame = true,
250
- disabled,
251
- eventTypes = ["mousedown", "touchstart"],
252
- excludeScrollbar,
253
- ignoreClass = DEFAULT_IGNORE_CLASS,
254
- refs: refsOpt
255
- } = {}) => {
256
- const [refsState, setRefsState] = import_react9.default.useState([]);
257
- const callbackRef = import_react9.default.useRef(callback);
258
- callbackRef.current = callback;
259
- const ref = import_react9.default.useCallback(
260
- (el) => setRefsState((prevState) => [...prevState, { current: el }]),
261
- []
262
- );
263
- import_react9.default.useEffect(
264
- () => {
265
- if (!refsOpt?.length && refsState.length === 0) return;
266
- const getEls = () => {
267
- const els = [];
268
- for (const { current } of refsOpt || refsState) {
269
- if (current) {
270
- els.push(current);
271
- }
272
- }
273
- return els;
274
- };
275
- const handler = (e) => {
276
- if (!hasIgnoreClass(e, ignoreClass) && !(excludeScrollbar && clickedOnScrollbar(e)) && getEls().every((el) => !el.contains(e.target)))
277
- callbackRef.current(e);
278
- };
279
- const blurHandler = (e) => (
280
- // On firefox the iframe becomes document.activeElement in the next event loop
281
- setTimeout(() => {
282
- const { activeElement } = document;
283
- if (activeElement?.tagName === "IFRAME" && !hasIgnoreClass(activeElement, ignoreClass) && !getEls().includes(activeElement))
284
- callbackRef.current(e);
285
- }, 0)
286
- );
287
- const removeEventListener = () => {
288
- for (const type of eventTypes) {
289
- document.removeEventListener(
290
- type,
291
- handler,
292
- getEventOptions(type)
293
- );
294
- }
295
- if (detectIFrame) window.removeEventListener("blur", blurHandler);
296
- };
297
- if (disabled) {
298
- removeEventListener();
299
- return;
300
- }
301
- for (const type of eventTypes) {
302
- document.addEventListener(type, handler, getEventOptions(type));
303
- }
304
- if (detectIFrame) window.addEventListener("blur", blurHandler);
305
- return () => removeEventListener();
306
- },
307
- // eslint-disable-next-line react-hooks/exhaustive-deps
308
- [
309
- refsState,
310
- ignoreClass,
311
- excludeScrollbar,
312
- disabled,
313
- detectIFrame,
314
- // eslint-disable-next-line react-hooks/exhaustive-deps
315
- JSON.stringify(eventTypes)
316
- ]
317
- );
318
- 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;
319
254
  };
320
255
 
321
- // src/useStableFn.ts
322
- var import_react10 = __toESM(require("react"));
323
- var useStableFn = (fn, deps = []) => {
324
- const fnRef = import_react10.default.useRef(fn);
325
- fnRef.current = fn;
326
- return import_react10.default.useCallback((...args) => fnRef.current(...args), deps);
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);
327
271
  };
328
272
 
329
- // src/useStableMemo.ts
330
- var import_react11 = __toESM(require("react"));
331
- var useStableMemo = (producer, deps) => {
332
- const [value, setValue] = import_react11.default.useState(producer);
333
- import_react11.default.useLayoutEffect(() => {
334
- setValue(producer);
335
- }, deps);
336
- return value;
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;
337
281
  };
338
282
 
339
- // src/withProviders.tsx
340
- var import_react12 = __toESM(require("react"));
341
- var withProviders = (...providers) => (WrappedComponent) => (props) => providers.reduceRight(
342
- (acc, prov) => {
343
- let Provider = prov;
344
- if (Array.isArray(prov)) {
345
- [Provider] = prov;
346
- return /* @__PURE__ */ import_react12.default.createElement(Provider, { ...prov[1] }, acc);
347
- }
348
- return /* @__PURE__ */ import_react12.default.createElement(Provider, null, acc);
349
- },
350
- /* @__PURE__ */ import_react12.default.createElement(WrappedComponent, { ...props })
351
- );
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));
352
298
 
353
- // src/withRef.tsx
354
- var import_react13 = __toESM(require("react"));
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
+ */
355
307
  function withRef(renderFunction) {
356
- return import_react13.default.forwardRef(renderFunction);
308
+ return React.forwardRef(renderFunction);
357
309
  }
358
- // Annotate the CommonJS export names for ESM import in node:
359
- 0 && (module.exports = {
360
- Box,
361
- CAN_USE_DOM,
362
- DEFAULT_IGNORE_CLASS,
363
- MemoizedChildren,
364
- PortalBody,
365
- Text,
366
- composeEventHandlers,
367
- composeRefs,
368
- createPrimitiveComponent,
369
- createPrimitiveElement,
370
- createSlotComponent,
371
- useComposedRef,
372
- useEffectOnce,
373
- useIsomorphicLayoutEffect,
374
- useMemoizedSelector,
375
- useOnClickOutside,
376
- useStableFn,
377
- useStableMemo,
378
- withProviders,
379
- withRef
380
- });
381
- //# 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 };