@zuzjs/ui 0.7.8 → 0.7.9
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/dist/cjs/comps/Box/index.d.ts +1 -2
- package/dist/cjs/comps/Box/index.js +14 -12
- package/dist/cjs/comps/Button/index.d.ts +1 -1
- package/dist/cjs/comps/Button/types.d.ts +1 -1
- package/dist/cjs/comps/ColorScheme/index.d.ts +3 -2
- package/dist/cjs/comps/ColorScheme/index.js +24 -9
- package/dist/cjs/comps/ColorScheme/types.d.ts +4 -0
- package/dist/cjs/comps/ColorScheme/types.js +1 -0
- package/dist/cjs/comps/ContextMenu/index.js +1 -2
- package/dist/cjs/comps/Crumb/index.d.ts +4 -0
- package/dist/cjs/comps/Crumb/index.js +13 -0
- package/dist/cjs/comps/Crumb/types.d.ts +11 -0
- package/dist/cjs/comps/Crumb/types.js +1 -0
- package/dist/cjs/comps/Drawer/index.js +16 -15
- package/dist/cjs/comps/Form/index.d.ts +3 -59
- package/dist/cjs/comps/Form/types.d.ts +43 -0
- package/dist/cjs/comps/Form/types.js +1 -0
- package/dist/cjs/comps/Icon/index.js +0 -1
- package/dist/cjs/comps/Image/index.js +0 -1
- package/dist/cjs/comps/KeyboardKeys/index.d.ts +8 -0
- package/dist/cjs/comps/KeyboardKeys/index.js +33 -0
- package/dist/cjs/comps/KeyboardKeys/types.d.ts +13 -0
- package/dist/cjs/comps/KeyboardKeys/types.js +51 -0
- package/dist/cjs/comps/Label/index.js +0 -1
- package/dist/cjs/comps/List/index.d.ts +3 -0
- package/dist/cjs/comps/List/index.js +4 -4
- package/dist/cjs/comps/List/item.js +5 -1
- package/dist/cjs/comps/List/types.d.ts +4 -1
- package/dist/cjs/comps/Network/index.js +3 -5
- package/dist/cjs/comps/Pagination/index.js +2 -2
- package/dist/cjs/comps/ScrollView/index.d.ts +5 -0
- package/dist/cjs/comps/ScrollView/index.js +13 -0
- package/dist/cjs/comps/ScrollView/types.d.ts +6 -0
- package/dist/cjs/comps/ScrollView/types.js +1 -0
- package/dist/cjs/comps/Search/index.d.ts +7 -10
- package/dist/cjs/comps/Search/index.js +10 -6
- package/dist/cjs/comps/Search/types.d.ts +12 -0
- package/dist/cjs/comps/Search/types.js +1 -0
- package/dist/cjs/comps/Segmented/index.d.ts +3 -2
- package/dist/cjs/comps/Segmented/index.js +6 -5
- package/dist/cjs/comps/Segmented/item.js +11 -2
- package/dist/cjs/comps/Segmented/types.d.ts +5 -1
- package/dist/cjs/comps/Select/index.d.ts +1 -1
- package/dist/cjs/comps/Select/types.d.ts +1 -1
- package/dist/cjs/comps/Sheet/index.js +8 -5
- package/dist/cjs/comps/Spinner/index.js +1 -2
- package/dist/cjs/comps/TabView/index.d.ts +1 -1
- package/dist/cjs/comps/TabView/types.d.ts +2 -2
- package/dist/cjs/comps/Table/index.js +12 -5
- package/dist/cjs/comps/Table/row.js +3 -2
- package/dist/cjs/comps/Table/types.d.ts +88 -1
- package/dist/cjs/comps/Text/index.d.ts +2 -0
- package/dist/cjs/comps/Text/index.js +4 -2
- package/dist/cjs/comps/TextArea/index.d.ts +2 -0
- package/dist/cjs/comps/TextArea/index.js +3 -4
- package/dist/cjs/comps/Treeview/index.js +3 -2
- package/dist/cjs/comps/Treeview/item.d.ts +1 -1
- package/dist/cjs/comps/Treeview/item.js +5 -4
- package/dist/cjs/comps/Treeview/types.d.ts +1 -1
- package/dist/cjs/comps/VideoPlayer/index.d.ts +2 -0
- package/dist/cjs/comps/VideoPlayer/index.js +7 -0
- package/dist/cjs/comps/index.d.ts +26 -18
- package/dist/cjs/comps/index.js +8 -0
- package/dist/cjs/funs/css.d.ts +3 -3
- package/dist/cjs/funs/css.js +20 -18
- package/dist/cjs/funs/index.d.ts +1 -0
- package/dist/cjs/funs/index.js +10 -0
- package/dist/cjs/funs/stylesheet.js +5 -0
- package/dist/cjs/hooks/index.d.ts +13 -6
- package/dist/cjs/hooks/index.js +14 -7
- package/dist/cjs/hooks/useAnchorPosition.d.ts +1 -2
- package/dist/cjs/hooks/useAnchorPosition.js +1 -0
- package/dist/cjs/hooks/useBase.js +27 -13
- package/dist/cjs/hooks/useCalendar.js +1 -0
- package/dist/cjs/hooks/useColorScheme.js +2 -2
- package/dist/cjs/hooks/useContextMenu.js +1 -0
- package/dist/cjs/hooks/useDB.js +1 -0
- package/dist/cjs/hooks/useDebounce.js +2 -1
- package/dist/cjs/hooks/useDelayed.js +2 -1
- package/dist/cjs/hooks/useDevice.js +1 -0
- package/dist/cjs/hooks/useDimensions.js +2 -1
- package/dist/cjs/hooks/useDom.d.ts +2 -0
- package/dist/cjs/hooks/useDom.js +3 -0
- package/dist/cjs/hooks/useDomMutation.d.ts +3 -0
- package/dist/cjs/hooks/useDomMutation.js +19 -0
- package/dist/cjs/hooks/useDrag.js +2 -1
- package/dist/cjs/hooks/useFileManager.d.ts +2 -0
- package/dist/cjs/hooks/useFileManager.js +3 -0
- package/dist/cjs/hooks/useImage.js +1 -0
- package/dist/cjs/hooks/useIntersectionObserver.js +2 -1
- package/dist/cjs/hooks/useMediaPlayer.d.ts +32 -0
- package/dist/cjs/hooks/useMediaPlayer.js +86 -0
- package/dist/cjs/hooks/useMergedRefs.d.ts +2 -0
- package/dist/cjs/hooks/useMergedRefs.js +14 -0
- package/dist/cjs/hooks/useMutationObserver.d.ts +3 -0
- package/dist/cjs/hooks/useMutationObserver.js +20 -0
- package/dist/cjs/hooks/useNetworkStatus.js +2 -1
- package/dist/cjs/hooks/usePlayer.d.ts +32 -0
- package/dist/cjs/hooks/usePlayer.js +85 -0
- package/dist/cjs/hooks/useResizeObserver.js +2 -1
- package/dist/cjs/hooks/useScrollbar.d.ts +16 -0
- package/dist/cjs/hooks/useScrollbar.js +160 -0
- package/dist/cjs/hooks/useSheet.js +1 -0
- package/dist/cjs/hooks/useShortcuts.d.ts +7 -0
- package/dist/cjs/hooks/useShortcuts.js +29 -0
- package/dist/cjs/hooks/useSlider.d.ts +7 -0
- package/dist/cjs/hooks/useSlider.js +23 -0
- package/dist/cjs/hooks/useTruncateText.d.ts +2 -0
- package/dist/cjs/hooks/useTruncateText.js +17 -0
- package/dist/cjs/hooks/useViewTransition.d.ts +2 -0
- package/dist/cjs/hooks/useViewTransition.js +13 -0
- package/dist/cjs/types/enums.d.ts +1 -0
- package/dist/cjs/types/enums.js +1 -0
- package/dist/cjs/types/index.d.ts +2 -1
- package/dist/cjs/types/interfaces.d.ts +2 -0
- package/dist/css/styles.css +1 -1
- package/dist/esm/comps/Box/index.d.ts +1 -2
- package/dist/esm/comps/Box/index.js +14 -12
- package/dist/esm/comps/Button/index.d.ts +1 -1
- package/dist/esm/comps/Button/types.d.ts +1 -1
- package/dist/esm/comps/ColorScheme/index.d.ts +3 -2
- package/dist/esm/comps/ColorScheme/index.js +24 -9
- package/dist/esm/comps/ColorScheme/types.d.ts +4 -0
- package/dist/esm/comps/ColorScheme/types.js +1 -0
- package/dist/esm/comps/ContextMenu/index.js +1 -2
- package/dist/esm/comps/Crumb/index.d.ts +4 -0
- package/dist/esm/comps/Crumb/index.js +13 -0
- package/dist/esm/comps/Crumb/types.d.ts +11 -0
- package/dist/esm/comps/Crumb/types.js +1 -0
- package/dist/esm/comps/Drawer/index.js +16 -15
- package/dist/esm/comps/Form/index.d.ts +3 -59
- package/dist/esm/comps/Form/types.d.ts +43 -0
- package/dist/esm/comps/Form/types.js +1 -0
- package/dist/esm/comps/Icon/index.js +0 -1
- package/dist/esm/comps/Image/index.js +0 -1
- package/dist/esm/comps/KeyboardKeys/index.d.ts +8 -0
- package/dist/esm/comps/KeyboardKeys/index.js +33 -0
- package/dist/esm/comps/KeyboardKeys/types.d.ts +13 -0
- package/dist/esm/comps/KeyboardKeys/types.js +51 -0
- package/dist/esm/comps/Label/index.js +0 -1
- package/dist/esm/comps/List/index.d.ts +3 -0
- package/dist/esm/comps/List/index.js +4 -4
- package/dist/esm/comps/List/item.js +5 -1
- package/dist/esm/comps/List/types.d.ts +4 -1
- package/dist/esm/comps/Network/index.js +3 -5
- package/dist/esm/comps/Pagination/index.js +2 -2
- package/dist/esm/comps/ScrollView/index.d.ts +5 -0
- package/dist/esm/comps/ScrollView/index.js +13 -0
- package/dist/esm/comps/ScrollView/types.d.ts +6 -0
- package/dist/esm/comps/ScrollView/types.js +1 -0
- package/dist/esm/comps/Search/index.d.ts +7 -10
- package/dist/esm/comps/Search/index.js +10 -6
- package/dist/esm/comps/Search/types.d.ts +12 -0
- package/dist/esm/comps/Search/types.js +1 -0
- package/dist/esm/comps/Segmented/index.d.ts +3 -2
- package/dist/esm/comps/Segmented/index.js +6 -5
- package/dist/esm/comps/Segmented/item.js +11 -2
- package/dist/esm/comps/Segmented/types.d.ts +5 -1
- package/dist/esm/comps/Select/index.d.ts +1 -1
- package/dist/esm/comps/Select/types.d.ts +1 -1
- package/dist/esm/comps/Sheet/index.js +8 -5
- package/dist/esm/comps/Spinner/index.js +1 -2
- package/dist/esm/comps/TabView/index.d.ts +1 -1
- package/dist/esm/comps/TabView/types.d.ts +2 -2
- package/dist/esm/comps/Table/index.js +12 -5
- package/dist/esm/comps/Table/row.js +3 -2
- package/dist/esm/comps/Table/types.d.ts +88 -1
- package/dist/esm/comps/Text/index.d.ts +2 -0
- package/dist/esm/comps/Text/index.js +4 -2
- package/dist/esm/comps/TextArea/index.d.ts +2 -0
- package/dist/esm/comps/TextArea/index.js +3 -4
- package/dist/esm/comps/Treeview/index.js +3 -2
- package/dist/esm/comps/Treeview/item.d.ts +1 -1
- package/dist/esm/comps/Treeview/item.js +5 -4
- package/dist/esm/comps/Treeview/types.d.ts +1 -1
- package/dist/esm/comps/VideoPlayer/index.d.ts +2 -0
- package/dist/esm/comps/VideoPlayer/index.js +7 -0
- package/dist/esm/comps/index.d.ts +26 -18
- package/dist/esm/comps/index.js +8 -0
- package/dist/esm/funs/css.d.ts +3 -3
- package/dist/esm/funs/css.js +20 -18
- package/dist/esm/funs/index.d.ts +1 -0
- package/dist/esm/funs/index.js +10 -0
- package/dist/esm/funs/stylesheet.js +5 -0
- package/dist/esm/hooks/index.d.ts +13 -6
- package/dist/esm/hooks/index.js +14 -7
- package/dist/esm/hooks/useAnchorPosition.d.ts +1 -2
- package/dist/esm/hooks/useAnchorPosition.js +1 -0
- package/dist/esm/hooks/useBase.js +27 -13
- package/dist/esm/hooks/useCalendar.js +1 -0
- package/dist/esm/hooks/useColorScheme.js +2 -2
- package/dist/esm/hooks/useContextMenu.js +1 -0
- package/dist/esm/hooks/useDB.js +1 -0
- package/dist/esm/hooks/useDebounce.js +2 -1
- package/dist/esm/hooks/useDelayed.js +2 -1
- package/dist/esm/hooks/useDevice.js +1 -0
- package/dist/esm/hooks/useDimensions.js +2 -1
- package/dist/esm/hooks/useDom.d.ts +2 -0
- package/dist/esm/hooks/useDom.js +3 -0
- package/dist/esm/hooks/useDomMutation.d.ts +3 -0
- package/dist/esm/hooks/useDomMutation.js +19 -0
- package/dist/esm/hooks/useDrag.js +2 -1
- package/dist/esm/hooks/useFileManager.d.ts +2 -0
- package/dist/esm/hooks/useFileManager.js +3 -0
- package/dist/esm/hooks/useImage.js +1 -0
- package/dist/esm/hooks/useIntersectionObserver.js +2 -1
- package/dist/esm/hooks/useMediaPlayer.d.ts +32 -0
- package/dist/esm/hooks/useMediaPlayer.js +86 -0
- package/dist/esm/hooks/useMergedRefs.d.ts +2 -0
- package/dist/esm/hooks/useMergedRefs.js +14 -0
- package/dist/esm/hooks/useMutationObserver.d.ts +3 -0
- package/dist/esm/hooks/useMutationObserver.js +20 -0
- package/dist/esm/hooks/useNetworkStatus.js +2 -1
- package/dist/esm/hooks/usePlayer.d.ts +32 -0
- package/dist/esm/hooks/usePlayer.js +85 -0
- package/dist/esm/hooks/useResizeObserver.js +2 -1
- package/dist/esm/hooks/useScrollbar.d.ts +16 -0
- package/dist/esm/hooks/useScrollbar.js +160 -0
- package/dist/esm/hooks/useSheet.js +1 -0
- package/dist/esm/hooks/useShortcuts.d.ts +7 -0
- package/dist/esm/hooks/useShortcuts.js +29 -0
- package/dist/esm/hooks/useSlider.d.ts +7 -0
- package/dist/esm/hooks/useSlider.js +23 -0
- package/dist/esm/hooks/useTruncateText.d.ts +2 -0
- package/dist/esm/hooks/useTruncateText.js +17 -0
- package/dist/esm/hooks/useViewTransition.d.ts +2 -0
- package/dist/esm/hooks/useViewTransition.js +13 -0
- package/dist/esm/types/enums.d.ts +1 -0
- package/dist/esm/types/enums.js +1 -0
- package/dist/esm/types/index.d.ts +2 -1
- package/dist/esm/types/interfaces.d.ts +2 -0
- package/dist/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- 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,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,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;
|
|
@@ -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;
|
|
@@ -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;
|
|
@@ -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,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,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,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;
|
package/dist/cjs/types/enums.js
CHANGED
|
@@ -138,6 +138,7 @@ export var KeyCode;
|
|
|
138
138
|
KeyCode[KeyCode["Ctrl"] = 17] = "Ctrl";
|
|
139
139
|
KeyCode[KeyCode["Alt"] = 18] = "Alt";
|
|
140
140
|
KeyCode[KeyCode["PauseBreak"] = 19] = "PauseBreak";
|
|
141
|
+
KeyCode[KeyCode["Command"] = 19] = "Command";
|
|
141
142
|
KeyCode[KeyCode["CapsLock"] = 20] = "CapsLock";
|
|
142
143
|
KeyCode[KeyCode["Escape"] = 27] = "Escape";
|
|
143
144
|
KeyCode[KeyCode["Space"] = 32] = "Space";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ComponentPropsWithoutRef, ElementType } from "react";
|
|
2
2
|
import { DragOptions } from "../hooks";
|
|
3
|
-
import { SHIMMER, SORT } from "./enums";
|
|
3
|
+
import { SHIMMER, SORT, TRANSITIONS } from "./enums";
|
|
4
4
|
import { animationProps, Skeleton } from "./interfaces";
|
|
5
5
|
export type Deprecated<T, M extends string> = T & {
|
|
6
6
|
__deprecatedMessage?: M;
|
|
@@ -45,6 +45,7 @@ export interface ZuzProps {
|
|
|
45
45
|
animate?: animationProps;
|
|
46
46
|
/** Animation configuration using {@link animationProps} */
|
|
47
47
|
fx?: animationProps;
|
|
48
|
+
transition?: TRANSITIONS;
|
|
48
49
|
/** Skeleton placeholder configuration using {@link Skeleton} */
|
|
49
50
|
skeleton?: Skeleton;
|
|
50
51
|
/** Additional class names for styling the component */
|
|
@@ -10,6 +10,8 @@ export interface animationProps {
|
|
|
10
10
|
* {@link TRANSITIONS}
|
|
11
11
|
*/
|
|
12
12
|
transition?: TRANSITIONS;
|
|
13
|
+
/** This will be removed / added to default calculations for x, y */
|
|
14
|
+
offset?: number;
|
|
13
15
|
/** Starting style properties for the animation */
|
|
14
16
|
from?: dynamicObject;
|
|
15
17
|
/** Target style properties after the animation completes */
|