@fluencypassdevs/cycle 1.21.0 → 1.27.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 (47) hide show
  1. package/bin/mcp.mjs +138 -4
  2. package/dist/chunk-GI7MEYSN.js +163 -0
  3. package/dist/chunk-GI7MEYSN.js.map +1 -0
  4. package/dist/{chunk-LM5ZJFLA.js → chunk-GKJ45JXA.js} +10 -4
  5. package/dist/chunk-GKJ45JXA.js.map +1 -0
  6. package/dist/{chunk-YHCDOHJL.js → chunk-OLYW5LVG.js} +3 -3
  7. package/dist/{chunk-YHCDOHJL.js.map → chunk-OLYW5LVG.js.map} +1 -1
  8. package/dist/chunk-ONEVPGJY.js +152 -0
  9. package/dist/chunk-ONEVPGJY.js.map +1 -0
  10. package/dist/chunk-P7Y2OBHX.js +97 -0
  11. package/dist/chunk-P7Y2OBHX.js.map +1 -0
  12. package/dist/{chunk-WXD7XZWE.js → chunk-R33NNSFO.js} +15 -6
  13. package/dist/chunk-R33NNSFO.js.map +1 -0
  14. package/dist/chunk-T73O7F3B.js +131 -0
  15. package/dist/chunk-T73O7F3B.js.map +1 -0
  16. package/dist/chunk-WVCNTN4F.js +232 -0
  17. package/dist/chunk-WVCNTN4F.js.map +1 -0
  18. package/dist/composites/chat-thread.js +1 -1
  19. package/dist/index.d.ts +8 -2
  20. package/dist/index.js +32 -27
  21. package/dist/marketing/effects/index.js +2 -2
  22. package/dist/marketing/motion/index.js +2 -2
  23. package/dist/marketing/typography/index.js +1 -1
  24. package/dist/styles/tokens.css +40 -0
  25. package/dist/ui/audio-player.d.ts +17 -3
  26. package/dist/ui/audio-player.js +1 -1
  27. package/dist/ui/chat-panel.js +2 -2
  28. package/dist/ui/command.d.ts +24 -0
  29. package/dist/ui/command.js +12 -0
  30. package/dist/ui/command.js.map +1 -0
  31. package/dist/ui/file-dropzone.d.ts +53 -0
  32. package/dist/ui/file-dropzone.js +12 -0
  33. package/dist/ui/file-dropzone.js.map +1 -0
  34. package/dist/ui/pagination.d.ts +26 -0
  35. package/dist/ui/pagination.js +11 -0
  36. package/dist/ui/pagination.js.map +1 -0
  37. package/dist/ui/stepper.d.ts +33 -0
  38. package/dist/ui/stepper.js +10 -0
  39. package/dist/ui/stepper.js.map +1 -0
  40. package/dist/ui/table.d.ts +13 -0
  41. package/dist/ui/table.js +7 -0
  42. package/dist/ui/table.js.map +1 -0
  43. package/dist/ui/video-player.d.ts +12 -3
  44. package/dist/ui/video-player.js +1 -1
  45. package/package.json +2 -1
  46. package/dist/chunk-LM5ZJFLA.js.map +0 -1
  47. package/dist/chunk-WXD7XZWE.js.map +0 -1
@@ -0,0 +1,53 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as React from 'react';
3
+
4
+ /** Motivo de rejeição na validação de SELEÇÃO (upload é problema do consumidor) */
5
+ type FileRejectionReason = "type" | "size" | "empty" | "count";
6
+ interface FileDropzoneLabels {
7
+ /** Instrução principal (default: "Arraste um arquivo ou clique para selecionar") */
8
+ instruction?: string;
9
+ /** Texto de apoio (ex: "MP3 ou WAV até 20 MB") — default derivado de accept/maxSize */
10
+ hint?: string;
11
+ /** Mensagens de erro por motivo de rejeição */
12
+ errors?: Partial<Record<FileRejectionReason, string>>;
13
+ }
14
+ interface FileDropzoneProps extends Omit<React.ComponentProps<"div">, "onDrop"> {
15
+ /** Tipos aceitos, sintaxe do input nativo (ex: "audio/*,.mp3" ou "image/png,image/jpeg") */
16
+ accept?: string;
17
+ /** Tamanho máximo por arquivo, em bytes */
18
+ maxSize?: number;
19
+ /** Permitir múltiplos arquivos */
20
+ multiple?: boolean;
21
+ /** Máximo de arquivos por seleção (só com multiple) */
22
+ maxFiles?: number;
23
+ disabled?: boolean;
24
+ /** Arquivos que passaram na validação de seleção */
25
+ onFilesAccepted: (files: File[]) => void;
26
+ /** Arquivo rejeitado + motivo (type | size | empty | count) */
27
+ onFileRejected?: (file: File, reason: FileRejectionReason) => void;
28
+ /** Textos customizáveis (defaults PT-BR) */
29
+ labels?: FileDropzoneLabels;
30
+ }
31
+ /** Formata bytes em PT-BR (1,2 MB) */
32
+ declare function formatFileSize(bytes: number): string;
33
+ declare function FileDropzone({ accept, maxSize, multiple, maxFiles, disabled, onFilesAccepted, onFileRejected, labels, className, ...props }: FileDropzoneProps): react_jsx_runtime.JSX.Element;
34
+ type FileDropzoneItemStatus = "idle" | "uploading" | "success" | "error";
35
+ interface FileDropzoneItemProps extends React.ComponentProps<"div"> {
36
+ /** Nome do arquivo */
37
+ name: string;
38
+ /** Tamanho em bytes (formatado em PT-BR) */
39
+ size?: number;
40
+ /** Estado do upload — o upload em si é do consumidor */
41
+ status?: FileDropzoneItemStatus;
42
+ /** Progresso 0–100 (exibido quando status="uploading") */
43
+ progress?: number;
44
+ /** Mensagem exibida quando status="error" */
45
+ error?: string;
46
+ /** Remove o arquivo da lista (também usado para cancelar) */
47
+ onRemove?: () => void;
48
+ /** Label do botão remover (default: "Remover arquivo") */
49
+ removeLabel?: string;
50
+ }
51
+ declare function FileDropzoneItem({ name, size, status, progress, error, onRemove, removeLabel, className, ...props }: FileDropzoneItemProps): react_jsx_runtime.JSX.Element;
52
+
53
+ export { FileDropzone, FileDropzoneItem, type FileDropzoneItemProps, type FileDropzoneItemStatus, type FileDropzoneLabels, type FileDropzoneProps, type FileRejectionReason, formatFileSize };
@@ -0,0 +1,12 @@
1
+ "use client";
2
+ export { FileDropzone, FileDropzoneItem, formatFileSize } from '../chunk-WVCNTN4F.js';
3
+ import '../chunk-TDBDX5NV.js';
4
+ import '../chunk-GDPUWRNH.js';
5
+ import '../chunk-N2F3ZG2S.js';
6
+ import '../chunk-KLX547KZ.js';
7
+ import '../chunk-US5LXJTO.js';
8
+ import '../chunk-LYTC7UMN.js';
9
+ import '../chunk-W4KJCBMW.js';
10
+ import '../chunk-2NMEKWO5.js';
11
+ //# sourceMappingURL=file-dropzone.js.map
12
+ //# sourceMappingURL=file-dropzone.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"file-dropzone.js"}
@@ -0,0 +1,26 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as React from 'react';
3
+
4
+ declare function Pagination({ className, ...props }: React.ComponentProps<"nav">): react_jsx_runtime.JSX.Element;
5
+ declare function PaginationContent({ className, ...props }: React.ComponentProps<"ul">): react_jsx_runtime.JSX.Element;
6
+ declare function PaginationItem({ ...props }: React.ComponentProps<"li">): react_jsx_runtime.JSX.Element;
7
+ interface PaginationLinkProps extends React.ComponentProps<"a"> {
8
+ /** Página atual — aplica visual outline + aria-current="page" */
9
+ isActive?: boolean;
10
+ /** Tamanho do botão (tokens do Button) */
11
+ size?: "icon-sm" | "icon" | "sm" | "default";
12
+ /** Renderiza o filho como link (ex: Next <Link>) mantendo o visual */
13
+ asChild?: boolean;
14
+ }
15
+ declare function PaginationLink({ className, isActive, size, asChild, ...props }: PaginationLinkProps): react_jsx_runtime.JSX.Element;
16
+ declare function PaginationPrevious({ className, label, ...props }: PaginationLinkProps & {
17
+ label?: string;
18
+ }): react_jsx_runtime.JSX.Element;
19
+ declare function PaginationNext({ className, label, ...props }: PaginationLinkProps & {
20
+ label?: string;
21
+ }): react_jsx_runtime.JSX.Element;
22
+ declare function PaginationEllipsis({ className, label, ...props }: React.ComponentProps<"span"> & {
23
+ label?: string;
24
+ }): react_jsx_runtime.JSX.Element;
25
+
26
+ export { Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, type PaginationLinkProps, PaginationNext, PaginationPrevious };
@@ -0,0 +1,11 @@
1
+ "use client";
2
+ export { Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious } from '../chunk-T73O7F3B.js';
3
+ import '../chunk-N2F3ZG2S.js';
4
+ import '../chunk-KLX547KZ.js';
5
+ import '../chunk-US5LXJTO.js';
6
+ import '../chunk-LYTC7UMN.js';
7
+ import '../chunk-LALM2LHM.js';
8
+ import '../chunk-W4KJCBMW.js';
9
+ import '../chunk-2NMEKWO5.js';
10
+ //# sourceMappingURL=pagination.js.map
11
+ //# sourceMappingURL=pagination.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"pagination.js"}
@@ -0,0 +1,33 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as class_variance_authority_types from 'class-variance-authority/types';
3
+ import * as React from 'react';
4
+ import { VariantProps } from 'class-variance-authority';
5
+
6
+ type StepStatus = "completed" | "current" | "upcoming" | "error";
7
+ interface StepperStep {
8
+ /** Rótulo da etapa (ex: "Dados do curso") */
9
+ label: string;
10
+ /** Texto de apoio opcional abaixo do rótulo */
11
+ description?: string;
12
+ }
13
+ declare const stepIndicatorVariants: (props?: ({
14
+ size?: "sm" | "default" | null | undefined;
15
+ status?: "current" | "error" | "completed" | "upcoming" | null | undefined;
16
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
17
+ interface StepperProps extends Omit<React.ComponentProps<"ol">, "onClick">, VariantProps<typeof stepIndicatorVariants> {
18
+ /** Etapas na ordem do fluxo (2–8) */
19
+ steps: StepperStep[];
20
+ /** Índice (0-based) da etapa atual */
21
+ currentStep: number;
22
+ /** Índices de etapas com erro de validação */
23
+ errorSteps?: number[];
24
+ /** Orientação — horizontal (desktop) ou vertical (mobile/sidebars) */
25
+ orientation?: "horizontal" | "vertical";
26
+ /** Classe de tema aplicada apenas nos estados ativos (ex: "theme-class") */
27
+ theme?: string;
28
+ /** Torna etapas CONCLUÍDAS clicáveis para voltar — validação de pulo fica no consumidor */
29
+ onStepClick?: (index: number) => void;
30
+ }
31
+ declare function Stepper({ steps, currentStep, errorSteps, orientation, size, theme, onStepClick, className, ...props }: StepperProps): react_jsx_runtime.JSX.Element;
32
+
33
+ export { type StepStatus, Stepper, type StepperProps, type StepperStep };
@@ -0,0 +1,10 @@
1
+ "use client";
2
+ export { Stepper } from '../chunk-ONEVPGJY.js';
3
+ import '../chunk-N2F3ZG2S.js';
4
+ import '../chunk-KLX547KZ.js';
5
+ import '../chunk-US5LXJTO.js';
6
+ import '../chunk-LYTC7UMN.js';
7
+ import '../chunk-W4KJCBMW.js';
8
+ import '../chunk-2NMEKWO5.js';
9
+ //# sourceMappingURL=stepper.js.map
10
+ //# sourceMappingURL=stepper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"stepper.js"}
@@ -0,0 +1,13 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as React from 'react';
3
+
4
+ declare function Table({ className, ...props }: React.ComponentProps<"table">): react_jsx_runtime.JSX.Element;
5
+ declare function TableHeader({ className, ...props }: React.ComponentProps<"thead">): react_jsx_runtime.JSX.Element;
6
+ declare function TableBody({ className, ...props }: React.ComponentProps<"tbody">): react_jsx_runtime.JSX.Element;
7
+ declare function TableFooter({ className, ...props }: React.ComponentProps<"tfoot">): react_jsx_runtime.JSX.Element;
8
+ declare function TableRow({ className, ...props }: React.ComponentProps<"tr">): react_jsx_runtime.JSX.Element;
9
+ declare function TableHead({ className, ...props }: React.ComponentProps<"th">): react_jsx_runtime.JSX.Element;
10
+ declare function TableCell({ className, ...props }: React.ComponentProps<"td">): react_jsx_runtime.JSX.Element;
11
+ declare function TableCaption({ className, ...props }: React.ComponentProps<"caption">): react_jsx_runtime.JSX.Element;
12
+
13
+ export { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow };
@@ -0,0 +1,7 @@
1
+ "use client";
2
+ export { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow } from '../chunk-P7Y2OBHX.js';
3
+ import '../chunk-LYTC7UMN.js';
4
+ import '../chunk-W4KJCBMW.js';
5
+ import '../chunk-2NMEKWO5.js';
6
+ //# sourceMappingURL=table.js.map
7
+ //# sourceMappingURL=table.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"table.js"}
@@ -20,9 +20,18 @@ interface VideoPlayerRef {
20
20
  }
21
21
  /** @deprecated Use `Partial<VideoDesktopLabels>` — kept for backward compatibility */
22
22
  type VideoPlayerLabels = Partial<VideoDesktopLabels>;
23
- interface VideoPlayerProps {
24
- /** URL do video (mp4, webm, m3u8 para HLS) */
23
+ /** Fonte de video: URL string ou objeto com MIME type explicito.
24
+ O Vidstack infere o tipo pela EXTENSAO no path da URL — quando ela nao
25
+ existe (blob: de arquivo local, endpoints sem extensao), o provider
26
+ nao carrega. Nesses casos, passar { src, type } (ex: type do File.type
27
+ local ou o ContentType salvo no upload). */
28
+ type VideoPlayerSrc = string | {
25
29
  src: string;
30
+ type: string;
31
+ };
32
+ interface VideoPlayerProps {
33
+ /** Fonte do video: URL (mp4, webm, m3u8 para HLS) ou { src, type } para blob:/URL sem extensao */
34
+ src: VideoPlayerSrc;
26
35
  /** URL da imagem de poster */
27
36
  poster?: string;
28
37
  /** Alt text do poster */
@@ -57,4 +66,4 @@ interface VideoPlayerProps {
57
66
  }
58
67
  declare const VideoPlayer: React.ForwardRefExoticComponent<VideoPlayerProps & React.RefAttributes<VideoPlayerRef>>;
59
68
 
60
- export { type CaptionTrack, VideoPlayer, type VideoPlayerLabels, type VideoPlayerProps, type VideoPlayerRef };
69
+ export { type CaptionTrack, VideoPlayer, type VideoPlayerLabels, type VideoPlayerProps, type VideoPlayerRef, type VideoPlayerSrc };
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- export { VideoPlayer } from '../chunk-WXD7XZWE.js';
2
+ export { VideoPlayer } from '../chunk-R33NNSFO.js';
3
3
  import '../chunk-EFT7BHN7.js';
4
4
  import '../chunk-N2F3ZG2S.js';
5
5
  import '../chunk-KLX547KZ.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluencypassdevs/cycle",
3
- "version": "1.21.0",
3
+ "version": "1.27.0",
4
4
  "description": "Cycle Design System — UI component library by Fluencypass (produto)",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -126,6 +126,7 @@
126
126
  "@tiptap/starter-kit": "^3.22.3",
127
127
  "class-variance-authority": "^0.7.1",
128
128
  "clsx": "^2.1.1",
129
+ "cmdk": "^1.1.1",
129
130
  "lucide-react": "^0.577.0",
130
131
  "radix-ui": "^1.4.3",
131
132
  "react-resizable-panels": "^4.7.5",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/ui/audio-player.tsx"],"names":["AudioPlayer"],"mappings":"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","file":"chunk-LM5ZJFLA.js","sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\nimport {\n MediaPlayer,\n MediaProvider,\n TimeSlider,\n VolumeSlider,\n Time,\n PlayButton,\n MuteButton,\n SeekButton,\n useMediaState,\n useMediaRemote,\n type MediaPlayerInstance,\n} from \"@vidstack/react\"\nimport \"@vidstack/react/player/styles/base.css\"\nimport {\n Play,\n Pause,\n Volume2,\n VolumeX,\n Volume1,\n RotateCcw,\n RotateCw,\n Gauge,\n Check,\n} from \"lucide-react\"\nimport { CycleIcon } from \"@/components/icons\"\nimport { cn } from \"@/lib/utils\"\nimport { type PlayerLocale, resolveAudioSpeedNormal } from \"@/components/ui/player-i18n\"\n\n/* ─── Types ─── */\n\nexport interface AudioPlayerRef {\n play(): void\n pause(): void\n readonly currentTime: number\n readonly duration: number\n}\n\nexport interface AudioPlayerLabels {\n /** Label da velocidade normal no menu (default depende do locale) */\n speedNormal?: string\n}\n\nexport interface AudioPlayerProps {\n /** URL do audio (mp3, ogg, m3u8) */\n src: string\n /** Nome da track/aula */\n title: string\n /** Subtitulo / nome do curso */\n subtitle?: string\n /** URL da imagem de capa (variante card) */\n coverArt?: string\n /** Alt text da imagem de capa */\n coverArtAlt?: string\n /** Variante de layout */\n variant?: \"default\" | \"card\"\n /** Icones, textos e sliders em primary-foreground — usar com .theme-* */\n filled?: boolean\n /** Iniciar automaticamente */\n autoPlay?: boolean\n /** Iniciar mutado */\n muted?: boolean\n /** Repetir ao terminar */\n loop?: boolean\n /** Exibir controle de velocidade (default: true — EdTech) */\n showSpeed?: boolean\n /** Tempo inicial em segundos — usado para retomar de onde o usuario parou (resume position) */\n startTime?: number\n /** Idioma dos controles (default: \"pt-BR\"). 13 locales pre-configurados. */\n locale?: PlayerLocale\n /** Overrides pontuais de labels — aplicados em cima do locale selecionado */\n labels?: AudioPlayerLabels\n /** Callback com progresso do audio (currentTime em segundos, duration em segundos) */\n onTimeUpdate?: (currentTime: number, duration: number) => void\n /** Callback disparado quando o audio termina */\n onEnded?: () => void\n className?: string\n}\n\n/* ─── Labels context ─── */\n\nconst AudioLabelsContext = React.createContext<{ speedNormal: string }>({ speedNormal: \"Normal\" })\nfunction useAudioLabels() {\n return React.useContext(AudioLabelsContext)\n}\n\n/* ─── Shared styles ─── */\n\nconst controlBtnClass =\n \"group/btn inline-flex size-9 cursor-pointer items-center justify-center rounded-md text-foreground outline-none transition-colors hover:bg-accent focus-visible:ring-2 focus-visible:ring-ring group-data-[filled]:text-primary-foreground group-data-[filled]:hover:bg-primary-foreground/10\"\n\n/** Play, Pause e Volume usam icones filled (solid) — igual YouTube */\nconst filledIconClass =\n \"fill-current !stroke-transparent text-foreground group-data-[filled]:text-primary-foreground\"\n\nconst outlineIconClass =\n \"text-foreground group-data-[filled]:text-primary-foreground\"\n\n/* ─── Sub-components ─── */\n\nfunction AudioPlayControl() {\n const isPaused = useMediaState(\"paused\")\n return (\n <PlayButton className={controlBtnClass}>\n {isPaused ? (\n <CycleIcon icon={Play} size=\"sm\" decorative className={filledIconClass} />\n ) : (\n <CycleIcon icon={Pause} size=\"sm\" decorative className={filledIconClass} />\n )}\n </PlayButton>\n )\n}\n\nfunction AudioSeekBackwardControl() {\n return (\n <SeekButton className={controlBtnClass} seconds={-10}>\n <CycleIcon icon={RotateCcw} size=\"sm\" decorative className={outlineIconClass} />\n </SeekButton>\n )\n}\n\nfunction AudioSeekForwardControl() {\n return (\n <SeekButton className={controlBtnClass} seconds={10}>\n <CycleIcon icon={RotateCw} size=\"sm\" decorative className={outlineIconClass} />\n </SeekButton>\n )\n}\n\nfunction AudioMuteControl() {\n const volume = useMediaState(\"volume\")\n const isMuted = useMediaState(\"muted\")\n\n const Icon = isMuted || volume === 0 ? VolumeX : volume < 0.5 ? Volume1 : Volume2\n\n return (\n <MuteButton className={controlBtnClass}>\n <CycleIcon icon={Icon} size=\"sm\" decorative className={filledIconClass} />\n </MuteButton>\n )\n}\n\nfunction AudioVolumeControl() {\n return (\n <VolumeSlider.Root className=\"group relative hidden h-9 w-20 cursor-pointer touch-none select-none items-center outline-none sm:inline-flex\">\n <VolumeSlider.Track className=\"relative h-[4px] w-full rounded-full bg-accent group-data-[filled]/root:bg-primary-foreground/30\">\n <VolumeSlider.TrackFill className=\"absolute h-full w-[var(--slider-fill)] rounded-full bg-primary group-data-[filled]/root:bg-primary-foreground\" />\n </VolumeSlider.Track>\n <VolumeSlider.Thumb className=\"absolute left-[var(--slider-fill)] top-1/2 size-3 -translate-x-1/2 -translate-y-1/2 rounded-full bg-primary opacity-0 transition-opacity group-data-[active]:opacity-100 group-data-[dragging]:opacity-100 group-data-[filled]/root:bg-primary-foreground\" />\n </VolumeSlider.Root>\n )\n}\n\nfunction AudioSeekBar() {\n return (\n <TimeSlider.Root className=\"group relative inline-flex h-9 w-full cursor-pointer touch-none select-none items-center outline-none\">\n <TimeSlider.Track className=\"relative h-[4px] w-full rounded-full bg-accent group-data-[filled]/root:bg-primary-foreground/30\">\n <TimeSlider.Progress className=\"absolute h-full w-[var(--slider-progress)] rounded-full bg-accent-foreground/20 group-data-[filled]/root:bg-primary-foreground/20\" />\n <TimeSlider.TrackFill className=\"absolute h-full w-[var(--slider-fill)] rounded-full bg-primary group-data-[filled]/root:bg-primary-foreground\" />\n </TimeSlider.Track>\n <TimeSlider.Thumb className=\"absolute left-[var(--slider-fill)] top-1/2 size-3 -translate-x-1/2 -translate-y-1/2 rounded-full bg-primary opacity-0 transition-opacity group-data-[active]:opacity-100 group-data-[dragging]:opacity-100 group-data-[filled]/root:bg-primary-foreground\" />\n\n {/* Time preview on hover */}\n <TimeSlider.Preview className=\"pointer-events-none flex flex-col items-center opacity-0 transition-opacity duration-200 data-[visible]:opacity-100\">\n <TimeSlider.Value className=\"rounded bg-popover px-1.5 py-0.5 text-[11px] font-mono text-popover-foreground border border-border shadow-sm\" />\n </TimeSlider.Preview>\n </TimeSlider.Root>\n )\n}\n\nfunction AudioTimeDisplay() {\n return (\n <div className=\"flex items-center gap-1 text-xs font-mono text-muted-foreground tabular-nums group-data-[filled]:text-primary-foreground/80\">\n <Time type=\"current\" />\n <span>/</span>\n <Time type=\"duration\" />\n </div>\n )\n}\n\nfunction AudioSpeedControl() {\n const playbackRate = useMediaState(\"playbackRate\")\n const remote = useMediaRemote()\n const [open, setOpen] = React.useState(false)\n const l = useAudioLabels()\n\n const rates = [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2]\n\n return (\n <div className=\"relative\">\n <button\n type=\"button\"\n onClick={() => setOpen(!open)}\n className={controlBtnClass}\n >\n {playbackRate === 1 ? (\n <CycleIcon icon={Gauge} size=\"sm\" decorative className={outlineIconClass} />\n ) : (\n <span className=\"text-xs font-mono font-semibold text-foreground group-data-[filled]:text-primary-foreground\">{playbackRate}x</span>\n )}\n </button>\n\n {open && (\n <>\n {/* Backdrop to close */}\n <div className=\"fixed inset-0 z-40\" onClick={() => setOpen(false)} />\n\n <div className=\"absolute bottom-full right-0 z-50 mb-2 min-w-[120px] rounded-lg border border-border bg-popover p-1 shadow-lg\">\n {rates.map((rate) => (\n <button\n key={rate}\n type=\"button\"\n onClick={() => {\n remote.changePlaybackRate(rate)\n setOpen(false)\n }}\n className={cn(\n \"flex w-full items-center gap-2 rounded-md px-3 py-1.5 text-sm text-popover-foreground/80 transition-colors hover:bg-accent hover:text-popover-foreground\",\n playbackRate === rate && \"text-popover-foreground font-medium\"\n )}\n >\n <span className=\"size-4 flex items-center justify-center\">\n {playbackRate === rate && <CycleIcon icon={Check} size=\"2xs\" decorative className=\"text-popover-foreground\" />}\n </span>\n <span className=\"font-mono\">{rate === 1 ? l.speedNormal : `${rate}x`}</span>\n </button>\n ))}\n </div>\n </>\n )}\n </div>\n )\n}\n\n/* ─── Main component ─── */\n\nexport const AudioPlayer = React.forwardRef<AudioPlayerRef, AudioPlayerProps>(\n function AudioPlayer(\n {\n src,\n title,\n subtitle,\n coverArt,\n coverArtAlt = \"\",\n variant = \"default\",\n filled = false,\n autoPlay = false,\n muted = false,\n loop = false,\n showSpeed = true,\n startTime,\n locale = \"pt-BR\",\n labels,\n onTimeUpdate,\n onEnded,\n className,\n },\n ref\n ) {\n const resolvedLabels = React.useMemo(\n () => ({ speedNormal: resolveAudioSpeedNormal(locale, labels?.speedNormal) }),\n [locale, labels]\n )\n const player = React.useRef<MediaPlayerInstance>(null)\n\n React.useImperativeHandle(ref, () => ({\n play() {\n player.current?.play()\n },\n pause() {\n player.current?.pause()\n },\n get currentTime() {\n return player.current?.currentTime ?? 0\n },\n get duration() {\n return player.current?.duration ?? 0\n },\n }))\n\n const handleTimeUpdate = React.useCallback(\n (detail: { currentTime: number }) => {\n if (onTimeUpdate && player.current) {\n onTimeUpdate(detail.currentTime, player.current.duration)\n }\n },\n [onTimeUpdate]\n )\n\n const handleEnded = React.useCallback(() => {\n onEnded?.()\n }, [onEnded])\n\n // Resume position: seek to startTime once the player is ready\n const hasAppliedStartTime = React.useRef(false)\n const handleCanPlay = React.useCallback(() => {\n if (startTime && startTime > 0 && !hasAppliedStartTime.current && player.current) {\n player.current.currentTime = startTime\n hasAppliedStartTime.current = true\n }\n }, [startTime])\n\n const playerEvents = {\n onCanPlay: handleCanPlay,\n ...(onTimeUpdate ? { onTimeUpdate: handleTimeUpdate } : {}),\n ...(onEnded ? { onEnded: handleEnded } : {}),\n }\n\n if (variant === \"card\") {\n return (\n <AudioLabelsContext.Provider value={resolvedLabels}>\n <MediaPlayer\n ref={player}\n src={src}\n autoPlay={autoPlay}\n muted={muted}\n loop={loop}\n viewType=\"audio\"\n data-filled={filled ? \"\" : undefined}\n style={filled ? { '--primary-foreground': 'var(--secondary-foreground)' } as Record<string, string> : undefined}\n className={cn(\n \"group/root group !block w-full rounded-xl border border-border bg-card p-4 shadow-sm md:p-6\",\n className\n )}\n {...playerEvents}\n >\n <MediaProvider className=\"!hidden\" />\n\n {/* Top: cover art + text */}\n <div className=\"flex gap-4 mb-4 md:gap-5 md:mb-6\">\n {coverArt && (\n <img\n src={coverArt}\n alt={coverArtAlt}\n className=\"size-16 shrink-0 rounded-lg object-cover bg-muted md:size-24 md:rounded-xl\"\n />\n )}\n <div className=\"flex min-w-0 flex-col justify-center\">\n <p className={cn(\n \"truncate heading-md md:heading-xl\",\n filled ? \"text-primary-foreground\" : \"text-card-foreground\"\n )}>{title}</p>\n {subtitle && (\n <p className={cn(\n \"truncate body-md md:body-lg\",\n filled ? \"text-primary-foreground/70\" : \"text-muted-foreground\"\n )}>{subtitle}</p>\n )}\n </div>\n </div>\n\n {/* Seek bar */}\n <div className=\"flex w-full items-center\">\n <AudioSeekBar />\n </div>\n\n {/* Time */}\n <div className=\"flex items-center justify-between px-0.5 -mt-1 mb-1 md:mb-2\">\n <div className={cn(\n \"text-[11px] font-mono tabular-nums md:text-xs\",\n filled ? \"text-primary-foreground/80\" : \"text-muted-foreground\"\n )}>\n <Time type=\"current\" />\n </div>\n <div className={cn(\n \"text-[11px] font-mono tabular-nums md:text-xs\",\n filled ? \"text-primary-foreground/80\" : \"text-muted-foreground\"\n )}>\n <Time type=\"duration\" />\n </div>\n </div>\n\n {/* Controls */}\n <div className=\"flex items-center gap-1 md:gap-2\">\n <AudioSeekBackwardControl />\n <AudioPlayControl />\n <AudioSeekForwardControl />\n\n <div className=\"flex-1\" />\n\n {showSpeed && <AudioSpeedControl />}\n <AudioMuteControl />\n <AudioVolumeControl />\n </div>\n </MediaPlayer>\n </AudioLabelsContext.Provider>\n )\n }\n\n // Default variant (compact bar)\n return (\n <AudioLabelsContext.Provider value={resolvedLabels}>\n <MediaPlayer\n ref={player}\n src={src}\n autoPlay={autoPlay}\n muted={muted}\n loop={loop}\n viewType=\"audio\"\n data-filled={filled ? \"\" : undefined}\n style={filled ? { '--primary-foreground': 'var(--secondary-foreground)' } as Record<string, string> : undefined}\n className={cn(\n \"group/root group !flex w-full items-center gap-1.5 rounded-xl border border-border bg-card px-2 py-1.5 shadow-sm\",\n className\n )}\n {...playerEvents}\n >\n <MediaProvider className=\"!hidden\" />\n\n {/* Left controls */}\n <AudioSeekBackwardControl />\n <AudioPlayControl />\n <AudioSeekForwardControl />\n\n {/* Seek bar */}\n <div className=\"flex-1 px-1\">\n <AudioSeekBar />\n </div>\n\n {/* Time */}\n <AudioTimeDisplay />\n\n {/* Right controls */}\n {showSpeed && <AudioSpeedControl />}\n <AudioMuteControl />\n <AudioVolumeControl />\n </MediaPlayer>\n </AudioLabelsContext.Provider>\n )\n }\n)\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/ui/video-player.tsx"],"names":["forwardRef","CaptionsIcon","VideoPlayer","_a"],"mappings":"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","file":"chunk-WXD7XZWE.js","sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\nimport {\n MediaPlayer,\n MediaProvider,\n Poster,\n Controls,\n Gesture,\n TimeSlider,\n VolumeSlider,\n Time,\n PlayButton,\n MuteButton,\n FullscreenButton,\n CaptionButton,\n PIPButton,\n SeekButton,\n Captions,\n Spinner,\n Track,\n Tooltip,\n Menu,\n LiveButton,\n MediaAnnouncer,\n useMediaState,\n useMediaRemote,\n useVideoQualityOptions,\n useCaptionOptions,\n type MediaPlayerInstance,\n} from \"@vidstack/react\"\n// Desktop-only controls use the above. Mobile uses DefaultVideoLayout below.\nimport {\n DefaultVideoLayout,\n defaultLayoutIcons,\n} from \"@vidstack/react/player/layouts/default\"\nimport \"@vidstack/react/player/styles/base.css\"\nimport \"@vidstack/react/player/styles/default/theme.css\"\nimport \"@vidstack/react/player/styles/default/layouts/video.css\"\nimport {\n Play,\n Pause,\n Volume2,\n VolumeX,\n Volume1,\n Maximize,\n Minimize,\n Captions as CaptionsIcon,\n CaptionsOff,\n PictureInPicture2,\n RotateCcw,\n RotateCw,\n Gauge,\n Settings,\n Check,\n} from \"lucide-react\"\nimport { CycleIcon } from \"@/components/icons\"\nimport { cn } from \"@/lib/utils\"\nimport {\n type PlayerLocale,\n type VideoDesktopLabels,\n resolveVideoLabels,\n resolveVidstackTranslations,\n} from \"@/components/ui/player-i18n\"\n\n/* ─── Types ─── */\n\nexport interface CaptionTrack {\n /** URL do arquivo VTT de legenda */\n src: string\n /** Codigo do idioma (BCP 47, ex: \"pt-BR\", \"en\", \"es\") */\n language: string\n /** Label exibido no seletor de legendas (ex: \"Portugues\", \"English\") */\n label: string\n /** Se true, esta faixa sera ativada por padrao */\n default?: boolean\n}\n\nexport interface VideoPlayerRef {\n play(): void\n pause(): void\n readonly currentTime: number\n readonly duration: number\n}\n\n/** @deprecated Use `Partial<VideoDesktopLabels>` — kept for backward compatibility */\nexport type VideoPlayerLabels = Partial<VideoDesktopLabels>\n\nexport interface VideoPlayerProps {\n /** URL do video (mp4, webm, m3u8 para HLS) */\n src: string\n /** URL da imagem de poster */\n poster?: string\n /** Alt text do poster */\n posterAlt?: string\n /** URL do arquivo de thumbnails (VTT sprite sheet) */\n thumbnails?: string\n /** URL do arquivo VTT de chapters (marcadores de seção no timeline) */\n chapters?: string\n /** Faixas de legenda/subtitles (VTT). Suporta multiplos idiomas. */\n captions?: CaptionTrack[]\n /** Exibir spinner durante buffering (default: true) */\n showBuffering?: boolean\n /** Habilitar anuncios de acessibilidade para screen readers (default: true) */\n announcer?: boolean\n /** Iniciar automaticamente */\n autoPlay?: boolean\n /** Iniciar mutado */\n muted?: boolean\n /** Repetir ao terminar */\n loop?: boolean\n /** Tempo inicial em segundos — usado para retomar de onde o usuario parou (resume position) */\n startTime?: number\n /** Idioma dos controles (default: \"pt-BR\"). 13 locales pre-configurados. */\n locale?: PlayerLocale\n /** Overrides pontuais de labels — aplicados em cima do locale selecionado */\n labels?: VideoPlayerLabels\n /** Callback com progresso do video (currentTime em segundos, duration em segundos) */\n onTimeUpdate?: (currentTime: number, duration: number) => void\n /** Callback disparado quando o video termina */\n onEnded?: () => void\n className?: string\n}\n\n/* ─── Labels context ─── */\n\nconst VideoLabelsContext = React.createContext<VideoDesktopLabels>(\n resolveVideoLabels(\"pt-BR\")\n)\nfunction useVideoLabels() {\n return React.useContext(VideoLabelsContext)\n}\n\n/* ─── Shared styles ─── */\n\nconst controlBtnClass =\n \"group inline-flex size-9 cursor-pointer items-center justify-center rounded-md text-white outline-none transition-colors hover:bg-white/20 focus-visible:ring-2 focus-visible:ring-white/50\"\n\nconst tooltipClass =\n \"z-50 rounded bg-black/90 px-2 py-1 text-xs font-medium text-white shadow-lg animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0\"\n\n/** Wraps a control button with a Vidstack tooltip. Desktop only (no hover on mobile). */\nfunction ControlTooltip({ label, children }: { label: string; children: React.ReactNode }) {\n return (\n <Tooltip.Root>\n <Tooltip.Trigger asChild>{children}</Tooltip.Trigger>\n <Tooltip.Content className={tooltipClass} placement=\"top\">\n {label}\n </Tooltip.Content>\n </Tooltip.Root>\n )\n}\n\n/** Play, Pause e Volume usam icones filled (solid) no player — igual YouTube */\nconst filledIconClass = \"text-white fill-current !stroke-transparent\"\n\n/* ─── Sub-components (controles customizados) ─── */\n\nfunction PlayOverlay() {\n const isPaused = useMediaState(\"paused\")\n const hasStarted = useMediaState(\"started\")\n\n if (!isPaused && hasStarted) return null\n\n return (\n <PlayButton className=\"absolute inset-0 z-10 flex cursor-pointer items-center justify-center bg-black/30 transition-opacity\">\n <div className=\"flex size-16 items-center justify-center rounded-full bg-white/20 backdrop-blur-sm transition-transform hover:scale-110\">\n <CycleIcon icon={Play} size=\"lg\" decorative className={cn(filledIconClass, \"ml-1\")} />\n </div>\n </PlayButton>\n )\n}\n\nfunction PlayControl() {\n const isPaused = useMediaState(\"paused\")\n const l = useVideoLabels()\n return (\n <ControlTooltip label={isPaused ? l.play : l.pause}>\n <PlayButton className={controlBtnClass}>\n {isPaused ? (\n <CycleIcon icon={Play} size=\"sm\" decorative className={filledIconClass} />\n ) : (\n <CycleIcon icon={Pause} size=\"sm\" decorative className={filledIconClass} />\n )}\n </PlayButton>\n </ControlTooltip>\n )\n}\n\nfunction SeekBackwardControl() {\n const l = useVideoLabels()\n return (\n <ControlTooltip label={l.seekBackward}>\n <SeekButton className={controlBtnClass} seconds={-10}>\n <CycleIcon icon={RotateCcw} size=\"sm\" decorative className=\"text-white\" />\n </SeekButton>\n </ControlTooltip>\n )\n}\n\nfunction SeekForwardControl() {\n const l = useVideoLabels()\n return (\n <ControlTooltip label={l.seekForward}>\n <SeekButton className={controlBtnClass} seconds={10}>\n <CycleIcon icon={RotateCw} size=\"sm\" decorative className=\"text-white\" />\n </SeekButton>\n </ControlTooltip>\n )\n}\n\nfunction MuteControl() {\n const volume = useMediaState(\"volume\")\n const isMuted = useMediaState(\"muted\")\n const l = useVideoLabels()\n\n const Icon = isMuted || volume === 0 ? VolumeX : volume < 0.5 ? Volume1 : Volume2\n const label = isMuted || volume === 0 ? l.unmute : l.mute\n\n return (\n <ControlTooltip label={label}>\n <MuteButton className={controlBtnClass}>\n <CycleIcon icon={Icon} size=\"sm\" decorative className={filledIconClass} />\n </MuteButton>\n </ControlTooltip>\n )\n}\n\nfunction VolumeControl() {\n return (\n <VolumeSlider.Root className=\"group relative hidden h-9 w-20 shrink-0 cursor-pointer touch-none select-none items-center outline-none @[480px]:inline-flex\">\n <VolumeSlider.Track className=\"relative h-[4px] w-full rounded-full bg-white/30\">\n <VolumeSlider.TrackFill className=\"absolute h-full w-[var(--slider-fill)] rounded-full bg-white\" />\n </VolumeSlider.Track>\n <VolumeSlider.Thumb className=\"absolute left-[var(--slider-fill)] top-1/2 size-3 -translate-x-1/2 -translate-y-1/2 rounded-full bg-white opacity-0 transition-opacity group-data-[active]:opacity-100 group-data-[dragging]:opacity-100\" />\n </VolumeSlider.Root>\n )\n}\n\nfunction BufferingIndicator() {\n return (\n <div className=\"pointer-events-none absolute inset-0 z-[35] flex items-center justify-center media-buffering:opacity-100 media-can-play:opacity-0 opacity-0 transition-opacity duration-300\">\n <Spinner.Root className=\"size-16 text-white\" size={64}>\n <Spinner.Track className=\"opacity-25\" width={4} />\n <Spinner.TrackFill className=\"opacity-75\" width={4} />\n </Spinner.Root>\n </div>\n )\n}\n\nfunction SeekBar({ thumbnails, chapters }: { thumbnails?: string; chapters?: boolean }) {\n const trackContent = (\n <>\n <TimeSlider.Track className=\"relative h-[4px] w-full rounded-full bg-white/30\">\n <TimeSlider.Progress className=\"absolute h-full w-[var(--slider-progress)] rounded-full bg-white/50\" />\n <TimeSlider.TrackFill className=\"absolute h-full w-[var(--slider-fill)] rounded-full bg-white\" />\n </TimeSlider.Track>\n </>\n )\n\n return (\n <TimeSlider.Root className=\"group relative inline-flex h-9 w-full cursor-pointer touch-none select-none items-center outline-none\">\n {chapters ? (\n <TimeSlider.Chapters className=\"relative flex w-full items-center\">\n {(cues, forwardRef) =>\n cues.map((cue) => (\n <div\n className=\"relative flex h-full w-full items-center last:mr-0 mr-0.5\"\n key={cue.startTime}\n ref={forwardRef}\n >\n {trackContent}\n </div>\n ))\n }\n </TimeSlider.Chapters>\n ) : (\n trackContent\n )}\n\n <TimeSlider.Thumb className=\"absolute left-[var(--slider-fill)] top-1/2 size-3 -translate-x-1/2 -translate-y-1/2 rounded-full bg-white opacity-0 transition-opacity group-data-[active]:opacity-100 group-data-[dragging]:opacity-100\" />\n\n {/* Thumbnail preview on hover */}\n {thumbnails && (\n <TimeSlider.Preview className=\"pointer-events-none flex flex-col items-center gap-1 opacity-0 transition-opacity duration-200 data-[visible]:opacity-100\">\n <TimeSlider.Thumbnail.Root\n src={thumbnails}\n className=\"block h-[var(--thumbnail-height)] max-h-[160px] min-h-[80px] w-[var(--thumbnail-width)] min-w-[120px] max-w-[200px] overflow-hidden rounded-md border-2 border-white bg-black\"\n >\n <TimeSlider.Thumbnail.Img />\n </TimeSlider.Thumbnail.Root>\n {chapters && <TimeSlider.ChapterTitle className=\"text-[11px] text-white/80\" />}\n <TimeSlider.Value className=\"rounded bg-black/80 px-1.5 py-0.5 text-[11px] font-mono text-white\" />\n </TimeSlider.Preview>\n )}\n\n {/* Time preview (no thumbnails) */}\n {!thumbnails && (\n <TimeSlider.Preview className=\"pointer-events-none flex flex-col items-center opacity-0 transition-opacity duration-200 data-[visible]:opacity-100\">\n {chapters && <TimeSlider.ChapterTitle className=\"text-[11px] text-white/80 mb-0.5\" />}\n <TimeSlider.Value className=\"rounded bg-black/80 px-1.5 py-0.5 text-[11px] font-mono text-white\" />\n </TimeSlider.Preview>\n )}\n </TimeSlider.Root>\n )\n}\n\nfunction TimeDisplay() {\n return (\n <div className=\"flex shrink-0 items-center gap-1 text-xs font-mono text-white/80 tabular-nums whitespace-nowrap\">\n <Time type=\"current\" />\n <span>/</span>\n <Time type=\"duration\" />\n </div>\n )\n}\n\nfunction CaptionControl() {\n const track = useMediaState(\"textTrack\")\n const hasCaptions = useMediaState(\"hasCaptions\")\n const options = useCaptionOptions()\n const l = useVideoLabels()\n\n // Single track or none: simple toggle button (native CaptionButton behavior)\n if (options.length <= 2) {\n return (\n <ControlTooltip label={track ? l.captionsOn : l.captionsOff}>\n <CaptionButton className={cn(controlBtnClass, !hasCaptions && \"opacity-50 pointer-events-none\")}>\n {track ? (\n <CycleIcon icon={CaptionsIcon} size=\"sm\" decorative className=\"text-white\" />\n ) : (\n <CycleIcon icon={CaptionsOff} size=\"sm\" decorative className=\"text-white\" />\n )}\n </CaptionButton>\n </ControlTooltip>\n )\n }\n\n // Multiple tracks: menu with language selection (native Vidstack Menu behavior)\n return (\n <Menu.Root>\n <ControlTooltip label={l.captions}>\n <Menu.Button className={controlBtnClass}>\n {track ? (\n <CycleIcon icon={CaptionsIcon} size=\"sm\" decorative className=\"text-white\" />\n ) : (\n <CycleIcon icon={CaptionsOff} size=\"sm\" decorative className=\"text-white\" />\n )}\n </Menu.Button>\n </ControlTooltip>\n\n <Menu.Content\n className=\"absolute bottom-full right-0 z-50 mb-2 min-w-[140px] rounded-lg border border-white/10 bg-black/90 backdrop-blur-md p-1 shadow-xl\"\n placement=\"top\"\n >\n <p className=\"px-3 py-1 text-[11px] font-semibold uppercase tracking-wider text-white/50\">\n {l.captions}\n </p>\n <Menu.RadioGroup value={options.selectedValue}>\n {options.map((option) => (\n <Menu.Radio\n key={option.value}\n value={option.value}\n onSelect={option.select}\n className={cn(\n \"flex w-full items-center gap-2 rounded-md px-3 py-1.5 text-sm text-white/80 transition-colors hover:bg-white/10 hover:text-white cursor-pointer\",\n option.selected && \"text-white font-medium\"\n )}\n >\n <span className=\"size-4 flex items-center justify-center\">\n {option.selected && <CycleIcon icon={Check} size=\"2xs\" decorative className=\"text-white\" />}\n </span>\n <span>{option.label}</span>\n </Menu.Radio>\n ))}\n </Menu.RadioGroup>\n </Menu.Content>\n </Menu.Root>\n )\n}\n\nfunction PIPControl() {\n const isPIP = useMediaState(\"pictureInPicture\")\n const canPIP = useMediaState(\"canPictureInPicture\")\n const l = useVideoLabels()\n\n if (!canPIP) return null\n\n return (\n <ControlTooltip label={isPIP ? l.pipExit : l.pip}>\n <PIPButton className={controlBtnClass}>\n <CycleIcon icon={PictureInPicture2} size=\"sm\" decorative className={cn(\"text-white\", isPIP && \"text-white/100\")} />\n </PIPButton>\n </ControlTooltip>\n )\n}\n\nfunction SpeedControl() {\n const playbackRate = useMediaState(\"playbackRate\")\n const remote = useMediaRemote()\n const [open, setOpen] = React.useState(false)\n const l = useVideoLabels()\n\n const rates = [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2]\n\n return (\n <div className=\"relative\">\n <ControlTooltip label={l.speed}>\n <button\n type=\"button\"\n onClick={() => setOpen(!open)}\n className={controlBtnClass}\n >\n {playbackRate === 1 ? (\n <CycleIcon icon={Gauge} size=\"sm\" decorative className=\"text-white\" />\n ) : (\n <span className=\"text-xs font-mono font-semibold text-white\">{playbackRate}x</span>\n )}\n </button>\n </ControlTooltip>\n\n {open && (\n <>\n {/* Backdrop to close */}\n <div className=\"fixed inset-0 z-40\" onClick={() => setOpen(false)} />\n\n <div className=\"absolute bottom-full right-0 z-50 mb-2 min-w-[120px] rounded-lg border border-white/10 bg-black/90 backdrop-blur-md p-1 shadow-xl\">\n {rates.map((rate) => (\n <button\n key={rate}\n type=\"button\"\n onClick={() => {\n remote.changePlaybackRate(rate)\n setOpen(false)\n }}\n className={cn(\n \"flex w-full items-center gap-2 rounded-md px-3 py-1.5 text-sm text-white/80 transition-colors hover:bg-white/10 hover:text-white\",\n playbackRate === rate && \"text-white font-medium\"\n )}\n >\n <span className=\"size-4 flex items-center justify-center\">\n {playbackRate === rate && <CycleIcon icon={Check} size=\"2xs\" decorative className=\"text-white\" />}\n </span>\n <span className=\"font-mono\">{rate === 1 ? l.speedNormal : `${rate}x`}</span>\n </button>\n ))}\n </div>\n </>\n )}\n </div>\n )\n}\n\nfunction QualityControl() {\n const options = useVideoQualityOptions({ auto: true, sort: \"descending\" })\n const [open, setOpen] = React.useState(false)\n const l = useVideoLabels()\n\n const currentLabel = options.selectedValue === \"auto\"\n ? `Auto${options.selectedQuality ? ` (${options.selectedQuality.height}p)` : \"\"}`\n : options.selectedQuality\n ? `${options.selectedQuality.height}p`\n : \"Auto\"\n\n if (options.disabled) return null\n\n return (\n <div className=\"relative\">\n <ControlTooltip label={l.quality}>\n <button\n type=\"button\"\n onClick={() => setOpen(!open)}\n className={controlBtnClass}\n >\n <CycleIcon icon={Settings} size=\"sm\" decorative className=\"text-white\" />\n </button>\n </ControlTooltip>\n\n {open && (\n <>\n <div className=\"fixed inset-0 z-40\" onClick={() => setOpen(false)} />\n\n <div className=\"absolute bottom-full right-0 z-50 mb-2 min-w-[140px] rounded-lg border border-white/10 bg-black/90 backdrop-blur-md p-1 shadow-xl\">\n <p className=\"px-3 py-1 text-[11px] font-semibold uppercase tracking-wider text-white/50\">\n {l.qualityMenu}\n </p>\n {options.map((option) => (\n <button\n key={option.value}\n type=\"button\"\n onClick={() => {\n option.select()\n setOpen(false)\n }}\n className={cn(\n \"flex w-full items-center gap-2 rounded-md px-3 py-1.5 text-sm text-white/80 transition-colors hover:bg-white/10 hover:text-white\",\n option.selected && \"text-white font-medium\"\n )}\n >\n <span className=\"size-4 flex items-center justify-center\">\n {option.selected && <CycleIcon icon={Check} size=\"2xs\" decorative className=\"text-white\" />}\n </span>\n <span className=\"font-mono\">{option.label}</span>\n </button>\n ))}\n </div>\n </>\n )}\n </div>\n )\n}\n\nfunction FullscreenControl() {\n const isFullscreen = useMediaState(\"fullscreen\")\n const l = useVideoLabels()\n return (\n <ControlTooltip label={isFullscreen ? l.fullscreenExit : l.fullscreen}>\n <FullscreenButton className={controlBtnClass}>\n {isFullscreen ? (\n <CycleIcon icon={Minimize} size=\"sm\" decorative className=\"text-white\" />\n ) : (\n <CycleIcon icon={Maximize} size=\"sm\" decorative className=\"text-white\" />\n )}\n </FullscreenButton>\n </ControlTooltip>\n )\n}\n\nfunction LiveIndicator() {\n const isLive = useMediaState(\"live\")\n const isLiveEdge = useMediaState(\"liveEdge\")\n const l = useVideoLabels()\n\n if (!isLive) return null\n\n return (\n <LiveButton\n className={cn(\n \"inline-flex cursor-pointer items-center gap-1.5 rounded-md px-2 py-1 text-xs font-semibold uppercase tracking-wider transition-colors\",\n isLiveEdge\n ? \"text-destructive\"\n : \"text-white/60 hover:text-white\"\n )}\n >\n <span\n className={cn(\n \"size-2 rounded-full\",\n isLiveEdge ? \"bg-destructive animate-pulse\" : \"bg-white/40\"\n )}\n />\n {l.live}\n </LiveButton>\n )\n}\n\n\n/* ─── Gesture helpers ─── */\n\ntype SeekDirection = \"backward\" | \"forward\"\n\nconst DOUBLE_TAP_THRESHOLD = 300\n\n/** Double-tap left/right edges to seek ±10s. z-10 so it doesn't block controls (z-20). */\nfunction SeekGestureZone({\n side,\n onSeekFeedback,\n}: {\n side: \"left\" | \"right\"\n onSeekFeedback: (direction: SeekDirection) => void\n}) {\n const remote = useMediaRemote()\n const currentTime = useMediaState(\"currentTime\")\n const lastTapRef = React.useRef(0)\n\n const handlePointerUp = React.useCallback(\n (e: React.PointerEvent) => {\n const now = Date.now()\n const delta = now - lastTapRef.current\n lastTapRef.current = now\n\n if (delta < DOUBLE_TAP_THRESHOLD) {\n e.stopPropagation()\n const seconds = side === \"left\" ? -10 : 10\n remote.seek(currentTime + seconds)\n onSeekFeedback(side === \"left\" ? \"backward\" : \"forward\")\n }\n },\n [remote, currentTime, side, onSeekFeedback]\n )\n\n return (\n <div\n className={cn(\n \"absolute top-0 z-10 block h-full w-1/5\",\n side === \"left\" ? \"left-0\" : \"right-0\"\n )}\n onPointerUp={handlePointerUp}\n />\n )\n}\n\nfunction SeekFeedbackOverlay({\n direction,\n visible,\n seconds,\n}: {\n direction: SeekDirection\n visible: boolean\n seconds: number\n}) {\n const isBackward = direction === \"backward\"\n\n return (\n <div\n className={cn(\n \"pointer-events-none absolute top-0 z-[35] flex h-full w-2/5 items-center transition-opacity duration-200\",\n isBackward ? \"left-0 justify-center\" : \"right-0 justify-center\",\n visible ? \"opacity-100\" : \"opacity-0\"\n )}\n >\n <div\n className={cn(\n \"flex flex-col items-center gap-1 transition-transform duration-300\",\n visible ? \"scale-100\" : \"scale-75\"\n )}\n >\n <div className=\"flex size-12 items-center justify-center rounded-full bg-white/20 backdrop-blur-sm\">\n <CycleIcon\n icon={isBackward ? RotateCcw : RotateCw}\n size=\"sm\"\n decorative\n className=\"text-white\"\n />\n </div>\n <span className=\"text-xs font-semibold text-white drop-shadow-md\">\n {seconds}s\n </span>\n </div>\n </div>\n )\n}\n\n\n/* ─── Hook: detect desktop via pointer capability ─── */\n/* Uses pointer: fine (mouse/trackpad) instead of viewport width.\n This way mobile devices keep the touch-optimized DefaultVideoLayout\n even when fullscreen in landscape exceeds the sm breakpoint. */\n\nfunction useIsDesktop() {\n const [isDesktop, setIsDesktop] = React.useState(false)\n\n React.useEffect(() => {\n const mq = window.matchMedia(\"(pointer: fine)\")\n setIsDesktop(mq.matches)\n const handler = (e: MediaQueryListEvent) => setIsDesktop(e.matches)\n mq.addEventListener(\"change\", handler)\n return () => mq.removeEventListener(\"change\", handler)\n }, [])\n\n return isDesktop\n}\n\n/* ─── Main component ─── */\n\nexport const VideoPlayer = React.forwardRef<VideoPlayerRef, VideoPlayerProps>(\n function VideoPlayer(\n {\n src,\n poster,\n posterAlt = \"\",\n thumbnails,\n chapters,\n captions,\n showBuffering = true,\n announcer = true,\n autoPlay = false,\n muted = false,\n loop = false,\n startTime,\n locale = \"pt-BR\",\n labels,\n onTimeUpdate,\n onEnded,\n className,\n },\n ref\n ) {\n const resolvedLabels = React.useMemo(\n () => resolveVideoLabels(locale, labels),\n [locale, labels]\n )\n const vidstackTranslations = React.useMemo(\n () => resolveVidstackTranslations(locale, labels),\n [locale, labels]\n )\n const player = React.useRef<MediaPlayerInstance>(null)\n\n React.useImperativeHandle(ref, () => ({\n play() {\n player.current?.play()\n },\n pause() {\n player.current?.pause()\n },\n get currentTime() {\n return player.current?.currentTime ?? 0\n },\n get duration() {\n return player.current?.duration ?? 0\n },\n }))\n\n const handleTimeUpdate = React.useCallback(\n (detail: { currentTime: number }) => {\n if (onTimeUpdate && player.current) {\n onTimeUpdate(detail.currentTime, player.current.duration)\n }\n },\n [onTimeUpdate]\n )\n\n const handleEnded = React.useCallback(() => {\n onEnded?.()\n }, [onEnded])\n\n // Resume position: seek to startTime once the player is ready\n const hasAppliedStartTime = React.useRef(false)\n const handleCanPlay = React.useCallback(() => {\n if (startTime && startTime > 0 && !hasAppliedStartTime.current && player.current) {\n player.current.currentTime = startTime\n hasAppliedStartTime.current = true\n }\n }, [startTime])\n\n const playerEvents = {\n onCanPlay: handleCanPlay,\n ...(onTimeUpdate ? { onTimeUpdate: handleTimeUpdate } : {}),\n ...(onEnded ? { onEnded: handleEnded } : {}),\n }\n const isDesktop = useIsDesktop()\n\n // Seek feedback state with accumulation (like YouTube)\n const [seekFeedback, setSeekFeedback] = React.useState<SeekDirection | null>(null)\n const [seekAccumulated, setSeekAccumulated] = React.useState(0)\n const feedbackTimeout = React.useRef<ReturnType<typeof setTimeout>>(undefined)\n\n const handleSeekFeedback = React.useCallback((direction: SeekDirection) => {\n clearTimeout(feedbackTimeout.current)\n\n setSeekFeedback((prev) => {\n if (prev === direction) {\n setSeekAccumulated((s) => s + 10)\n } else {\n setSeekAccumulated(10)\n }\n return direction\n })\n\n feedbackTimeout.current = setTimeout(() => {\n setSeekFeedback(null)\n setSeekAccumulated(0)\n }, 700)\n }, [])\n\n // Mobile: listen for seek requests from DefaultVideoLayout gestures\n React.useEffect(() => {\n const el = player.current?.el\n if (!el || isDesktop) return\n\n const handler = (e: Event) => {\n const seekTo = (e as CustomEvent<number>).detail\n const current = player.current?.currentTime ?? 0\n const delta = seekTo - current\n // Only show feedback for gesture seeks (~±10s), not slider scrubs\n if (Math.abs(Math.abs(delta) - 10) < 2) {\n handleSeekFeedback(delta < 0 ? \"backward\" : \"forward\")\n }\n }\n\n el.addEventListener(\"media-seek-request\", handler)\n return () => el.removeEventListener(\"media-seek-request\", handler)\n }, [isDesktop, handleSeekFeedback])\n\n React.useEffect(() => {\n return () => clearTimeout(feedbackTimeout.current)\n }, [])\n\n return (\n <VideoLabelsContext.Provider value={resolvedLabels}>\n <MediaPlayer\n ref={player}\n src={src}\n autoPlay={autoPlay}\n muted={muted}\n loop={loop}\n playsInline\n crossOrigin=\"\"\n className={cn(\n \"group relative aspect-video w-full overflow-hidden bg-black text-white\",\n isDesktop ? \"rounded-[16px]\" : \"rounded-none\",\n className\n )}\n {...playerEvents}\n >\n <MediaProvider>\n {poster && (\n <Poster\n className={cn(\"absolute inset-0 block h-full w-full object-cover opacity-0 transition-opacity data-[visible]:opacity-100\", isDesktop && \"rounded-[16px]\")}\n src={poster}\n alt={posterAlt}\n />\n )}\n\n {/* ─── Chapters track (VTT) ─── */}\n {chapters && (\n <Track\n src={chapters}\n kind=\"chapters\"\n language=\"en\"\n default\n />\n )}\n\n {/* ─── Caption/subtitle tracks (VTT) ─── */}\n {captions?.map((track) => (\n <Track\n key={track.language}\n src={track.src}\n kind=\"subtitles\"\n language={track.language}\n label={track.label}\n default={track.default}\n />\n ))}\n </MediaProvider>\n\n {/* ─── Accessibility: screen reader announcements ─── */}\n {announcer && <MediaAnnouncer />}\n\n {/* ─── Buffering spinner ─── */}\n {showBuffering && <BufferingIndicator />}\n\n {/* ─── Seek feedback indicators (both mobile & desktop) ─── */}\n <SeekFeedbackOverlay direction=\"backward\" visible={seekFeedback === \"backward\"} seconds={seekAccumulated} />\n <SeekFeedbackOverlay direction=\"forward\" visible={seekFeedback === \"forward\"} seconds={seekAccumulated} />\n\n {/* ─── MOBILE: Vidstack DefaultVideoLayout (touch, gestos, menus nativos) ─── */}\n {!isDesktop && (\n <DefaultVideoLayout\n icons={defaultLayoutIcons}\n thumbnails={thumbnails}\n colorScheme=\"dark\"\n translations={vidstackTranslations}\n />\n )}\n\n {/* ─── DESKTOP: Controles customizados do Cycle Design ─── */}\n {isDesktop && (\n <>\n {/* Captions overlay */}\n <Captions className=\"absolute inset-x-0 bottom-8 z-10 flex flex-col items-center select-none break-words text-center transition-[bottom] duration-200 ease-in-out group-data-[started]:group-hover:bottom-[72px] group-data-[paused]:bottom-[72px] media-preview:opacity-0 [&>[data-part=cue]]:inline [&>[data-part=cue]]:rounded-md [&>[data-part=cue]]:bg-black/95 [&>[data-part=cue]]:px-4 [&>[data-part=cue]]:py-1.5 [&>[data-part=cue]]:text-[15px] [&>[data-part=cue]]:leading-snug [&>[data-part=cue]]:text-white [&>[data-part=cue]]:drop-shadow-[0_1px_3px_rgba(0,0,0,0.8)]\" />\n\n {/* Play overlay (paused state — big play button) */}\n <PlayOverlay />\n\n {/* Gestures: click to pause, double-click fullscreen */}\n <Gesture className=\"absolute inset-0 z-0 block h-full w-full\" event=\"pointerup\" action=\"toggle:paused\" />\n <Gesture className=\"absolute inset-0 z-0 block h-full w-full\" event=\"dblpointerup\" action=\"toggle:fullscreen\" />\n\n {/* Double-tap seek zones on edges */}\n <SeekGestureZone side=\"left\" onSeekFeedback={handleSeekFeedback} />\n <SeekGestureZone side=\"right\" onSeekFeedback={handleSeekFeedback} />\n\n {/* Controls overlay (hover to show) */}\n <Controls.Root className=\"absolute inset-0 z-20 flex h-full w-full flex-col bg-gradient-to-t from-black/60 via-transparent to-transparent opacity-0 transition-opacity duration-200 group-data-[started]:group-hover:opacity-100 group-data-[paused]:opacity-100\">\n <div className=\"flex-1\" />\n\n {/* Seek bar */}\n <Controls.Group className=\"flex w-full items-center px-3\">\n <SeekBar thumbnails={thumbnails} chapters={!!chapters} />\n </Controls.Group>\n\n {/* Bottom bar */}\n <Controls.Group className=\"@container flex w-full items-center gap-1 px-2 pb-2\">\n <PlayControl />\n <SeekBackwardControl />\n <SeekForwardControl />\n <MuteControl />\n <VolumeControl />\n <TimeDisplay />\n <LiveIndicator />\n\n <div className=\"flex-1\" />\n\n <CaptionControl />\n <SpeedControl />\n <QualityControl />\n <PIPControl />\n <FullscreenControl />\n </Controls.Group>\n </Controls.Root>\n </>\n )}\n </MediaPlayer>\n </VideoLabelsContext.Provider>\n )\n }\n)\n"]}