@pyreon/hooks 0.1.1 → 0.2.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/lib/index.d.ts +264 -386
- package/package.json +3 -3
package/lib/index.d.ts
CHANGED
|
@@ -1,434 +1,312 @@
|
|
|
1
|
-
import { onMount
|
|
2
|
-
import { computed, effect, signal, watch } from "@pyreon/reactivity";
|
|
3
|
-
import { useTheme } from "@pyreon/styler";
|
|
4
|
-
import { get, throttle } from "@pyreon/ui-core";
|
|
5
|
-
|
|
6
|
-
//#region src/useBreakpoint.ts
|
|
1
|
+
import { onMount } from "@pyreon/core";
|
|
7
2
|
|
|
3
|
+
//#region src/useBreakpoint.d.ts
|
|
4
|
+
type BreakpointMap = Record<string, number>;
|
|
8
5
|
/**
|
|
9
|
-
* Return the currently active breakpoint name as a reactive signal.
|
|
10
|
-
*/
|
|
11
|
-
function useBreakpoint(breakpoints
|
|
12
|
-
const sorted = Object.entries(breakpoints).sort(([, a], [, b]) => a - b);
|
|
13
|
-
const active = signal(getActive(sorted));
|
|
14
|
-
let rafId;
|
|
15
|
-
function getActive(bps) {
|
|
16
|
-
if (typeof window === "undefined") return bps[0]?.[0] ?? "";
|
|
17
|
-
const w = window.innerWidth;
|
|
18
|
-
let result = bps[0]?.[0] ?? "";
|
|
19
|
-
for (const [name, min] of bps) if (w >= min) result = name;else break;
|
|
20
|
-
return result;
|
|
21
|
-
}
|
|
22
|
-
function onResize() {
|
|
23
|
-
if (rafId !== void 0) cancelAnimationFrame(rafId);
|
|
24
|
-
rafId = requestAnimationFrame(() => {
|
|
25
|
-
const next = getActive(sorted);
|
|
26
|
-
if (next !== active.peek()) active.set(next);
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
onMount(() => {
|
|
30
|
-
window.addEventListener("resize", onResize);
|
|
31
|
-
});
|
|
32
|
-
onUnmount(() => {
|
|
33
|
-
window.removeEventListener("resize", onResize);
|
|
34
|
-
if (rafId !== void 0) cancelAnimationFrame(rafId);
|
|
35
|
-
});
|
|
36
|
-
return active;
|
|
37
|
-
}
|
|
38
|
-
|
|
6
|
+
* Return the currently active breakpoint name as a reactive signal.
|
|
7
|
+
*/
|
|
8
|
+
declare function useBreakpoint(breakpoints?: BreakpointMap): () => string;
|
|
39
9
|
//#endregion
|
|
40
|
-
//#region src/useClickOutside.ts
|
|
10
|
+
//#region src/useClickOutside.d.ts
|
|
41
11
|
/**
|
|
42
|
-
* Call handler when a click occurs outside the target element.
|
|
43
|
-
*/
|
|
44
|
-
function useClickOutside(getEl, handler)
|
|
45
|
-
const listener = e => {
|
|
46
|
-
const el = getEl();
|
|
47
|
-
if (!el || el.contains(e.target)) return;
|
|
48
|
-
handler();
|
|
49
|
-
};
|
|
50
|
-
onMount(() => {
|
|
51
|
-
document.addEventListener("mousedown", listener, true);
|
|
52
|
-
document.addEventListener("touchstart", listener, true);
|
|
53
|
-
});
|
|
54
|
-
onUnmount(() => {
|
|
55
|
-
document.removeEventListener("mousedown", listener, true);
|
|
56
|
-
document.removeEventListener("touchstart", listener, true);
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
|
|
12
|
+
* Call handler when a click occurs outside the target element.
|
|
13
|
+
*/
|
|
14
|
+
declare function useClickOutside(getEl: () => HTMLElement | null, handler: () => void): void;
|
|
60
15
|
//#endregion
|
|
61
|
-
//#region src/
|
|
16
|
+
//#region src/useColorScheme.d.ts
|
|
62
17
|
/**
|
|
63
|
-
*
|
|
64
|
-
*/
|
|
65
|
-
function
|
|
66
|
-
const matches = signal(false);
|
|
67
|
-
let mql;
|
|
68
|
-
const onChange = e => {
|
|
69
|
-
matches.set(e.matches);
|
|
70
|
-
};
|
|
71
|
-
onMount(() => {
|
|
72
|
-
mql = window.matchMedia(query);
|
|
73
|
-
matches.set(mql.matches);
|
|
74
|
-
mql.addEventListener("change", onChange);
|
|
75
|
-
});
|
|
76
|
-
onUnmount(() => {
|
|
77
|
-
mql?.removeEventListener("change", onChange);
|
|
78
|
-
});
|
|
79
|
-
return matches;
|
|
80
|
-
}
|
|
81
|
-
|
|
18
|
+
* Returns the OS color scheme preference as 'light' or 'dark'.
|
|
19
|
+
*/
|
|
20
|
+
declare function useColorScheme(): () => "light" | "dark";
|
|
82
21
|
//#endregion
|
|
83
|
-
//#region src/
|
|
22
|
+
//#region src/useControllableState.d.ts
|
|
23
|
+
type UseControllableStateOptions<T> = {
|
|
24
|
+
value?: T | undefined;
|
|
25
|
+
defaultValue: T;
|
|
26
|
+
onChange?: ((value: T) => void) | undefined;
|
|
27
|
+
};
|
|
28
|
+
type UseControllableState = <T>(options: UseControllableStateOptions<T>) => [() => T, (next: T | ((prev: T) => T)) => void];
|
|
84
29
|
/**
|
|
85
|
-
*
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
30
|
+
* Unified controlled/uncontrolled state pattern.
|
|
31
|
+
* When `value` is provided the component is controlled; otherwise
|
|
32
|
+
* internal state is used with `defaultValue` as the initial value.
|
|
33
|
+
* The `onChange` callback fires in both modes.
|
|
34
|
+
*
|
|
35
|
+
* Returns [getter, setter] where getter is a reactive function.
|
|
36
|
+
*/
|
|
37
|
+
declare const useControllableState: UseControllableState;
|
|
92
38
|
//#endregion
|
|
93
|
-
//#region src/
|
|
39
|
+
//#region src/useDebouncedCallback.d.ts
|
|
40
|
+
type DebouncedFn<T extends (...args: any[]) => any> = {
|
|
41
|
+
(...args: Parameters<T>): void;
|
|
42
|
+
cancel: () => void;
|
|
43
|
+
flush: () => void;
|
|
44
|
+
};
|
|
45
|
+
type UseDebouncedCallback = <T extends (...args: any[]) => any>(callback: T, delay: number) => DebouncedFn<T>;
|
|
94
46
|
/**
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
*/
|
|
102
|
-
|
|
47
|
+
* Returns a debounced version of the callback.
|
|
48
|
+
* The returned function has `.cancel()` and `.flush()` methods.
|
|
49
|
+
* Always calls the latest callback (no stale closures).
|
|
50
|
+
* Cleans up on unmount.
|
|
51
|
+
*/
|
|
52
|
+
declare const useDebouncedCallback: UseDebouncedCallback;
|
|
103
53
|
//#endregion
|
|
104
|
-
//#region src/useDebouncedValue.ts
|
|
54
|
+
//#region src/useDebouncedValue.d.ts
|
|
105
55
|
/**
|
|
106
|
-
* Return a debounced version of a reactive value.
|
|
107
|
-
*/
|
|
108
|
-
function useDebouncedValue(getter, delayMs)
|
|
109
|
-
const debounced = signal(getter());
|
|
110
|
-
let timer;
|
|
111
|
-
effect(() => {
|
|
112
|
-
const val = getter();
|
|
113
|
-
if (timer !== void 0) clearTimeout(timer);
|
|
114
|
-
timer = setTimeout(() => {
|
|
115
|
-
debounced.set(val);
|
|
116
|
-
}, delayMs);
|
|
117
|
-
});
|
|
118
|
-
onUnmount(() => {
|
|
119
|
-
if (timer !== void 0) clearTimeout(timer);
|
|
120
|
-
});
|
|
121
|
-
return debounced;
|
|
122
|
-
}
|
|
123
|
-
|
|
56
|
+
* Return a debounced version of a reactive value.
|
|
57
|
+
*/
|
|
58
|
+
declare function useDebouncedValue<T>(getter: () => T, delayMs: number): () => T;
|
|
124
59
|
//#endregion
|
|
125
|
-
//#region src/useElementSize.ts
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
function useElementSize(getEl) {
|
|
130
|
-
const size = signal({
|
|
131
|
-
width: 0,
|
|
132
|
-
height: 0
|
|
133
|
-
});
|
|
134
|
-
let observer;
|
|
135
|
-
onMount(() => {
|
|
136
|
-
const el = getEl();
|
|
137
|
-
if (!el) return void 0;
|
|
138
|
-
observer = new ResizeObserver(([entry]) => {
|
|
139
|
-
if (!entry) return;
|
|
140
|
-
const {
|
|
141
|
-
width,
|
|
142
|
-
height
|
|
143
|
-
} = entry.contentRect;
|
|
144
|
-
size.set({
|
|
145
|
-
width,
|
|
146
|
-
height
|
|
147
|
-
});
|
|
148
|
-
});
|
|
149
|
-
observer.observe(el);
|
|
150
|
-
const rect = el.getBoundingClientRect();
|
|
151
|
-
size.set({
|
|
152
|
-
width: rect.width,
|
|
153
|
-
height: rect.height
|
|
154
|
-
});
|
|
155
|
-
});
|
|
156
|
-
onUnmount(() => {
|
|
157
|
-
observer?.disconnect();
|
|
158
|
-
});
|
|
159
|
-
return size;
|
|
60
|
+
//#region src/useElementSize.d.ts
|
|
61
|
+
interface Size {
|
|
62
|
+
width: number;
|
|
63
|
+
height: number;
|
|
160
64
|
}
|
|
161
|
-
|
|
162
|
-
//#endregion
|
|
163
|
-
//#region src/useFocus.ts
|
|
164
65
|
/**
|
|
165
|
-
*
|
|
166
|
-
*/
|
|
167
|
-
function
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
66
|
+
* Observe element dimensions reactively via ResizeObserver.
|
|
67
|
+
*/
|
|
68
|
+
declare function useElementSize(getEl: () => HTMLElement | null): () => Size;
|
|
69
|
+
//#endregion
|
|
70
|
+
//#region src/useFocus.d.ts
|
|
71
|
+
interface UseFocusResult {
|
|
72
|
+
focused: () => boolean;
|
|
73
|
+
props: {
|
|
74
|
+
onFocus: () => void;
|
|
75
|
+
onBlur: () => void;
|
|
175
76
|
};
|
|
176
77
|
}
|
|
177
|
-
|
|
78
|
+
/**
|
|
79
|
+
* Track focus state reactively.
|
|
80
|
+
*/
|
|
81
|
+
declare function useFocus(): UseFocusResult;
|
|
178
82
|
//#endregion
|
|
179
|
-
//#region src/useFocusTrap.ts
|
|
180
|
-
|
|
83
|
+
//#region src/useFocusTrap.d.ts
|
|
181
84
|
/**
|
|
182
|
-
* Trap Tab/Shift+Tab focus within a container element.
|
|
183
|
-
*/
|
|
184
|
-
function useFocusTrap(getEl)
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
if (document.activeElement === first) {
|
|
195
|
-
e.preventDefault();
|
|
196
|
-
last.focus();
|
|
197
|
-
}
|
|
198
|
-
} else if (document.activeElement === last) {
|
|
199
|
-
e.preventDefault();
|
|
200
|
-
first.focus();
|
|
201
|
-
}
|
|
85
|
+
* Trap Tab/Shift+Tab focus within a container element.
|
|
86
|
+
*/
|
|
87
|
+
declare function useFocusTrap(getEl: () => HTMLElement | null): void;
|
|
88
|
+
//#endregion
|
|
89
|
+
//#region src/useHover.d.ts
|
|
90
|
+
interface UseHoverResult {
|
|
91
|
+
/** Reactive boolean — true when element is hovered */
|
|
92
|
+
hovered: () => boolean;
|
|
93
|
+
/** Props to spread onto the element */
|
|
94
|
+
props: {
|
|
95
|
+
onMouseEnter: () => void;
|
|
96
|
+
onMouseLeave: () => void;
|
|
202
97
|
};
|
|
203
|
-
onMount(() => {
|
|
204
|
-
document.addEventListener("keydown", listener);
|
|
205
|
-
});
|
|
206
|
-
onUnmount(() => {
|
|
207
|
-
document.removeEventListener("keydown", listener);
|
|
208
|
-
});
|
|
209
98
|
}
|
|
210
|
-
|
|
99
|
+
/**
|
|
100
|
+
* Track hover state reactively.
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* const { hovered, props } = useHover()
|
|
104
|
+
* h('div', { ...props, class: () => hovered() ? 'active' : '' })
|
|
105
|
+
*/
|
|
106
|
+
declare function useHover(): UseHoverResult;
|
|
211
107
|
//#endregion
|
|
212
|
-
//#region src/
|
|
108
|
+
//#region src/useIntersection.d.ts
|
|
213
109
|
/**
|
|
214
|
-
*
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
* const { hovered, props } = useHover()
|
|
218
|
-
* h('div', { ...props, class: () => hovered() ? 'active' : '' })
|
|
219
|
-
*/
|
|
220
|
-
function useHover() {
|
|
221
|
-
const hovered = signal(false);
|
|
222
|
-
return {
|
|
223
|
-
hovered,
|
|
224
|
-
props: {
|
|
225
|
-
onMouseEnter: () => hovered.set(true),
|
|
226
|
-
onMouseLeave: () => hovered.set(false)
|
|
227
|
-
}
|
|
228
|
-
};
|
|
229
|
-
}
|
|
230
|
-
|
|
110
|
+
* Observe element intersection reactively.
|
|
111
|
+
*/
|
|
112
|
+
declare function useIntersection(getEl: () => HTMLElement | null, options?: IntersectionObserverInit): () => IntersectionObserverEntry | null;
|
|
231
113
|
//#endregion
|
|
232
|
-
//#region src/
|
|
114
|
+
//#region src/useInterval.d.ts
|
|
115
|
+
type UseInterval = (callback: () => void, delay: number | null) => void;
|
|
233
116
|
/**
|
|
234
|
-
*
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
onMount(() => {
|
|
240
|
-
const el = getEl();
|
|
241
|
-
if (!el) return void 0;
|
|
242
|
-
observer = new IntersectionObserver(([e]) => {
|
|
243
|
-
if (e) entry.set(e);
|
|
244
|
-
}, options);
|
|
245
|
-
observer.observe(el);
|
|
246
|
-
});
|
|
247
|
-
onUnmount(() => {
|
|
248
|
-
observer?.disconnect();
|
|
249
|
-
});
|
|
250
|
-
return entry;
|
|
251
|
-
}
|
|
252
|
-
|
|
117
|
+
* Declarative `setInterval` with auto-cleanup.
|
|
118
|
+
* Pass `null` as `delay` to pause the interval.
|
|
119
|
+
* Always calls the latest callback (no stale closures).
|
|
120
|
+
*/
|
|
121
|
+
declare const useInterval: UseInterval;
|
|
253
122
|
//#endregion
|
|
254
|
-
//#region src/
|
|
123
|
+
//#region src/useIsomorphicLayoutEffect.d.ts
|
|
255
124
|
/**
|
|
256
|
-
*
|
|
257
|
-
*
|
|
258
|
-
*
|
|
259
|
-
|
|
260
|
-
|
|
125
|
+
* In Pyreon there is no SSR warning distinction between effect and
|
|
126
|
+
* layout-effect as there is in React.
|
|
127
|
+
*
|
|
128
|
+
* On the client `onMount` fires synchronously after the component is
|
|
129
|
+
* mounted (similar to useLayoutEffect). On the server `effect` is a
|
|
130
|
+
* no-op. This export provides the appropriate primitive for each env.
|
|
131
|
+
*
|
|
132
|
+
* Consumers that need layout-timing should use `onMount` directly.
|
|
133
|
+
* This hook is provided for API parity with the original library.
|
|
134
|
+
*/
|
|
135
|
+
type UseIsomorphicLayoutEffect = typeof onMount;
|
|
136
|
+
declare const useIsomorphicLayoutEffect: UseIsomorphicLayoutEffect;
|
|
261
137
|
//#endregion
|
|
262
|
-
//#region src/useKeyboard.ts
|
|
138
|
+
//#region src/useKeyboard.d.ts
|
|
263
139
|
/**
|
|
264
|
-
* Listen for a specific key press.
|
|
265
|
-
*/
|
|
266
|
-
function useKeyboard(key, handler, options
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
if (ke.key === key) handler(ke);
|
|
271
|
-
};
|
|
272
|
-
onMount(() => {
|
|
273
|
-
(options?.target ?? document).addEventListener(eventName, listener);
|
|
274
|
-
});
|
|
275
|
-
onUnmount(() => {
|
|
276
|
-
(options?.target ?? document).removeEventListener(eventName, listener);
|
|
277
|
-
});
|
|
278
|
-
}
|
|
279
|
-
|
|
140
|
+
* Listen for a specific key press.
|
|
141
|
+
*/
|
|
142
|
+
declare function useKeyboard(key: string, handler: (event: KeyboardEvent) => void, options?: {
|
|
143
|
+
event?: "keydown" | "keyup";
|
|
144
|
+
target?: EventTarget;
|
|
145
|
+
}): void;
|
|
280
146
|
//#endregion
|
|
281
|
-
//#region src/useLatest.ts
|
|
147
|
+
//#region src/useLatest.d.ts
|
|
148
|
+
type UseLatest = <T>(value: T) => {
|
|
149
|
+
readonly current: T;
|
|
150
|
+
};
|
|
282
151
|
/**
|
|
283
|
-
* Returns a ref-like object that always holds the latest value.
|
|
284
|
-
* Useful to avoid stale closures in callbacks and effects.
|
|
285
|
-
*
|
|
286
|
-
* In Pyreon, since the component body runs once, this simply wraps
|
|
287
|
-
* the value in a mutable object. The caller is expected to call this
|
|
288
|
-
* once and update `.current` manually if needed, or pass a reactive
|
|
289
|
-
* getter to read the latest value.
|
|
290
|
-
*/
|
|
291
|
-
|
|
152
|
+
* Returns a ref-like object that always holds the latest value.
|
|
153
|
+
* Useful to avoid stale closures in callbacks and effects.
|
|
154
|
+
*
|
|
155
|
+
* In Pyreon, since the component body runs once, this simply wraps
|
|
156
|
+
* the value in a mutable object. The caller is expected to call this
|
|
157
|
+
* once and update `.current` manually if needed, or pass a reactive
|
|
158
|
+
* getter to read the latest value.
|
|
159
|
+
*/
|
|
160
|
+
declare const useLatest: UseLatest;
|
|
292
161
|
//#endregion
|
|
293
|
-
//#region src/
|
|
162
|
+
//#region src/useMediaQuery.d.ts
|
|
294
163
|
/**
|
|
295
|
-
*
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
function usePrevious(getter) {
|
|
299
|
-
const prev = signal(void 0);
|
|
300
|
-
let current;
|
|
301
|
-
effect(() => {
|
|
302
|
-
const next = getter();
|
|
303
|
-
prev.set(current);
|
|
304
|
-
current = next;
|
|
305
|
-
});
|
|
306
|
-
return prev;
|
|
307
|
-
}
|
|
308
|
-
|
|
164
|
+
* Subscribe to a CSS media query, returns a reactive boolean.
|
|
165
|
+
*/
|
|
166
|
+
declare function useMediaQuery(query: string): () => boolean;
|
|
309
167
|
//#endregion
|
|
310
|
-
//#region src/
|
|
168
|
+
//#region src/useMergedRef.d.ts
|
|
169
|
+
type RefCallback<T> = (node: T | null) => void;
|
|
170
|
+
type RefObject<T> = {
|
|
171
|
+
current: T | null;
|
|
172
|
+
};
|
|
173
|
+
type Ref<T> = RefCallback<T> | RefObject<T>;
|
|
174
|
+
type UseMergedRef = <T>(...refs: (Ref<T> | undefined)[]) => (node: T | null) => void;
|
|
311
175
|
/**
|
|
312
|
-
*
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
}
|
|
317
|
-
|
|
176
|
+
* Merges multiple refs (callback or object) into a single callback ref.
|
|
177
|
+
* Handles undefined, callback refs, and object refs with `.current`.
|
|
178
|
+
*/
|
|
179
|
+
declare const useMergedRef: <T>(...refs: (Ref<T> | undefined)[]) => ((node: T | null) => void);
|
|
318
180
|
//#endregion
|
|
319
|
-
//#region src/
|
|
181
|
+
//#region src/usePrevious.d.ts
|
|
320
182
|
/**
|
|
321
|
-
*
|
|
322
|
-
*
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
183
|
+
* Track the previous value of a reactive getter.
|
|
184
|
+
* Returns undefined on first access.
|
|
185
|
+
*/
|
|
186
|
+
declare function usePrevious<T>(getter: () => T): () => T | undefined;
|
|
187
|
+
//#endregion
|
|
188
|
+
//#region src/useReducedMotion.d.ts
|
|
327
189
|
/**
|
|
328
|
-
*
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
function useScrollLock() {
|
|
332
|
-
let isLocked = false;
|
|
333
|
-
const lock = () => {
|
|
334
|
-
if (isLocked) return;
|
|
335
|
-
isLocked = true;
|
|
336
|
-
if (lockCount === 0) {
|
|
337
|
-
savedOverflow = document.body.style.overflow;
|
|
338
|
-
document.body.style.overflow = "hidden";
|
|
339
|
-
}
|
|
340
|
-
lockCount++;
|
|
341
|
-
};
|
|
342
|
-
const unlock = () => {
|
|
343
|
-
if (!isLocked) return;
|
|
344
|
-
isLocked = false;
|
|
345
|
-
lockCount--;
|
|
346
|
-
if (lockCount === 0) document.body.style.overflow = savedOverflow;
|
|
347
|
-
};
|
|
348
|
-
onUnmount(() => {
|
|
349
|
-
if (isLocked) unlock();
|
|
350
|
-
});
|
|
351
|
-
return {
|
|
352
|
-
lock,
|
|
353
|
-
unlock
|
|
354
|
-
};
|
|
355
|
-
}
|
|
356
|
-
|
|
190
|
+
* Returns true when the user prefers reduced motion.
|
|
191
|
+
*/
|
|
192
|
+
declare function useReducedMotion(): () => boolean;
|
|
357
193
|
//#endregion
|
|
358
|
-
//#region src/
|
|
194
|
+
//#region src/useRootSize.d.ts
|
|
195
|
+
type RootSizeResult = {
|
|
196
|
+
rootSize: number;
|
|
197
|
+
pxToRem: (px: number) => string;
|
|
198
|
+
remToPx: (rem: number) => number;
|
|
199
|
+
};
|
|
200
|
+
type UseRootSize = () => RootSizeResult;
|
|
359
201
|
/**
|
|
360
|
-
* Returns
|
|
361
|
-
*
|
|
362
|
-
*
|
|
363
|
-
*
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
* ```ts
|
|
367
|
-
* const spacing = useSpacing()
|
|
368
|
-
* spacing(1) // "8px"
|
|
369
|
-
* spacing(2) // "16px"
|
|
370
|
-
* spacing(0.5) // "4px"
|
|
371
|
-
* ```
|
|
372
|
-
*/
|
|
373
|
-
|
|
202
|
+
* Returns `rootSize` from the theme context along with
|
|
203
|
+
* `pxToRem` and `remToPx` conversion utilities.
|
|
204
|
+
*
|
|
205
|
+
* Defaults to `16` when no rootSize is set in the theme.
|
|
206
|
+
*/
|
|
207
|
+
declare const useRootSize: UseRootSize;
|
|
374
208
|
//#endregion
|
|
375
|
-
//#region src/
|
|
209
|
+
//#region src/useScrollLock.d.ts
|
|
376
210
|
/**
|
|
377
|
-
*
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
setTrue: () => value.set(true),
|
|
385
|
-
setFalse: () => value.set(false)
|
|
386
|
-
};
|
|
387
|
-
}
|
|
388
|
-
|
|
211
|
+
* Lock page scroll. Uses reference counting for concurrent locks.
|
|
212
|
+
* Returns an unlock function.
|
|
213
|
+
*/
|
|
214
|
+
declare function useScrollLock(): {
|
|
215
|
+
lock: () => void;
|
|
216
|
+
unlock: () => void;
|
|
217
|
+
};
|
|
389
218
|
//#endregion
|
|
390
|
-
//#region src/
|
|
219
|
+
//#region src/useSpacing.d.ts
|
|
220
|
+
type UseSpacing = (base?: number | undefined) => (multiplier: number) => string;
|
|
391
221
|
/**
|
|
392
|
-
*
|
|
393
|
-
*
|
|
394
|
-
*
|
|
395
|
-
*
|
|
396
|
-
*
|
|
397
|
-
* @
|
|
398
|
-
*
|
|
399
|
-
|
|
400
|
-
|
|
222
|
+
* Returns a `spacing(n)` function that computes spacing values
|
|
223
|
+
* based on `rootSize` from the theme.
|
|
224
|
+
*
|
|
225
|
+
* @param base - Base spacing unit in px (defaults to `rootSize / 2`, i.e. 8px)
|
|
226
|
+
*
|
|
227
|
+
* @example
|
|
228
|
+
* ```ts
|
|
229
|
+
* const spacing = useSpacing()
|
|
230
|
+
* spacing(1) // "8px"
|
|
231
|
+
* spacing(2) // "16px"
|
|
232
|
+
* spacing(0.5) // "4px"
|
|
233
|
+
* ```
|
|
234
|
+
*/
|
|
235
|
+
declare const useSpacing: UseSpacing;
|
|
236
|
+
//#endregion
|
|
237
|
+
//#region src/useThemeValue.d.ts
|
|
238
|
+
type UseThemeValue = <T = unknown>(path: string) => T | undefined;
|
|
239
|
+
/**
|
|
240
|
+
* Deep-reads a value from the current theme by dot-separated path.
|
|
241
|
+
*
|
|
242
|
+
* @example
|
|
243
|
+
* ```ts
|
|
244
|
+
* const primary = useThemeValue<string>('colors.primary')
|
|
245
|
+
* const columns = useThemeValue<number>('grid.columns')
|
|
246
|
+
* ```
|
|
247
|
+
*/
|
|
248
|
+
declare const useThemeValue: UseThemeValue;
|
|
249
|
+
//#endregion
|
|
250
|
+
//#region src/useThrottledCallback.d.ts
|
|
251
|
+
type ThrottledFn<T extends (...args: any[]) => any> = {
|
|
252
|
+
(...args: Parameters<T>): void;
|
|
253
|
+
cancel: () => void;
|
|
254
|
+
};
|
|
255
|
+
type UseThrottledCallback = <T extends (...args: any[]) => any>(callback: T, delay: number) => ThrottledFn<T>;
|
|
256
|
+
/**
|
|
257
|
+
* Returns a throttled version of the callback.
|
|
258
|
+
* Uses `throttle` from `@pyreon/ui-core`.
|
|
259
|
+
* Always calls the latest callback (no stale closures).
|
|
260
|
+
* Cleans up on unmount.
|
|
261
|
+
*/
|
|
262
|
+
declare const useThrottledCallback: UseThrottledCallback;
|
|
401
263
|
//#endregion
|
|
402
|
-
//#region src/
|
|
264
|
+
//#region src/useTimeout.d.ts
|
|
265
|
+
type UseTimeout = (callback: () => void, delay: number | null) => {
|
|
266
|
+
reset: () => void;
|
|
267
|
+
clear: () => void;
|
|
268
|
+
};
|
|
403
269
|
/**
|
|
404
|
-
*
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
size.set({
|
|
417
|
-
width: window.innerWidth,
|
|
418
|
-
height: window.innerHeight
|
|
419
|
-
});
|
|
420
|
-
}, throttleMs);
|
|
421
|
-
}
|
|
422
|
-
onMount(() => {
|
|
423
|
-
window.addEventListener("resize", onResize);
|
|
424
|
-
});
|
|
425
|
-
onUnmount(() => {
|
|
426
|
-
window.removeEventListener("resize", onResize);
|
|
427
|
-
if (timer !== void 0) clearTimeout(timer);
|
|
428
|
-
});
|
|
429
|
-
return size;
|
|
270
|
+
* Declarative `setTimeout` with auto-cleanup.
|
|
271
|
+
* Pass `null` as `delay` to disable. Returns `reset` and `clear` controls.
|
|
272
|
+
* Always calls the latest callback (no stale closures).
|
|
273
|
+
*/
|
|
274
|
+
declare const useTimeout: UseTimeout;
|
|
275
|
+
//#endregion
|
|
276
|
+
//#region src/useToggle.d.ts
|
|
277
|
+
interface UseToggleResult {
|
|
278
|
+
value: () => boolean;
|
|
279
|
+
toggle: () => void;
|
|
280
|
+
setTrue: () => void;
|
|
281
|
+
setFalse: () => void;
|
|
430
282
|
}
|
|
431
|
-
|
|
283
|
+
/**
|
|
284
|
+
* Simple boolean toggle.
|
|
285
|
+
*/
|
|
286
|
+
declare function useToggle(initial?: boolean): UseToggleResult;
|
|
287
|
+
//#endregion
|
|
288
|
+
//#region src/useUpdateEffect.d.ts
|
|
289
|
+
type UseUpdateEffect = <T>(source: () => T, callback: (newVal: T, oldVal: T | undefined) => undefined | (() => void)) => void;
|
|
290
|
+
/**
|
|
291
|
+
* Like `effect` but skips the initial value — only fires on updates.
|
|
292
|
+
*
|
|
293
|
+
* In Pyreon, this is implemented using `watch()` which already skips
|
|
294
|
+
* the initial value by default (immediate defaults to false).
|
|
295
|
+
*
|
|
296
|
+
* @param source - A reactive getter to watch
|
|
297
|
+
* @param callback - Called when source changes, receives (newVal, oldVal)
|
|
298
|
+
*/
|
|
299
|
+
declare const useUpdateEffect: UseUpdateEffect;
|
|
300
|
+
//#endregion
|
|
301
|
+
//#region src/useWindowResize.d.ts
|
|
302
|
+
interface WindowSize {
|
|
303
|
+
width: number;
|
|
304
|
+
height: number;
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Track window dimensions reactively with throttling.
|
|
308
|
+
*/
|
|
309
|
+
declare function useWindowResize(throttleMs?: number): () => WindowSize;
|
|
432
310
|
//#endregion
|
|
433
|
-
export { useBreakpoint, useClickOutside, useColorScheme, useControllableState, useDebouncedCallback, useDebouncedValue, useElementSize, useFocus, useFocusTrap, useHover, useIntersection, useInterval, useIsomorphicLayoutEffect, useKeyboard, useLatest, useMediaQuery, useMergedRef, usePrevious, useReducedMotion, useRootSize, useScrollLock, useSpacing, useThemeValue, useThrottledCallback, useTimeout, useToggle, useUpdateEffect, useWindowResize };
|
|
434
|
-
//# sourceMappingURL=
|
|
311
|
+
export { type BreakpointMap, type Size, type UseControllableState, type UseDebouncedCallback, type UseFocusResult, type UseHoverResult, type UseInterval, type UseIsomorphicLayoutEffect, type UseLatest, type UseMergedRef, type UseRootSize, type UseSpacing, type UseThemeValue, type UseThrottledCallback, type UseTimeout, type UseToggleResult, type UseUpdateEffect, type WindowSize, useBreakpoint, useClickOutside, useColorScheme, useControllableState, useDebouncedCallback, useDebouncedValue, useElementSize, useFocus, useFocusTrap, useHover, useIntersection, useInterval, useIsomorphicLayoutEffect, useKeyboard, useLatest, useMediaQuery, useMergedRef, usePrevious, useReducedMotion, useRootSize, useScrollLock, useSpacing, useThemeValue, useThrottledCallback, useTimeout, useToggle, useUpdateEffect, useWindowResize };
|
|
312
|
+
//# sourceMappingURL=index2.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pyreon/hooks",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/pyreon/ui-system",
|
|
@@ -43,8 +43,8 @@
|
|
|
43
43
|
"peerDependencies": {
|
|
44
44
|
"@pyreon/core": ">=0.4.0 <1.0.0",
|
|
45
45
|
"@pyreon/reactivity": ">=0.4.0 <1.0.0",
|
|
46
|
-
"@pyreon/styler": ">=0.
|
|
47
|
-
"@pyreon/ui-core": ">=0.
|
|
46
|
+
"@pyreon/styler": ">=0.2.0",
|
|
47
|
+
"@pyreon/ui-core": ">=0.2.0"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@vitus-labs/tools-rolldown": "^1.15.3",
|