@therealtinhtute/baroiplayer 1.0.4 → 1.0.6
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/index.d.ts +38 -1
- package/dist/package.json +22 -2
- package/dist/src/components/media-player-controls.js +1 -1
- package/dist/src/components/media-player-controls.tsx +1 -1
- package/dist/src/components/media-player-error.js +2 -2
- package/dist/src/components/media-player-error.tsx +2 -2
- package/dist/src/components/media-player-fullscreen.js +2 -2
- package/dist/src/components/media-player-fullscreen.tsx +2 -2
- package/dist/src/components/media-player-play.js +2 -2
- package/dist/src/components/media-player-play.tsx +2 -2
- package/dist/src/components/media-player-root.js +1 -1
- package/dist/src/components/media-player-root.tsx +1 -1
- package/dist/src/components/media-player-seek.js +1 -1
- package/dist/src/components/media-player-seek.tsx +1 -1
- package/dist/src/components/media-player-tooltip.js +1 -1
- package/dist/src/components/media-player-tooltip.tsx +1 -1
- package/dist/src/components/media-player-volume.js +2 -2
- package/dist/src/components/media-player-volume.tsx +3 -3
- package/dist/src/components/react-player-wrapper.js +5 -5
- package/dist/src/components/react-player-wrapper.tsx +5 -5
- package/dist/src/components/ui/button.tsx +49 -0
- package/dist/src/components/ui/dropdown-menu.tsx +137 -0
- package/dist/src/components/ui/icons.tsx +174 -0
- package/dist/src/components/ui/slider.tsx +55 -0
- package/dist/src/components/ui/tooltip.tsx +131 -0
- package/dist/src/hooks/use-mobile.ts +125 -0
- package/dist/src/hooks/use-touch-gestures.js +1 -1
- package/dist/src/hooks/use-touch-gestures.ts +1 -1
- package/package.json +22 -2
- package/src/components/media-player-controls.js +1 -1
- package/src/components/media-player-controls.tsx +1 -1
- package/src/components/media-player-error.js +2 -2
- package/src/components/media-player-error.tsx +2 -2
- package/src/components/media-player-fullscreen.js +2 -2
- package/src/components/media-player-fullscreen.tsx +2 -2
- package/src/components/media-player-play.js +2 -2
- package/src/components/media-player-play.tsx +2 -2
- package/src/components/media-player-root.js +1 -1
- package/src/components/media-player-root.tsx +1 -1
- package/src/components/media-player-seek.js +1 -1
- package/src/components/media-player-seek.tsx +1 -1
- package/src/components/media-player-tooltip.js +1 -1
- package/src/components/media-player-tooltip.tsx +1 -1
- package/src/components/media-player-volume.js +2 -2
- package/src/components/media-player-volume.tsx +3 -3
- package/src/components/react-player-wrapper.js +5 -5
- package/src/components/react-player-wrapper.tsx +5 -5
- package/src/components/ui/button.tsx +49 -0
- package/src/components/ui/dropdown-menu.tsx +137 -0
- package/src/components/ui/icons.tsx +174 -0
- package/src/components/ui/slider.tsx +55 -0
- package/src/components/ui/tooltip.tsx +131 -0
- package/src/hooks/use-mobile.ts +125 -0
- package/src/hooks/use-touch-gestures.js +1 -1
- package/src/hooks/use-touch-gestures.ts +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
2
|
// Auto-generated TypeScript declarations for @therealtinhtute/baroiplayer
|
|
3
|
-
// Generated on 2025-10-12T09:
|
|
3
|
+
// Generated on 2025-10-12T09:55:45.696Z
|
|
4
4
|
|
|
5
5
|
import type { ReactNode, ComponentType } from 'react';
|
|
6
6
|
|
|
@@ -578,12 +578,40 @@ export declare function ModernMediaPlayer(...args: any[]): any;
|
|
|
578
578
|
// Exports from src/components/simple-video-player.tsx
|
|
579
579
|
export declare function SimpleVideoPlayer(...args: any[]): any;
|
|
580
580
|
|
|
581
|
+
// Exports from src/components/ui/button.tsx
|
|
582
|
+
export interface ButtonProps {}
|
|
583
|
+
|
|
581
584
|
// Exports from src/components/ui/enhanced-seek-bar.tsx
|
|
582
585
|
export declare const EnhancedSeekBar: any;
|
|
583
586
|
|
|
584
587
|
// Exports from src/components/ui/fullscreen-button.tsx
|
|
585
588
|
export declare const FullscreenButton: any;
|
|
586
589
|
|
|
590
|
+
// Exports from src/components/ui/icons.tsx
|
|
591
|
+
export declare const PlayIcon: any;
|
|
592
|
+
export declare const PauseIcon: any;
|
|
593
|
+
export declare const VolumeIcon: any;
|
|
594
|
+
export declare const Volume1Icon: any;
|
|
595
|
+
export declare const Volume2Icon: any;
|
|
596
|
+
export declare const VolumeXIcon: any;
|
|
597
|
+
export declare const MuteIcon: any;
|
|
598
|
+
export declare const Maximize2Icon: any;
|
|
599
|
+
export declare const Minimize2Icon: any;
|
|
600
|
+
export declare const FullscreenIcon: any;
|
|
601
|
+
export declare const ExitFullscreenIcon: any;
|
|
602
|
+
export declare const Rewind10Icon: any;
|
|
603
|
+
export declare const Forward10Icon: any;
|
|
604
|
+
export declare const SpeedIcon: any;
|
|
605
|
+
export declare const QualityIcon: any;
|
|
606
|
+
export declare const SubtitlesIcon: any;
|
|
607
|
+
export declare const PictureInPictureIcon: any;
|
|
608
|
+
export declare const DownloadIcon: any;
|
|
609
|
+
export declare const ShareIcon: any;
|
|
610
|
+
export declare const LoadingIcon: any;
|
|
611
|
+
export declare const AlertTriangleIcon: any;
|
|
612
|
+
export declare const RefreshCcwIcon: any;
|
|
613
|
+
export declare const RotateCcwIcon: any;
|
|
614
|
+
|
|
587
615
|
// Exports from src/components/ui/media-resource-preloader.d.ts
|
|
588
616
|
export default any;
|
|
589
617
|
|
|
@@ -597,6 +625,9 @@ export declare const PlayButton: any;
|
|
|
597
625
|
// Exports from src/components/ui/seek-bar.tsx
|
|
598
626
|
export declare const SeekBar: any;
|
|
599
627
|
|
|
628
|
+
// Exports from src/components/ui/slider.tsx
|
|
629
|
+
export interface SliderProps {}
|
|
630
|
+
|
|
600
631
|
// Exports from src/components/ui/time-display.tsx
|
|
601
632
|
export declare const TimeDisplay: any;
|
|
602
633
|
|
|
@@ -1197,6 +1228,12 @@ export declare function useMemoryOptimization(...args: any[]): any;
|
|
|
1197
1228
|
export declare function useMediaResourceCleanup(...args: any[]): any;
|
|
1198
1229
|
export declare function usePerformanceMonitoring(...args: any[]): any;
|
|
1199
1230
|
|
|
1231
|
+
// Exports from src/hooks/use-mobile.ts
|
|
1232
|
+
export declare function useDeviceInfo(...args: any[]): any;
|
|
1233
|
+
export declare function useContainerQuery(...args: any[]): any;
|
|
1234
|
+
export declare function useMobileOptimizations(...args: any[]): any;
|
|
1235
|
+
export declare function useHapticFeedback(...args: any[]): any;
|
|
1236
|
+
|
|
1200
1237
|
// Exports from src/hooks/use-optimistic-controls.d.ts
|
|
1201
1238
|
export interface MediaState {}
|
|
1202
1239
|
|
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@therealtinhtute/baroiplayer",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"module": "./index.mjs",
|
|
@@ -32,11 +32,31 @@
|
|
|
32
32
|
"peerDependencies": {
|
|
33
33
|
"react": ">=18.0.0",
|
|
34
34
|
"react-dom": ">=18.0.0",
|
|
35
|
-
"tailwindcss": ">=4.0.0"
|
|
35
|
+
"tailwindcss": ">=4.0.0",
|
|
36
|
+
"video.js": ">=7.0.0",
|
|
37
|
+
"hls.js": ">=1.0.0",
|
|
38
|
+
"@videojs/http-streaming": ">=2.0.0",
|
|
39
|
+
"videojs-contrib-quality-levels": ">=2.0.0",
|
|
40
|
+
"videojs-hls-quality-selector": ">=2.0.0"
|
|
36
41
|
},
|
|
37
42
|
"peerDependenciesMeta": {
|
|
38
43
|
"tailwindcss": {
|
|
39
44
|
"optional": true
|
|
45
|
+
},
|
|
46
|
+
"video.js": {
|
|
47
|
+
"optional": true
|
|
48
|
+
},
|
|
49
|
+
"hls.js": {
|
|
50
|
+
"optional": true
|
|
51
|
+
},
|
|
52
|
+
"@videojs/http-streaming": {
|
|
53
|
+
"optional": true
|
|
54
|
+
},
|
|
55
|
+
"videojs-contrib-quality-levels": {
|
|
56
|
+
"optional": true
|
|
57
|
+
},
|
|
58
|
+
"videojs-hls-quality-selector": {
|
|
59
|
+
"optional": true
|
|
40
60
|
}
|
|
41
61
|
}
|
|
42
62
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
3
|
import React from "react";
|
|
4
4
|
import { useMediaSelector } from "../context/media-context";
|
|
5
|
-
import { useDeviceInfo, useContainerQuery } from "
|
|
5
|
+
import { useDeviceInfo, useContainerQuery } from "../hooks/use-mobile";
|
|
6
6
|
import { cn } from "../lib/utils";
|
|
7
7
|
export function MediaPlayerControls({ children, className, asChild = false, variant, adaptiveLayout = true, ...props }) {
|
|
8
8
|
const isFullscreen = useMediaSelector((state) => state.isFullscreen);
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import React from "react"
|
|
4
4
|
import { useMediaSelector } from "../context/media-context"
|
|
5
|
-
import { useDeviceInfo, useContainerQuery } from "
|
|
5
|
+
import { useDeviceInfo, useContainerQuery } from "../hooks/use-mobile"
|
|
6
6
|
import { cn } from "../lib/utils"
|
|
7
7
|
|
|
8
8
|
export interface MediaPlayerControlsProps {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { Button } from "
|
|
4
|
-
import { AlertTriangleIcon, RefreshCcwIcon, RotateCcwIcon } from "
|
|
3
|
+
import { Button } from "../components/ui/button";
|
|
4
|
+
import { AlertTriangleIcon, RefreshCcwIcon, RotateCcwIcon } from "../components/ui/icons";
|
|
5
5
|
import React from "react";
|
|
6
6
|
import { useMediaContext, useMediaSelector } from "../context/media-context";
|
|
7
7
|
import { cn } from "../lib/utils";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client"
|
|
2
2
|
|
|
3
|
-
import { Button } from "
|
|
4
|
-
import { AlertTriangleIcon, RefreshCcwIcon, RotateCcwIcon } from "
|
|
3
|
+
import { Button } from "../components/ui/button"
|
|
4
|
+
import { AlertTriangleIcon, RefreshCcwIcon, RotateCcwIcon } from "../components/ui/icons"
|
|
5
5
|
import React from "react"
|
|
6
6
|
import { useMediaContext, useMediaSelector } from "../context/media-context"
|
|
7
7
|
import { cn } from "../lib/utils"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
import { Button } from "
|
|
4
|
-
import { Maximize2Icon, Minimize2Icon } from "
|
|
3
|
+
import { Button } from "../components/ui/button";
|
|
4
|
+
import { Maximize2Icon, Minimize2Icon } from "../components/ui/icons";
|
|
5
5
|
import React from "react";
|
|
6
6
|
import { MediaActionTypes, useMediaContext, useMediaDispatch, useMediaSelector } from "../context/media-context";
|
|
7
7
|
import { MediaPlayerTooltip } from "./media-player-tooltip";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client"
|
|
2
2
|
|
|
3
|
-
import { Button } from "
|
|
4
|
-
import { Maximize2Icon, Minimize2Icon } from "
|
|
3
|
+
import { Button } from "../components/ui/button"
|
|
4
|
+
import { Maximize2Icon, Minimize2Icon } from "../components/ui/icons"
|
|
5
5
|
import React from "react"
|
|
6
6
|
import {
|
|
7
7
|
MediaActionTypes,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
import { Button } from "
|
|
4
|
-
import { PauseIcon, PlayIcon } from "
|
|
3
|
+
import { Button } from "../components/ui/button";
|
|
4
|
+
import { PauseIcon, PlayIcon } from "../components/ui/icons";
|
|
5
5
|
import React from "react";
|
|
6
6
|
import { MediaActionTypes, useMediaContext, useMediaDispatch, useMediaSelector } from "../context/media-context";
|
|
7
7
|
import { MediaPlayerTooltip } from "./media-player-tooltip";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client"
|
|
2
2
|
|
|
3
|
-
import { Button } from "
|
|
4
|
-
import { PauseIcon, PlayIcon } from "
|
|
3
|
+
import { Button } from "../components/ui/button"
|
|
4
|
+
import { PauseIcon, PlayIcon } from "../components/ui/icons"
|
|
5
5
|
import React from "react"
|
|
6
6
|
import {
|
|
7
7
|
MediaActionTypes,
|
|
@@ -4,7 +4,7 @@ import React from "react";
|
|
|
4
4
|
import { MediaActionTypes, useMediaContext, useMediaDispatch, useMediaSelector } from "../context/media-context";
|
|
5
5
|
import { MediaProvider } from "../context/media-provider";
|
|
6
6
|
import { useMediaGestures } from "../hooks/use-touch-gestures";
|
|
7
|
-
import { useMobileOptimizations, useDeviceInfo } from "
|
|
7
|
+
import { useMobileOptimizations, useDeviceInfo } from "../hooks/use-mobile";
|
|
8
8
|
import { cn } from "../lib/utils";
|
|
9
9
|
// Utility function to compose refs
|
|
10
10
|
function composeRefs(...refs) {
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
} from "../context/media-context"
|
|
10
10
|
import { MediaProvider } from "../context/media-provider"
|
|
11
11
|
import { useMediaGestures } from "../hooks/use-touch-gestures"
|
|
12
|
-
import { useMobileOptimizations, useDeviceInfo } from "
|
|
12
|
+
import { useMobileOptimizations, useDeviceInfo } from "../hooks/use-mobile"
|
|
13
13
|
import { cn } from "../lib/utils"
|
|
14
14
|
|
|
15
15
|
// Utility function to compose refs
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
-
import { Slider } from "
|
|
3
|
+
import { Slider } from "../components/ui/slider";
|
|
4
4
|
import React from "react";
|
|
5
5
|
import { MediaActionTypes, useMediaContext, useMediaDispatch, useMediaSelector } from "../context/media-context";
|
|
6
6
|
import { formatTime } from "../lib/format-time";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { Tooltip, TooltipContent, TooltipTrigger } from "
|
|
3
|
+
import { Tooltip, TooltipContent, TooltipTrigger } from "../components/ui/tooltip";
|
|
4
4
|
import { useMediaContext } from "../context/media-context";
|
|
5
5
|
export function MediaPlayerTooltip({ children, tooltip, shortcut, delayDuration, sideOffset }) {
|
|
6
6
|
const context = useMediaContext();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client"
|
|
2
2
|
|
|
3
|
-
import { Tooltip, TooltipContent, TooltipTrigger } from "
|
|
3
|
+
import { Tooltip, TooltipContent, TooltipTrigger } from "../components/ui/tooltip"
|
|
4
4
|
import React from "react"
|
|
5
5
|
import { useMediaContext } from "../context/media-context"
|
|
6
6
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { Button } from "
|
|
4
|
-
import { Slider } from "
|
|
3
|
+
import { Button } from "../components/ui/button";
|
|
4
|
+
import { Slider } from "../components/ui/slider";
|
|
5
5
|
import { Volume1Icon, Volume2Icon, VolumeXIcon } from "lucide-react";
|
|
6
6
|
import React from "react";
|
|
7
7
|
import { MediaActionTypes, useMediaContext, useMediaDispatch, useMediaSelector } from "../context/media-context";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use client"
|
|
2
2
|
|
|
3
|
-
import { Button } from "
|
|
4
|
-
import { Slider } from "
|
|
5
|
-
import { Volume1Icon, Volume2Icon, VolumeXIcon } from "
|
|
3
|
+
import { Button } from "../components/ui/button"
|
|
4
|
+
import { Slider } from "../components/ui/slider"
|
|
5
|
+
import { Volume1Icon, Volume2Icon, VolumeXIcon } from "../components/ui/icons"
|
|
6
6
|
import React from "react"
|
|
7
7
|
import {
|
|
8
8
|
MediaActionTypes,
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import "../styles/pixel-art.css";
|
|
4
|
-
import { Button } from "
|
|
5
|
-
import { DownloadIcon, ExitFullscreenIcon, Forward10Icon, FullscreenIcon, LoadingIcon, MuteIcon, PauseIcon, PictureInPictureIcon, PlayIcon, QualityIcon, Rewind10Icon, ShareIcon, SpeedIcon, SubtitlesIcon, VolumeIcon } from "
|
|
6
|
-
import { Slider } from "
|
|
7
|
-
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger } from "
|
|
8
|
-
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "
|
|
4
|
+
import { Button } from "../components/ui/button";
|
|
5
|
+
import { DownloadIcon, ExitFullscreenIcon, Forward10Icon, FullscreenIcon, LoadingIcon, MuteIcon, PauseIcon, PictureInPictureIcon, PlayIcon, QualityIcon, Rewind10Icon, ShareIcon, SpeedIcon, SubtitlesIcon, VolumeIcon } from "../components/ui/icons";
|
|
6
|
+
import { Slider } from "../components/ui/slider";
|
|
7
|
+
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger } from "../components/ui/dropdown-menu";
|
|
8
|
+
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "../components/ui/tooltip";
|
|
9
9
|
import { useState, useRef, useEffect, Suspense, lazy } from "react";
|
|
10
10
|
// Dynamic import for lazy loading
|
|
11
11
|
const ReactPlayer = lazy(() => import("react-player"));
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client"
|
|
2
2
|
|
|
3
3
|
import "../styles/pixel-art.css"
|
|
4
|
-
import { Button } from "
|
|
4
|
+
import { Button } from "../components/ui/button"
|
|
5
5
|
import {
|
|
6
6
|
DownloadIcon,
|
|
7
7
|
ExitFullscreenIcon,
|
|
@@ -21,8 +21,8 @@ import {
|
|
|
21
21
|
SpeedIcon,
|
|
22
22
|
SubtitlesIcon,
|
|
23
23
|
VolumeIcon
|
|
24
|
-
} from "
|
|
25
|
-
import { Slider } from "
|
|
24
|
+
} from "../components/ui/icons"
|
|
25
|
+
import { Slider } from "../components/ui/slider"
|
|
26
26
|
import {
|
|
27
27
|
DropdownMenu,
|
|
28
28
|
DropdownMenuContent,
|
|
@@ -30,8 +30,8 @@ import {
|
|
|
30
30
|
DropdownMenuLabel,
|
|
31
31
|
DropdownMenuSeparator,
|
|
32
32
|
DropdownMenuTrigger
|
|
33
|
-
} from "
|
|
34
|
-
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "
|
|
33
|
+
} from "../components/ui/dropdown-menu"
|
|
34
|
+
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "../components/ui/tooltip"
|
|
35
35
|
import React, { useState, useRef, useEffect, useCallback, Suspense, lazy } from "react"
|
|
36
36
|
// Dynamic import for lazy loading
|
|
37
37
|
const ReactPlayer = lazy(() => import("react-player"))
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import React, { forwardRef } from 'react';
|
|
2
|
+
import { cn } from '../lib/utils';
|
|
3
|
+
|
|
4
|
+
export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
5
|
+
variant?: 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link';
|
|
6
|
+
size?: 'default' | 'sm' | 'lg' | 'icon';
|
|
7
|
+
asChild?: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const Button = forwardRef<HTMLButtonElement, ButtonProps>(
|
|
11
|
+
({ className, variant = 'default', size = 'default', asChild = false, ...props }, ref) => {
|
|
12
|
+
const baseClasses = 'inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50';
|
|
13
|
+
|
|
14
|
+
const variants = {
|
|
15
|
+
default: 'bg-primary text-primary-foreground hover:bg-primary/90',
|
|
16
|
+
destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
|
|
17
|
+
outline: 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',
|
|
18
|
+
secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
|
|
19
|
+
ghost: 'hover:bg-accent hover:text-accent-foreground',
|
|
20
|
+
link: 'text-primary underline-offset-4 hover:underline',
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const sizes = {
|
|
24
|
+
default: 'h-10 px-4 py-2',
|
|
25
|
+
sm: 'h-9 rounded-md px-3',
|
|
26
|
+
lg: 'h-11 rounded-md px-8',
|
|
27
|
+
icon: 'h-10 w-10',
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const Comp = asChild ? 'span' : 'button';
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<Comp
|
|
34
|
+
className={cn(
|
|
35
|
+
baseClasses,
|
|
36
|
+
variants[variant],
|
|
37
|
+
sizes[size],
|
|
38
|
+
className
|
|
39
|
+
)}
|
|
40
|
+
ref={ref}
|
|
41
|
+
{...props}
|
|
42
|
+
/>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
Button.displayName = 'Button';
|
|
48
|
+
|
|
49
|
+
export { Button };
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import React, { useState, useRef, useEffect, forwardRef } from 'react';
|
|
2
|
+
import { cn } from '../lib/utils';
|
|
3
|
+
|
|
4
|
+
interface DropdownMenuProps {
|
|
5
|
+
children: React.ReactNode;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
interface DropdownMenuTriggerProps {
|
|
9
|
+
children: React.ReactNode;
|
|
10
|
+
asChild?: boolean;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface DropdownMenuContentProps {
|
|
14
|
+
children: React.ReactNode;
|
|
15
|
+
className?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
interface DropdownMenuItemProps {
|
|
19
|
+
children: React.ReactNode;
|
|
20
|
+
className?: string;
|
|
21
|
+
onClick?: () => void;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
interface DropdownMenuLabelProps {
|
|
25
|
+
children: React.ReactNode;
|
|
26
|
+
className?: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
interface DropdownMenuSeparatorProps {
|
|
30
|
+
className?: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const DropdownMenu: React.FC<DropdownMenuProps> = ({ children }) => {
|
|
34
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
35
|
+
const dropdownRef = useRef<HTMLDivElement>(null);
|
|
36
|
+
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
const handleClickOutside = (event: MouseEvent) => {
|
|
39
|
+
if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
|
|
40
|
+
setIsOpen(false);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
document.addEventListener('mousedown', handleClickOutside);
|
|
45
|
+
return () => document.removeEventListener('mousedown', handleClickOutside);
|
|
46
|
+
}, []);
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<div ref={dropdownRef} className="relative inline-block text-left">
|
|
50
|
+
{React.Children.map(children, (child) => {
|
|
51
|
+
if (React.isValidElement(child)) {
|
|
52
|
+
return React.cloneElement(child as React.ReactElement, { isOpen, setIsOpen });
|
|
53
|
+
}
|
|
54
|
+
return child;
|
|
55
|
+
})}
|
|
56
|
+
</div>
|
|
57
|
+
);
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const DropdownMenuTrigger: React.FC<DropdownMenuTriggerProps> = ({ children, asChild = false, isOpen, setIsOpen }) => {
|
|
61
|
+
const handleClick = () => {
|
|
62
|
+
setIsOpen?.(!isOpen);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const TriggerComponent = asChild ? 'div' : 'button';
|
|
66
|
+
|
|
67
|
+
return (
|
|
68
|
+
<TriggerComponent
|
|
69
|
+
onClick={handleClick}
|
|
70
|
+
className={cn(
|
|
71
|
+
'inline-flex justify-center w-full rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500',
|
|
72
|
+
!asChild && 'cursor-pointer'
|
|
73
|
+
)}
|
|
74
|
+
>
|
|
75
|
+
{children}
|
|
76
|
+
</TriggerComponent>
|
|
77
|
+
);
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const DropdownMenuContent: React.FC<DropdownMenuContentProps> = ({ children, className, isOpen }) => {
|
|
81
|
+
if (!isOpen) return null;
|
|
82
|
+
|
|
83
|
+
return (
|
|
84
|
+
<div className={cn(
|
|
85
|
+
'absolute right-0 z-10 mt-2 w-56 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 focus:outline-none',
|
|
86
|
+
className
|
|
87
|
+
)}>
|
|
88
|
+
<div className="py-1">
|
|
89
|
+
{children}
|
|
90
|
+
</div>
|
|
91
|
+
</div>
|
|
92
|
+
);
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const DropdownMenuItem: React.FC<DropdownMenuItemProps> = ({ children, className, onClick }) => {
|
|
96
|
+
return (
|
|
97
|
+
<button
|
|
98
|
+
onClick={onClick}
|
|
99
|
+
className={cn(
|
|
100
|
+
'w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900',
|
|
101
|
+
className
|
|
102
|
+
)}
|
|
103
|
+
role="menuitem"
|
|
104
|
+
>
|
|
105
|
+
{children}
|
|
106
|
+
</button>
|
|
107
|
+
);
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const DropdownMenuLabel: React.FC<DropdownMenuLabelProps> = ({ children, className }) => {
|
|
111
|
+
return (
|
|
112
|
+
<div className={cn(
|
|
113
|
+
'px-4 py-2 text-sm font-medium text-gray-700',
|
|
114
|
+
className
|
|
115
|
+
)}>
|
|
116
|
+
{children}
|
|
117
|
+
</div>
|
|
118
|
+
);
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
const DropdownMenuSeparator: React.FC<DropdownMenuSeparatorProps> = ({ className }) => {
|
|
122
|
+
return (
|
|
123
|
+
<div className={cn(
|
|
124
|
+
'border-t border-gray-100 my-1',
|
|
125
|
+
className
|
|
126
|
+
)} />
|
|
127
|
+
);
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
export {
|
|
131
|
+
DropdownMenu,
|
|
132
|
+
DropdownMenuTrigger,
|
|
133
|
+
DropdownMenuContent,
|
|
134
|
+
DropdownMenuItem,
|
|
135
|
+
DropdownMenuLabel,
|
|
136
|
+
DropdownMenuSeparator
|
|
137
|
+
};
|