react-simplikit 0.0.35 → 0.0.37
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/README.md +1 -1
- package/dist/components/ImpressionArea/index.cjs +8 -10
- package/dist/components/ImpressionArea/index.d.cts +8 -6
- package/dist/hooks/useAsyncEffect/index.d.cts +1 -1
- package/dist/hooks/useCallbackOncePerRender/index.d.cts +2 -3
- package/dist/hooks/useControlledState/index.d.cts +1 -1
- package/dist/hooks/useCounter/index.cjs +1 -1
- package/dist/hooks/useCounter/index.d.cts +3 -5
- package/dist/hooks/useDebouncedCallback/index.cjs +144 -0
- package/dist/hooks/useDebouncedCallback/index.d.cts +32 -0
- package/dist/hooks/useDoubleClick/index.d.cts +4 -4
- package/dist/hooks/useGeolocation/index.cjs +153 -0
- package/dist/hooks/useGeolocation/index.d.cts +106 -0
- package/dist/hooks/useImpressionRef/index.d.cts +2 -2
- package/dist/hooks/useIntersectionObserver/index.d.cts +2 -2
- package/dist/hooks/useIsomorphicLayoutEffect/index.d.cts +3 -3
- package/dist/hooks/useLongPress/index.cjs +123 -0
- package/dist/hooks/useLongPress/index.d.cts +70 -0
- package/dist/hooks/useMap/index.cjs +77 -0
- package/dist/hooks/useMap/index.d.cts +46 -0
- package/dist/hooks/usePrevious/index.d.cts +2 -2
- package/dist/hooks/useRefEffect/index.d.cts +1 -1
- package/dist/hooks/useStorageState/index.d.cts +1 -1
- package/dist/hooks/useThrottle/index.d.cts +1 -1
- package/dist/hooks/useVisibilityEvent/index.d.cts +1 -1
- package/dist/index.cjs +444 -88
- package/dist/index.d.cts +9 -1
- package/esm/components/ImpressionArea/index.d.ts +8 -6
- package/esm/components/ImpressionArea/index.js +8 -10
- package/esm/hooks/useAsyncEffect/index.d.ts +1 -1
- package/esm/hooks/useCallbackOncePerRender/index.d.ts +2 -3
- package/esm/hooks/useControlledState/index.d.ts +1 -1
- package/esm/hooks/useCounter/index.d.ts +3 -5
- package/esm/hooks/useCounter/index.js +1 -1
- package/esm/hooks/useDebouncedCallback/index.d.ts +32 -0
- package/esm/hooks/useDebouncedCallback/index.js +117 -0
- package/esm/hooks/useDoubleClick/index.d.ts +4 -4
- package/esm/hooks/useGeolocation/index.d.ts +106 -0
- package/esm/hooks/useGeolocation/index.js +126 -0
- package/esm/hooks/useImpressionRef/index.d.ts +2 -2
- package/esm/hooks/useIntersectionObserver/index.d.ts +2 -2
- package/esm/hooks/useIsomorphicLayoutEffect/index.d.ts +3 -3
- package/esm/hooks/useLongPress/index.d.ts +70 -0
- package/esm/hooks/useLongPress/index.js +96 -0
- package/esm/hooks/useMap/index.d.ts +46 -0
- package/esm/hooks/useMap/index.js +50 -0
- package/esm/hooks/usePrevious/index.d.ts +2 -2
- package/esm/hooks/useRefEffect/index.d.ts +1 -1
- package/esm/hooks/useStorageState/index.d.ts +1 -1
- package/esm/hooks/useThrottle/index.d.ts +1 -1
- package/esm/hooks/useVisibilityEvent/index.d.ts +1 -1
- package/esm/index.d.ts +9 -1
- package/esm/index.js +412 -64
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|

|
|
2
2
|
|
|
3
|
-
# react-simplikit · [](https://github.com/toss/slash/blob/main/LICENSE) [](https://codecov.io/gh/toss/react-simplikit)
|
|
3
|
+
# react-simplikit · [](https://github.com/toss/slash/blob/main/LICENSE) [](https://codecov.io/gh/toss/react-simplikit) [](https://discord.gg/vGXbVjP2nY)
|
|
4
4
|
|
|
5
5
|
English | [Korean](./README-ko_kr.md)
|
|
6
6
|
|
|
@@ -24,6 +24,9 @@ __export(ImpressionArea_exports, {
|
|
|
24
24
|
});
|
|
25
25
|
module.exports = __toCommonJS(ImpressionArea_exports);
|
|
26
26
|
|
|
27
|
+
// src/components/ImpressionArea/ImpressionArea.tsx
|
|
28
|
+
var import_react7 = require("react");
|
|
29
|
+
|
|
27
30
|
// src/hooks/useImpressionRef/useImpressionRef.ts
|
|
28
31
|
var import_react6 = require("react");
|
|
29
32
|
|
|
@@ -267,16 +270,8 @@ function mergeRefs(...refs) {
|
|
|
267
270
|
|
|
268
271
|
// src/components/ImpressionArea/ImpressionArea.tsx
|
|
269
272
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
rootMargin,
|
|
273
|
-
areaThreshold,
|
|
274
|
-
timeThreshold,
|
|
275
|
-
onImpressionStart,
|
|
276
|
-
onImpressionEnd,
|
|
277
|
-
ref,
|
|
278
|
-
...props
|
|
279
|
-
}) {
|
|
273
|
+
var ImpressionArea = (0, import_react7.forwardRef)(ImpressionAreaImpl);
|
|
274
|
+
function ImpressionAreaImpl({ as, rootMargin, areaThreshold, timeThreshold, onImpressionStart, onImpressionEnd, ...props }, ref) {
|
|
280
275
|
const Component = as ?? "div";
|
|
281
276
|
const impressionRef = useImpressionRef({
|
|
282
277
|
onImpressionStart,
|
|
@@ -287,6 +282,9 @@ function ImpressionArea({
|
|
|
287
282
|
});
|
|
288
283
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Component, { ref: mergeRefs(ref, impressionRef), ...props });
|
|
289
284
|
}
|
|
285
|
+
Object.assign(ImpressionArea, {
|
|
286
|
+
displayName: "ImpressionArea"
|
|
287
|
+
});
|
|
290
288
|
// Annotate the CommonJS export names for ESM import in node:
|
|
291
289
|
0 && (module.exports = {
|
|
292
290
|
ImpressionArea
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { ElementType, Ref, ReactNode } from 'react';
|
|
1
|
+
import { ElementType, ReactNode, Ref } from 'react';
|
|
3
2
|
import { UseImpressionRefOptions } from '../../hooks/useImpressionRef/index.cjs';
|
|
4
3
|
|
|
4
|
+
type Element<T extends ElementType, InstrinsicElements = T extends keyof React.JSX.IntrinsicElements ? React.JSX.IntrinsicElements[T] : HTMLElement> = InstrinsicElements extends React.ClassAttributes<infer E extends HTMLElement> ? E : HTMLElement;
|
|
5
5
|
type Props<Tag extends ElementType> = React.ComponentPropsWithoutRef<Tag> & UseImpressionRefOptions & {
|
|
6
6
|
as?: Tag;
|
|
7
|
-
ref?: Ref<HTMLElement>;
|
|
8
7
|
children?: ReactNode;
|
|
9
8
|
className?: string;
|
|
10
9
|
};
|
|
@@ -14,13 +13,14 @@ type Props<Tag extends ElementType> = React.ComponentPropsWithoutRef<Tag> & UseI
|
|
|
14
13
|
* and executes callbacks when the element enters or exits the viewport. This component uses the `useImpressionRef`
|
|
15
14
|
* hook to track the element's visibility.
|
|
16
15
|
*
|
|
17
|
-
* @
|
|
16
|
+
* @template {ElementType} T - The HTML tag to render. Defaults to `div`.
|
|
17
|
+
* @param {T} [as='div'] - The HTML tag to render. Defaults to `div`.
|
|
18
18
|
* @param {string} [rootMargin] - Margin to adjust the detection area.
|
|
19
19
|
* @param {number} [areaThreshold] - Minimum ratio of the element that must be visible (0 to 1).
|
|
20
20
|
* @param {number} [timeThreshold] - Minimum time the element must be visible (in milliseconds).
|
|
21
21
|
* @param {() => void} [onImpressionStart] - Callback function executed when the element enters the view.
|
|
22
22
|
* @param {() => void} [onImpressionEnd] - Callback function executed when the element exits the view.
|
|
23
|
-
* @param {Ref<
|
|
23
|
+
* @param {Ref<Element<T>>} [ref] - Reference to the element.
|
|
24
24
|
* @param {React.ReactNode} [children] - Child elements to be rendered inside the component.
|
|
25
25
|
* @param {string} [className] - Additional class names for styling.
|
|
26
26
|
*
|
|
@@ -40,6 +40,8 @@ type Props<Tag extends ElementType> = React.ComponentPropsWithoutRef<Tag> & UseI
|
|
|
40
40
|
* );
|
|
41
41
|
* }
|
|
42
42
|
*/
|
|
43
|
-
declare
|
|
43
|
+
declare const ImpressionArea: <T extends ElementType = "div">(props: Props<T> & {
|
|
44
|
+
ref?: Ref<Element<T>>;
|
|
45
|
+
}) => React.ReactNode;
|
|
44
46
|
|
|
45
47
|
export { ImpressionArea };
|
|
@@ -2,7 +2,7 @@ import { DependencyList } from 'react';
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* @description
|
|
5
|
-
* `useAsyncEffect` is a
|
|
5
|
+
* `useAsyncEffect` is a React hook for handling asynchronous side effects in React components.
|
|
6
6
|
* It follows the same cleanup pattern as `useEffect` while ensuring async operations are handled safely.
|
|
7
7
|
*
|
|
8
8
|
* @param {() => Promise<void | (() => void)>} [effect] - An asynchronous function executed in the `useEffect` pattern.
|
|
@@ -2,9 +2,8 @@ import { DependencyList } from 'react';
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* @description
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* be repeated, even if the component re-renders.
|
|
5
|
+
* `useCallbackOncePerRender` is a React hook that ensures a callback function is executed only once, regardless of how many times it's called.
|
|
6
|
+
* This is useful for one-time operations that should not be repeated, even if the component re-renders.
|
|
8
7
|
*
|
|
9
8
|
* @param {() => void} callback - The callback function to be executed once.
|
|
10
9
|
* @param {DependencyList} deps - Dependencies array that will trigger a new one-time execution when changed.
|
|
@@ -13,7 +13,7 @@ type UseControlledStateProps<T> = ControlledState<T> & {
|
|
|
13
13
|
};
|
|
14
14
|
/**
|
|
15
15
|
* @description
|
|
16
|
-
* `useControlledState` is a hook that allows you to control both controlled and uncontrolled states.
|
|
16
|
+
* `useControlledState` is a React hook that allows you to control both controlled and uncontrolled states.
|
|
17
17
|
* If you pass the state to `value`, it will be a controlled state, and if you pass the state to `defaultValue`, it will be an uncontrolled state.
|
|
18
18
|
* If both `value` and `defaultValue` are passed, `value` will take precedence.
|
|
19
19
|
*
|
|
@@ -26,7 +26,7 @@ module.exports = __toCommonJS(useCounter_exports);
|
|
|
26
26
|
|
|
27
27
|
// src/hooks/useCounter/useCounter.ts
|
|
28
28
|
var import_react = require("react");
|
|
29
|
-
function useCounter(
|
|
29
|
+
function useCounter(initialValue = 0, { min, max, step = 1 } = {}) {
|
|
30
30
|
const validateValue = (value) => {
|
|
31
31
|
let validatedValue = value;
|
|
32
32
|
if (min !== void 0 && validatedValue < min) {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
type UseCounterOptions = {
|
|
2
|
-
initialValue?: number;
|
|
3
2
|
min?: number;
|
|
4
3
|
max?: number;
|
|
5
4
|
step?: number;
|
|
@@ -16,8 +15,8 @@ type UseCounterReturn = {
|
|
|
16
15
|
* `useCounter` is a React hook that manages a numeric counter state with increment, decrement, and reset capabilities.
|
|
17
16
|
* Optionally, you can provide minimum and maximum values to constrain the counter's range.
|
|
18
17
|
*
|
|
18
|
+
* @param {number} [initialValue=0] - Initial value for the counter. Defaults to 0.
|
|
19
19
|
* @param {UseCounterOptions} options - The options for the counter.
|
|
20
|
-
* @param {number} [options.initialValue=0] - Initial value for the counter. Defaults to 0.
|
|
21
20
|
* @param {number} [options.min] - Minimum value the counter can reach. If not provided, there is no lower limit.
|
|
22
21
|
* @param {number} [options.max] - Maximum value the counter can reach. If not provided, there is no upper limit.
|
|
23
22
|
* @param {number} [options.step=1] - Value to increment or decrement by. Defaults to 1.
|
|
@@ -33,8 +32,7 @@ type UseCounterReturn = {
|
|
|
33
32
|
* import { useCounter } from 'react-simplikit';
|
|
34
33
|
*
|
|
35
34
|
* function ShoppingCart() {
|
|
36
|
-
* const { count, increment, decrement, reset } = useCounter({
|
|
37
|
-
* initialValue: 1,
|
|
35
|
+
* const { count, increment, decrement, reset } = useCounter(1, {
|
|
38
36
|
* min: 1,
|
|
39
37
|
* max: 10,
|
|
40
38
|
* });
|
|
@@ -49,6 +47,6 @@ type UseCounterReturn = {
|
|
|
49
47
|
* );
|
|
50
48
|
* }
|
|
51
49
|
*/
|
|
52
|
-
declare function useCounter(
|
|
50
|
+
declare function useCounter(initialValue?: number, { min, max, step }?: UseCounterOptions): UseCounterReturn;
|
|
53
51
|
|
|
54
52
|
export { useCounter };
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/hooks/useDebouncedCallback/index.ts
|
|
21
|
+
var useDebouncedCallback_exports = {};
|
|
22
|
+
__export(useDebouncedCallback_exports, {
|
|
23
|
+
useDebouncedCallback: () => useDebouncedCallback
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(useDebouncedCallback_exports);
|
|
26
|
+
|
|
27
|
+
// src/hooks/useDebouncedCallback/useDebouncedCallback.ts
|
|
28
|
+
var import_react2 = require("react");
|
|
29
|
+
|
|
30
|
+
// src/hooks/useDebounce/debounce.ts
|
|
31
|
+
function debounce(func, debounceMs, { edges = ["leading", "trailing"] } = {}) {
|
|
32
|
+
let pendingThis = void 0;
|
|
33
|
+
let pendingArgs = null;
|
|
34
|
+
const leading = edges != null && edges.includes("leading");
|
|
35
|
+
const trailing = edges == null || edges.includes("trailing");
|
|
36
|
+
const invoke = () => {
|
|
37
|
+
if (pendingArgs !== null) {
|
|
38
|
+
func.apply(pendingThis, pendingArgs);
|
|
39
|
+
pendingThis = void 0;
|
|
40
|
+
pendingArgs = null;
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
const onTimerEnd = () => {
|
|
44
|
+
if (trailing) {
|
|
45
|
+
invoke();
|
|
46
|
+
}
|
|
47
|
+
cancel();
|
|
48
|
+
};
|
|
49
|
+
let timeoutId = null;
|
|
50
|
+
const schedule = () => {
|
|
51
|
+
if (timeoutId != null) {
|
|
52
|
+
clearTimeout(timeoutId);
|
|
53
|
+
}
|
|
54
|
+
timeoutId = setTimeout(() => {
|
|
55
|
+
timeoutId = null;
|
|
56
|
+
onTimerEnd();
|
|
57
|
+
}, debounceMs);
|
|
58
|
+
};
|
|
59
|
+
const cancelTimer = () => {
|
|
60
|
+
if (timeoutId !== null) {
|
|
61
|
+
clearTimeout(timeoutId);
|
|
62
|
+
timeoutId = null;
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
const cancel = () => {
|
|
66
|
+
cancelTimer();
|
|
67
|
+
pendingThis = void 0;
|
|
68
|
+
pendingArgs = null;
|
|
69
|
+
};
|
|
70
|
+
const debounced = function(...args) {
|
|
71
|
+
pendingThis = this;
|
|
72
|
+
pendingArgs = args;
|
|
73
|
+
const isFirstCall = timeoutId == null;
|
|
74
|
+
schedule();
|
|
75
|
+
if (leading && isFirstCall) {
|
|
76
|
+
invoke();
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
debounced.cancel = cancel;
|
|
80
|
+
return debounced;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// src/hooks/usePreservedCallback/usePreservedCallback.ts
|
|
84
|
+
var import_react = require("react");
|
|
85
|
+
function usePreservedCallback(callback) {
|
|
86
|
+
const callbackRef = (0, import_react.useRef)(callback);
|
|
87
|
+
(0, import_react.useEffect)(() => {
|
|
88
|
+
callbackRef.current = callback;
|
|
89
|
+
}, [callback]);
|
|
90
|
+
return (0, import_react.useCallback)((...args) => {
|
|
91
|
+
return callbackRef.current(...args);
|
|
92
|
+
}, []);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// src/hooks/useDebouncedCallback/useDebouncedCallback.ts
|
|
96
|
+
function useDebouncedCallback({
|
|
97
|
+
onChange,
|
|
98
|
+
timeThreshold,
|
|
99
|
+
leading = false,
|
|
100
|
+
trailing = true
|
|
101
|
+
}) {
|
|
102
|
+
const handleChange = usePreservedCallback(onChange);
|
|
103
|
+
const ref = (0, import_react2.useRef)({ value: false, clearPreviousDebounce: () => {
|
|
104
|
+
} });
|
|
105
|
+
(0, import_react2.useEffect)(() => {
|
|
106
|
+
const current = ref.current;
|
|
107
|
+
return () => {
|
|
108
|
+
current.clearPreviousDebounce();
|
|
109
|
+
};
|
|
110
|
+
}, []);
|
|
111
|
+
const edges = (0, import_react2.useMemo)(() => {
|
|
112
|
+
const _edges = [];
|
|
113
|
+
if (leading) {
|
|
114
|
+
_edges.push("leading");
|
|
115
|
+
}
|
|
116
|
+
if (trailing) {
|
|
117
|
+
_edges.push("trailing");
|
|
118
|
+
}
|
|
119
|
+
return _edges;
|
|
120
|
+
}, [leading, trailing]);
|
|
121
|
+
return (0, import_react2.useCallback)(
|
|
122
|
+
(nextValue) => {
|
|
123
|
+
if (nextValue === ref.current.value) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
const debounced = debounce(
|
|
127
|
+
() => {
|
|
128
|
+
handleChange(nextValue);
|
|
129
|
+
ref.current.value = nextValue;
|
|
130
|
+
},
|
|
131
|
+
timeThreshold,
|
|
132
|
+
{ edges }
|
|
133
|
+
);
|
|
134
|
+
ref.current.clearPreviousDebounce();
|
|
135
|
+
debounced();
|
|
136
|
+
ref.current.clearPreviousDebounce = debounced.cancel;
|
|
137
|
+
},
|
|
138
|
+
[handleChange, timeThreshold, edges]
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
142
|
+
0 && (module.exports = {
|
|
143
|
+
useDebouncedCallback
|
|
144
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
type DebounceOptions = {
|
|
2
|
+
leading?: boolean;
|
|
3
|
+
trailing?: boolean;
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* @description
|
|
7
|
+
* `useDebouncedCallback` is a React hook that returns a debounced version of the provided callback function.
|
|
8
|
+
* It helps optimize event handling by delaying function execution and grouping multiple calls into one.
|
|
9
|
+
*
|
|
10
|
+
* Note that if both 'leading' and 'trailing' are set, the function will be called at both the start and end of the delay period. However, it must be called at least twice within debounceMs interval for this to happen, since one debounced function call cannot trigger the function twice.
|
|
11
|
+
*
|
|
12
|
+
* @param {Object} options - The options object.
|
|
13
|
+
* @param {Function} options.onChange - The callback function to debounce.
|
|
14
|
+
* @param {number} options.timeThreshold - The number of milliseconds to delay the function execution.
|
|
15
|
+
* @param {boolean} [options.leading=false] - If `true`, the function is called at the start of the sequence.
|
|
16
|
+
* @param {boolean} [options.trailing=true] - If `true`, the function is called at the end of the sequence.
|
|
17
|
+
*
|
|
18
|
+
* @returns {Function} A debounced function that delays invoking the callback.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* function SearchInput() {
|
|
22
|
+
* const [query, setQuery] = useState('');
|
|
23
|
+
* const debouncedSetQuery = useDebouncedCallback({ onChange: setQuery, timeThreshold: 100 });
|
|
24
|
+
* return <input type="text" onChange={(e) => debouncedSetQuery(e.target.value)} />;
|
|
25
|
+
* }
|
|
26
|
+
*/
|
|
27
|
+
declare function useDebouncedCallback({ onChange, timeThreshold, leading, trailing, }: DebounceOptions & {
|
|
28
|
+
onChange: (newValue: boolean) => void;
|
|
29
|
+
timeThreshold: number;
|
|
30
|
+
}): (nextValue: boolean) => void;
|
|
31
|
+
|
|
32
|
+
export { useDebouncedCallback };
|
|
@@ -11,10 +11,10 @@ type UseDoubleClickProps<E extends HTMLElement> = {
|
|
|
11
11
|
* It delays the single click callback execution for a specified time, and cancels it if a second click (i.e. a double click) occurs within that time.
|
|
12
12
|
*
|
|
13
13
|
* @template {HTMLElement} E - The specific type of HTMLElement to be used with this hook (e.g., HTMLButtonElement, HTMLDivElement).
|
|
14
|
-
* @param {Object}
|
|
15
|
-
* @param {number} [
|
|
16
|
-
* @param {(event: MouseEvent<E>) => void} [
|
|
17
|
-
* @param {(event: MouseEvent<E>) => void}
|
|
14
|
+
* @param {Object} props - Configuration options for click handling.
|
|
15
|
+
* @param {number} [props.delay=250] - The number of milliseconds to wait before triggering the single click callback. Defaults to 250ms.
|
|
16
|
+
* @param {(event: MouseEvent<E>) => void} [props.click] - The callback function to be executed on a single click.
|
|
17
|
+
* @param {(event: MouseEvent<E>) => void} props.doubleClick - The callback function to be executed on a double click. Required.
|
|
18
18
|
*
|
|
19
19
|
* @returns {(event: MouseEvent<E>) => void} A click handler function to attach to an element's `onClick` event.
|
|
20
20
|
*
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/hooks/useGeolocation/index.ts
|
|
21
|
+
var useGeolocation_exports = {};
|
|
22
|
+
__export(useGeolocation_exports, {
|
|
23
|
+
useGeolocation: () => useGeolocation
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(useGeolocation_exports);
|
|
26
|
+
|
|
27
|
+
// src/hooks/useGeolocation/useGeolocation.ts
|
|
28
|
+
var import_react = require("react");
|
|
29
|
+
var CustomGeoLocationError = class extends Error {
|
|
30
|
+
code;
|
|
31
|
+
constructor({ code, message }) {
|
|
32
|
+
super(message);
|
|
33
|
+
this.name = "CustomGeoLocationError";
|
|
34
|
+
this.code = code;
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
var GeolocationMountBehavior = {
|
|
38
|
+
GET: "get",
|
|
39
|
+
WATCH: "watch"
|
|
40
|
+
};
|
|
41
|
+
function useGeolocation(options) {
|
|
42
|
+
const [state, setState] = (0, import_react.useState)({
|
|
43
|
+
loading: !!options?.mountBehavior,
|
|
44
|
+
error: null,
|
|
45
|
+
data: null
|
|
46
|
+
});
|
|
47
|
+
const [isTracking, setIsTracking] = (0, import_react.useState)(false);
|
|
48
|
+
const watchIdRef = (0, import_react.useRef)(null);
|
|
49
|
+
const checkGeolocationSupport = (0, import_react.useCallback)(() => {
|
|
50
|
+
if (typeof window === "undefined" || navigator.geolocation === void 0) {
|
|
51
|
+
setState((prev) => ({
|
|
52
|
+
...prev,
|
|
53
|
+
loading: false,
|
|
54
|
+
error: new CustomGeoLocationError({
|
|
55
|
+
code: 0,
|
|
56
|
+
message: "Geolocation is not supported by this environment."
|
|
57
|
+
})
|
|
58
|
+
}));
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
return true;
|
|
62
|
+
}, []);
|
|
63
|
+
const handleSuccess = (0, import_react.useCallback)((position) => {
|
|
64
|
+
const { coords } = position;
|
|
65
|
+
setState((prev) => ({
|
|
66
|
+
...prev,
|
|
67
|
+
loading: false,
|
|
68
|
+
error: null,
|
|
69
|
+
data: {
|
|
70
|
+
latitude: coords.latitude,
|
|
71
|
+
longitude: coords.longitude,
|
|
72
|
+
accuracy: coords.accuracy,
|
|
73
|
+
altitude: coords.altitude,
|
|
74
|
+
altitudeAccuracy: coords.altitudeAccuracy,
|
|
75
|
+
heading: coords.heading,
|
|
76
|
+
speed: coords.speed,
|
|
77
|
+
timestamp: position.timestamp
|
|
78
|
+
}
|
|
79
|
+
}));
|
|
80
|
+
}, []);
|
|
81
|
+
const handleError = (0, import_react.useCallback)((error) => {
|
|
82
|
+
const { code, message } = error;
|
|
83
|
+
setState((prev) => ({
|
|
84
|
+
...prev,
|
|
85
|
+
loading: false,
|
|
86
|
+
error: new CustomGeoLocationError({ code, message })
|
|
87
|
+
}));
|
|
88
|
+
}, []);
|
|
89
|
+
const getGeolocationOptions = (0, import_react.useCallback)(
|
|
90
|
+
() => ({
|
|
91
|
+
enableHighAccuracy: options?.enableHighAccuracy,
|
|
92
|
+
maximumAge: options?.maximumAge,
|
|
93
|
+
timeout: options?.timeout
|
|
94
|
+
}),
|
|
95
|
+
[options?.enableHighAccuracy, options?.maximumAge, options?.timeout]
|
|
96
|
+
);
|
|
97
|
+
const getCurrentPosition = (0, import_react.useCallback)(() => {
|
|
98
|
+
if (!checkGeolocationSupport()) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
setState((prev) => ({ ...prev, loading: true }));
|
|
102
|
+
navigator.geolocation.getCurrentPosition(handleSuccess, handleError, getGeolocationOptions());
|
|
103
|
+
}, [handleSuccess, handleError, getGeolocationOptions, checkGeolocationSupport]);
|
|
104
|
+
const startTracking = (0, import_react.useCallback)(() => {
|
|
105
|
+
if (!checkGeolocationSupport()) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
if (watchIdRef.current !== null) {
|
|
109
|
+
navigator.geolocation.clearWatch(watchIdRef.current);
|
|
110
|
+
}
|
|
111
|
+
setState((prev) => ({ ...prev, loading: true }));
|
|
112
|
+
watchIdRef.current = navigator.geolocation.watchPosition(
|
|
113
|
+
(position) => {
|
|
114
|
+
setIsTracking(true);
|
|
115
|
+
handleSuccess(position);
|
|
116
|
+
},
|
|
117
|
+
handleError,
|
|
118
|
+
getGeolocationOptions()
|
|
119
|
+
);
|
|
120
|
+
}, [handleSuccess, handleError, getGeolocationOptions, checkGeolocationSupport]);
|
|
121
|
+
const stopTracking = (0, import_react.useCallback)(() => {
|
|
122
|
+
if (watchIdRef.current === null) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
navigator.geolocation.clearWatch(watchIdRef.current);
|
|
126
|
+
watchIdRef.current = null;
|
|
127
|
+
setIsTracking(false);
|
|
128
|
+
}, []);
|
|
129
|
+
(0, import_react.useEffect)(() => {
|
|
130
|
+
if (options?.mountBehavior === GeolocationMountBehavior.WATCH) {
|
|
131
|
+
startTracking();
|
|
132
|
+
} else if (options?.mountBehavior === GeolocationMountBehavior.GET) {
|
|
133
|
+
getCurrentPosition();
|
|
134
|
+
}
|
|
135
|
+
return () => {
|
|
136
|
+
if (watchIdRef.current !== null) {
|
|
137
|
+
navigator.geolocation.clearWatch(watchIdRef.current);
|
|
138
|
+
watchIdRef.current = null;
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
}, [options?.mountBehavior, getCurrentPosition, startTracking]);
|
|
142
|
+
return {
|
|
143
|
+
...state,
|
|
144
|
+
getCurrentPosition,
|
|
145
|
+
startTracking,
|
|
146
|
+
stopTracking,
|
|
147
|
+
isTracking
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
151
|
+
0 && (module.exports = {
|
|
152
|
+
useGeolocation
|
|
153
|
+
});
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
declare class CustomGeoLocationError extends Error {
|
|
2
|
+
code: number;
|
|
3
|
+
constructor({ code, message }: {
|
|
4
|
+
message: string;
|
|
5
|
+
code: number;
|
|
6
|
+
});
|
|
7
|
+
}
|
|
8
|
+
type GeolocationData = {
|
|
9
|
+
latitude: number;
|
|
10
|
+
longitude: number;
|
|
11
|
+
accuracy: number;
|
|
12
|
+
altitude: number | null;
|
|
13
|
+
altitudeAccuracy: number | null;
|
|
14
|
+
heading: number | null;
|
|
15
|
+
speed: number | null;
|
|
16
|
+
timestamp: number;
|
|
17
|
+
};
|
|
18
|
+
declare const GeolocationMountBehavior: {
|
|
19
|
+
readonly GET: "get";
|
|
20
|
+
readonly WATCH: "watch";
|
|
21
|
+
};
|
|
22
|
+
type GeolocationMountBehaviorType = (typeof GeolocationMountBehavior)[keyof typeof GeolocationMountBehavior];
|
|
23
|
+
type GeolocationOptions = {
|
|
24
|
+
mountBehavior?: GeolocationMountBehaviorType;
|
|
25
|
+
} & PositionOptions;
|
|
26
|
+
/**
|
|
27
|
+
* @description
|
|
28
|
+
* `useGeolocation` is a React hook that retrieves and tracks the user's geographical location.
|
|
29
|
+
* It uses the browser's `Geolocation API` to support both one-time position retrieval and continuous location tracking.
|
|
30
|
+
*
|
|
31
|
+
* @param {GeolocationOptions} [options] - Geolocation options configuration
|
|
32
|
+
* @param {GeolocationMountBehaviorType} [options.mountBehavior] - How the hook behaves on mount:
|
|
33
|
+
* -- If not provided, no automatic location fetching occurs
|
|
34
|
+
* -- `get`: automatically fetches location once when component mounts
|
|
35
|
+
* -- `watch`: automatically starts tracking location changes when component mounts
|
|
36
|
+
* @param {boolean} [options.enableHighAccuracy=false] - If true, provides more accurate position information (increases battery consumption)
|
|
37
|
+
* @param {number} [options.maximumAge=0] - Maximum age in milliseconds of a cached position that is acceptable to return
|
|
38
|
+
* @param {number} [options.timeout=Infinity] - Maximum time (in milliseconds) allowed for the location request
|
|
39
|
+
*
|
|
40
|
+
* @returns {Object} Object containing location data and related functions
|
|
41
|
+
* - loading `boolean` - Whether location data is currently being fetched;
|
|
42
|
+
* - error `CustomGeoLocationError|null` - Error object if an error occurred, or null
|
|
43
|
+
* The hook uses standard Geolocation API error codes (`1-3`) and adds a custom code (`0`)
|
|
44
|
+
* : `0` - Geolocation is not supported by the environment
|
|
45
|
+
* : `1` - User denied permission to access geolocation
|
|
46
|
+
* : `2` - Position unavailable
|
|
47
|
+
* : `3` - Timeout - geolocation request took too long;
|
|
48
|
+
* - data `GeolocationData|null` - Location data object or null
|
|
49
|
+
* : latitude `number` - The latitude in decimal degrees
|
|
50
|
+
* : longitude `number` - The longitude in decimal degrees
|
|
51
|
+
* : accuracy `number` - The accuracy of position in meters
|
|
52
|
+
* : altitude `number|null` - The altitude in meters above the WGS84 ellipsoid
|
|
53
|
+
* : altitudeAccuracy `number|null` - The altitude accuracy in meters
|
|
54
|
+
* : heading `number|null` - The heading in degrees clockwise from true north
|
|
55
|
+
* : speed `number|null` - The speed in meters per second
|
|
56
|
+
* : timestamp `number` - The time when the position was retrieved;
|
|
57
|
+
* - getCurrentPosition `Function` - Function to get the current position once;
|
|
58
|
+
* - startTracking `Function` - Function to start tracking location changes;
|
|
59
|
+
* - stopTracking `Function` - Function to stop tracking location;
|
|
60
|
+
* - isTracking `boolean` - Whether location tracking is currently active;
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* // Basic usage
|
|
64
|
+
* const {
|
|
65
|
+
* loading,
|
|
66
|
+
* error,
|
|
67
|
+
* data,
|
|
68
|
+
* getCurrentPosition
|
|
69
|
+
* } = useGeolocation();
|
|
70
|
+
*
|
|
71
|
+
* // Automatically fetch location when component mounts
|
|
72
|
+
* const {
|
|
73
|
+
* loading,
|
|
74
|
+
* error,
|
|
75
|
+
* data
|
|
76
|
+
* } = useGeolocation({ mountBehavior: 'get' });
|
|
77
|
+
*
|
|
78
|
+
* // Location tracking
|
|
79
|
+
* const {
|
|
80
|
+
* loading,
|
|
81
|
+
* error,
|
|
82
|
+
* data,
|
|
83
|
+
* startTracking,
|
|
84
|
+
* stopTracking,
|
|
85
|
+
* isTracking
|
|
86
|
+
* } = useGeolocation();
|
|
87
|
+
*
|
|
88
|
+
* const handleStartTracking = () => {
|
|
89
|
+
* startTracking();
|
|
90
|
+
* };
|
|
91
|
+
*
|
|
92
|
+
* const handleStopTracking = () => {
|
|
93
|
+
* stopTracking();
|
|
94
|
+
* };
|
|
95
|
+
*/
|
|
96
|
+
declare function useGeolocation(options?: GeolocationOptions): {
|
|
97
|
+
getCurrentPosition: () => void;
|
|
98
|
+
startTracking: () => void;
|
|
99
|
+
stopTracking: () => void;
|
|
100
|
+
isTracking: boolean;
|
|
101
|
+
loading: boolean;
|
|
102
|
+
error: CustomGeoLocationError | null;
|
|
103
|
+
data: GeolocationData | null;
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
export { useGeolocation };
|
|
@@ -7,8 +7,8 @@ type UseImpressionRefOptions = Partial<{
|
|
|
7
7
|
}>;
|
|
8
8
|
/**
|
|
9
9
|
* @description
|
|
10
|
-
* `useImpressionRef` is a
|
|
11
|
-
*
|
|
10
|
+
* `useImpressionRef` is a React hook that measures the time a specific DOM element is visible on the screen and executes callbacks when the element enters or exits the viewport.
|
|
11
|
+
* It uses `IntersectionObserver` and the `Visibility API` to track the element's visibility.
|
|
12
12
|
*
|
|
13
13
|
* @param {UseImpressionRefOptions} options - Options for tracking the element's visibility.
|
|
14
14
|
* @param {() => void} [options.onImpressionStart] - Callback function executed when the element enters the view
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @description
|
|
3
|
-
* `useIntersectionObserver` is a
|
|
4
|
-
*
|
|
3
|
+
* `useIntersectionObserver` is a React hook that detects whether a specific DOM element is visible on the screen.
|
|
4
|
+
* It uses the `IntersectionObserver` API to execute a callback when the element enters or exits the viewport.
|
|
5
5
|
*
|
|
6
6
|
* @param {(entry: IntersectionObserverEntry) => void} callback - A callback function that is executed when the visibility of the element changes.
|
|
7
7
|
* You can check `entry.isIntersecting` to determine if the element is in view.
|
|
@@ -2,11 +2,11 @@ import { useEffect } from 'react';
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* @description
|
|
5
|
-
*
|
|
5
|
+
* `useIsomorphicLayoutEffect` is a React hook that provides the behavior of `useLayoutEffect` without triggering warnings during server-side rendering.
|
|
6
|
+
* During SSR, there is no DOM to synchronously measure or mutate, so React warns about using `useLayoutEffect`.
|
|
6
7
|
*
|
|
7
|
-
* This hook
|
|
8
|
+
* This hook runs synchronously after DOM updates but before paint, making it ideal for:
|
|
8
9
|
*
|
|
9
|
-
* It runs synchronously after DOM updates but before paint, making it ideal for:
|
|
10
10
|
* - Measuring DOM elements after render
|
|
11
11
|
* - Applying DOM changes before paint
|
|
12
12
|
* - Preventing UI flashes or layout shifts
|