@stacksjs/composables 0.70.88 → 0.70.91

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.
Files changed (333) hide show
  1. package/dist/_shared.d.ts +49 -0
  2. package/dist/_shared.js +23 -0
  3. package/dist/cloneFnJSON.d.ts +5 -0
  4. package/dist/cloneFnJSON.js +3 -0
  5. package/dist/computedAsync.d.ts +28 -0
  6. package/dist/computedAsync.js +20 -0
  7. package/dist/computedEager.d.ts +27 -0
  8. package/dist/computedEager.js +10 -0
  9. package/dist/createEventHook.d.ts +16 -0
  10. package/dist/createEventHook.js +15 -0
  11. package/dist/createFetch.d.ts +14 -0
  12. package/dist/createFetch.js +8 -0
  13. package/dist/createGlobalState.d.ts +17 -0
  14. package/dist/createGlobalState.js +10 -0
  15. package/dist/createSharedComposable.d.ts +8 -0
  16. package/dist/createSharedComposable.js +9 -0
  17. package/dist/extendRef.d.ts +9 -0
  18. package/dist/extendRef.js +6 -0
  19. package/dist/formatTimeAgo.d.ts +23 -0
  20. package/dist/formatTimeAgo.js +33 -0
  21. package/dist/index.d.ts +271 -0
  22. package/dist/index.js +210 -0
  23. package/dist/isDefined.d.ts +5 -0
  24. package/dist/isDefined.js +3 -0
  25. package/dist/makeDestructurable.d.ts +18 -0
  26. package/dist/makeDestructurable.js +16 -0
  27. package/dist/onClickOutside.d.ts +14 -0
  28. package/dist/onClickOutside.js +25 -0
  29. package/dist/onKeyStroke.d.ts +26 -0
  30. package/dist/onKeyStroke.js +31 -0
  31. package/dist/onLongPress.d.ts +14 -0
  32. package/dist/onLongPress.js +43 -0
  33. package/dist/onStartTyping.d.ts +8 -0
  34. package/dist/onStartTyping.js +23 -0
  35. package/dist/refAutoReset.d.ts +11 -0
  36. package/dist/refAutoReset.js +15 -0
  37. package/dist/refDefault.d.ts +9 -0
  38. package/dist/refDefault.js +8 -0
  39. package/dist/resolveRef.d.ts +7 -0
  40. package/dist/resolveRef.js +7 -0
  41. package/dist/ssrHandlers.d.ts +13 -0
  42. package/dist/ssrHandlers.js +8 -0
  43. package/dist/syncRef.d.ts +21 -0
  44. package/dist/syncRef.js +35 -0
  45. package/dist/tryOnMounted.d.ts +22 -0
  46. package/dist/tryOnMounted.js +22 -0
  47. package/dist/unrefElement.d.ts +6 -0
  48. package/dist/unrefElement.js +9 -0
  49. package/dist/until.d.ts +34 -0
  50. package/dist/until.js +62 -0
  51. package/dist/useActiveElement.d.ts +6 -0
  52. package/dist/useActiveElement.js +19 -0
  53. package/dist/useAnimate.d.ts +18 -0
  54. package/dist/useAnimate.js +48 -0
  55. package/dist/useArrayUtils.d.ts +42 -0
  56. package/dist/useArrayUtils.js +114 -0
  57. package/dist/useAsyncQueue.d.ts +18 -0
  58. package/dist/useAsyncQueue.js +22 -0
  59. package/dist/useAsyncState.d.ts +23 -0
  60. package/dist/useAsyncState.js +35 -0
  61. package/dist/useBase64.d.ts +12 -0
  62. package/dist/useBase64.js +45 -0
  63. package/dist/useBattery.d.ts +15 -0
  64. package/dist/useBattery.js +38 -0
  65. package/dist/useBreakpoints.d.ts +96 -0
  66. package/dist/useBreakpoints.js +97 -0
  67. package/dist/useBroadcastChannel.d.ts +14 -0
  68. package/dist/useBroadcastChannel.js +31 -0
  69. package/dist/useBrowserLocation.d.ts +18 -0
  70. package/dist/useBrowserLocation.js +64 -0
  71. package/dist/useClipboard.d.ts +17 -0
  72. package/dist/useClipboard.js +32 -0
  73. package/dist/useClipboardItems.d.ts +11 -0
  74. package/dist/useClipboardItems.js +15 -0
  75. package/dist/useCloned.d.ts +15 -0
  76. package/dist/useCloned.js +16 -0
  77. package/dist/useColorMode.d.ts +18 -0
  78. package/dist/useColorMode.js +60 -0
  79. package/dist/useConfirmDialog.d.ts +14 -0
  80. package/dist/useConfirmDialog.js +34 -0
  81. package/dist/useCounter.d.ts +20 -0
  82. package/dist/useCounter.js +28 -0
  83. package/dist/useCssVar.d.ts +10 -0
  84. package/dist/useCssVar.js +23 -0
  85. package/dist/useCycleList.d.ts +18 -0
  86. package/dist/useCycleList.js +27 -0
  87. package/dist/useDark.d.ts +11 -0
  88. package/dist/useDark.js +38 -0
  89. package/dist/useDateFormat.d.ts +10 -0
  90. package/dist/useDateFormat.js +11 -0
  91. package/dist/useDebounce.d.ts +10 -0
  92. package/dist/useDebounce.js +16 -0
  93. package/dist/useDebounceFn.d.ts +10 -0
  94. package/dist/useDebounceFn.js +18 -0
  95. package/dist/useDebouncedRef.d.ts +11 -0
  96. package/dist/useDebouncedRef.js +22 -0
  97. package/dist/useDebouncedRefHistory.d.ts +5 -0
  98. package/dist/useDebouncedRefHistory.js +36 -0
  99. package/dist/useDeviceMotion.d.ts +27 -0
  100. package/dist/useDeviceMotion.js +53 -0
  101. package/dist/useDeviceOrientation.d.ts +15 -0
  102. package/dist/useDeviceOrientation.js +23 -0
  103. package/dist/useDevicePixelRatio.d.ts +5 -0
  104. package/dist/useDevicePixelRatio.js +24 -0
  105. package/dist/useDocumentVisibility.d.ts +5 -0
  106. package/dist/useDocumentVisibility.js +16 -0
  107. package/dist/useDraggable.d.ts +23 -0
  108. package/dist/useDraggable.js +58 -0
  109. package/dist/useDropZone.d.ts +15 -0
  110. package/dist/useDropZone.js +52 -0
  111. package/dist/useElementBounding.d.ts +21 -0
  112. package/dist/useElementBounding.js +59 -0
  113. package/dist/useElementByPoint.d.ts +10 -0
  114. package/dist/useElementByPoint.js +18 -0
  115. package/dist/useElementHover.d.ts +9 -0
  116. package/dist/useElementHover.js +28 -0
  117. package/dist/useElementSize.d.ts +19 -0
  118. package/dist/useElementSize.js +34 -0
  119. package/dist/useElementVisibility.d.ts +10 -0
  120. package/dist/useElementVisibility.js +10 -0
  121. package/dist/useEventBus.d.ts +14 -0
  122. package/dist/useEventBus.js +41 -0
  123. package/dist/useEventListener.d.ts +14 -0
  124. package/dist/useEventListener.js +29 -0
  125. package/dist/useEventSource.d.ts +32 -0
  126. package/dist/useEventSource.js +72 -0
  127. package/dist/useEyeDropper.d.ts +10 -0
  128. package/dist/useEyeDropper.js +17 -0
  129. package/dist/useFavicon.d.ts +8 -0
  130. package/dist/useFavicon.js +22 -0
  131. package/dist/useFetch.d.ts +35 -0
  132. package/dist/useFetch.js +61 -0
  133. package/dist/useFileDialog.d.ts +15 -0
  134. package/dist/useFileDialog.js +24 -0
  135. package/dist/useFocus.d.ts +13 -0
  136. package/dist/useFocus.js +42 -0
  137. package/dist/useFocusWithin.d.ts +9 -0
  138. package/dist/useFocusWithin.js +29 -0
  139. package/dist/useForm.d.ts +97 -0
  140. package/dist/useForm.js +182 -0
  141. package/dist/useFps.d.ts +7 -0
  142. package/dist/useFps.js +22 -0
  143. package/dist/useFullscreen.d.ts +16 -0
  144. package/dist/useFullscreen.js +67 -0
  145. package/dist/useGeolocation.d.ts +26 -0
  146. package/dist/useGeolocation.js +55 -0
  147. package/dist/useIdle.d.ts +18 -0
  148. package/dist/useIdle.js +46 -0
  149. package/dist/useImage.d.ts +18 -0
  150. package/dist/useImage.js +32 -0
  151. package/dist/useInfiniteScroll.d.ts +11 -0
  152. package/dist/useInfiniteScroll.js +50 -0
  153. package/dist/useIntersectionObserver.d.ts +16 -0
  154. package/dist/useIntersectionObserver.js +27 -0
  155. package/dist/useInterval.d.ts +13 -0
  156. package/dist/useInterval.js +32 -0
  157. package/dist/useIntervalFn.d.ts +16 -0
  158. package/dist/useIntervalFn.js +24 -0
  159. package/dist/useKeyModifier.d.ts +6 -0
  160. package/dist/useKeyModifier.js +22 -0
  161. package/dist/useLastChanged.d.ts +11 -0
  162. package/dist/useLastChanged.js +8 -0
  163. package/dist/useLocalStorage.d.ts +17 -0
  164. package/dist/useLocalStorage.js +4 -0
  165. package/dist/useMagicKeys.d.ts +16 -0
  166. package/dist/useMagicKeys.js +81 -0
  167. package/dist/useManualRefHistory.d.ts +27 -0
  168. package/dist/useManualRefHistory.js +64 -0
  169. package/dist/useMath.d.ts +17 -0
  170. package/dist/useMath.js +52 -0
  171. package/dist/useMediaQuery.d.ts +9 -0
  172. package/dist/useMediaQuery.js +19 -0
  173. package/dist/useMemoize.d.ts +13 -0
  174. package/dist/useMemoize.js +24 -0
  175. package/dist/useMounted.d.ts +6 -0
  176. package/dist/useMounted.js +8 -0
  177. package/dist/useMouse.d.ts +19 -0
  178. package/dist/useMouse.js +67 -0
  179. package/dist/useMouseInElement.d.ts +17 -0
  180. package/dist/useMouseInElement.js +31 -0
  181. package/dist/useMousePressed.d.ts +10 -0
  182. package/dist/useMousePressed.js +31 -0
  183. package/dist/useMutationObserver.d.ts +16 -0
  184. package/dist/useMutationObserver.js +27 -0
  185. package/dist/useNavigatorLanguage.d.ts +5 -0
  186. package/dist/useNavigatorLanguage.js +17 -0
  187. package/dist/useNetwork.d.ts +18 -0
  188. package/dist/useNetwork.js +58 -0
  189. package/dist/useNow.d.ts +8 -0
  190. package/dist/useNow.js +10 -0
  191. package/dist/useObjectUrl.d.ts +8 -0
  192. package/dist/useObjectUrl.js +23 -0
  193. package/dist/useOffsetPagination.d.ts +21 -0
  194. package/dist/useOffsetPagination.js +45 -0
  195. package/dist/useOnline.d.ts +7 -0
  196. package/dist/useOnline.js +20 -0
  197. package/dist/usePageLeave.d.ts +9 -0
  198. package/dist/usePageLeave.js +27 -0
  199. package/dist/useParallax.d.ts +15 -0
  200. package/dist/useParallax.js +33 -0
  201. package/dist/useParentElement.d.ts +6 -0
  202. package/dist/useParentElement.js +8 -0
  203. package/dist/usePermission.d.ts +7 -0
  204. package/dist/usePermission.js +21 -0
  205. package/dist/usePointer.d.ts +15 -0
  206. package/dist/usePointer.js +32 -0
  207. package/dist/usePointerLock.d.ts +13 -0
  208. package/dist/usePointerLock.js +33 -0
  209. package/dist/usePointerSwipe.d.ts +20 -0
  210. package/dist/usePointerSwipe.js +52 -0
  211. package/dist/usePreferredColorScheme.d.ts +6 -0
  212. package/dist/usePreferredColorScheme.js +25 -0
  213. package/dist/usePreferredContrast.d.ts +6 -0
  214. package/dist/usePreferredContrast.js +29 -0
  215. package/dist/usePreferredLanguages.d.ts +5 -0
  216. package/dist/usePreferredLanguages.js +16 -0
  217. package/dist/usePreferredReducedMotion.d.ts +6 -0
  218. package/dist/usePreferredReducedMotion.js +18 -0
  219. package/dist/usePrevious.d.ts +9 -0
  220. package/dist/usePrevious.js +8 -0
  221. package/dist/useQuery.d.ts +106 -0
  222. package/dist/useQuery.js +265 -0
  223. package/dist/useRafFn.d.ts +19 -0
  224. package/dist/useRafFn.js +37 -0
  225. package/dist/useRefHistory.d.ts +28 -0
  226. package/dist/useRefHistory.js +72 -0
  227. package/dist/useResizeObserver.d.ts +16 -0
  228. package/dist/useResizeObserver.js +27 -0
  229. package/dist/useScreenOrientation.d.ts +13 -0
  230. package/dist/useScreenOrientation.js +27 -0
  231. package/dist/useScreenSafeArea.d.ts +12 -0
  232. package/dist/useScreenSafeArea.js +25 -0
  233. package/dist/useScriptTag.d.ts +20 -0
  234. package/dist/useScriptTag.js +52 -0
  235. package/dist/useScroll.d.ts +36 -0
  236. package/dist/useScroll.js +116 -0
  237. package/dist/useScrollLock.d.ts +10 -0
  238. package/dist/useScrollLock.js +39 -0
  239. package/dist/useSessionStorage.d.ts +17 -0
  240. package/dist/useSessionStorage.js +4 -0
  241. package/dist/useShare.d.ts +15 -0
  242. package/dist/useShare.js +11 -0
  243. package/dist/useSorted.d.ts +10 -0
  244. package/dist/useSorted.js +10 -0
  245. package/dist/useStepper.d.ts +23 -0
  246. package/dist/useStepper.js +46 -0
  247. package/dist/useStorage.d.ts +18 -0
  248. package/dist/useStorage.js +54 -0
  249. package/dist/useStyleTag.d.ts +17 -0
  250. package/dist/useStyleTag.js +39 -0
  251. package/dist/useSupported.d.ts +8 -0
  252. package/dist/useSupported.js +10 -0
  253. package/dist/useSwipe.d.ts +20 -0
  254. package/dist/useSwipe.js +58 -0
  255. package/dist/useTextDirection.d.ts +9 -0
  256. package/dist/useTextDirection.js +16 -0
  257. package/dist/useTextSelection.d.ts +10 -0
  258. package/dist/useTextSelection.js +27 -0
  259. package/dist/useTextareaAutosize.d.ts +10 -0
  260. package/dist/useTextareaAutosize.js +20 -0
  261. package/dist/useThrottle.d.ts +9 -0
  262. package/dist/useThrottle.js +23 -0
  263. package/dist/useThrottleFn.d.ts +11 -0
  264. package/dist/useThrottleFn.js +36 -0
  265. package/dist/useThrottledRef.d.ts +11 -0
  266. package/dist/useThrottledRef.js +30 -0
  267. package/dist/useThrottledRefHistory.d.ts +5 -0
  268. package/dist/useThrottledRefHistory.js +43 -0
  269. package/dist/useTimeAgo.d.ts +16 -0
  270. package/dist/useTimeAgo.js +58 -0
  271. package/dist/useTimeout.d.ts +12 -0
  272. package/dist/useTimeout.js +32 -0
  273. package/dist/useTimeoutFn.d.ts +16 -0
  274. package/dist/useTimeoutFn.js +27 -0
  275. package/dist/useTimeoutPoll.d.ts +10 -0
  276. package/dist/useTimeoutPoll.js +33 -0
  277. package/dist/useTimestamp.d.ts +15 -0
  278. package/dist/useTimestamp.js +43 -0
  279. package/dist/useTitle.d.ts +10 -0
  280. package/dist/useTitle.js +12 -0
  281. package/dist/useToNumber.d.ts +11 -0
  282. package/dist/useToNumber.js +25 -0
  283. package/dist/useToString.d.ts +6 -0
  284. package/dist/useToString.js +10 -0
  285. package/dist/useToggle.d.ts +6 -0
  286. package/dist/useToggle.js +12 -0
  287. package/dist/useTransition.d.ts +28 -0
  288. package/dist/useTransition.js +89 -0
  289. package/dist/useUrlSearchParams.d.ts +18 -0
  290. package/dist/useUrlSearchParams.js +72 -0
  291. package/dist/useVibrate.d.ts +13 -0
  292. package/dist/useVibrate.js +14 -0
  293. package/dist/useVirtualList.d.ts +23 -0
  294. package/dist/useVirtualList.js +49 -0
  295. package/dist/useWakeLock.d.ts +12 -0
  296. package/dist/useWakeLock.js +32 -0
  297. package/dist/useWebNotification.d.ts +25 -0
  298. package/dist/useWebNotification.js +39 -0
  299. package/dist/useWebSocket.d.ts +38 -0
  300. package/dist/useWebSocket.js +103 -0
  301. package/dist/useWebWorker.d.ts +18 -0
  302. package/dist/useWebWorker.js +56 -0
  303. package/dist/useWindowFocus.d.ts +5 -0
  304. package/dist/useWindowFocus.js +20 -0
  305. package/dist/useWindowScroll.d.ts +9 -0
  306. package/dist/useWindowScroll.js +17 -0
  307. package/dist/useWindowSize.d.ts +15 -0
  308. package/dist/useWindowSize.js +28 -0
  309. package/dist/watchArray.d.ts +5 -0
  310. package/dist/watchArray.js +9 -0
  311. package/dist/watchAtMost.d.ts +5 -0
  312. package/dist/watchAtMost.js +12 -0
  313. package/dist/watchDebounced.d.ts +23 -0
  314. package/dist/watchDebounced.js +20 -0
  315. package/dist/watchDeep.d.ts +7 -0
  316. package/dist/watchDeep.js +13 -0
  317. package/dist/watchIgnorable.d.ts +12 -0
  318. package/dist/watchIgnorable.js +19 -0
  319. package/dist/watchImmediate.d.ts +5 -0
  320. package/dist/watchImmediate.js +7 -0
  321. package/dist/watchOnce.d.ts +19 -0
  322. package/dist/watchOnce.js +17 -0
  323. package/dist/watchPausable.d.ts +13 -0
  324. package/dist/watchPausable.js +23 -0
  325. package/dist/watchThrottled.d.ts +23 -0
  326. package/dist/watchThrottled.js +37 -0
  327. package/dist/watchTriggerable.d.ts +5 -0
  328. package/dist/watchTriggerable.js +10 -0
  329. package/dist/watchWithFilter.d.ts +7 -0
  330. package/dist/watchWithFilter.js +6 -0
  331. package/dist/whenever.d.ts +18 -0
  332. package/dist/whenever.js +7 -0
  333. package/package.json +2 -2
@@ -0,0 +1,24 @@
1
+ import { onUnmounted, ref } from "@stacksjs/stx";
2
+ export function useIntervalFn(cb, interval = 1000, options = {}) {
3
+ const { immediate = !0 } = options, isActive = ref(!1);
4
+ let intervalId = null;
5
+ function pause() {
6
+ if (intervalId !== null) {
7
+ clearInterval(intervalId);
8
+ intervalId = null;
9
+ }
10
+ isActive.value = !1;
11
+ }
12
+ function resume() {
13
+ if (intervalId !== null)
14
+ return;
15
+ isActive.value = !0;
16
+ intervalId = setInterval(cb, interval);
17
+ }
18
+ if (immediate)
19
+ resume();
20
+ try {
21
+ onUnmounted(pause);
22
+ } catch {}
23
+ return { pause, resume, isActive };
24
+ }
@@ -0,0 +1,6 @@
1
+ import type { Ref } from '@stacksjs/stx';
2
+ /**
3
+ * Reactive key modifier state (e.g., Shift, Control, Alt, Meta).
4
+ */
5
+ export declare function useKeyModifier(modifier: KeyModifier): Ref<boolean>;
6
+ export type KeyModifier = 'Alt' | 'AltGraph' | 'CapsLock' | 'Control' | 'Fn' | 'FnLock' | 'Meta' | 'NumLock' | 'ScrollLock' | 'Shift' | 'Symbol' | 'SymbolLock';
@@ -0,0 +1,22 @@
1
+ import { onUnmounted, ref } from "@stacksjs/stx";
2
+ export function useKeyModifier(modifier) {
3
+ const state = ref(!1);
4
+ if (typeof window > "u")
5
+ return state;
6
+ const handler = (e) => {
7
+ state.value = e.getModifierState(modifier);
8
+ };
9
+ window.addEventListener("keydown", handler, { passive: !0 });
10
+ window.addEventListener("keyup", handler, { passive: !0 });
11
+ window.addEventListener("mousedown", handler, { passive: !0 });
12
+ window.addEventListener("mouseup", handler, { passive: !0 });
13
+ try {
14
+ onUnmounted(() => {
15
+ window.removeEventListener("keydown", handler);
16
+ window.removeEventListener("keyup", handler);
17
+ window.removeEventListener("mousedown", handler);
18
+ window.removeEventListener("mouseup", handler);
19
+ });
20
+ } catch {}
21
+ return state;
22
+ }
@@ -0,0 +1,11 @@
1
+ import type { Ref } from '@stacksjs/stx';
2
+ /**
3
+ * Track the timestamp of when a ref last changed.
4
+ *
5
+ * @param source - The reactive source to watch
6
+ * @param options - Optional initial timestamp value
7
+ */
8
+ export declare function useLastChanged(source: Ref<any>, options?: UseLastChangedOptions): Ref<number | null>;
9
+ export declare interface UseLastChangedOptions {
10
+ initialValue?: number | null
11
+ }
@@ -0,0 +1,8 @@
1
+ import { ref, watch } from "@stacksjs/stx";
2
+ export function useLastChanged(source, options = {}) {
3
+ const { initialValue = null } = options, lastChanged = ref(initialValue);
4
+ watch(source, () => {
5
+ lastChanged.value = Date.now();
6
+ });
7
+ return lastChanged;
8
+ }
@@ -0,0 +1,17 @@
1
+ import type { Ref } from '@stacksjs/stx';
2
+ /**
3
+ * Reactive localStorage wrapper.
4
+ * Convenience composable that delegates to useStorage with localStorage.
5
+ *
6
+ * @param key - Storage key
7
+ * @param defaultValue - Default value when key doesn't exist
8
+ * @param options - Serializer options
9
+ */
10
+ export declare function useLocalStorage<T>(key: string, defaultValue: T, options?: UseLocalStorageOptions<T>): Ref<T>;
11
+ declare interface UseLocalStorageSerializer<T> {
12
+ read: (raw: string) => T
13
+ write: (value: T) => string
14
+ }
15
+ declare interface UseLocalStorageOptions<T> {
16
+ serializer?: UseLocalStorageSerializer<T>
17
+ }
@@ -0,0 +1,4 @@
1
+ import { useStorage } from "./useStorage";
2
+ export function useLocalStorage(key, defaultValue, options) {
3
+ return useStorage(key, defaultValue, typeof localStorage < "u" ? localStorage : void 0, options);
4
+ }
@@ -0,0 +1,16 @@
1
+ import type { Ref } from '@stacksjs/stx';
2
+ /**
3
+ * Reactive key press tracking.
4
+ * Returns a proxy that provides reactive boolean refs for any key.
5
+ *
6
+ * @example
7
+ * ```ts
8
+ * const keys = useMagicKeys()
9
+ * whenever(keys['ctrl+s'], () => save())
10
+ * ```
11
+ */
12
+ export declare function useMagicKeys(): Record<string, Ref<boolean>> & { current: Ref<Set<string>> };
13
+ export declare interface UseMagicKeysReturn {
14
+ [key: string]: Ref<boolean> | Ref<Set<string>>
15
+ current: Ref<Set<string>>
16
+ }
@@ -0,0 +1,81 @@
1
+ import { onUnmounted, ref } from "@stacksjs/stx";
2
+ export function useMagicKeys() {
3
+ const current = ref(new Set), refs = new Map;
4
+ function getRef(key) {
5
+ const lower = key.toLowerCase();
6
+ if (!refs.has(lower))
7
+ refs.set(lower, ref(!1));
8
+ return refs.get(lower);
9
+ }
10
+ function updateCombos() {
11
+ for (const [key, r] of refs)
12
+ if (key.includes("+")) {
13
+ const parts = key.split("+").map((p) => p.trim().toLowerCase());
14
+ r.value = parts.every((p) => current.value.has(p));
15
+ }
16
+ }
17
+ if (typeof window < "u") {
18
+ const onKeyDown = (e) => {
19
+ const key = e.key.toLowerCase();
20
+ current.value.add(key);
21
+ current.value = new Set(current.value);
22
+ const r = getRef(key);
23
+ r.value = !0;
24
+ if (e.ctrlKey) {
25
+ getRef("ctrl").value = !0;
26
+ current.value.add("ctrl");
27
+ }
28
+ if (e.shiftKey) {
29
+ getRef("shift").value = !0;
30
+ current.value.add("shift");
31
+ }
32
+ if (e.altKey) {
33
+ getRef("alt").value = !0;
34
+ current.value.add("alt");
35
+ }
36
+ if (e.metaKey) {
37
+ getRef("meta").value = !0;
38
+ current.value.add("meta");
39
+ }
40
+ updateCombos();
41
+ }, onKeyUp = (e) => {
42
+ const key = e.key.toLowerCase();
43
+ current.value.delete(key);
44
+ current.value = new Set(current.value);
45
+ const r = getRef(key);
46
+ r.value = !1;
47
+ if (!e.ctrlKey) {
48
+ getRef("ctrl").value = !1;
49
+ current.value.delete("ctrl");
50
+ }
51
+ if (!e.shiftKey) {
52
+ getRef("shift").value = !1;
53
+ current.value.delete("shift");
54
+ }
55
+ if (!e.altKey) {
56
+ getRef("alt").value = !1;
57
+ current.value.delete("alt");
58
+ }
59
+ if (!e.metaKey) {
60
+ getRef("meta").value = !1;
61
+ current.value.delete("meta");
62
+ }
63
+ updateCombos();
64
+ };
65
+ window.addEventListener("keydown", onKeyDown, { passive: !0 });
66
+ window.addEventListener("keyup", onKeyUp, { passive: !0 });
67
+ try {
68
+ onUnmounted(() => {
69
+ window.removeEventListener("keydown", onKeyDown);
70
+ window.removeEventListener("keyup", onKeyUp);
71
+ });
72
+ } catch {}
73
+ }
74
+ return new Proxy({ current }, {
75
+ get(target, prop) {
76
+ if (prop === "current")
77
+ return current;
78
+ return getRef(prop);
79
+ }
80
+ });
81
+ }
@@ -0,0 +1,27 @@
1
+ import type { Ref } from '@stacksjs/stx';
2
+ /**
3
+ * Manual commit-based ref history tracking.
4
+ * Provides undo/redo capabilities with manual commits.
5
+ *
6
+ * @param source - The reactive source to track
7
+ * @param options - Capacity limit and clone behavior
8
+ */
9
+ export declare function useManualRefHistory<T>(source: Ref<T>, options?: UseManualRefHistoryOptions): UseManualRefHistoryReturn<T>;
10
+ export declare interface UseManualRefHistoryRecord<T> {
11
+ snapshot: T
12
+ timestamp: number
13
+ }
14
+ export declare interface UseManualRefHistoryOptions {
15
+ capacity?: number
16
+ clone?: boolean
17
+ }
18
+ export declare interface UseManualRefHistoryReturn<T> {
19
+ history: Ref<UseManualRefHistoryRecord<T>[]>
20
+ commit: () => void
21
+ undo: () => void
22
+ redo: () => void
23
+ canUndo: Ref<boolean>
24
+ canRedo: Ref<boolean>
25
+ clear: () => void
26
+ last: Ref<UseManualRefHistoryRecord<T>>
27
+ }
@@ -0,0 +1,64 @@
1
+ import { computed, ref } from "@stacksjs/stx";
2
+ function cloneValue(val, shouldClone) {
3
+ if (!shouldClone)
4
+ return val;
5
+ if (typeof structuredClone === "function")
6
+ return structuredClone(val);
7
+ return JSON.parse(JSON.stringify(val));
8
+ }
9
+ export function useManualRefHistory(source, options = {}) {
10
+ const { capacity = 1 / 0, clone = !1 } = options, undoStack = ref([
11
+ { snapshot: cloneValue(source.value, clone), timestamp: Date.now() }
12
+ ]), redoStack = ref([]), canUndo = computed(() => undoStack.value.length > 1), canRedo = computed(() => redoStack.value.length > 0), last = computed(() => {
13
+ return undoStack.value[undoStack.value.length - 1];
14
+ });
15
+ function commit() {
16
+ const record = {
17
+ snapshot: cloneValue(source.value, clone),
18
+ timestamp: Date.now()
19
+ };
20
+ undoStack.value = [...undoStack.value, record];
21
+ if (capacity !== 1 / 0 && undoStack.value.length > capacity)
22
+ undoStack.value = undoStack.value.slice(undoStack.value.length - capacity);
23
+ redoStack.value = [];
24
+ }
25
+ function undo() {
26
+ if (undoStack.value.length <= 1)
27
+ return;
28
+ const current = undoStack.value[undoStack.value.length - 1], newUndoStack = undoStack.value.slice(0, -1);
29
+ undoStack.value = newUndoStack;
30
+ if (current)
31
+ redoStack.value = [...redoStack.value, current];
32
+ const previous = newUndoStack[newUndoStack.length - 1];
33
+ if (!previous)
34
+ return;
35
+ source.value = cloneValue(previous.snapshot, clone);
36
+ }
37
+ function redo() {
38
+ if (redoStack.value.length === 0)
39
+ return;
40
+ const next = redoStack.value[redoStack.value.length - 1];
41
+ redoStack.value = redoStack.value.slice(0, -1);
42
+ if (next)
43
+ undoStack.value = [...undoStack.value, next];
44
+ if (!next)
45
+ return;
46
+ source.value = cloneValue(next.snapshot, clone);
47
+ }
48
+ function clear() {
49
+ undoStack.value = [
50
+ { snapshot: cloneValue(source.value, clone), timestamp: Date.now() }
51
+ ];
52
+ redoStack.value = [];
53
+ }
54
+ return {
55
+ history: undoStack,
56
+ commit,
57
+ undo,
58
+ redo,
59
+ canUndo,
60
+ canRedo,
61
+ clear,
62
+ last
63
+ };
64
+ }
@@ -0,0 +1,17 @@
1
+ import type { Ref } from '@stacksjs/stx';
2
+ export declare function useAbs(value: MaybeRef<number>): Ref<number>;
3
+ export declare function useAverage(...args: MaybeRef<number>[]): Ref<number>;
4
+ export declare function useCeil(value: MaybeRef<number>): Ref<number>;
5
+ export declare function useClamp(value: MaybeRef<number>, min: MaybeRef<number>, max: MaybeRef<number>): Ref<number>;
6
+ export declare function useFloor(value: MaybeRef<number>): Ref<number>;
7
+ export declare function useMax(...args: MaybeRef<number>[]): Ref<number>;
8
+ export declare function useMin(...args: MaybeRef<number>[]): Ref<number>;
9
+ export declare function usePrecision(value: MaybeRef<number>, digits?: MaybeRef<number>): Ref<number>;
10
+ export declare function useRound(value: MaybeRef<number>): Ref<number>;
11
+ export declare function useSum(...args: MaybeRef<number>[]): Ref<number>;
12
+ export declare function useTrunc(value: MaybeRef<number>): Ref<number>;
13
+ export declare function logicNot(value: MaybeRef<boolean>): Ref<boolean>;
14
+ export declare function logicOr(...args: MaybeRef<boolean>[]): Ref<boolean>;
15
+ export declare function and(...args: MaybeRef<boolean>[]): Ref<boolean>;
16
+ export declare const or: unknown;
17
+ declare type MaybeRef<T> = T | Ref<T>;
@@ -0,0 +1,52 @@
1
+ import { computed, ref } from "@stacksjs/stx";
2
+ function unref(val) {
3
+ if (val && typeof val === "object" && "value" in val && "subscribe" in val)
4
+ return val.value;
5
+ return val;
6
+ }
7
+ export function useAbs(value) {
8
+ return computed(() => Math.abs(unref(value)));
9
+ }
10
+ export function useAverage(...args) {
11
+ return computed(() => {
12
+ const values = args.map(unref);
13
+ return values.length ? values.reduce((a, b) => a + b, 0) / values.length : 0;
14
+ });
15
+ }
16
+ export function useCeil(value) {
17
+ return computed(() => Math.ceil(unref(value)));
18
+ }
19
+ export function useClamp(value, min, max) {
20
+ return computed(() => Math.min(unref(max), Math.max(unref(min), unref(value))));
21
+ }
22
+ export function useFloor(value) {
23
+ return computed(() => Math.floor(unref(value)));
24
+ }
25
+ export function useMax(...args) {
26
+ return computed(() => Math.max(...args.map(unref)));
27
+ }
28
+ export function useMin(...args) {
29
+ return computed(() => Math.min(...args.map(unref)));
30
+ }
31
+ export function usePrecision(value, digits = 0) {
32
+ return computed(() => Number(unref(value).toFixed(Math.max(0, Math.min(100, unref(digits))))));
33
+ }
34
+ export function useRound(value) {
35
+ return computed(() => Math.round(unref(value)));
36
+ }
37
+ export function useSum(...args) {
38
+ return computed(() => args.map(unref).reduce((a, b) => a + b, 0));
39
+ }
40
+ export function useTrunc(value) {
41
+ return computed(() => Math.trunc(unref(value)));
42
+ }
43
+ export function logicNot(value) {
44
+ return computed(() => !unref(value));
45
+ }
46
+ export function logicOr(...args) {
47
+ return computed(() => args.some((a) => unref(a)));
48
+ }
49
+ export const or = logicOr;
50
+ export function and(...args) {
51
+ return computed(() => args.every((a) => unref(a)));
52
+ }
@@ -0,0 +1,9 @@
1
+ import type { MaybeRefOrGetter } from './_shared';
2
+ import type { Ref } from '@stacksjs/stx';
3
+ /**
4
+ * Reactive media query matching.
5
+ * Returns a ref that tracks whether the given CSS media query matches.
6
+ *
7
+ * @param query - CSS media query string (or ref/getter)
8
+ */
9
+ export declare function useMediaQuery(query: MaybeRefOrGetter<string>): Ref<boolean>;
@@ -0,0 +1,19 @@
1
+ import { onUnmounted, ref } from "@stacksjs/stx";
2
+ import { defaultWindow, toValue } from "./_shared";
3
+ export function useMediaQuery(query) {
4
+ const win = defaultWindow(), matches = ref(!1);
5
+ if (!win || !win.matchMedia)
6
+ return matches;
7
+ const queryStr = toValue(query), mediaQuery = win.matchMedia(queryStr);
8
+ matches.value = mediaQuery.matches;
9
+ const handler = (e) => {
10
+ matches.value = e.matches;
11
+ };
12
+ mediaQuery.addEventListener("change", handler);
13
+ try {
14
+ onUnmounted(() => {
15
+ mediaQuery.removeEventListener("change", handler);
16
+ });
17
+ } catch {}
18
+ return matches;
19
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Memoize a function based on its arguments.
3
+ *
4
+ * @param fn - The function to memoize
5
+ * @param getKey - Optional function to generate cache key from arguments
6
+ * @returns A memoized version of the function with cache control methods
7
+ */
8
+ export declare function useMemoize<T, Args extends any[]>(_fn: (..._args: Args) => T, getKey?: (...args: Args) => string): ((...args: Args) => T) & {
9
+ load: (...args: Args) => T
10
+ delete: (...args: Args) => void
11
+ clear: () => void
12
+ cache: Map<string, T>
13
+ };
@@ -0,0 +1,24 @@
1
+ export function useMemoize(_fn, getKey) {
2
+ const cache = new Map, keyFn = getKey ?? ((...args) => JSON.stringify(args)), memoized = function(...args) {
3
+ const key = keyFn(...args);
4
+ if (cache.has(key))
5
+ return cache.get(key);
6
+ const result = _fn(...args);
7
+ cache.set(key, result);
8
+ return result;
9
+ };
10
+ memoized.load = (...args) => {
11
+ const key = keyFn(...args), result = _fn(...args);
12
+ cache.set(key, result);
13
+ return result;
14
+ };
15
+ memoized.delete = (...args) => {
16
+ const key = keyFn(...args);
17
+ cache.delete(key);
18
+ };
19
+ memoized.clear = () => {
20
+ cache.clear();
21
+ };
22
+ memoized.cache = cache;
23
+ return memoized;
24
+ }
@@ -0,0 +1,6 @@
1
+ import type { Ref } from '@stacksjs/stx';
2
+ /**
3
+ * Reactive state indicating if the component is mounted.
4
+ * Returns a ref that becomes true after the initial execution context.
5
+ */
6
+ export declare function useMounted(): Ref<boolean>;
@@ -0,0 +1,8 @@
1
+ import { ref } from "@stacksjs/stx";
2
+ export function useMounted() {
3
+ const isMounted = ref(!1);
4
+ Promise.resolve().then(() => {
5
+ isMounted.value = !0;
6
+ });
7
+ return isMounted;
8
+ }
@@ -0,0 +1,19 @@
1
+ import type { Ref } from '@stacksjs/stx';
2
+ /**
3
+ * Reactive mouse position.
4
+ * Tracks the mouse (and optionally touch) position on the page.
5
+ *
6
+ * @param options - Configuration for coordinate type, touch tracking, and initial values
7
+ * @returns Reactive x, y coordinates and source type
8
+ */
9
+ export declare function useMouse(options?: UseMouseOptions): UseMouseReturn;
10
+ export declare interface UseMouseOptions {
11
+ type?: 'page' | 'client' | 'screen'
12
+ touch?: boolean
13
+ initialValue?: { x: number, y: number }
14
+ }
15
+ export declare interface UseMouseReturn {
16
+ x: Ref<number>
17
+ y: Ref<number>
18
+ sourceType: Ref<'mouse' | 'touch' | null>
19
+ }
@@ -0,0 +1,67 @@
1
+ import { onUnmounted, ref } from "@stacksjs/stx";
2
+ import { noop } from "./_shared";
3
+ export function useMouse(options) {
4
+ const type = options?.type ?? "page", touch = options?.touch ?? !0, initialValue = options?.initialValue ?? { x: 0, y: 0 }, x = ref(initialValue.x), y = ref(initialValue.y), sourceType = ref(null);
5
+ let cleanup = noop;
6
+ if (typeof window < "u") {
7
+ const cleanups = [], getMouseCoords = (event) => {
8
+ switch (type) {
9
+ case "page":
10
+ return { x: event.pageX, y: event.pageY };
11
+ case "client":
12
+ return { x: event.clientX, y: event.clientY };
13
+ case "screen":
14
+ return { x: event.screenX, y: event.screenY };
15
+ default:
16
+ return { x: event.pageX, y: event.pageY };
17
+ }
18
+ }, mouseHandler = (event) => {
19
+ const coords = getMouseCoords(event);
20
+ x.value = coords.x;
21
+ y.value = coords.y;
22
+ sourceType.value = "mouse";
23
+ };
24
+ window.addEventListener("mousemove", mouseHandler, { passive: !0 });
25
+ cleanups.push(() => window.removeEventListener("mousemove", mouseHandler));
26
+ if (touch) {
27
+ const touchHandler = (event) => {
28
+ if (event.touches.length > 0) {
29
+ const touchEvent = event.touches[0];
30
+ if (!touchEvent)
31
+ return;
32
+ switch (type) {
33
+ case "page":
34
+ x.value = touchEvent.pageX;
35
+ y.value = touchEvent.pageY;
36
+ break;
37
+ case "client":
38
+ x.value = touchEvent.clientX;
39
+ y.value = touchEvent.clientY;
40
+ break;
41
+ case "screen":
42
+ x.value = touchEvent.screenX;
43
+ y.value = touchEvent.screenY;
44
+ break;
45
+ }
46
+ sourceType.value = "touch";
47
+ }
48
+ };
49
+ window.addEventListener("touchstart", touchHandler, { passive: !0 });
50
+ window.addEventListener("touchmove", touchHandler, { passive: !0 });
51
+ cleanups.push(() => {
52
+ window.removeEventListener("touchstart", touchHandler);
53
+ window.removeEventListener("touchmove", touchHandler);
54
+ });
55
+ }
56
+ cleanup = () => {
57
+ for (const fn of cleanups)
58
+ fn();
59
+ cleanups.length = 0;
60
+ cleanup = noop;
61
+ };
62
+ }
63
+ try {
64
+ onUnmounted(() => cleanup());
65
+ } catch {}
66
+ return { x, y, sourceType };
67
+ }
@@ -0,0 +1,17 @@
1
+ import type { MaybeRef } from './_shared';
2
+ import type { Ref } from '@stacksjs/stx';
3
+ /**
4
+ * Reactive mouse position relative to an element.
5
+ */
6
+ export declare function useMouseInElement(target: MaybeRef<HTMLElement | null | undefined>): UseMouseInElementReturn;
7
+ export declare interface UseMouseInElementReturn {
8
+ x: Ref<number>
9
+ y: Ref<number>
10
+ elementX: Ref<number>
11
+ elementY: Ref<number>
12
+ elementPositionX: Ref<number>
13
+ elementPositionY: Ref<number>
14
+ elementHeight: Ref<number>
15
+ elementWidth: Ref<number>
16
+ isOutside: Ref<boolean>
17
+ }
@@ -0,0 +1,31 @@
1
+ import { onUnmounted, ref } from "@stacksjs/stx";
2
+ import { unref } from "./_shared";
3
+ export function useMouseInElement(target) {
4
+ const x = ref(0), y = ref(0), elementX = ref(0), elementY = ref(0), elementPositionX = ref(0), elementPositionY = ref(0), elementHeight = ref(0), elementWidth = ref(0), isOutside = ref(!0);
5
+ if (typeof window > "u")
6
+ return { x, y, elementX, elementY, elementPositionX, elementPositionY, elementHeight, elementWidth, isOutside };
7
+ const handler = (event) => {
8
+ x.value = event.pageX;
9
+ y.value = event.pageY;
10
+ const el = unref(target);
11
+ if (!el) {
12
+ isOutside.value = !0;
13
+ return;
14
+ }
15
+ const rect = el.getBoundingClientRect();
16
+ elementPositionX.value = rect.left + window.scrollX;
17
+ elementPositionY.value = rect.top + window.scrollY;
18
+ elementHeight.value = rect.height;
19
+ elementWidth.value = rect.width;
20
+ elementX.value = event.pageX - elementPositionX.value;
21
+ elementY.value = event.pageY - elementPositionY.value;
22
+ isOutside.value = elementX.value < 0 || elementY.value < 0 || elementX.value > elementWidth.value || elementY.value > elementHeight.value;
23
+ };
24
+ window.addEventListener("mousemove", handler, { passive: !0 });
25
+ try {
26
+ onUnmounted(() => {
27
+ window.removeEventListener("mousemove", handler);
28
+ });
29
+ } catch {}
30
+ return { x, y, elementX, elementY, elementPositionX, elementPositionY, elementHeight, elementWidth, isOutside };
31
+ }
@@ -0,0 +1,10 @@
1
+ import type { MaybeRef } from './_shared';
2
+ import type { Ref } from '@stacksjs/stx';
3
+ /**
4
+ * Reactive mouse/touch pressed state.
5
+ */
6
+ export declare function useMousePressed(target?: MaybeRef<HTMLElement | Window | null | undefined>): UseMousePressedReturn;
7
+ export declare interface UseMousePressedReturn {
8
+ pressed: Ref<boolean>
9
+ sourceType: Ref<'mouse' | 'touch' | null>
10
+ }
@@ -0,0 +1,31 @@
1
+ import { onUnmounted, ref } from "@stacksjs/stx";
2
+ import { unref } from "./_shared";
3
+ export function useMousePressed(target) {
4
+ const pressed = ref(!1), sourceType = ref(null);
5
+ if (typeof window > "u")
6
+ return { pressed, sourceType };
7
+ const el = unref(target) ?? window, onMouseDown = () => {
8
+ pressed.value = !0;
9
+ sourceType.value = "mouse";
10
+ }, onTouchStart = () => {
11
+ pressed.value = !0;
12
+ sourceType.value = "touch";
13
+ }, onUp = () => {
14
+ pressed.value = !1;
15
+ };
16
+ el.addEventListener("mousedown", onMouseDown, { passive: !0 });
17
+ el.addEventListener("touchstart", onTouchStart, { passive: !0 });
18
+ window.addEventListener("mouseup", onUp, { passive: !0 });
19
+ window.addEventListener("touchend", onUp, { passive: !0 });
20
+ window.addEventListener("touchcancel", onUp, { passive: !0 });
21
+ try {
22
+ onUnmounted(() => {
23
+ el.removeEventListener("mousedown", onMouseDown);
24
+ el.removeEventListener("touchstart", onTouchStart);
25
+ window.removeEventListener("mouseup", onUp);
26
+ window.removeEventListener("touchend", onUp);
27
+ window.removeEventListener("touchcancel", onUp);
28
+ });
29
+ } catch {}
30
+ return { pressed, sourceType };
31
+ }
@@ -0,0 +1,16 @@
1
+ import { type MaybeRef } from './_shared';
2
+ import type { Ref } from '@stacksjs/stx';
3
+ /**
4
+ * Reactive MutationObserver.
5
+ * Observes the target element and calls the callback when mutations occur.
6
+ *
7
+ * @param target - The element to observe (or a Ref to one)
8
+ * @param callback - MutationCallback
9
+ * @param options - MutationObserverInit options
10
+ * @returns isSupported ref and stop function
11
+ */
12
+ export declare function useMutationObserver(target: MaybeRef<HTMLElement | null>, callback: MutationCallback, options?: MutationObserverInit): UseMutationObserverReturn;
13
+ export declare interface UseMutationObserverReturn {
14
+ isSupported: Ref<boolean>
15
+ stop: () => void
16
+ }