@zuzjs/ui 0.7.8 → 0.8.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.
Files changed (248) hide show
  1. package/dist/cjs/comps/Alert/index.d.ts +2 -2
  2. package/dist/cjs/comps/Alert/index.js +1 -1
  3. package/dist/cjs/comps/Alert/types.d.ts +3 -2
  4. package/dist/cjs/comps/Box/index.d.ts +1 -2
  5. package/dist/cjs/comps/Box/index.js +14 -12
  6. package/dist/cjs/comps/Button/index.d.ts +1 -1
  7. package/dist/cjs/comps/Button/types.d.ts +1 -1
  8. package/dist/cjs/comps/ColorScheme/index.d.ts +3 -2
  9. package/dist/cjs/comps/ColorScheme/index.js +24 -9
  10. package/dist/cjs/comps/ColorScheme/types.d.ts +4 -0
  11. package/dist/cjs/comps/ColorScheme/types.js +1 -0
  12. package/dist/cjs/comps/ContextMenu/index.js +1 -2
  13. package/dist/cjs/comps/Cover/index.js +1 -1
  14. package/dist/cjs/comps/Crumb/index.d.ts +4 -0
  15. package/dist/cjs/comps/Crumb/index.js +13 -0
  16. package/dist/cjs/comps/Crumb/types.d.ts +11 -0
  17. package/dist/cjs/comps/Crumb/types.js +1 -0
  18. package/dist/cjs/comps/Drawer/index.js +16 -15
  19. package/dist/cjs/comps/Form/index.d.ts +3 -59
  20. package/dist/cjs/comps/Form/types.d.ts +43 -0
  21. package/dist/cjs/comps/Form/types.js +1 -0
  22. package/dist/cjs/comps/Icon/index.js +0 -1
  23. package/dist/cjs/comps/Image/index.js +0 -1
  24. package/dist/cjs/comps/KeyboardKeys/index.d.ts +8 -0
  25. package/dist/cjs/comps/KeyboardKeys/index.js +33 -0
  26. package/dist/cjs/comps/KeyboardKeys/types.d.ts +13 -0
  27. package/dist/cjs/comps/KeyboardKeys/types.js +51 -0
  28. package/dist/cjs/comps/Label/index.js +0 -1
  29. package/dist/cjs/comps/List/index.d.ts +4 -1
  30. package/dist/cjs/comps/List/index.js +4 -4
  31. package/dist/cjs/comps/List/item.js +5 -1
  32. package/dist/cjs/comps/List/types.d.ts +4 -1
  33. package/dist/cjs/comps/Network/index.js +3 -5
  34. package/dist/cjs/comps/Pagination/index.js +2 -2
  35. package/dist/cjs/comps/ScrollView/index.d.ts +5 -0
  36. package/dist/cjs/comps/ScrollView/index.js +13 -0
  37. package/dist/cjs/comps/ScrollView/types.d.ts +6 -0
  38. package/dist/cjs/comps/ScrollView/types.js +1 -0
  39. package/dist/cjs/comps/Search/index.d.ts +7 -10
  40. package/dist/cjs/comps/Search/index.js +10 -6
  41. package/dist/cjs/comps/Search/types.d.ts +12 -0
  42. package/dist/cjs/comps/Search/types.js +1 -0
  43. package/dist/cjs/comps/Segmented/index.d.ts +3 -2
  44. package/dist/cjs/comps/Segmented/index.js +6 -5
  45. package/dist/cjs/comps/Segmented/item.js +11 -2
  46. package/dist/cjs/comps/Segmented/types.d.ts +5 -1
  47. package/dist/cjs/comps/Select/index.d.ts +1 -1
  48. package/dist/cjs/comps/Select/types.d.ts +1 -1
  49. package/dist/cjs/comps/Sheet/index.d.ts +4 -0
  50. package/dist/cjs/comps/Sheet/index.js +11 -6
  51. package/dist/cjs/comps/Spinner/index.js +1 -2
  52. package/dist/cjs/comps/TabView/index.d.ts +1 -1
  53. package/dist/cjs/comps/TabView/types.d.ts +2 -2
  54. package/dist/cjs/comps/Table/index.js +12 -5
  55. package/dist/cjs/comps/Table/row.js +3 -2
  56. package/dist/cjs/comps/Table/types.d.ts +88 -1
  57. package/dist/cjs/comps/Text/index.d.ts +2 -0
  58. package/dist/cjs/comps/Text/index.js +4 -2
  59. package/dist/cjs/comps/TextArea/index.d.ts +2 -0
  60. package/dist/cjs/comps/TextArea/index.js +3 -4
  61. package/dist/cjs/comps/Treeview/index.js +3 -2
  62. package/dist/cjs/comps/Treeview/item.d.ts +1 -1
  63. package/dist/cjs/comps/Treeview/item.js +5 -4
  64. package/dist/cjs/comps/Treeview/types.d.ts +1 -1
  65. package/dist/cjs/comps/VideoPlayer/index.d.ts +2 -0
  66. package/dist/cjs/comps/VideoPlayer/index.js +7 -0
  67. package/dist/cjs/comps/index.d.ts +26 -18
  68. package/dist/cjs/comps/index.js +8 -0
  69. package/dist/cjs/funs/css.d.ts +3 -3
  70. package/dist/cjs/funs/css.js +20 -18
  71. package/dist/cjs/funs/index.d.ts +2 -1
  72. package/dist/cjs/funs/index.js +12 -2
  73. package/dist/cjs/funs/stylesheet.js +7 -0
  74. package/dist/cjs/hooks/index.d.ts +15 -6
  75. package/dist/cjs/hooks/index.js +16 -7
  76. package/dist/cjs/hooks/useAnchorPosition.d.ts +1 -2
  77. package/dist/cjs/hooks/useAnchorPosition.js +1 -0
  78. package/dist/cjs/hooks/useBase.js +27 -13
  79. package/dist/cjs/hooks/useCalendar.js +1 -0
  80. package/dist/cjs/hooks/useColorScheme.js +2 -2
  81. package/dist/cjs/hooks/useContextMenu.js +1 -0
  82. package/dist/cjs/hooks/useDB.js +1 -0
  83. package/dist/cjs/hooks/useDebounce.js +2 -1
  84. package/dist/cjs/hooks/useDelayed.js +2 -1
  85. package/dist/cjs/hooks/useDevice.js +1 -0
  86. package/dist/cjs/hooks/useDimensions.js +2 -1
  87. package/dist/cjs/hooks/useDom.d.ts +2 -0
  88. package/dist/cjs/hooks/useDom.js +3 -0
  89. package/dist/cjs/hooks/useDomMutation.d.ts +3 -0
  90. package/dist/cjs/hooks/useDomMutation.js +19 -0
  91. package/dist/cjs/hooks/useDrag.js +2 -1
  92. package/dist/cjs/hooks/useFileManager.d.ts +2 -0
  93. package/dist/cjs/hooks/useFileManager.js +3 -0
  94. package/dist/cjs/hooks/useImage.js +1 -0
  95. package/dist/cjs/hooks/useIntersectionObserver.js +2 -1
  96. package/dist/cjs/hooks/useMediaPlayer.d.ts +32 -0
  97. package/dist/cjs/hooks/useMediaPlayer.js +86 -0
  98. package/dist/cjs/hooks/useMergedRefs.d.ts +2 -0
  99. package/dist/cjs/hooks/useMergedRefs.js +14 -0
  100. package/dist/cjs/hooks/useMutationObserver.d.ts +3 -0
  101. package/dist/cjs/hooks/useMutationObserver.js +20 -0
  102. package/dist/cjs/hooks/useNetworkStatus.js +2 -1
  103. package/dist/cjs/hooks/usePlayer.d.ts +32 -0
  104. package/dist/cjs/hooks/usePlayer.js +85 -0
  105. package/dist/cjs/hooks/useResizeObserver.js +2 -1
  106. package/dist/cjs/hooks/useScrollbar.d.ts +16 -0
  107. package/dist/cjs/hooks/useScrollbar.js +160 -0
  108. package/dist/cjs/hooks/useSheet.js +1 -0
  109. package/dist/cjs/hooks/useShortcuts.d.ts +7 -0
  110. package/dist/cjs/hooks/useShortcuts.js +29 -0
  111. package/dist/cjs/hooks/useSlider.d.ts +7 -0
  112. package/dist/cjs/hooks/useSlider.js +23 -0
  113. package/dist/cjs/hooks/useTruncateText.d.ts +2 -0
  114. package/dist/cjs/hooks/useTruncateText.js +17 -0
  115. package/dist/cjs/hooks/useViewTransition.d.ts +2 -0
  116. package/dist/cjs/hooks/useViewTransition.js +13 -0
  117. package/dist/cjs/hooks/useWebSocket.d.ts +15 -0
  118. package/dist/cjs/hooks/useWebSocket.js +87 -0
  119. package/dist/cjs/types/enums.d.ts +1 -0
  120. package/dist/cjs/types/enums.js +1 -0
  121. package/dist/cjs/types/index.d.ts +2 -1
  122. package/dist/cjs/types/interfaces.d.ts +2 -0
  123. package/dist/css/styles.css +1 -1
  124. package/dist/esm/comps/Alert/index.d.ts +2 -2
  125. package/dist/esm/comps/Alert/index.js +1 -1
  126. package/dist/esm/comps/Alert/types.d.ts +3 -2
  127. package/dist/esm/comps/Box/index.d.ts +1 -2
  128. package/dist/esm/comps/Box/index.js +14 -12
  129. package/dist/esm/comps/Button/index.d.ts +1 -1
  130. package/dist/esm/comps/Button/types.d.ts +1 -1
  131. package/dist/esm/comps/ColorScheme/index.d.ts +3 -2
  132. package/dist/esm/comps/ColorScheme/index.js +24 -9
  133. package/dist/esm/comps/ColorScheme/types.d.ts +4 -0
  134. package/dist/esm/comps/ColorScheme/types.js +1 -0
  135. package/dist/esm/comps/ContextMenu/index.js +1 -2
  136. package/dist/esm/comps/Cover/index.js +1 -1
  137. package/dist/esm/comps/Crumb/index.d.ts +4 -0
  138. package/dist/esm/comps/Crumb/index.js +13 -0
  139. package/dist/esm/comps/Crumb/types.d.ts +11 -0
  140. package/dist/esm/comps/Crumb/types.js +1 -0
  141. package/dist/esm/comps/Drawer/index.js +16 -15
  142. package/dist/esm/comps/Form/index.d.ts +3 -59
  143. package/dist/esm/comps/Form/types.d.ts +43 -0
  144. package/dist/esm/comps/Form/types.js +1 -0
  145. package/dist/esm/comps/Icon/index.js +0 -1
  146. package/dist/esm/comps/Image/index.js +0 -1
  147. package/dist/esm/comps/KeyboardKeys/index.d.ts +8 -0
  148. package/dist/esm/comps/KeyboardKeys/index.js +33 -0
  149. package/dist/esm/comps/KeyboardKeys/types.d.ts +13 -0
  150. package/dist/esm/comps/KeyboardKeys/types.js +51 -0
  151. package/dist/esm/comps/Label/index.js +0 -1
  152. package/dist/esm/comps/List/index.d.ts +4 -1
  153. package/dist/esm/comps/List/index.js +4 -4
  154. package/dist/esm/comps/List/item.js +5 -1
  155. package/dist/esm/comps/List/types.d.ts +4 -1
  156. package/dist/esm/comps/Network/index.js +3 -5
  157. package/dist/esm/comps/Pagination/index.js +2 -2
  158. package/dist/esm/comps/ScrollView/index.d.ts +5 -0
  159. package/dist/esm/comps/ScrollView/index.js +13 -0
  160. package/dist/esm/comps/ScrollView/types.d.ts +6 -0
  161. package/dist/esm/comps/ScrollView/types.js +1 -0
  162. package/dist/esm/comps/Search/index.d.ts +7 -10
  163. package/dist/esm/comps/Search/index.js +10 -6
  164. package/dist/esm/comps/Search/types.d.ts +12 -0
  165. package/dist/esm/comps/Search/types.js +1 -0
  166. package/dist/esm/comps/Segmented/index.d.ts +3 -2
  167. package/dist/esm/comps/Segmented/index.js +6 -5
  168. package/dist/esm/comps/Segmented/item.js +11 -2
  169. package/dist/esm/comps/Segmented/types.d.ts +5 -1
  170. package/dist/esm/comps/Select/index.d.ts +1 -1
  171. package/dist/esm/comps/Select/types.d.ts +1 -1
  172. package/dist/esm/comps/Sheet/index.d.ts +4 -0
  173. package/dist/esm/comps/Sheet/index.js +11 -6
  174. package/dist/esm/comps/Spinner/index.js +1 -2
  175. package/dist/esm/comps/TabView/index.d.ts +1 -1
  176. package/dist/esm/comps/TabView/types.d.ts +2 -2
  177. package/dist/esm/comps/Table/index.js +12 -5
  178. package/dist/esm/comps/Table/row.js +3 -2
  179. package/dist/esm/comps/Table/types.d.ts +88 -1
  180. package/dist/esm/comps/Text/index.d.ts +2 -0
  181. package/dist/esm/comps/Text/index.js +4 -2
  182. package/dist/esm/comps/TextArea/index.d.ts +2 -0
  183. package/dist/esm/comps/TextArea/index.js +3 -4
  184. package/dist/esm/comps/Treeview/index.js +3 -2
  185. package/dist/esm/comps/Treeview/item.d.ts +1 -1
  186. package/dist/esm/comps/Treeview/item.js +5 -4
  187. package/dist/esm/comps/Treeview/types.d.ts +1 -1
  188. package/dist/esm/comps/VideoPlayer/index.d.ts +2 -0
  189. package/dist/esm/comps/VideoPlayer/index.js +7 -0
  190. package/dist/esm/comps/index.d.ts +26 -18
  191. package/dist/esm/comps/index.js +8 -0
  192. package/dist/esm/funs/css.d.ts +3 -3
  193. package/dist/esm/funs/css.js +20 -18
  194. package/dist/esm/funs/index.d.ts +2 -1
  195. package/dist/esm/funs/index.js +12 -2
  196. package/dist/esm/funs/stylesheet.js +7 -0
  197. package/dist/esm/hooks/index.d.ts +15 -6
  198. package/dist/esm/hooks/index.js +16 -7
  199. package/dist/esm/hooks/useAnchorPosition.d.ts +1 -2
  200. package/dist/esm/hooks/useAnchorPosition.js +1 -0
  201. package/dist/esm/hooks/useBase.js +27 -13
  202. package/dist/esm/hooks/useCalendar.js +1 -0
  203. package/dist/esm/hooks/useColorScheme.js +2 -2
  204. package/dist/esm/hooks/useContextMenu.js +1 -0
  205. package/dist/esm/hooks/useDB.js +1 -0
  206. package/dist/esm/hooks/useDebounce.js +2 -1
  207. package/dist/esm/hooks/useDelayed.js +2 -1
  208. package/dist/esm/hooks/useDevice.js +1 -0
  209. package/dist/esm/hooks/useDimensions.js +2 -1
  210. package/dist/esm/hooks/useDom.d.ts +2 -0
  211. package/dist/esm/hooks/useDom.js +3 -0
  212. package/dist/esm/hooks/useDomMutation.d.ts +3 -0
  213. package/dist/esm/hooks/useDomMutation.js +19 -0
  214. package/dist/esm/hooks/useDrag.js +2 -1
  215. package/dist/esm/hooks/useFileManager.d.ts +2 -0
  216. package/dist/esm/hooks/useFileManager.js +3 -0
  217. package/dist/esm/hooks/useImage.js +1 -0
  218. package/dist/esm/hooks/useIntersectionObserver.js +2 -1
  219. package/dist/esm/hooks/useMediaPlayer.d.ts +32 -0
  220. package/dist/esm/hooks/useMediaPlayer.js +86 -0
  221. package/dist/esm/hooks/useMergedRefs.d.ts +2 -0
  222. package/dist/esm/hooks/useMergedRefs.js +14 -0
  223. package/dist/esm/hooks/useMutationObserver.d.ts +3 -0
  224. package/dist/esm/hooks/useMutationObserver.js +20 -0
  225. package/dist/esm/hooks/useNetworkStatus.js +2 -1
  226. package/dist/esm/hooks/usePlayer.d.ts +32 -0
  227. package/dist/esm/hooks/usePlayer.js +85 -0
  228. package/dist/esm/hooks/useResizeObserver.js +2 -1
  229. package/dist/esm/hooks/useScrollbar.d.ts +16 -0
  230. package/dist/esm/hooks/useScrollbar.js +160 -0
  231. package/dist/esm/hooks/useSheet.js +1 -0
  232. package/dist/esm/hooks/useShortcuts.d.ts +7 -0
  233. package/dist/esm/hooks/useShortcuts.js +29 -0
  234. package/dist/esm/hooks/useSlider.d.ts +7 -0
  235. package/dist/esm/hooks/useSlider.js +23 -0
  236. package/dist/esm/hooks/useTruncateText.d.ts +2 -0
  237. package/dist/esm/hooks/useTruncateText.js +17 -0
  238. package/dist/esm/hooks/useViewTransition.d.ts +2 -0
  239. package/dist/esm/hooks/useViewTransition.js +13 -0
  240. package/dist/esm/hooks/useWebSocket.d.ts +15 -0
  241. package/dist/esm/hooks/useWebSocket.js +87 -0
  242. package/dist/esm/types/enums.d.ts +1 -0
  243. package/dist/esm/types/enums.js +1 -0
  244. package/dist/esm/types/index.d.ts +2 -1
  245. package/dist/esm/types/interfaces.d.ts +2 -0
  246. package/dist/tsconfig.esm.tsbuildinfo +1 -1
  247. package/dist/tsconfig.tsbuildinfo +1 -1
  248. package/package.json +1 -1
@@ -0,0 +1,86 @@
1
+ "use client";
2
+ import { useCallback, useRef, useState } from "react";
3
+ const useMediaPlayer = ({ src, type = "video", autoPlay = false, loop = false, controls = false }) => {
4
+ const mediaRef = useRef(null);
5
+ const [isPlaying, setIsPlaying] = useState(autoPlay);
6
+ const [volume, setVolume] = useState(1);
7
+ const [isFullscreen, setIsFullscreen] = useState(false);
8
+ const [currentTime, setCurrentTime] = useState(0);
9
+ const [duration, setDuration] = useState(0);
10
+ // Play / Pause toggle
11
+ const togglePlay = useCallback(() => {
12
+ if (mediaRef.current) {
13
+ if (mediaRef.current.paused) {
14
+ mediaRef.current.play();
15
+ setIsPlaying(true);
16
+ }
17
+ else {
18
+ mediaRef.current.pause();
19
+ setIsPlaying(false);
20
+ }
21
+ }
22
+ }, []);
23
+ // Seek media
24
+ const seek = useCallback((time) => {
25
+ if (mediaRef.current) {
26
+ mediaRef.current.currentTime = time;
27
+ setCurrentTime(time);
28
+ }
29
+ }, []);
30
+ // Change volume
31
+ const changeVolume = useCallback((newVolume) => {
32
+ if (mediaRef.current) {
33
+ mediaRef.current.volume = newVolume;
34
+ setVolume(newVolume);
35
+ }
36
+ }, []);
37
+ // Toggle fullscreen (only for video)
38
+ const toggleFullscreen = useCallback(() => {
39
+ if (type === "video" && mediaRef.current) {
40
+ if (!document.fullscreenElement) {
41
+ mediaRef.current.requestFullscreen?.();
42
+ setIsFullscreen(true);
43
+ }
44
+ else {
45
+ document.exitFullscreen?.();
46
+ setIsFullscreen(false);
47
+ }
48
+ }
49
+ }, [type]);
50
+ // Update time
51
+ const handleTimeUpdate = useCallback(() => {
52
+ if (mediaRef.current) {
53
+ setCurrentTime(mediaRef.current.currentTime);
54
+ }
55
+ }, []);
56
+ // Set duration
57
+ const handleLoadedMetadata = useCallback(() => {
58
+ if (mediaRef.current) {
59
+ setDuration(mediaRef.current.duration);
60
+ }
61
+ }, []);
62
+ return {
63
+ mediaRef,
64
+ isPlaying,
65
+ togglePlay,
66
+ seek,
67
+ volume,
68
+ changeVolume,
69
+ isFullscreen,
70
+ toggleFullscreen,
71
+ currentTime,
72
+ duration,
73
+ handleTimeUpdate,
74
+ handleLoadedMetadata,
75
+ mediaProps: {
76
+ ref: mediaRef,
77
+ src,
78
+ autoPlay,
79
+ loop,
80
+ controls,
81
+ onTimeUpdate: handleTimeUpdate,
82
+ onLoadedMetadata: handleLoadedMetadata,
83
+ },
84
+ };
85
+ };
86
+ export default useMediaPlayer;
@@ -0,0 +1,2 @@
1
+ declare const useMergedRefs: <T>(...refs: (React.Ref<T> | undefined)[]) => (node: T) => void;
2
+ export default useMergedRefs;
@@ -0,0 +1,14 @@
1
+ import { useCallback } from "react";
2
+ const useMergedRefs = (...refs) => {
3
+ return useCallback((node) => {
4
+ refs.forEach((ref) => {
5
+ if (!ref)
6
+ return;
7
+ if (typeof ref === "function")
8
+ ref(node);
9
+ else if ("current" in ref)
10
+ ref.current = node;
11
+ });
12
+ }, [refs]);
13
+ };
14
+ export default useMergedRefs;
@@ -0,0 +1,3 @@
1
+ export type MutationCallback = (mutations: MutationRecord[], observer: MutationObserver) => void;
2
+ declare const useMutationObserver: (target: HTMLElement | null, callback: MutationCallback, options?: MutationObserverInit) => void;
3
+ export default useMutationObserver;
@@ -0,0 +1,20 @@
1
+ "use client";
2
+ import { useEffect, useRef } from "react";
3
+ const useMutationObserver = (target, callback, options = { childList: true, subtree: true }) => {
4
+ const observerRef = useRef(null);
5
+ useEffect(() => {
6
+ if (!target)
7
+ return;
8
+ // Create a new MutationObserver and pass the callback
9
+ observerRef.current = new MutationObserver(callback);
10
+ // Start observing the target element
11
+ observerRef.current.observe(target, options);
12
+ // Cleanup function to disconnect the observer
13
+ return () => {
14
+ if (observerRef.current) {
15
+ observerRef.current.disconnect();
16
+ }
17
+ };
18
+ }, [target, callback, options]);
19
+ };
20
+ export default useMutationObserver;
@@ -1,4 +1,5 @@
1
- import { useState, useEffect } from 'react';
1
+ "use client";
2
+ import { useEffect, useState } from 'react';
2
3
  const useNetworkStatus = () => {
3
4
  const [isOnline, setIsOnline] = useState(null);
4
5
  const updateNetworkStatus = () => {
@@ -0,0 +1,32 @@
1
+ export type MediaType = "video" | "audio";
2
+ export type MediaPlayerProps = {
3
+ src: string;
4
+ type?: MediaType;
5
+ autoPlay?: boolean;
6
+ loop?: boolean;
7
+ controls?: boolean;
8
+ };
9
+ declare const useMediaPlayer: ({ src, type, autoPlay, loop, controls }: MediaPlayerProps) => {
10
+ mediaRef: import("react").RefObject<(HTMLVideoElement & HTMLAudioElement) | null>;
11
+ isPlaying: boolean;
12
+ togglePlay: () => void;
13
+ seek: (time: number) => void;
14
+ volume: number;
15
+ changeVolume: (newVolume: number) => void;
16
+ isFullscreen: boolean;
17
+ toggleFullscreen: () => void;
18
+ currentTime: number;
19
+ duration: number;
20
+ handleTimeUpdate: () => void;
21
+ handleLoadedMetadata: () => void;
22
+ mediaProps: {
23
+ ref: import("react").RefObject<(HTMLVideoElement & HTMLAudioElement) | null>;
24
+ src: string;
25
+ autoPlay: boolean;
26
+ loop: boolean;
27
+ controls: boolean;
28
+ onTimeUpdate: () => void;
29
+ onLoadedMetadata: () => void;
30
+ };
31
+ };
32
+ export default useMediaPlayer;
@@ -0,0 +1,85 @@
1
+ import { useCallback, useRef, useState } from "react";
2
+ const useMediaPlayer = ({ src, type = "video", autoPlay = false, loop = false, controls = false }) => {
3
+ const mediaRef = useRef(null);
4
+ const [isPlaying, setIsPlaying] = useState(autoPlay);
5
+ const [volume, setVolume] = useState(1);
6
+ const [isFullscreen, setIsFullscreen] = useState(false);
7
+ const [currentTime, setCurrentTime] = useState(0);
8
+ const [duration, setDuration] = useState(0);
9
+ // Play / Pause toggle
10
+ const togglePlay = useCallback(() => {
11
+ if (mediaRef.current) {
12
+ if (mediaRef.current.paused) {
13
+ mediaRef.current.play();
14
+ setIsPlaying(true);
15
+ }
16
+ else {
17
+ mediaRef.current.pause();
18
+ setIsPlaying(false);
19
+ }
20
+ }
21
+ }, []);
22
+ // Seek media
23
+ const seek = useCallback((time) => {
24
+ if (mediaRef.current) {
25
+ mediaRef.current.currentTime = time;
26
+ setCurrentTime(time);
27
+ }
28
+ }, []);
29
+ // Change volume
30
+ const changeVolume = useCallback((newVolume) => {
31
+ if (mediaRef.current) {
32
+ mediaRef.current.volume = newVolume;
33
+ setVolume(newVolume);
34
+ }
35
+ }, []);
36
+ // Toggle fullscreen (only for video)
37
+ const toggleFullscreen = useCallback(() => {
38
+ if (type === "video" && mediaRef.current) {
39
+ if (!document.fullscreenElement) {
40
+ mediaRef.current.requestFullscreen?.();
41
+ setIsFullscreen(true);
42
+ }
43
+ else {
44
+ document.exitFullscreen?.();
45
+ setIsFullscreen(false);
46
+ }
47
+ }
48
+ }, [type]);
49
+ // Update time
50
+ const handleTimeUpdate = useCallback(() => {
51
+ if (mediaRef.current) {
52
+ setCurrentTime(mediaRef.current.currentTime);
53
+ }
54
+ }, []);
55
+ // Set duration
56
+ const handleLoadedMetadata = useCallback(() => {
57
+ if (mediaRef.current) {
58
+ setDuration(mediaRef.current.duration);
59
+ }
60
+ }, []);
61
+ return {
62
+ mediaRef,
63
+ isPlaying,
64
+ togglePlay,
65
+ seek,
66
+ volume,
67
+ changeVolume,
68
+ isFullscreen,
69
+ toggleFullscreen,
70
+ currentTime,
71
+ duration,
72
+ handleTimeUpdate,
73
+ handleLoadedMetadata,
74
+ mediaProps: {
75
+ ref: mediaRef,
76
+ src,
77
+ autoPlay,
78
+ loop,
79
+ controls,
80
+ onTimeUpdate: handleTimeUpdate,
81
+ onLoadedMetadata: handleLoadedMetadata,
82
+ },
83
+ };
84
+ };
85
+ export default useMediaPlayer;
@@ -1,4 +1,5 @@
1
- import { useState, useEffect } from 'react';
1
+ "use client";
2
+ import { useEffect, useState } from 'react';
2
3
  const useResizeObserver = (ref) => {
3
4
  const [size, setSize] = useState({ width: 0, height: 0, top: 0, left: 0 });
4
5
  useEffect(() => {
@@ -0,0 +1,16 @@
1
+ export interface ScrollBreakpoint {
2
+ [key: number]: () => void;
3
+ }
4
+ declare const useScrollbar: (breakpoints?: ScrollBreakpoint) => {
5
+ rootRef: import("react").RefObject<HTMLDivElement | null>;
6
+ containerRef: import("react").RefObject<HTMLDivElement | null>;
7
+ thumbY: import("react").RefObject<HTMLDivElement | null>;
8
+ thumbX: import("react").RefObject<HTMLDivElement | null>;
9
+ scrollToTop: () => void | undefined;
10
+ scrollToBottom: () => void | undefined;
11
+ scrollToLeft: () => void | undefined;
12
+ scrollToRight: () => void | undefined;
13
+ onScrollY: (e: React.MouseEvent) => void;
14
+ onScrollX: (e: React.MouseEvent) => void;
15
+ };
16
+ export default useScrollbar;
@@ -0,0 +1,160 @@
1
+ "use client";
2
+ import { useCallback, useEffect, useRef } from "react";
3
+ import { useMutationObserver } from "..";
4
+ const useScrollbar = (breakpoints = {}) => {
5
+ const rootRef = useRef(null);
6
+ const containerRef = useRef(null);
7
+ const thumbY = useRef(null);
8
+ const thumbX = useRef(null);
9
+ const isDraggingY = useRef(false);
10
+ const isDraggingX = useRef(false);
11
+ const dragStartX = useRef(0);
12
+ const dragStartY = useRef(0);
13
+ const scrollStartY = useRef(0);
14
+ const scrollStartX = useRef(0);
15
+ const thumbHeight = useRef(30); // Default min height
16
+ const thumbWidth = useRef(30); // Default min height
17
+ const updateThumb = useCallback(() => {
18
+ if (!containerRef.current || !thumbY.current || !thumbX.current)
19
+ return;
20
+ const { clientHeight, scrollHeight, scrollTop, clientWidth, scrollWidth, scrollLeft } = containerRef.current;
21
+ //Y thumb
22
+ const thumbSizeY = Math.max((clientHeight / scrollHeight) * clientHeight, 30); // Min thumb size: 30px
23
+ thumbHeight.current = thumbSizeY;
24
+ const thumbPosY = (scrollTop / (scrollHeight - clientHeight)) * (clientHeight - thumbSizeY);
25
+ thumbY.current.style.height = `${thumbSizeY}px`;
26
+ thumbY.current.style.top = `${thumbPosY}px`;
27
+ //X thumb
28
+ const thumbSizeX = Math.max((clientWidth / scrollWidth) * clientWidth, 30); // Min thumb size: 30px
29
+ thumbWidth.current = thumbSizeX;
30
+ const thumbPosX = (scrollLeft / (scrollWidth - clientWidth)) * (clientWidth - thumbSizeX);
31
+ thumbX.current.style.width = `${thumbSizeX}px`;
32
+ thumbX.current.style.left = `${thumbPosX}px`;
33
+ if (thumbY.current.clientHeight == clientHeight && rootRef) {
34
+ rootRef.current?.classList.add(`--no-y`);
35
+ }
36
+ else
37
+ rootRef.current?.classList.remove(`--no-y`);
38
+ if (thumbX.current.clientWidth == clientWidth && rootRef) {
39
+ rootRef.current?.classList.add(`--no-x`);
40
+ }
41
+ else
42
+ rootRef.current?.classList.remove(`--no-x`);
43
+ }, []);
44
+ const postScroll = (scrollPercentY) => {
45
+ updateThumb();
46
+ // Trigger breakpoints
47
+ Object.keys(breakpoints).forEach((key) => {
48
+ const breakpoint = parseFloat(key);
49
+ if (Math.abs(scrollPercentY - breakpoint) < 1) {
50
+ breakpoints[breakpoint]?.();
51
+ }
52
+ });
53
+ };
54
+ const handleScroll = useCallback(() => {
55
+ if (!containerRef.current)
56
+ return;
57
+ const { scrollTop, scrollHeight, clientHeight, scrollLeft, scrollWidth, clientWidth } = containerRef.current;
58
+ const scrollPercentY = (scrollTop / (scrollHeight - clientHeight)) * 100;
59
+ const scrollPercentX = (scrollLeft / (scrollWidth - clientWidth)) * 100;
60
+ postScroll(scrollPercentY);
61
+ postScroll(scrollPercentX);
62
+ }, [breakpoints, updateThumb]);
63
+ // Dragging logic
64
+ const onScrollY = (e) => {
65
+ isDraggingY.current = true;
66
+ dragStartY.current = e.clientY;
67
+ scrollStartY.current = containerRef.current?.scrollTop || 0;
68
+ document.body.style.userSelect = "none";
69
+ if (rootRef.current)
70
+ rootRef.current?.classList.add(`--scrolling`);
71
+ };
72
+ const onScrollX = (e) => {
73
+ isDraggingX.current = true;
74
+ dragStartX.current = e.clientX;
75
+ scrollStartX.current = containerRef.current?.scrollLeft || 0;
76
+ document.body.style.userSelect = "none";
77
+ if (rootRef.current)
78
+ rootRef.current?.classList.add(`--scrolling`);
79
+ };
80
+ const handleDragMove = useCallback((e) => {
81
+ if (!containerRef.current || !thumbY.current || !thumbX.current)
82
+ return;
83
+ const { clientHeight, scrollHeight, clientWidth, scrollWidth } = containerRef.current;
84
+ if (isDraggingY.current) {
85
+ const maxScroll = scrollHeight - clientHeight;
86
+ const maxThumbMove = clientHeight - thumbHeight.current;
87
+ const deltaY = e.clientY - dragStartY.current;
88
+ const newScrollTop = Math.min(Math.max(scrollStartY.current + (deltaY / maxThumbMove) * maxScroll, 0), maxScroll);
89
+ containerRef.current.scrollTop = newScrollTop;
90
+ }
91
+ if (isDraggingX.current) {
92
+ const maxScrollX = scrollWidth - clientWidth;
93
+ const maxThumbMoveX = clientWidth - thumbWidth.current;
94
+ const deltaX = e.clientX - dragStartX.current;
95
+ const newScrollLeft = Math.min(Math.max(scrollStartX.current + (deltaX / maxThumbMoveX) * maxScrollX, 0), maxScrollX);
96
+ containerRef.current.scrollLeft = newScrollLeft;
97
+ }
98
+ }, []);
99
+ const handleDragEnd = () => {
100
+ isDraggingY.current = false;
101
+ isDraggingX.current = false;
102
+ document.body.style.userSelect = "";
103
+ if (rootRef.current)
104
+ rootRef.current?.classList.remove(`--scrolling`);
105
+ };
106
+ const scrollToTop = () => containerRef.current?.scrollTo({ top: 0, behavior: "smooth" });
107
+ const scrollToBottom = () => containerRef.current?.scrollTo({ top: containerRef.current.scrollHeight, behavior: "smooth" });
108
+ const scrollToLeft = () => containerRef.current?.scrollTo({ left: 0, behavior: "smooth" });
109
+ const scrollToRight = () => containerRef.current?.scrollTo({ left: containerRef.current.scrollWidth, behavior: "smooth" });
110
+ useEffect(() => {
111
+ const container = containerRef.current;
112
+ if (!container)
113
+ return;
114
+ const handleWheel = (e) => {
115
+ e.preventDefault();
116
+ e.stopPropagation();
117
+ if (!containerRef.current)
118
+ return;
119
+ // Adjust scrollTop manually based on deltaY
120
+ const { scrollTop, scrollHeight, clientHeight, scrollLeft, scrollWidth, clientWidth } = containerRef.current;
121
+ if (Math.abs(e.deltaY) > Math.abs(e.deltaX)) {
122
+ const maxScrollY = scrollHeight - clientHeight;
123
+ let newScrollTop = scrollTop + e.deltaY;
124
+ newScrollTop = Math.max(0, Math.min(newScrollTop, maxScrollY));
125
+ containerRef.current.scrollTop = newScrollTop;
126
+ }
127
+ if (Math.abs(e.deltaX) > Math.abs(e.deltaY)) {
128
+ const maxScrollX = scrollWidth - clientWidth;
129
+ let newScrollLeft = scrollLeft + e.deltaX;
130
+ newScrollLeft = Math.max(0, Math.min(newScrollLeft, maxScrollX));
131
+ containerRef.current.scrollLeft = newScrollLeft;
132
+ }
133
+ const scrollPercentY = (containerRef.current.scrollTop / (containerRef.current.scrollHeight - clientHeight)) * 100;
134
+ const scrollPercentX = (containerRef.current.scrollLeft / (containerRef.current.scrollWidth - clientWidth)) * 100;
135
+ postScroll(scrollPercentY);
136
+ postScroll(scrollPercentX);
137
+ };
138
+ window.addEventListener("resize", updateThumb);
139
+ container.addEventListener("scroll", handleScroll);
140
+ // Prevent blocking default scrolling (fixes touchpad scrolling)
141
+ container.addEventListener("wheel", handleWheel, { passive: false });
142
+ document.addEventListener("mousemove", handleDragMove);
143
+ document.addEventListener("mouseup", handleDragEnd);
144
+ updateThumb();
145
+ return () => {
146
+ window.removeEventListener("resize", updateThumb);
147
+ window.removeEventListener("wheel", handleWheel);
148
+ container.removeEventListener("scroll", handleScroll);
149
+ document.removeEventListener("mousemove", handleDragMove);
150
+ document.removeEventListener("mouseup", handleDragEnd);
151
+ };
152
+ }, [handleScroll, handleDragMove, updateThumb]);
153
+ useMutationObserver(containerRef.current, updateThumb);
154
+ return {
155
+ rootRef, containerRef, thumbY, thumbX,
156
+ scrollToTop, scrollToBottom, scrollToLeft, scrollToRight,
157
+ onScrollY, onScrollX
158
+ };
159
+ };
160
+ export default useScrollbar;
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { useEffect } from "react";
2
3
  const useSheet = (sheet) => {
3
4
  const show = (e) => {
@@ -0,0 +1,7 @@
1
+ import { KeyCode } from "../types/enums";
2
+ export type Shortcut = {
3
+ keys: KeyCode[];
4
+ callback: (event: KeyboardEvent) => void;
5
+ };
6
+ declare const useShortcuts: (shortcuts: Shortcut[], preventDefault?: boolean) => void;
7
+ export default useShortcuts;
@@ -0,0 +1,29 @@
1
+ "use client";
2
+ import { useEffect } from "react";
3
+ import { KeyCode } from "../types/enums";
4
+ const useShortcuts = (shortcuts, preventDefault) => {
5
+ useEffect(() => {
6
+ const handleKeyDown = (event) => {
7
+ const pressedKeys = [];
8
+ if (event.ctrlKey)
9
+ pressedKeys.push(KeyCode.Ctrl);
10
+ if (event.shiftKey)
11
+ pressedKeys.push(KeyCode.Shift);
12
+ if (event.altKey)
13
+ pressedKeys.push(KeyCode.Alt);
14
+ if (event.metaKey)
15
+ pressedKeys.push(KeyCode.PauseBreak); // Meta key (Cmd on Mac)
16
+ pressedKeys.push(event.keyCode); // Convert event key to KeyCode enum
17
+ shortcuts.forEach(({ keys, callback }) => {
18
+ if (keys.every(key => pressedKeys.includes(key))) {
19
+ if (preventDefault ?? true)
20
+ event.preventDefault();
21
+ callback(event);
22
+ }
23
+ });
24
+ };
25
+ window.addEventListener("keydown", handleKeyDown);
26
+ return () => window.removeEventListener("keydown", handleKeyDown);
27
+ }, [shortcuts, preventDefault]);
28
+ };
29
+ export default useShortcuts;
@@ -0,0 +1,7 @@
1
+ declare const useSlider: () => {
2
+ push: (key: string) => void;
3
+ goBack: () => void;
4
+ prevKey: string | null;
5
+ direction: "left" | "right";
6
+ };
7
+ export default useSlider;
@@ -0,0 +1,23 @@
1
+ "use client";
2
+ import { useState } from "react";
3
+ import { useViewTransition } from "..";
4
+ const useSlider = () => {
5
+ const [history, setHistory] = useState(["root"]);
6
+ const [prevKey, setPrevKey] = useState(null);
7
+ const [direction, setDirection] = useState("left");
8
+ const startTransition = useViewTransition();
9
+ const push = (key) => {
10
+ setDirection("left");
11
+ setPrevKey(history[history.length - 1]);
12
+ startTransition(() => setHistory((prev) => [...prev, key]));
13
+ };
14
+ const goBack = () => {
15
+ if (history.length <= 1)
16
+ return;
17
+ setDirection("right");
18
+ setPrevKey(history[history.length - 1]);
19
+ startTransition(() => setHistory((prev) => prev.slice(0, -1)));
20
+ };
21
+ return { push, goBack, prevKey, direction };
22
+ };
23
+ export default useSlider;
@@ -0,0 +1,2 @@
1
+ declare const useTruncateText: (lines: number) => import("react").RefObject<HTMLDivElement | null>;
2
+ export default useTruncateText;
@@ -0,0 +1,17 @@
1
+ "use client";
2
+ import { useEffect, useRef } from "react";
3
+ const useTruncateText = (lines) => {
4
+ const ref = useRef(null);
5
+ useEffect(() => {
6
+ if (!ref.current)
7
+ return;
8
+ const el = ref.current;
9
+ const lineHeight = parseFloat(getComputedStyle(el).lineHeight);
10
+ const maxHeight = lineHeight * lines;
11
+ while (el.scrollHeight > maxHeight) {
12
+ el.textContent = el.textContent?.trim().slice(0, -1) + "…";
13
+ }
14
+ }, [lines]);
15
+ return ref;
16
+ };
17
+ export default useTruncateText;
@@ -0,0 +1,2 @@
1
+ declare const useViewTransition: () => (callback: () => void) => void;
2
+ export default useViewTransition;
@@ -0,0 +1,13 @@
1
+ import { useCallback } from "react";
2
+ const useViewTransition = () => {
3
+ const startTransition = useCallback((callback) => {
4
+ if (document.startViewTransition) {
5
+ document.startViewTransition(callback);
6
+ }
7
+ else {
8
+ callback(); // Fallback for browsers without View Transitions
9
+ }
10
+ }, []);
11
+ return startTransition;
12
+ };
13
+ export default useViewTransition;
@@ -0,0 +1,15 @@
1
+ import { dynamicObject } from "..";
2
+ export type WebSocketOptions = {
3
+ onOpen?: (event: Event) => void;
4
+ onClose?: (event: CloseEvent) => void;
5
+ onRawMessage?: (event: MessageEvent) => void;
6
+ onMessage?: (data: dynamicObject) => void;
7
+ onError?: (event: Event) => void;
8
+ reconnect?: boolean;
9
+ };
10
+ declare const useWebSocket: (url: string, options?: WebSocketOptions) => {
11
+ isConnected: boolean;
12
+ messages: any[];
13
+ sendMessage: (message: string | object) => void;
14
+ };
15
+ export default useWebSocket;
@@ -0,0 +1,87 @@
1
+ "use client";
2
+ import { useCallback, useEffect, useState } from "react";
3
+ const socketInstances = new Map();
4
+ const listenersMap = new Map();
5
+ const reconnectIntervals = new Map(); // Store dynamic reconnect intervals
6
+ const useWebSocket = (url, options) => {
7
+ const { onOpen, onClose, onRawMessage, onMessage, onError, reconnect = true } = options || {};
8
+ const [isConnected, setIsConnected] = useState(false);
9
+ const [messages, setMessages] = useState([]);
10
+ const getReconnectInterval = (url) => reconnectIntervals.get(url) ?? 2;
11
+ const increaseReconnectInterval = (url) => {
12
+ const current = getReconnectInterval(url);
13
+ const next = Math.min(current * 2, 60); // Double each time, max 60s
14
+ reconnectIntervals.set(url, next);
15
+ return next * 1000;
16
+ };
17
+ const resetReconnectInterval = (url) => {
18
+ reconnectIntervals.set(url, 2); // Reset to 1s on successful reconnect
19
+ };
20
+ const connect = useCallback(() => {
21
+ if (socketInstances.has(url))
22
+ return; // Prevent duplicate connection
23
+ const socket = new WebSocket(url);
24
+ socketInstances.set(url, socket);
25
+ listenersMap.set(url, []);
26
+ socket.onopen = (event) => {
27
+ setIsConnected(true);
28
+ resetReconnectInterval(url);
29
+ onOpen?.(event);
30
+ };
31
+ socket.onmessage = (event) => {
32
+ setMessages((prev) => [...prev, event.data]);
33
+ onRawMessage?.(event);
34
+ const raw = JSON.parse(Buffer.isBuffer(event) ? event.toString(`utf8`) : `string` == typeof event ? event : event.data);
35
+ onMessage?.(raw);
36
+ listenersMap.get(url)?.forEach((listener) => listener(event));
37
+ };
38
+ socket.onerror = (event) => {
39
+ onError?.(event);
40
+ };
41
+ socket.onclose = (event) => {
42
+ setIsConnected(false);
43
+ onClose?.(event);
44
+ socketInstances.delete(url);
45
+ listenersMap.delete(url);
46
+ if (reconnect && event.code !== 1000) { // 1000 = normal close
47
+ const delay = increaseReconnectInterval(url);
48
+ console.log(`Reconnecting in ${delay / 1000} seconds...`);
49
+ setTimeout(() => {
50
+ if (!socketInstances.has(url))
51
+ connect(); // Ensure only one instance reconnects
52
+ }, delay);
53
+ }
54
+ };
55
+ }, [url, onOpen, onClose, onMessage, onError, reconnect]);
56
+ useEffect(() => {
57
+ connect();
58
+ return () => {
59
+ if (listenersMap.get(url)?.length === 0) {
60
+ socketInstances.get(url)?.close();
61
+ socketInstances.delete(url);
62
+ listenersMap.delete(url);
63
+ reconnectIntervals.delete(url);
64
+ }
65
+ };
66
+ }, []);
67
+ useEffect(() => {
68
+ const messageListener = (event) => setMessages((prev) => [...prev, event.data]);
69
+ listenersMap.get(url)?.push(messageListener);
70
+ return () => {
71
+ const listeners = listenersMap.get(url) || [];
72
+ listenersMap.set(url, listeners.filter((listener) => listener !== messageListener));
73
+ };
74
+ }, [url]);
75
+ const sendMessage = useCallback((message) => {
76
+ const socket = socketInstances.get(url);
77
+ if (socket && socket.readyState === WebSocket.OPEN) {
78
+ const data = typeof message === "string" ? message : JSON.stringify(message);
79
+ socket.send(data);
80
+ }
81
+ else {
82
+ console.warn("WebSocket is not connected.");
83
+ }
84
+ }, [url]);
85
+ return { isConnected, messages, sendMessage };
86
+ };
87
+ export default useWebSocket;