@zayne-labs/toolkit-react 0.9.46 → 0.9.47

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.
@@ -0,0 +1,277 @@
1
+ import { AnyFunction, CallbackFn, NonEmptyArray, Prettify, SelectorFn } from "@zayne-labs/toolkit-type-helpers";
2
+ import * as react5 from "react";
3
+ import * as react12 from "react";
4
+ import * as react19 from "react";
5
+ import { RefCallback, useEffect } from "react";
6
+ import * as _zayne_labs_toolkit_core7 from "@zayne-labs/toolkit-core";
7
+ import * as _zayne_labs_toolkit_core17 from "@zayne-labs/toolkit-core";
8
+ import * as _zayne_labs_toolkit_core21 from "@zayne-labs/toolkit-core";
9
+ import { AnimationIntervalOptions, LocationInfo, LocationStoreApi, LocationStoreOptions, ScrollObserverOptions, StorageOptions, StorageStoreApi, StoreApi, URLSearchParamsInit } from "@zayne-labs/toolkit-core";
10
+
11
+ //#region src/hooks/createCustomContext.d.ts
12
+ declare class ContextError extends Error {
13
+ name: string;
14
+ constructor(...args: Parameters<typeof Error>);
15
+ }
16
+ declare const getErrorMessage: (hook: string, provider: string) => string;
17
+ type CustomContextOptions<TContextValue, TStrict extends boolean> = {
18
+ defaultValue?: TContextValue | null;
19
+ errorMessage?: string;
20
+ extension?: (contextValue: NoInfer<TContextValue> | null) => TContextValue | null;
21
+ hookName?: string;
22
+ name?: string;
23
+ providerName?: string;
24
+ strict?: TStrict;
25
+ };
26
+ type UseCustomContextResult<TContextValue, TStrict extends boolean> = TStrict extends true ? TContextValue : TContextValue | null;
27
+ declare const createCustomContext: <TContextValue, TStrict extends boolean = true>(options?: CustomContextOptions<TContextValue, TStrict>) => [react5.Context<TContextValue | null>, () => UseCustomContextResult<TContextValue, TStrict>] & {
28
+ "~inferredUnion": react5.Context<TContextValue | null> | (() => UseCustomContextResult<TContextValue, TStrict>);
29
+ };
30
+
31
+ //#endregion
32
+ //#region src/hooks/effects/useAfterMountEffect.d.ts
33
+ declare const useAfterMountEffect: typeof useEffect;
34
+
35
+ //#endregion
36
+ //#region src/hooks/effects/useAsyncEffect.d.ts
37
+ declare function useAsyncEffect(effect: () => Promise<ReturnType<React.EffectCallback>>, deps?: React.DependencyList): void;
38
+
39
+ //#endregion
40
+ //#region src/hooks/effects/useEffectOnce.d.ts
41
+ declare const useEffectOnce: (callBackFn: React.EffectCallback) => void;
42
+
43
+ //#endregion
44
+ //#region src/hooks/effects/useLifeCycle.d.ts
45
+ type Destructor = ReturnType<React.EffectCallback>;
46
+ type LifeCycleOptions = {
47
+ onMount?: () => void;
48
+ onUnmount?: Destructor;
49
+ };
50
+ declare const useLifeCycle: ({
51
+ onMount,
52
+ onUnmount
53
+ }: LifeCycleOptions) => void;
54
+
55
+ //#endregion
56
+ //#region src/hooks/effects/useMountEffect.d.ts
57
+ declare const useMountEffect: (callBackFn: () => void) => void;
58
+
59
+ //#endregion
60
+ //#region src/hooks/effects/useUnMountEffect.d.ts
61
+ declare const useUnmountEffect: (cleanUpFn: Destructor) => void;
62
+
63
+ //#endregion
64
+ //#region src/hooks/useAnimateElementRefs.d.ts
65
+ type ElementsInfoArray<TTargetElement extends string> = NonEmptyArray<{
66
+ animationClass: string;
67
+ targetElement: TTargetElement;
68
+ }>;
69
+ /**
70
+ * This is a custom React hook that adds and removes animation classes to specified HTML elements.
71
+ * @param elementsInfoArray - An array of objects that contain information about the animation class and the target HTML element.
72
+ * @returns - An object containing the refs of the animated elements and a function to handle the initiation and removal animation.
73
+ */
74
+ declare const useAnimateElementRefs: <TTargetElement extends string>(elementsInfoArray: ElementsInfoArray<TTargetElement>) => {
75
+ animatedElements: Record<TTargetElement, HTMLElement | null>;
76
+ handleElementsAnimation: () => void;
77
+ };
78
+
79
+ //#endregion
80
+ //#region src/hooks/useAnimationInterval.d.ts
81
+ type AnimationOptions = Prettify<AnimationIntervalOptions & {
82
+ intervalDuration: number | null;
83
+ onAnimation: () => void;
84
+ }>;
85
+ declare const useAnimationInterval: (options: AnimationOptions) => {
86
+ start: () => void;
87
+ stop: () => void;
88
+ };
89
+
90
+ //#endregion
91
+ //#region src/hooks/useCallbackRef.d.ts
92
+ /**
93
+ * Returns a stable function that always points to the latest version of the callback function.
94
+ * @param callbackFn - The function to reference
95
+ * @returns a stable function that always points to the latest version of the callback function
96
+ */
97
+ declare const useCallbackRef: <TCallback = AnyFunction>(callbackFn: TCallback | undefined) => TCallback;
98
+
99
+ //#endregion
100
+ //#region src/hooks/useClickOutside.d.ts
101
+ type UseClickOutsideOptions = {
102
+ enabled?: boolean;
103
+ };
104
+ declare const useClickOutside: <TElement extends HTMLElement>(refOrRefArray: Array<React.RefObject<TElement>> | React.RefObject<TElement>, callback: (event: MouseEvent | TouchEvent) => void, options?: UseClickOutsideOptions) => void;
105
+
106
+ //#endregion
107
+ //#region src/hooks/useConstant.d.ts
108
+ declare const useConstant: <TResult>(initCallbackFn: () => TResult) => TResult;
109
+
110
+ //#endregion
111
+ //#region src/hooks/useCopyToClipboard.d.ts
112
+ declare const useCopyToClipboard: () => {
113
+ copiedValue: string;
114
+ handleCopy: (value: string) => void;
115
+ };
116
+
117
+ //#endregion
118
+ //#region src/hooks/useDebounce.d.ts
119
+ declare const useDebouncedFn: <TParams>(callBackFn: CallbackFn<TParams>, delay: number | undefined) => {
120
+ (...params: TParams[]): void;
121
+ (params: TParams | TParams[], overrideOptions: {
122
+ $delay: number;
123
+ }): void;
124
+ cancel: () => void;
125
+ cancelMaxWait(): void;
126
+ };
127
+ declare const useDebouncedState: <TValue>(defaultValue: TValue, delay: number | undefined) => readonly [TValue, {
128
+ (...params: react12.SetStateAction<TValue>[]): void;
129
+ (params: react12.SetStateAction<TValue> | react12.SetStateAction<TValue>[], overrideOptions: {
130
+ $delay: number;
131
+ }): void;
132
+ cancel: () => void;
133
+ cancelMaxWait(): void;
134
+ }, react12.Dispatch<react12.SetStateAction<TValue>>];
135
+
136
+ //#endregion
137
+ //#region src/hooks/useDisclosure.d.ts
138
+ type DisclosureOptions = {
139
+ hasScrollControl?: boolean;
140
+ initialState?: boolean | (() => boolean);
141
+ };
142
+ declare const useDisclosure: (options?: DisclosureOptions) => {
143
+ isOpen: boolean;
144
+ onClose: () => void;
145
+ onOpen: () => void;
146
+ onToggle: <TValue>(value?: TValue) => void;
147
+ };
148
+
149
+ //#endregion
150
+ //#region src/hooks/useIsServer.d.ts
151
+ /**
152
+ * @description Returns whether the component is currently being server side rendered or
153
+ * hydrated on the client. Can be used to delay browser-specific rendering
154
+ * until after hydration.
155
+ */
156
+ declare const useIsServer: () => boolean;
157
+
158
+ //#endregion
159
+ //#region src/hooks/useLocationState.d.ts
160
+ type UseLocationResult<TSlice> = [state: TSlice, actions: LocationStoreApi];
161
+ declare const createUseLocationState: (options?: LocationStoreOptions) => Omit<_zayne_labs_toolkit_core7.StoreApi<_zayne_labs_toolkit_core7.URLInfoObject>, "setState" | "resetState"> & {
162
+ push: (url: string | _zayne_labs_toolkit_core7.PartialURLInfo, options?: {
163
+ state?: _zayne_labs_toolkit_core7.PartialURLInfo["state"];
164
+ }) => void;
165
+ replace: LocationStoreApi["push"];
166
+ triggerPopstateEvent: (nextLocationState?: LocationInfo["state"]) => void;
167
+ } & (<TSlice = _zayne_labs_toolkit_core7.URLInfoObject>(selector?: SelectorFn<LocationInfo, TSlice>) => UseLocationResult<TSlice>);
168
+ declare const useLocationState: <TSlice = LocationInfo>(selector?: SelectorFn<LocationInfo, TSlice>, options?: LocationStoreOptions) => UseLocationResult<TSlice>;
169
+
170
+ //#endregion
171
+ //#region src/hooks/useToggle.d.ts
172
+ type InitialState = boolean | (() => boolean);
173
+ declare const useToggle: (initialValue?: InitialState) => readonly [boolean, <TValue>(newValue?: TValue) => void];
174
+
175
+ //#endregion
176
+ //#region src/hooks/usePresence/types.d.ts
177
+ type UsePresenceOptions<TDuration extends number | undefined> = {
178
+ defaultValue?: boolean;
179
+ /**
180
+ * @description The duration of the animation or transition
181
+ */
182
+ duration?: TDuration;
183
+ /**
184
+ * @description A callback function that will be called when the animation or transition ends
185
+ */
186
+ onExitComplete?: () => void;
187
+ };
188
+ type UsePresenceResult<TElement, TDuration> = Prettify<(TDuration extends undefined ? {
189
+ elementRef: React.RefObject<TElement>;
190
+ } : unknown) & {
191
+ isPresent: boolean;
192
+ isVisible: boolean;
193
+ toggleVisibility: ReturnType<typeof useToggle>[1];
194
+ }>;
195
+ type TypeOption = {
196
+ /**
197
+ * @description The type of animation, whether animation or transition
198
+ * @default "transition"
199
+ */
200
+ type?: "animation" | "transition";
201
+ };
202
+ type UsePresence = <TElement extends HTMLElement, TDuration extends number | undefined = undefined>(options?: Prettify<TypeOption & UsePresenceOptions<TDuration>>) => UsePresenceResult<TElement, TDuration>;
203
+
204
+ //#endregion
205
+ //#region src/hooks/usePresence/usePresence.d.ts
206
+ /**
207
+ * usePresence hook provides a way to animate an element, before removing it from the DOM.
208
+ * @param defaultValue - The default value for the presence state. Defaults to `true`.
209
+ * @param options - The options for the usePresence hook.
210
+ * @returns A object containing the boolean that should be used to conditionally render the element (isPresent), another boolean used to toggle the animation classes, and a function to toggle the state.
211
+ */
212
+ declare const usePresence: UsePresence;
213
+
214
+ //#endregion
215
+ //#region src/hooks/useScrollObserver.d.ts
216
+ declare const useScrollObserver: <TElement extends HTMLElement>(options?: ScrollObserverOptions) => {
217
+ isScrolled: boolean;
218
+ observedElementRef: RefCallback<TElement>;
219
+ };
220
+
221
+ //#endregion
222
+ //#region src/hooks/useSearch.d.ts
223
+ declare const useSearch: <TData>(initialData: TData[], delay?: number) => {
224
+ data: TData[];
225
+ isLoading: boolean;
226
+ query: string;
227
+ setQuery: react19.Dispatch<react19.SetStateAction<string>>;
228
+ };
229
+
230
+ //#endregion
231
+ //#region src/hooks/useSearchParams.d.ts
232
+ type UseSearchParamsOptions = LocationStoreOptions & {
233
+ action?: "push" | "replace";
234
+ };
235
+ declare const useSearchParams: <TSearchParams extends URLSearchParamsInit>(options?: UseSearchParamsOptions) => readonly [URLSearchParams, {
236
+ (newQueryParams: TSearchParams | ((prev: URLSearchParams) => TSearchParams)): void;
237
+ triggerPopstateEvent: (nextLocationState?: _zayne_labs_toolkit_core17.LocationInfo["state"]) => void;
238
+ }];
239
+ declare const useSearchParamsObject: <TSearchParams extends Record<string, string>>(options?: UseSearchParamsOptions) => readonly [TSearchParams, {
240
+ (newQueryParams: TSearchParams | ((prev: TSearchParams) => TSearchParams)): void;
241
+ triggerPopstateEvent: (nextLocationState?: _zayne_labs_toolkit_core17.LocationInfo["state"]) => void;
242
+ }];
243
+
244
+ //#endregion
245
+ //#region src/hooks/useStorageState.d.ts
246
+ type UseStorageResult<TState, TSlice = TState> = [state: TSlice, actions: StorageStoreApi<TState>];
247
+ /**
248
+ * @description Creates a custom hook that returns a storage state and actions to modify it. You can use this if you need shared options.
249
+ * @note You must use this if you want to be able to prevent syncing state across tabs.
250
+ */
251
+ declare const createUseStorageState: <TState>(baseOptions: StorageOptions<TState>) => _zayne_labs_toolkit_core21.StoreApi<TState> & {
252
+ removeState: () => void;
253
+ } & (<TSlice = TState>(selector?: SelectorFn<TState, TSlice>) => UseStorageResult<TState, TSlice>);
254
+ type UseStorageStateOptions<TValue> = Omit<StorageOptions<TValue>, "initialValue" | "key">;
255
+ declare const useStorageState: <TValue, TSlice = TValue>(key: string, initialValue?: TValue, options?: UseStorageStateOptions<TValue> & {
256
+ select?: SelectorFn<TValue, TSlice>;
257
+ }) => UseStorageResult<TValue, TSlice>;
258
+
259
+ //#endregion
260
+ //#region src/hooks/useStore.d.ts
261
+ declare const useStore: <TState, TSlice>(store: StoreApi<TState>, selector?: SelectorFn<TState, TSlice>) => TSlice;
262
+
263
+ //#endregion
264
+ //#region src/hooks/useThrottle.d.ts
265
+ declare const useThrottleBySetTimeout: <TParams>(callbackFn: CallbackFn<TParams>, delay: number) => {
266
+ (...params: TParams[]): void;
267
+ cancelTimeout(): void;
268
+ };
269
+ declare const useThrottleByTimer: <TParams>(callbackFn: CallbackFn<TParams>, delay: number) => (...params: TParams[]) => void;
270
+ declare const useThrottleByFrame: <TParams>(callbackFn: CallbackFn<TParams>) => {
271
+ (...params: TParams[]): void;
272
+ cancelAnimation(): void;
273
+ };
274
+
275
+ //#endregion
276
+ export { ContextError as ContextError$1, CustomContextOptions, createCustomContext as createCustomContext$1, createUseLocationState as createUseLocationState$1, createUseStorageState as createUseStorageState$1, getErrorMessage as getErrorMessage$1, useAfterMountEffect as useAfterMountEffect$1, useAnimateElementRefs as useAnimateElementRefs$1, useAnimationInterval as useAnimationInterval$1, useAsyncEffect as useAsyncEffect$1, useCallbackRef as useCallbackRef$1, useClickOutside as useClickOutside$1, useConstant as useConstant$1, useCopyToClipboard as useCopyToClipboard$1, useDebouncedFn as useDebouncedFn$1, useDebouncedState as useDebouncedState$1, useDisclosure as useDisclosure$1, useEffectOnce as useEffectOnce$1, useIsServer as useIsServer$1, useLifeCycle as useLifeCycle$1, useLocationState as useLocationState$1, useMountEffect as useMountEffect$1, usePresence as usePresence$1, useScrollObserver as useScrollObserver$1, useSearch as useSearch$1, useSearchParams as useSearchParams$1, useSearchParamsObject as useSearchParamsObject$1, useStorageState as useStorageState$1, useStore as useStore$1, useThrottleByFrame as useThrottleByFrame$1, useThrottleBySetTimeout as useThrottleBySetTimeout$1, useThrottleByTimer as useThrottleByTimer$1, useToggle as useToggle$1, useUnmountEffect as useUnmountEffect$1 };
277
+ //# sourceMappingURL=index-DeDvIi3X.d.ts.map
@@ -1,6 +1,7 @@
1
- import { RefCallback } from 'react';
2
- import { AnyFunction, UnionDiscriminator, AnyObject, Prettify } from '@zayne-labs/toolkit-type-helpers';
1
+ import { AnyFunction, AnyObject, Prettify, UnionDiscriminator } from "@zayne-labs/toolkit-type-helpers";
2
+ import { RefCallback } from "react";
3
3
 
4
+ //#region src/utils/composeRefs.d.ts
4
5
  type PossibleRef<TRef extends HTMLElement> = React.Ref<TRef> | undefined;
5
6
  /**
6
7
  * @description Set a given ref to a given value.
@@ -14,10 +15,14 @@ declare const setRef: <TRef extends HTMLElement>(ref: PossibleRef<TRef>, node: T
14
15
  declare const composeRefs: <TRef extends HTMLElement>(...refs: Array<PossibleRef<TRef>>) => RefCallback<TRef>;
15
16
  declare const useComposeRefs: <TRef extends HTMLElement>(...refs: Array<PossibleRef<TRef>>) => () => RefCallback<TRef>;
16
17
 
18
+ //#endregion
19
+ //#region src/utils/composeEventHandlers.d.ts
17
20
  declare const composeTwoEventHandlers: (formerHandler: AnyFunction | undefined, latterHandler: AnyFunction | undefined) => (event: unknown) => unknown;
18
21
  declare const composeEventHandlers: (...eventHandlerArray: Array<AnyFunction | undefined>) => (event: unknown) => unknown;
19
22
 
20
- type UnionToIntersection<TUnion> = (TUnion extends unknown ? (param: TUnion) => void : "") extends (param: infer TParam) => void ? TParam : "";
23
+ //#endregion
24
+ //#region src/utils/mergeProps.d.ts
25
+ type UnionToIntersection<TUnion> = (TUnion extends unknown ? (param: TUnion) => void : "") extends ((param: infer TParam) => void) ? TParam : "";
21
26
  /**
22
27
  * Merges multiple sets of React props.
23
28
  *
@@ -34,15 +39,19 @@ type UnionToIntersection<TUnion> = (TUnion extends unknown ? (param: TUnion) =>
34
39
  */
35
40
  declare const mergeProps: <TProps extends Record<never, never>>(...propsObjectArray: Array<TProps | undefined>) => UnionToIntersection<TProps>;
36
41
 
42
+ //#endregion
43
+ //#region src/utils/mergeTwoProps.d.ts
37
44
  declare const mergeTwoProps: <TProps extends Record<never, never>>(formerProps: TProps | undefined, latterProps: TProps | undefined) => TProps;
38
45
 
46
+ //#endregion
47
+ //#region src/utils/types/common.d.ts
39
48
  type ForwardedRefType<TComponent extends HTMLElement | React.ElementType> = TComponent extends React.ElementType ? React.ForwardedRef<React.Ref<TComponent>> : React.ForwardedRef<TComponent>;
40
49
  type InferProps<TComponent extends HTMLElement | React.ElementType> = TComponent extends React.ElementType ? React.ComponentPropsWithRef<TComponent> : React.HTMLAttributes<TComponent>;
41
50
  type StateSetter<TSetter = unknown> = React.Dispatch<React.SetStateAction<TSetter>>;
42
51
  type CssWithCustomProperties<TExtra extends Record<string, string> = NonNullable<unknown>> = React.CSSProperties & Record<`--${string}`, string> & TExtra;
43
52
  type DefaultPossibleMessages = {
44
- children: "Hey, Sorry but the children prop is redundant since you're currently using the render prop";
45
- render: "Hey, Sorry but the render prop is redundant since you're currently using the children prop";
53
+ children: "Hey, Sorry but the children prop is redundant since you're currently using the render prop";
54
+ render: "Hey, Sorry but the render prop is redundant since you're currently using the children prop";
46
55
  };
47
56
  /**
48
57
  * @description Represents a set of props that can be used to render a component conditionally based on a discriminated union type.
@@ -51,16 +60,20 @@ type DefaultPossibleMessages = {
51
60
  * @template TErrorMessages An object of custom messages to display on the disallowed property.
52
61
  */
53
62
  type DiscriminatedRenderProps<TRenderPropType, TErrorMessages extends Record<"children" | "render", string> = DefaultPossibleMessages> = UnionDiscriminator<[{
54
- children: TRenderPropType;
63
+ children: TRenderPropType;
55
64
  }, {
56
- render: TRenderPropType;
65
+ render: TRenderPropType;
57
66
  }], TErrorMessages>;
58
67
 
68
+ //#endregion
69
+ //#region src/utils/types/polymorphism.d.ts
59
70
  type AsProp<TElement extends React.ElementType> = {
60
- as?: TElement;
71
+ as?: TElement;
61
72
  };
62
73
  type InferRemainingProps<TElement extends React.ElementType, TProps> = Omit<InferProps<TElement>, keyof TProps>;
63
74
  type MergedGivenPropsWithAs<TElement extends React.ElementType, TProps> = Prettify<Omit<AsProp<TElement>, keyof TProps> & TProps>;
64
75
  type PolymorphicProps<TElement extends React.ElementType, TProps extends AnyObject = NonNullable<unknown>> = MergedGivenPropsWithAs<TElement, TProps> & InferRemainingProps<TElement, TProps>;
65
76
 
66
- export { type AsProp, type CssWithCustomProperties, type DiscriminatedRenderProps, type ForwardedRefType, type InferProps, type PolymorphicProps, type StateSetter, composeEventHandlers, composeRefs, composeTwoEventHandlers, mergeProps, mergeTwoProps, setRef, useComposeRefs };
77
+ //#endregion
78
+ export { AsProp, CssWithCustomProperties, DiscriminatedRenderProps, ForwardedRefType, InferProps, PolymorphicProps, StateSetter, composeEventHandlers, composeRefs, composeTwoEventHandlers, mergeProps, mergeTwoProps, setRef, useComposeRefs };
79
+ //# sourceMappingURL=index.d.ts.map
@@ -1,123 +1,130 @@
1
- import { isFunction, isObject } from '@zayne-labs/toolkit-type-helpers';
2
- import { useCallback } from 'react';
1
+ import { isFunction, isObject } from "@zayne-labs/toolkit-type-helpers";
2
+ import { useCallback } from "react";
3
3
 
4
- // src/utils/composeRefs.ts
5
- var setRef = (ref, node) => {
6
- if (!ref) return;
7
- if (isFunction(ref)) {
8
- return ref(node);
9
- }
10
- ref.current = node;
4
+ //#region src/utils/composeRefs.ts
5
+ /**
6
+ * @description Set a given ref to a given value.
7
+ *
8
+ * This utility takes care of different types of refs: callback refs and RefObject(s)
9
+ */
10
+ const setRef = (ref, node) => {
11
+ if (!ref) return;
12
+ if (isFunction(ref)) return ref(node);
13
+ ref.current = node;
11
14
  };
12
- var composeRefs = (...refs) => {
13
- const mergedRefCallBack = (node) => {
14
- const cleanupFnArray = refs.map((ref) => setRef(ref, node));
15
- const cleanupFn = () => cleanupFnArray.forEach((cleanup) => cleanup?.());
16
- return cleanupFn;
17
- };
18
- return mergedRefCallBack;
15
+ /**
16
+ * @description A utility to combine refs. Accepts callback refs and RefObject(s)
17
+ */
18
+ const composeRefs = (...refs) => {
19
+ const mergedRefCallBack = (node) => {
20
+ const cleanupFnArray = refs.map((ref) => setRef(ref, node));
21
+ const cleanupFn = () => cleanupFnArray.forEach((cleanup) => cleanup?.());
22
+ return cleanupFn;
23
+ };
24
+ return mergedRefCallBack;
19
25
  };
20
- var useComposeRefs = (...refs) => {
21
- const mergedRef = useCallback(() => composeRefs(...refs), refs);
22
- return mergedRef;
26
+ const useComposeRefs = (...refs) => {
27
+ const mergedRef = useCallback(() => composeRefs(...refs), refs);
28
+ return mergedRef;
23
29
  };
24
- var isSyntheticEvent = (event) => {
25
- return isObject(event) && Object.hasOwn(event, "nativeEvent");
30
+
31
+ //#endregion
32
+ //#region src/utils/composeEventHandlers.ts
33
+ const isSyntheticEvent = (event) => {
34
+ return isObject(event) && Object.hasOwn(event, "nativeEvent");
26
35
  };
27
- var composeTwoEventHandlers = (formerHandler, latterHandler) => {
28
- const mergedEventHandler = (event) => {
29
- if (isSyntheticEvent(event)) {
30
- const result2 = latterHandler?.(event);
31
- if (!event.defaultPrevented) {
32
- formerHandler?.(event);
33
- }
34
- return result2;
35
- }
36
- const result = latterHandler?.(event);
37
- formerHandler?.(event);
38
- return result;
39
- };
40
- return mergedEventHandler;
36
+ const composeTwoEventHandlers = (formerHandler, latterHandler) => {
37
+ const mergedEventHandler = (event) => {
38
+ if (isSyntheticEvent(event)) {
39
+ const result$1 = latterHandler?.(event);
40
+ if (!event.defaultPrevented) formerHandler?.(event);
41
+ return result$1;
42
+ }
43
+ const result = latterHandler?.(event);
44
+ formerHandler?.(event);
45
+ return result;
46
+ };
47
+ return mergedEventHandler;
41
48
  };
42
- var composeEventHandlers = (...eventHandlerArray) => {
43
- const mergedEventHandler = (event) => {
44
- if (eventHandlerArray.length === 0) return;
45
- if (eventHandlerArray.length === 1) {
46
- return eventHandlerArray[0]?.(event);
47
- }
48
- let accumulatedHandlers;
49
- for (const eventHandler of eventHandlerArray) {
50
- if (!eventHandler) continue;
51
- accumulatedHandlers = composeTwoEventHandlers(accumulatedHandlers, eventHandler);
52
- }
53
- return accumulatedHandlers?.(event);
54
- };
55
- return mergedEventHandler;
49
+ const composeEventHandlers = (...eventHandlerArray) => {
50
+ const mergedEventHandler = (event) => {
51
+ if (eventHandlerArray.length === 0) return;
52
+ if (eventHandlerArray.length === 1) return eventHandlerArray[0]?.(event);
53
+ let accumulatedHandlers;
54
+ for (const eventHandler of eventHandlerArray) {
55
+ if (!eventHandler) continue;
56
+ accumulatedHandlers = composeTwoEventHandlers(accumulatedHandlers, eventHandler);
57
+ }
58
+ return accumulatedHandlers?.(event);
59
+ };
60
+ return mergedEventHandler;
56
61
  };
57
- var isEventHandler = (key, value) => {
58
- const thirdCharCode = key.codePointAt(2);
59
- if (!isFunction(value) || thirdCharCode === void 0) {
60
- return false;
61
- }
62
- const isHandler = key.startsWith("on") && thirdCharCode >= 65 && thirdCharCode <= 90;
63
- return isHandler;
62
+
63
+ //#endregion
64
+ //#region src/utils/mergeTwoProps.ts
65
+ const isEventHandler = (key, value) => {
66
+ const thirdCharCode = key.codePointAt(2);
67
+ if (!isFunction(value) || thirdCharCode === void 0) return false;
68
+ const isHandler = key.startsWith("on") && thirdCharCode >= 65 && thirdCharCode <= 90;
69
+ return isHandler;
64
70
  };
65
- var mergeTwoClassNames = (formerClassName, latterClassName) => {
66
- if (!latterClassName || !formerClassName) {
67
- return latterClassName || formerClassName;
68
- }
69
- return formerClassName + " " + latterClassName;
71
+ const mergeTwoClassNames = (formerClassName, latterClassName) => {
72
+ if (!latterClassName || !formerClassName) return latterClassName || formerClassName;
73
+ return formerClassName + " " + latterClassName;
70
74
  };
71
- var mergeTwoProps = (formerProps, latterProps) => {
72
- if (!latterProps || !formerProps) {
73
- return latterProps ?? formerProps ?? {};
74
- }
75
- const propsAccumulator = { ...formerProps };
76
- for (const latterPropName of Object.keys(latterProps)) {
77
- const formerPropValue = formerProps[latterPropName];
78
- const latterPropValue = latterProps[latterPropName];
79
- if (latterPropName === "className" || latterPropName === "class") {
80
- propsAccumulator[latterPropName] = mergeTwoClassNames(
81
- formerPropValue,
82
- latterPropValue
83
- );
84
- continue;
85
- }
86
- if (latterPropName === "style") {
87
- propsAccumulator[latterPropName] = {
88
- ...formerPropValue,
89
- ...latterPropValue
90
- };
91
- continue;
92
- }
93
- if (isEventHandler(latterPropName, latterPropValue)) {
94
- propsAccumulator[latterPropName] = composeTwoEventHandlers(
95
- formerPropValue,
96
- latterPropValue
97
- );
98
- continue;
99
- }
100
- propsAccumulator[latterPropName] = latterPropValue;
101
- }
102
- return propsAccumulator;
75
+ const mergeTwoProps = (formerProps, latterProps) => {
76
+ if (!latterProps || !formerProps) return latterProps ?? formerProps ?? {};
77
+ const propsAccumulator = { ...formerProps };
78
+ for (const latterPropName of Object.keys(latterProps)) {
79
+ const formerPropValue = formerProps[latterPropName];
80
+ const latterPropValue = latterProps[latterPropName];
81
+ if (latterPropName === "className" || latterPropName === "class") {
82
+ propsAccumulator[latterPropName] = mergeTwoClassNames(formerPropValue, latterPropValue);
83
+ continue;
84
+ }
85
+ if (latterPropName === "style") {
86
+ propsAccumulator[latterPropName] = {
87
+ ...formerPropValue,
88
+ ...latterPropValue
89
+ };
90
+ continue;
91
+ }
92
+ if (isEventHandler(latterPropName, latterPropValue)) {
93
+ propsAccumulator[latterPropName] = composeTwoEventHandlers(formerPropValue, latterPropValue);
94
+ continue;
95
+ }
96
+ propsAccumulator[latterPropName] = latterPropValue;
97
+ }
98
+ return propsAccumulator;
103
99
  };
104
100
 
105
- // src/utils/mergeProps.ts
106
- var mergeProps = (...propsObjectArray) => {
107
- if (propsObjectArray.length === 0) {
108
- return {};
109
- }
110
- if (propsObjectArray.length === 1) {
111
- return propsObjectArray[0];
112
- }
113
- let accumulatedProps = {};
114
- for (const propsObject of propsObjectArray) {
115
- if (!propsObject) continue;
116
- accumulatedProps = mergeTwoProps(accumulatedProps, propsObject);
117
- }
118
- return accumulatedProps;
101
+ //#endregion
102
+ //#region src/utils/mergeProps.ts
103
+ /**
104
+ * Merges multiple sets of React props.
105
+ *
106
+ * - It follows the Object.assign pattern where the rightmost object's fields overwrite
107
+ * the conflicting ones from others. This doesn't apply to event handlers, `className` and `style` props.
108
+ * - Event handlers are merged such that they are called in sequence (the rightmost one being called first),
109
+ * and allows the user to prevent the previous event handlers from being executed by calling the `preventDefault` method.
110
+ * - It also merges the `className` and `style` props, whereby the classes are concatenated
111
+ * and the rightmost styles overwrite the previous ones.
112
+ *
113
+ * @important **`ref` is not merged.**
114
+ * @param props props to merge.
115
+ * @returns the merged props.
116
+ */
117
+ const mergeProps = (...propsObjectArray) => {
118
+ if (propsObjectArray.length === 0) return {};
119
+ if (propsObjectArray.length === 1) return propsObjectArray[0];
120
+ let accumulatedProps = {};
121
+ for (const propsObject of propsObjectArray) {
122
+ if (!propsObject) continue;
123
+ accumulatedProps = mergeTwoProps(accumulatedProps, propsObject);
124
+ }
125
+ return accumulatedProps;
119
126
  };
120
127
 
128
+ //#endregion
121
129
  export { composeEventHandlers, composeRefs, composeTwoEventHandlers, mergeProps, mergeTwoProps, setRef, useComposeRefs };
122
- //# sourceMappingURL=index.js.map
123
130
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/utils/composeRefs.ts","../../../src/utils/composeEventHandlers.ts","../../../src/utils/mergeTwoProps.ts","../../../src/utils/mergeProps.ts"],"names":["result","isFunction"],"mappings":"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","file":"index.js","sourcesContent":["import { isFunction } from \"@zayne-labs/toolkit-type-helpers\";\nimport { type RefCallback, useCallback } from \"react\";\n\ntype PossibleRef<TRef extends HTMLElement> = React.Ref<TRef> | undefined;\n\n/**\n * @description Set a given ref to a given value.\n *\n * This utility takes care of different types of refs: callback refs and RefObject(s)\n */\nexport const setRef = <TRef extends HTMLElement>(\n\tref: PossibleRef<TRef>,\n\tnode: TRef | null\n): ReturnType<RefCallback<TRef>> => {\n\tif (!ref) return;\n\n\tif (isFunction(ref)) {\n\t\treturn ref(node);\n\t}\n\n\t// eslint-disable-next-line no-param-reassign -- Mutation is needed here\n\tref.current = node;\n};\n\n/**\n * @description A utility to combine refs. Accepts callback refs and RefObject(s)\n */\nexport const composeRefs = <TRef extends HTMLElement>(\n\t...refs: Array<PossibleRef<TRef>>\n): RefCallback<TRef> => {\n\tconst mergedRefCallBack: RefCallback<TRef> = (node) => {\n\t\tconst cleanupFnArray = refs.map((ref) => setRef(ref, node));\n\n\t\tconst cleanupFn = () => cleanupFnArray.forEach((cleanup) => cleanup?.());\n\n\t\treturn cleanupFn;\n\t};\n\n\treturn mergedRefCallBack;\n};\n\nexport const useComposeRefs = <TRef extends HTMLElement>(...refs: Array<PossibleRef<TRef>>) => {\n\t// eslint-disable-next-line react-hooks/exhaustive-deps -- Allow\n\tconst mergedRef = useCallback(() => composeRefs(...refs), refs);\n\n\treturn mergedRef;\n};\n","import { type AnyFunction, isObject } from \"@zayne-labs/toolkit-type-helpers\";\n\nconst isSyntheticEvent = (event: unknown): event is React.SyntheticEvent => {\n\treturn isObject(event) && Object.hasOwn(event, \"nativeEvent\");\n};\n\nexport const composeTwoEventHandlers = (\n\tformerHandler: AnyFunction | undefined,\n\tlatterHandler: AnyFunction | undefined\n) => {\n\tconst mergedEventHandler = (event: unknown) => {\n\t\tif (isSyntheticEvent(event)) {\n\t\t\tconst result = latterHandler?.(event) as unknown;\n\n\t\t\tif (!event.defaultPrevented) {\n\t\t\t\tformerHandler?.(event);\n\t\t\t}\n\n\t\t\treturn result;\n\t\t}\n\n\t\tconst result = latterHandler?.(event) as unknown;\n\t\tformerHandler?.(event);\n\t\treturn result;\n\t};\n\n\treturn mergedEventHandler;\n};\n\nexport const composeEventHandlers = (...eventHandlerArray: Array<AnyFunction | undefined>) => {\n\tconst mergedEventHandler = (event: unknown) => {\n\t\tif (eventHandlerArray.length === 0) return;\n\n\t\tif (eventHandlerArray.length === 1) {\n\t\t\treturn eventHandlerArray[0]?.(event) as unknown;\n\t\t}\n\n\t\tlet accumulatedHandlers: AnyFunction | undefined;\n\n\t\tfor (const eventHandler of eventHandlerArray) {\n\t\t\tif (!eventHandler) continue;\n\n\t\t\taccumulatedHandlers = composeTwoEventHandlers(accumulatedHandlers, eventHandler);\n\t\t}\n\n\t\treturn accumulatedHandlers?.(event) as unknown;\n\t};\n\n\treturn mergedEventHandler;\n};\n","import { type AnyFunction, isFunction } from \"@zayne-labs/toolkit-type-helpers\";\nimport { composeTwoEventHandlers } from \"./composeEventHandlers\";\n\n// == This approach is more efficient than using a regex.\nconst isEventHandler = (key: string, value: unknown): value is AnyFunction => {\n\tconst thirdCharCode = key.codePointAt(2);\n\n\tif (!isFunction(value) || thirdCharCode === undefined) {\n\t\treturn false;\n\t}\n\n\tconst isHandler = key.startsWith(\"on\") && thirdCharCode >= 65 /* A */ && thirdCharCode <= 90; /* Z */\n\n\treturn isHandler;\n};\n\nconst mergeTwoClassNames = (formerClassName: string | undefined, latterClassName: string | undefined) => {\n\tif (!latterClassName || !formerClassName) {\n\t\t// eslint-disable-next-line ts-eslint/prefer-nullish-coalescing -- Logical OR is fit for this case\n\t\treturn latterClassName || formerClassName;\n\t}\n\n\t// eslint-disable-next-line prefer-template -- String concatenation is more performant than template literals in this case\n\treturn formerClassName + \" \" + latterClassName;\n};\n\nexport const mergeTwoProps = <TProps extends Record<never, never>>(\n\tformerProps: TProps | undefined,\n\tlatterProps: TProps | undefined\n): TProps => {\n\t// == If no props are provided, return an empty object\n\tif (!latterProps || !formerProps) {\n\t\treturn latterProps ?? formerProps ?? ({} as TProps);\n\t}\n\n\tconst propsAccumulator = { ...formerProps } as Record<string, unknown>;\n\n\tfor (const latterPropName of Object.keys(latterProps)) {\n\t\tconst formerPropValue = (formerProps as Record<string, unknown>)[latterPropName];\n\t\tconst latterPropValue = (latterProps as Record<string, unknown>)[latterPropName];\n\n\t\t// == If the prop is `className` or `class`, we merge them\n\t\tif (latterPropName === \"className\" || latterPropName === \"class\") {\n\t\t\tpropsAccumulator[latterPropName] = mergeTwoClassNames(\n\t\t\t\tformerPropValue as string,\n\t\t\t\tlatterPropValue as string\n\t\t\t);\n\t\t\tcontinue;\n\t\t}\n\n\t\t// == If the prop is `style`, we merge them\n\t\tif (latterPropName === \"style\") {\n\t\t\tpropsAccumulator[latterPropName] = {\n\t\t\t\t...(formerPropValue as object),\n\t\t\t\t...(latterPropValue as object),\n\t\t\t};\n\t\t\tcontinue;\n\t\t}\n\n\t\t// == If the handler exists on both, we compose them\n\t\tif (isEventHandler(latterPropName, latterPropValue)) {\n\t\t\tpropsAccumulator[latterPropName] = composeTwoEventHandlers(\n\t\t\t\tformerPropValue as AnyFunction | undefined,\n\t\t\t\tlatterPropValue\n\t\t\t);\n\n\t\t\tcontinue;\n\t\t}\n\n\t\t// == latterProps override by default\n\t\tpropsAccumulator[latterPropName] = latterPropValue;\n\t}\n\n\treturn propsAccumulator as TProps;\n};\n","import { mergeTwoProps } from \"./mergeTwoProps\";\n\ntype UnionToIntersection<TUnion> = (TUnion extends unknown ? (param: TUnion) => void : \"\") extends (\n\tparam: infer TParam\n) => void\n\t? TParam\n\t: \"\";\n\n/**\n * Merges multiple sets of React props.\n *\n * - It follows the Object.assign pattern where the rightmost object's fields overwrite\n * the conflicting ones from others. This doesn't apply to event handlers, `className` and `style` props.\n * - Event handlers are merged such that they are called in sequence (the rightmost one being called first),\n * and allows the user to prevent the previous event handlers from being executed by calling the `preventDefault` method.\n * - It also merges the `className` and `style` props, whereby the classes are concatenated\n * and the rightmost styles overwrite the previous ones.\n *\n * @important **`ref` is not merged.**\n * @param props props to merge.\n * @returns the merged props.\n */\n\nconst mergeProps = <TProps extends Record<never, never>>(\n\t...propsObjectArray: Array<TProps | undefined>\n): UnionToIntersection<TProps> => {\n\tif (propsObjectArray.length === 0) {\n\t\treturn {} as never;\n\t}\n\n\tif (propsObjectArray.length === 1) {\n\t\treturn propsObjectArray[0] as never;\n\t}\n\n\tlet accumulatedProps: Record<string, unknown> = {};\n\n\tfor (const propsObject of propsObjectArray) {\n\t\tif (!propsObject) continue;\n\n\t\taccumulatedProps = mergeTwoProps(accumulatedProps, propsObject);\n\t}\n\n\treturn accumulatedProps as never;\n};\n\nexport { mergeProps };\n"]}
1
+ {"version":3,"file":"index.js","names":["ref: PossibleRef<TRef>","node: TRef | null","mergedRefCallBack: RefCallback<TRef>","event: unknown","formerHandler: AnyFunction | undefined","latterHandler: AnyFunction | undefined","result","accumulatedHandlers: AnyFunction | undefined","key: string","value: unknown","formerClassName: string | undefined","latterClassName: string | undefined","formerProps: TProps | undefined","latterProps: TProps | undefined","accumulatedProps: Record<string, unknown>"],"sources":["../../../src/utils/composeRefs.ts","../../../src/utils/composeEventHandlers.ts","../../../src/utils/mergeTwoProps.ts","../../../src/utils/mergeProps.ts"],"sourcesContent":["import { isFunction } from \"@zayne-labs/toolkit-type-helpers\";\nimport { type RefCallback, useCallback } from \"react\";\n\ntype PossibleRef<TRef extends HTMLElement> = React.Ref<TRef> | undefined;\n\n/**\n * @description Set a given ref to a given value.\n *\n * This utility takes care of different types of refs: callback refs and RefObject(s)\n */\nexport const setRef = <TRef extends HTMLElement>(\n\tref: PossibleRef<TRef>,\n\tnode: TRef | null\n): ReturnType<RefCallback<TRef>> => {\n\tif (!ref) return;\n\n\tif (isFunction(ref)) {\n\t\treturn ref(node);\n\t}\n\n\t// eslint-disable-next-line no-param-reassign -- Mutation is needed here\n\tref.current = node;\n};\n\n/**\n * @description A utility to combine refs. Accepts callback refs and RefObject(s)\n */\nexport const composeRefs = <TRef extends HTMLElement>(\n\t...refs: Array<PossibleRef<TRef>>\n): RefCallback<TRef> => {\n\tconst mergedRefCallBack: RefCallback<TRef> = (node) => {\n\t\tconst cleanupFnArray = refs.map((ref) => setRef(ref, node));\n\n\t\tconst cleanupFn = () => cleanupFnArray.forEach((cleanup) => cleanup?.());\n\n\t\treturn cleanupFn;\n\t};\n\n\treturn mergedRefCallBack;\n};\n\nexport const useComposeRefs = <TRef extends HTMLElement>(...refs: Array<PossibleRef<TRef>>) => {\n\t// eslint-disable-next-line react-hooks/exhaustive-deps -- Allow\n\tconst mergedRef = useCallback(() => composeRefs(...refs), refs);\n\n\treturn mergedRef;\n};\n","import { type AnyFunction, isObject } from \"@zayne-labs/toolkit-type-helpers\";\n\nconst isSyntheticEvent = (event: unknown): event is React.SyntheticEvent => {\n\treturn isObject(event) && Object.hasOwn(event, \"nativeEvent\");\n};\n\nexport const composeTwoEventHandlers = (\n\tformerHandler: AnyFunction | undefined,\n\tlatterHandler: AnyFunction | undefined\n) => {\n\tconst mergedEventHandler = (event: unknown) => {\n\t\tif (isSyntheticEvent(event)) {\n\t\t\tconst result = latterHandler?.(event) as unknown;\n\n\t\t\tif (!event.defaultPrevented) {\n\t\t\t\tformerHandler?.(event);\n\t\t\t}\n\n\t\t\treturn result;\n\t\t}\n\n\t\tconst result = latterHandler?.(event) as unknown;\n\t\tformerHandler?.(event);\n\t\treturn result;\n\t};\n\n\treturn mergedEventHandler;\n};\n\nexport const composeEventHandlers = (...eventHandlerArray: Array<AnyFunction | undefined>) => {\n\tconst mergedEventHandler = (event: unknown) => {\n\t\tif (eventHandlerArray.length === 0) return;\n\n\t\tif (eventHandlerArray.length === 1) {\n\t\t\treturn eventHandlerArray[0]?.(event) as unknown;\n\t\t}\n\n\t\tlet accumulatedHandlers: AnyFunction | undefined;\n\n\t\tfor (const eventHandler of eventHandlerArray) {\n\t\t\tif (!eventHandler) continue;\n\n\t\t\taccumulatedHandlers = composeTwoEventHandlers(accumulatedHandlers, eventHandler);\n\t\t}\n\n\t\treturn accumulatedHandlers?.(event) as unknown;\n\t};\n\n\treturn mergedEventHandler;\n};\n","import { type AnyFunction, isFunction } from \"@zayne-labs/toolkit-type-helpers\";\nimport { composeTwoEventHandlers } from \"./composeEventHandlers\";\n\n// == This approach is more efficient than using a regex.\nconst isEventHandler = (key: string, value: unknown): value is AnyFunction => {\n\tconst thirdCharCode = key.codePointAt(2);\n\n\tif (!isFunction(value) || thirdCharCode === undefined) {\n\t\treturn false;\n\t}\n\n\tconst isHandler = key.startsWith(\"on\") && thirdCharCode >= 65 /* A */ && thirdCharCode <= 90; /* Z */\n\n\treturn isHandler;\n};\n\nconst mergeTwoClassNames = (formerClassName: string | undefined, latterClassName: string | undefined) => {\n\tif (!latterClassName || !formerClassName) {\n\t\t// eslint-disable-next-line ts-eslint/prefer-nullish-coalescing -- Logical OR is fit for this case\n\t\treturn latterClassName || formerClassName;\n\t}\n\n\t// eslint-disable-next-line prefer-template -- String concatenation is more performant than template literals in this case\n\treturn formerClassName + \" \" + latterClassName;\n};\n\nexport const mergeTwoProps = <TProps extends Record<never, never>>(\n\tformerProps: TProps | undefined,\n\tlatterProps: TProps | undefined\n): TProps => {\n\t// == If no props are provided, return an empty object\n\tif (!latterProps || !formerProps) {\n\t\treturn latterProps ?? formerProps ?? ({} as TProps);\n\t}\n\n\tconst propsAccumulator = { ...formerProps } as Record<string, unknown>;\n\n\tfor (const latterPropName of Object.keys(latterProps)) {\n\t\tconst formerPropValue = (formerProps as Record<string, unknown>)[latterPropName];\n\t\tconst latterPropValue = (latterProps as Record<string, unknown>)[latterPropName];\n\n\t\t// == If the prop is `className` or `class`, we merge them\n\t\tif (latterPropName === \"className\" || latterPropName === \"class\") {\n\t\t\tpropsAccumulator[latterPropName] = mergeTwoClassNames(\n\t\t\t\tformerPropValue as string,\n\t\t\t\tlatterPropValue as string\n\t\t\t);\n\t\t\tcontinue;\n\t\t}\n\n\t\t// == If the prop is `style`, we merge them\n\t\tif (latterPropName === \"style\") {\n\t\t\tpropsAccumulator[latterPropName] = {\n\t\t\t\t...(formerPropValue as object),\n\t\t\t\t...(latterPropValue as object),\n\t\t\t};\n\t\t\tcontinue;\n\t\t}\n\n\t\t// == If the handler exists on both, we compose them\n\t\tif (isEventHandler(latterPropName, latterPropValue)) {\n\t\t\tpropsAccumulator[latterPropName] = composeTwoEventHandlers(\n\t\t\t\tformerPropValue as AnyFunction | undefined,\n\t\t\t\tlatterPropValue\n\t\t\t);\n\n\t\t\tcontinue;\n\t\t}\n\n\t\t// == latterProps override by default\n\t\tpropsAccumulator[latterPropName] = latterPropValue;\n\t}\n\n\treturn propsAccumulator as TProps;\n};\n","import { mergeTwoProps } from \"./mergeTwoProps\";\n\ntype UnionToIntersection<TUnion> = (TUnion extends unknown ? (param: TUnion) => void : \"\") extends (\n\tparam: infer TParam\n) => void\n\t? TParam\n\t: \"\";\n\n/**\n * Merges multiple sets of React props.\n *\n * - It follows the Object.assign pattern where the rightmost object's fields overwrite\n * the conflicting ones from others. This doesn't apply to event handlers, `className` and `style` props.\n * - Event handlers are merged such that they are called in sequence (the rightmost one being called first),\n * and allows the user to prevent the previous event handlers from being executed by calling the `preventDefault` method.\n * - It also merges the `className` and `style` props, whereby the classes are concatenated\n * and the rightmost styles overwrite the previous ones.\n *\n * @important **`ref` is not merged.**\n * @param props props to merge.\n * @returns the merged props.\n */\n\nconst mergeProps = <TProps extends Record<never, never>>(\n\t...propsObjectArray: Array<TProps | undefined>\n): UnionToIntersection<TProps> => {\n\tif (propsObjectArray.length === 0) {\n\t\treturn {} as never;\n\t}\n\n\tif (propsObjectArray.length === 1) {\n\t\treturn propsObjectArray[0] as never;\n\t}\n\n\tlet accumulatedProps: Record<string, unknown> = {};\n\n\tfor (const propsObject of propsObjectArray) {\n\t\tif (!propsObject) continue;\n\n\t\taccumulatedProps = mergeTwoProps(accumulatedProps, propsObject);\n\t}\n\n\treturn accumulatedProps as never;\n};\n\nexport { mergeProps };\n"],"mappings":"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"}