@fluencypassdevs/cycle 0.1.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.
- package/README.md +36 -0
- package/dist/chunk-2MXR6RRJ.js +106 -0
- package/dist/chunk-2MXR6RRJ.js.map +1 -0
- package/dist/chunk-2WPH3IQP.js +48 -0
- package/dist/chunk-2WPH3IQP.js.map +1 -0
- package/dist/chunk-3LXU5C35.js +68 -0
- package/dist/chunk-3LXU5C35.js.map +1 -0
- package/dist/chunk-6LML23MS.js +347 -0
- package/dist/chunk-6LML23MS.js.map +1 -0
- package/dist/chunk-726XFHED.js +22 -0
- package/dist/chunk-726XFHED.js.map +1 -0
- package/dist/chunk-7UMEJDC3.js +62 -0
- package/dist/chunk-7UMEJDC3.js.map +1 -0
- package/dist/chunk-7XT6ISPQ.js +97 -0
- package/dist/chunk-7XT6ISPQ.js.map +1 -0
- package/dist/chunk-AL2ALTBH.js +115 -0
- package/dist/chunk-AL2ALTBH.js.map +1 -0
- package/dist/chunk-CIM6KJH5.js +59 -0
- package/dist/chunk-CIM6KJH5.js.map +1 -0
- package/dist/chunk-CSL4DRPW.js +39 -0
- package/dist/chunk-CSL4DRPW.js.map +1 -0
- package/dist/chunk-HZJRM5EK.js +97 -0
- package/dist/chunk-HZJRM5EK.js.map +1 -0
- package/dist/chunk-IJTNFN6N.js +61 -0
- package/dist/chunk-IJTNFN6N.js.map +1 -0
- package/dist/chunk-K567KZD5.js +63 -0
- package/dist/chunk-K567KZD5.js.map +1 -0
- package/dist/chunk-MSLQRGSP.js +113 -0
- package/dist/chunk-MSLQRGSP.js.map +1 -0
- package/dist/chunk-NGOZFA33.js +60 -0
- package/dist/chunk-NGOZFA33.js.map +1 -0
- package/dist/chunk-NVA4ZJOS.js +66 -0
- package/dist/chunk-NVA4ZJOS.js.map +1 -0
- package/dist/chunk-OT2HCBR2.js +37 -0
- package/dist/chunk-OT2HCBR2.js.map +1 -0
- package/dist/chunk-PM6ZUCMQ.js +73 -0
- package/dist/chunk-PM6ZUCMQ.js.map +1 -0
- package/dist/chunk-PXWCEJ2C.js +223 -0
- package/dist/chunk-PXWCEJ2C.js.map +1 -0
- package/dist/chunk-QTL6W4I2.js +57 -0
- package/dist/chunk-QTL6W4I2.js.map +1 -0
- package/dist/chunk-QZVQPUVT.js +129 -0
- package/dist/chunk-QZVQPUVT.js.map +1 -0
- package/dist/chunk-R4LITCVX.js +111 -0
- package/dist/chunk-R4LITCVX.js.map +1 -0
- package/dist/chunk-TYCPXAXF.js +10 -0
- package/dist/chunk-TYCPXAXF.js.map +1 -0
- package/dist/chunk-UEJLA7Q6.js +70 -0
- package/dist/chunk-UEJLA7Q6.js.map +1 -0
- package/dist/chunk-UVCEQOQR.js +104 -0
- package/dist/chunk-UVCEQOQR.js.map +1 -0
- package/dist/chunk-VECLN5AT.js +202 -0
- package/dist/chunk-VECLN5AT.js.map +1 -0
- package/dist/chunk-XX3I65LQ.js +435 -0
- package/dist/chunk-XX3I65LQ.js.map +1 -0
- package/dist/chunk-YINJ5YZ5.js +35 -0
- package/dist/chunk-YINJ5YZ5.js.map +1 -0
- package/dist/icons/index.d.ts +617 -0
- package/dist/icons/index.js +5 -0
- package/dist/icons/index.js.map +1 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.js +30 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/utils.d.ts +5 -0
- package/dist/lib/utils.js +4 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/styles/tailwind-theme.css +87 -0
- package/dist/styles/tokens.css +496 -0
- package/dist/ui/accordion.d.ts +10 -0
- package/dist/ui/accordion.js +5 -0
- package/dist/ui/accordion.js.map +1 -0
- package/dist/ui/audio-player.d.ts +30 -0
- package/dist/ui/audio-player.js +7 -0
- package/dist/ui/audio-player.js.map +1 -0
- package/dist/ui/avatar.d.ts +16 -0
- package/dist/ui/avatar.js +5 -0
- package/dist/ui/avatar.js.map +1 -0
- package/dist/ui/badge.d.ts +15 -0
- package/dist/ui/badge.js +5 -0
- package/dist/ui/badge.js.map +1 -0
- package/dist/ui/button.d.ts +15 -0
- package/dist/ui/button.js +5 -0
- package/dist/ui/button.js.map +1 -0
- package/dist/ui/chat-bubble.d.ts +21 -0
- package/dist/ui/chat-bubble.js +6 -0
- package/dist/ui/chat-bubble.js.map +1 -0
- package/dist/ui/chat-panel.d.ts +35 -0
- package/dist/ui/chat-panel.js +10 -0
- package/dist/ui/chat-panel.js.map +1 -0
- package/dist/ui/checkbox.d.ts +17 -0
- package/dist/ui/checkbox.js +5 -0
- package/dist/ui/checkbox.js.map +1 -0
- package/dist/ui/file-card.d.ts +27 -0
- package/dist/ui/file-card.js +5 -0
- package/dist/ui/file-card.js.map +1 -0
- package/dist/ui/input.d.ts +11 -0
- package/dist/ui/input.js +5 -0
- package/dist/ui/input.js.map +1 -0
- package/dist/ui/label.d.ts +9 -0
- package/dist/ui/label.js +5 -0
- package/dist/ui/label.js.map +1 -0
- package/dist/ui/like-dislike.d.ts +32 -0
- package/dist/ui/like-dislike.js +9 -0
- package/dist/ui/like-dislike.js.map +1 -0
- package/dist/ui/live-waiting.d.ts +16 -0
- package/dist/ui/live-waiting.js +8 -0
- package/dist/ui/live-waiting.js.map +1 -0
- package/dist/ui/progress-stage.d.ts +19 -0
- package/dist/ui/progress-stage.js +5 -0
- package/dist/ui/progress-stage.js.map +1 -0
- package/dist/ui/progress.d.ts +19 -0
- package/dist/ui/progress.js +5 -0
- package/dist/ui/progress.js.map +1 -0
- package/dist/ui/radio-group.d.ts +19 -0
- package/dist/ui/radio-group.js +5 -0
- package/dist/ui/radio-group.js.map +1 -0
- package/dist/ui/scroll-area.d.ts +8 -0
- package/dist/ui/scroll-area.js +5 -0
- package/dist/ui/scroll-area.js.map +1 -0
- package/dist/ui/sheet.d.ts +17 -0
- package/dist/ui/sheet.js +5 -0
- package/dist/ui/sheet.js.map +1 -0
- package/dist/ui/slider.d.ts +16 -0
- package/dist/ui/slider.js +5 -0
- package/dist/ui/slider.js.map +1 -0
- package/dist/ui/switch.d.ts +16 -0
- package/dist/ui/switch.js +5 -0
- package/dist/ui/switch.js.map +1 -0
- package/dist/ui/tabs.d.ts +15 -0
- package/dist/ui/tabs.js +5 -0
- package/dist/ui/tabs.js.map +1 -0
- package/dist/ui/textarea.d.ts +12 -0
- package/dist/ui/textarea.js +5 -0
- package/dist/ui/textarea.js.map +1 -0
- package/dist/ui/toggle.d.ts +17 -0
- package/dist/ui/toggle.js +5 -0
- package/dist/ui/toggle.js.map +1 -0
- package/dist/ui/video-player.d.ts +28 -0
- package/dist/ui/video-player.js +7 -0
- package/dist/ui/video-player.js.map +1 -0
- package/package.json +90 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/ui/file-card.tsx"],"names":[],"mappings":"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","file":"chunk-R4LITCVX.js","sourcesContent":["import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { FileText } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst fileCardVariants = cva(\n \"inline-flex w-full items-start gap-3 border border-border bg-secondary text-left transition-all select-none focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-1 disabled:opacity-50 disabled:pointer-events-none hover:bg-accent active:scale-[0.98]\",\n {\n variants: {\n size: {\n sm: \"rounded-lg px-3 py-4\",\n md: \"rounded-xl px-4 py-6\",\n lg: \"rounded-2xl px-6 py-8\",\n },\n },\n defaultVariants: {\n size: \"lg\",\n },\n }\n)\n\nconst titleVariants = cva(\"font-medium text-foreground truncate\", {\n variants: {\n size: {\n sm: \"text-xs leading-3\",\n md: \"text-sm leading-3.5\",\n lg: \"text-sm leading-3.5\",\n },\n },\n defaultVariants: {\n size: \"lg\",\n },\n})\n\nconst iconVariants = cva(\"shrink-0 text-muted-foreground\", {\n variants: {\n size: {\n sm: \"size-4\",\n md: \"size-6\",\n lg: \"size-6\",\n },\n },\n defaultVariants: {\n size: \"lg\",\n },\n})\n\nexport interface FileCardProps\n extends Omit<React.ComponentProps<\"button\">, \"children\" | \"size\">,\n VariantProps<typeof fileCardVariants> {\n /** Nome do arquivo exibido como titulo */\n title: string\n /** Tipo do arquivo (ex: \"PDF\", \"DOCX\", \"PNG\") */\n fileType?: string\n /** Tamanho do arquivo (ex: \"180 KB\", \"2.4 MB\") */\n fileSize?: string\n /** URL de download — se fornecido, renderiza como <a> */\n href?: string\n /** Exibir icone de arquivo */\n icon?: boolean\n /** Exibir linha de descricao (tipo + tamanho) */\n showDescription?: boolean\n /** Exibir peso do arquivo na descricao */\n showFileSize?: boolean\n}\n\nfunction FileCard({\n title,\n fileType,\n fileSize,\n href,\n icon = true,\n showDescription = true,\n showFileSize = true,\n size = \"lg\",\n disabled = false,\n className,\n ...props\n}: FileCardProps) {\n const content = (\n <>\n {icon && (\n <FileText className={cn(iconVariants({ size }))} />\n )}\n <div className=\"flex min-w-0 flex-1 flex-col gap-1\">\n <span className={cn(titleVariants({ size }))}>{title}</span>\n {showDescription && fileType && (\n <span className=\"flex items-center gap-2 text-xs text-[#a1a1a1] whitespace-nowrap\">\n <span>{fileType}</span>\n {showFileSize && fileSize && (\n <>\n <span>•</span>\n <span>{fileSize}</span>\n </>\n )}\n </span>\n )}\n </div>\n </>\n )\n\n const classes = cn(fileCardVariants({ size }), className)\n\n if (href && !disabled) {\n return (\n <a\n href={href}\n download\n className={classes}\n aria-label={`Download ${title}`}\n >\n {content}\n </a>\n )\n }\n\n return (\n <button\n data-slot=\"file-card\"\n type=\"button\"\n disabled={disabled}\n className={classes}\n {...props}\n >\n {content}\n </button>\n )\n}\n\nexport { FileCard, fileCardVariants }\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/utils.ts"],"names":[],"mappings":";;;AAGO,SAAS,MAAM,MAAA,EAAsB;AAC1C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC7B","file":"chunk-TYCPXAXF.js","sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n"]}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { cn } from './chunk-TYCPXAXF.js';
|
|
2
|
+
import { __objRest, __spreadValues, __spreadProps } from './chunk-YINJ5YZ5.js';
|
|
3
|
+
import { ChevronDownIcon } from 'lucide-react';
|
|
4
|
+
import { Accordion as Accordion$1 } from 'radix-ui';
|
|
5
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
6
|
+
|
|
7
|
+
function Accordion(_a) {
|
|
8
|
+
var props = __objRest(_a, []);
|
|
9
|
+
return /* @__PURE__ */ jsx(Accordion$1.Root, __spreadValues({ "data-slot": "accordion" }, props));
|
|
10
|
+
}
|
|
11
|
+
function AccordionItem(_a) {
|
|
12
|
+
var _b = _a, {
|
|
13
|
+
className
|
|
14
|
+
} = _b, props = __objRest(_b, [
|
|
15
|
+
"className"
|
|
16
|
+
]);
|
|
17
|
+
return /* @__PURE__ */ jsx(
|
|
18
|
+
Accordion$1.Item,
|
|
19
|
+
__spreadValues({
|
|
20
|
+
"data-slot": "accordion-item",
|
|
21
|
+
className: cn("border-b last:border-b-0", className)
|
|
22
|
+
}, props)
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
function AccordionTrigger(_a) {
|
|
26
|
+
var _b = _a, {
|
|
27
|
+
className,
|
|
28
|
+
children
|
|
29
|
+
} = _b, props = __objRest(_b, [
|
|
30
|
+
"className",
|
|
31
|
+
"children"
|
|
32
|
+
]);
|
|
33
|
+
return /* @__PURE__ */ jsx(Accordion$1.Header, { className: "flex", children: /* @__PURE__ */ jsxs(
|
|
34
|
+
Accordion$1.Trigger,
|
|
35
|
+
__spreadProps(__spreadValues({
|
|
36
|
+
"data-slot": "accordion-trigger",
|
|
37
|
+
className: cn(
|
|
38
|
+
"flex flex-1 items-start justify-between gap-4 rounded-md py-4 text-left text-sm font-medium transition-all outline-none hover:underline focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 [&[data-state=open]>svg]:rotate-180",
|
|
39
|
+
className
|
|
40
|
+
)
|
|
41
|
+
}, props), {
|
|
42
|
+
children: [
|
|
43
|
+
children,
|
|
44
|
+
/* @__PURE__ */ jsx(ChevronDownIcon, { className: "pointer-events-none size-4 shrink-0 translate-y-0.5 text-muted-foreground transition-transform duration-200" })
|
|
45
|
+
]
|
|
46
|
+
})
|
|
47
|
+
) });
|
|
48
|
+
}
|
|
49
|
+
function AccordionContent(_a) {
|
|
50
|
+
var _b = _a, {
|
|
51
|
+
className,
|
|
52
|
+
children
|
|
53
|
+
} = _b, props = __objRest(_b, [
|
|
54
|
+
"className",
|
|
55
|
+
"children"
|
|
56
|
+
]);
|
|
57
|
+
return /* @__PURE__ */ jsx(
|
|
58
|
+
Accordion$1.Content,
|
|
59
|
+
__spreadProps(__spreadValues({
|
|
60
|
+
"data-slot": "accordion-content",
|
|
61
|
+
className: "overflow-hidden text-sm data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down"
|
|
62
|
+
}, props), {
|
|
63
|
+
children: /* @__PURE__ */ jsx("div", { className: cn("pt-0 pb-4", className), children })
|
|
64
|
+
})
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger };
|
|
69
|
+
//# sourceMappingURL=chunk-UEJLA7Q6.js.map
|
|
70
|
+
//# sourceMappingURL=chunk-UEJLA7Q6.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/ui/accordion.tsx"],"names":["AccordionPrimitive"],"mappings":";;;;;;AAQA,SAAS,UAAU,EAAA,EAEsC;AAFtC,EAAA,IACd,kBADc,EAAA,EACd,EAAA,CAAA;AAEH,EAAA,2BAAQA,WAAA,CAAmB,IAAA,EAAnB,cAAA,CAAA,EAAwB,WAAA,EAAU,eAAgB,KAAA,CAAO,CAAA;AACnE;AAEA,SAAS,cAAc,EAAA,EAGkC;AAHlC,EAAA,IAAA,EAAA,GAAA,EAAA,EACrB;AAAA,IAAA;AAAA,GAfF,GAcuB,EAAA,EAElB,KAAA,GAAA,SAAA,CAFkB,EAAA,EAElB;AAAA,IADH;AAAA,GAAA,CAAA;AAGA,EAAA,uBACE,GAAA;AAAA,IAACA,WAAA,CAAmB,IAAA;AAAA,IAAnB,cAAA,CAAA;AAAA,MACC,WAAA,EAAU,gBAAA;AAAA,MACV,SAAA,EAAW,EAAA,CAAG,0BAAA,EAA4B,SAAS;AAAA,KAAA,EAC/C,KAAA;AAAA,GACN;AAEJ;AAEA,SAAS,iBAAiB,EAAA,EAIkC;AAJlC,EAAA,IAAA,EAAA,GAAA,EAAA,EACxB;AAAA,IAAA,SAAA;AAAA,IACA;AAAA,GA7BF,GA2B0B,EAAA,EAGrB,KAAA,GAAA,SAAA,CAHqB,EAAA,EAGrB;AAAA,IAFH,WAAA;AAAA,IACA;AAAA,GAAA,CAAA;AAGA,EAAA,uBACE,GAAA,CAACA,WAAA,CAAmB,MAAA,EAAnB,EAA0B,WAAU,MAAA,EACnC,QAAA,kBAAA,IAAA;AAAA,IAACA,WAAA,CAAmB,OAAA;AAAA,IAAnB,aAAA,CAAA,cAAA,CAAA;AAAA,MACC,WAAA,EAAU,mBAAA;AAAA,MACV,SAAA,EAAW,EAAA;AAAA,QACT,4SAAA;AAAA,QACA;AAAA;AACF,KAAA,EACI,KAAA,CAAA,EANL;AAAA,MAQE,QAAA,EAAA;AAAA,QAAA,QAAA;AAAA,wBACD,GAAA,CAAC,eAAA,EAAA,EAAgB,SAAA,EAAU,6GAAA,EAA8G;AAAA;AAAA,KAAA;AAAA,GAC3I,EACF,CAAA;AAEJ;AAEA,SAAS,iBAAiB,EAAA,EAIkC;AAJlC,EAAA,IAAA,EAAA,GAAA,EAAA,EACxB;AAAA,IAAA,SAAA;AAAA,IACA;AAAA,GAnDF,GAiD0B,EAAA,EAGrB,KAAA,GAAA,SAAA,CAHqB,EAAA,EAGrB;AAAA,IAFH,WAAA;AAAA,IACA;AAAA,GAAA,CAAA;AAGA,EAAA,uBACE,GAAA;AAAA,IAACA,WAAA,CAAmB,OAAA;AAAA,IAAnB,aAAA,CAAA,cAAA,CAAA;AAAA,MACC,WAAA,EAAU,mBAAA;AAAA,MACV,SAAA,EAAU;AAAA,KAAA,EACN,KAAA,CAAA,EAHL;AAAA,MAKC,8BAAC,KAAA,EAAA,EAAI,SAAA,EAAW,GAAG,WAAA,EAAa,SAAS,GAAI,QAAA,EAAS;AAAA,KAAA;AAAA,GACxD;AAEJ","file":"chunk-UEJLA7Q6.js","sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\nimport { ChevronDownIcon } from \"lucide-react\"\nimport { Accordion as AccordionPrimitive } from \"radix-ui\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Accordion({\n ...props\n}: React.ComponentProps<typeof AccordionPrimitive.Root>) {\n return <AccordionPrimitive.Root data-slot=\"accordion\" {...props} />\n}\n\nfunction AccordionItem({\n className,\n ...props\n}: React.ComponentProps<typeof AccordionPrimitive.Item>) {\n return (\n <AccordionPrimitive.Item\n data-slot=\"accordion-item\"\n className={cn(\"border-b last:border-b-0\", className)}\n {...props}\n />\n )\n}\n\nfunction AccordionTrigger({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof AccordionPrimitive.Trigger>) {\n return (\n <AccordionPrimitive.Header className=\"flex\">\n <AccordionPrimitive.Trigger\n data-slot=\"accordion-trigger\"\n className={cn(\n \"flex flex-1 items-start justify-between gap-4 rounded-md py-4 text-left text-sm font-medium transition-all outline-none hover:underline focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 [&[data-state=open]>svg]:rotate-180\",\n className\n )}\n {...props}\n >\n {children}\n <ChevronDownIcon className=\"pointer-events-none size-4 shrink-0 translate-y-0.5 text-muted-foreground transition-transform duration-200\" />\n </AccordionPrimitive.Trigger>\n </AccordionPrimitive.Header>\n )\n}\n\nfunction AccordionContent({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof AccordionPrimitive.Content>) {\n return (\n <AccordionPrimitive.Content\n data-slot=\"accordion-content\"\n className=\"overflow-hidden text-sm data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down\"\n {...props}\n >\n <div className={cn(\"pt-0 pb-4\", className)}>{children}</div>\n </AccordionPrimitive.Content>\n )\n}\n\nexport { Accordion, AccordionItem, AccordionTrigger, AccordionContent }\n"]}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { ChatBubble } from './chunk-HZJRM5EK.js';
|
|
2
|
+
import { CycleIcon } from './chunk-OT2HCBR2.js';
|
|
3
|
+
import { ScrollArea } from './chunk-3LXU5C35.js';
|
|
4
|
+
import { Button } from './chunk-7UMEJDC3.js';
|
|
5
|
+
import { cn } from './chunk-TYCPXAXF.js';
|
|
6
|
+
import { __objRest, __spreadProps, __spreadValues } from './chunk-YINJ5YZ5.js';
|
|
7
|
+
import * as React from 'react';
|
|
8
|
+
import { SendIcon } from 'lucide-react';
|
|
9
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
10
|
+
|
|
11
|
+
function ChatPanel(_a) {
|
|
12
|
+
var _b = _a, {
|
|
13
|
+
messages,
|
|
14
|
+
onSendMessage,
|
|
15
|
+
disabled = false,
|
|
16
|
+
placeholder = "Envie uma mensagem...",
|
|
17
|
+
title = "Chat",
|
|
18
|
+
className
|
|
19
|
+
} = _b, props = __objRest(_b, [
|
|
20
|
+
"messages",
|
|
21
|
+
"onSendMessage",
|
|
22
|
+
"disabled",
|
|
23
|
+
"placeholder",
|
|
24
|
+
"title",
|
|
25
|
+
"className"
|
|
26
|
+
]);
|
|
27
|
+
const [input, setInput] = React.useState("");
|
|
28
|
+
const scrollRef = React.useRef(null);
|
|
29
|
+
React.useEffect(() => {
|
|
30
|
+
const el = scrollRef.current;
|
|
31
|
+
if (el) {
|
|
32
|
+
el.scrollTop = el.scrollHeight;
|
|
33
|
+
}
|
|
34
|
+
}, [messages.length]);
|
|
35
|
+
function handleSubmit(e) {
|
|
36
|
+
e.preventDefault();
|
|
37
|
+
const trimmed = input.trim();
|
|
38
|
+
if (!trimmed || disabled) return;
|
|
39
|
+
onSendMessage == null ? void 0 : onSendMessage(trimmed);
|
|
40
|
+
setInput("");
|
|
41
|
+
}
|
|
42
|
+
return /* @__PURE__ */ jsxs(
|
|
43
|
+
"div",
|
|
44
|
+
__spreadProps(__spreadValues({
|
|
45
|
+
"data-slot": "chat-panel",
|
|
46
|
+
className: cn(
|
|
47
|
+
"flex flex-col bg-background border-l border-border",
|
|
48
|
+
className
|
|
49
|
+
)
|
|
50
|
+
}, props), {
|
|
51
|
+
children: [
|
|
52
|
+
/* @__PURE__ */ jsx("div", { className: "shrink-0 flex items-center h-12 px-4 border-b border-border", children: /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-foreground", children: title }) }),
|
|
53
|
+
/* @__PURE__ */ jsx(ScrollArea, { className: "flex-1 min-h-0", children: /* @__PURE__ */ jsxs("div", { ref: scrollRef, className: "flex flex-col gap-3 p-4", children: [
|
|
54
|
+
messages.length === 0 && /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground text-center py-8", children: "Nenhuma mensagem ainda." }),
|
|
55
|
+
messages.map((msg) => /* @__PURE__ */ jsx(
|
|
56
|
+
ChatBubble,
|
|
57
|
+
{
|
|
58
|
+
author: msg.author,
|
|
59
|
+
avatar: msg.avatar,
|
|
60
|
+
message: msg.message,
|
|
61
|
+
timestamp: msg.timestamp,
|
|
62
|
+
variant: msg.variant
|
|
63
|
+
},
|
|
64
|
+
msg.id
|
|
65
|
+
))
|
|
66
|
+
] }) }),
|
|
67
|
+
onSendMessage && /* @__PURE__ */ jsxs(
|
|
68
|
+
"form",
|
|
69
|
+
{
|
|
70
|
+
onSubmit: handleSubmit,
|
|
71
|
+
className: "shrink-0 flex items-center gap-2 p-3 border-t border-border",
|
|
72
|
+
children: [
|
|
73
|
+
/* @__PURE__ */ jsx(
|
|
74
|
+
"input",
|
|
75
|
+
{
|
|
76
|
+
type: "text",
|
|
77
|
+
value: input,
|
|
78
|
+
onChange: (e) => setInput(e.target.value),
|
|
79
|
+
placeholder,
|
|
80
|
+
disabled,
|
|
81
|
+
className: "flex-1 min-w-0 h-9 rounded-lg border border-input bg-background px-3 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-1 ring-offset-background disabled:opacity-50 disabled:cursor-not-allowed"
|
|
82
|
+
}
|
|
83
|
+
),
|
|
84
|
+
/* @__PURE__ */ jsx(
|
|
85
|
+
Button,
|
|
86
|
+
{
|
|
87
|
+
type: "submit",
|
|
88
|
+
size: "icon-sm",
|
|
89
|
+
disabled: disabled || !input.trim(),
|
|
90
|
+
className: "shrink-0",
|
|
91
|
+
children: /* @__PURE__ */ jsx(CycleIcon, { icon: SendIcon, size: "xs", decorative: true })
|
|
92
|
+
}
|
|
93
|
+
)
|
|
94
|
+
]
|
|
95
|
+
}
|
|
96
|
+
)
|
|
97
|
+
]
|
|
98
|
+
})
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export { ChatPanel };
|
|
103
|
+
//# sourceMappingURL=chunk-UVCEQOQR.js.map
|
|
104
|
+
//# sourceMappingURL=chunk-UVCEQOQR.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/ui/chat-panel.tsx"],"names":[],"mappings":"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","file":"chunk-UVCEQOQR.js","sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\nimport { SendIcon } from \"lucide-react\"\nimport { CycleIcon } from \"@/components/icons/CycleIcon\"\nimport { Button } from \"@/components/ui/button\"\nimport { ScrollArea } from \"@/components/ui/scroll-area\"\nimport { ChatBubble, type ChatBubbleProps } from \"@/components/ui/chat-bubble\"\nimport { cn } from \"@/lib/utils\"\n\n/* ─── Types ─── */\n\nexport interface ChatMessage {\n /** Unique message ID */\n id: string\n /** Author display name */\n author: string\n /** Avatar URL */\n avatar?: string\n /** Message text */\n message: string\n /** Timestamp label (e.g. \"14:32\") */\n timestamp?: string\n /** Message variant */\n variant?: ChatBubbleProps[\"variant\"]\n}\n\nexport interface ChatPanelProps extends React.ComponentProps<\"div\"> {\n /** Chat messages array */\n messages: ChatMessage[]\n /** Callback when the user sends a message */\n onSendMessage?: (message: string) => void\n /** Disable the input (e.g. when chat is read-only or ended) */\n disabled?: boolean\n /** Input placeholder text */\n placeholder?: string\n /** Title shown at the top of the panel */\n title?: string\n}\n\n/* ─── Component ─── */\n\nfunction ChatPanel({\n messages,\n onSendMessage,\n disabled = false,\n placeholder = \"Envie uma mensagem...\",\n title = \"Chat\",\n className,\n ...props\n}: ChatPanelProps) {\n const [input, setInput] = React.useState(\"\")\n const scrollRef = React.useRef<HTMLDivElement>(null)\n\n /* Auto-scroll to bottom on new messages */\n React.useEffect(() => {\n const el = scrollRef.current\n if (el) {\n el.scrollTop = el.scrollHeight\n }\n }, [messages.length])\n\n function handleSubmit(e: React.FormEvent) {\n e.preventDefault()\n const trimmed = input.trim()\n if (!trimmed || disabled) return\n onSendMessage?.(trimmed)\n setInput(\"\")\n }\n\n return (\n <div\n data-slot=\"chat-panel\"\n className={cn(\n \"flex flex-col bg-background border-l border-border\",\n className\n )}\n {...props}\n >\n {/* Header */}\n <div className=\"shrink-0 flex items-center h-12 px-4 border-b border-border\">\n <h3 className=\"text-sm font-semibold text-foreground\">{title}</h3>\n </div>\n\n {/* Messages */}\n <ScrollArea className=\"flex-1 min-h-0\">\n <div ref={scrollRef} className=\"flex flex-col gap-3 p-4\">\n {messages.length === 0 && (\n <p className=\"text-sm text-muted-foreground text-center py-8\">\n Nenhuma mensagem ainda.\n </p>\n )}\n {messages.map((msg) => (\n <ChatBubble\n key={msg.id}\n author={msg.author}\n avatar={msg.avatar}\n message={msg.message}\n timestamp={msg.timestamp}\n variant={msg.variant}\n />\n ))}\n </div>\n </ScrollArea>\n\n {/* Input */}\n {onSendMessage && (\n <form\n onSubmit={handleSubmit}\n className=\"shrink-0 flex items-center gap-2 p-3 border-t border-border\"\n >\n <input\n type=\"text\"\n value={input}\n onChange={(e) => setInput(e.target.value)}\n placeholder={placeholder}\n disabled={disabled}\n className=\"flex-1 min-w-0 h-9 rounded-lg border border-input bg-background px-3 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-1 ring-offset-background disabled:opacity-50 disabled:cursor-not-allowed\"\n />\n <Button\n type=\"submit\"\n size=\"icon-sm\"\n disabled={disabled || !input.trim()}\n className=\"shrink-0\"\n >\n <CycleIcon icon={SendIcon} size=\"xs\" decorative />\n </Button>\n </form>\n )}\n </div>\n )\n}\n\nexport { ChatPanel }\n"]}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { CycleIcon } from './chunk-OT2HCBR2.js';
|
|
2
|
+
import { cn } from './chunk-TYCPXAXF.js';
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { MediaPlayer, MediaProvider, Time, TimeSlider, SeekButton, useMediaState, PlayButton, useMediaRemote, MuteButton, VolumeSlider } from '@vidstack/react';
|
|
5
|
+
import '@vidstack/react/player/styles/base.css';
|
|
6
|
+
import { RotateCcw, Play, Pause, RotateCw, Gauge, Check, VolumeX, Volume1, Volume2 } from 'lucide-react';
|
|
7
|
+
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
8
|
+
|
|
9
|
+
var controlBtnClass = "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";
|
|
10
|
+
var filledIconClass = "fill-current !stroke-transparent text-foreground group-data-[filled]:text-primary-foreground";
|
|
11
|
+
var outlineIconClass = "text-foreground group-data-[filled]:text-primary-foreground";
|
|
12
|
+
function AudioPlayControl() {
|
|
13
|
+
const isPaused = useMediaState("paused");
|
|
14
|
+
return /* @__PURE__ */ jsx(PlayButton, { className: controlBtnClass, children: isPaused ? /* @__PURE__ */ jsx(CycleIcon, { icon: Play, size: "sm", decorative: true, className: filledIconClass }) : /* @__PURE__ */ jsx(CycleIcon, { icon: Pause, size: "sm", decorative: true, className: filledIconClass }) });
|
|
15
|
+
}
|
|
16
|
+
function AudioSeekBackwardControl() {
|
|
17
|
+
return /* @__PURE__ */ jsx(SeekButton, { className: controlBtnClass, seconds: -10, children: /* @__PURE__ */ jsx(CycleIcon, { icon: RotateCcw, size: "sm", decorative: true, className: outlineIconClass }) });
|
|
18
|
+
}
|
|
19
|
+
function AudioSeekForwardControl() {
|
|
20
|
+
return /* @__PURE__ */ jsx(SeekButton, { className: controlBtnClass, seconds: 10, children: /* @__PURE__ */ jsx(CycleIcon, { icon: RotateCw, size: "sm", decorative: true, className: outlineIconClass }) });
|
|
21
|
+
}
|
|
22
|
+
function AudioMuteControl() {
|
|
23
|
+
const volume = useMediaState("volume");
|
|
24
|
+
const isMuted = useMediaState("muted");
|
|
25
|
+
const Icon = isMuted || volume === 0 ? VolumeX : volume < 0.5 ? Volume1 : Volume2;
|
|
26
|
+
return /* @__PURE__ */ jsx(MuteButton, { className: controlBtnClass, children: /* @__PURE__ */ jsx(CycleIcon, { icon: Icon, size: "sm", decorative: true, className: filledIconClass }) });
|
|
27
|
+
}
|
|
28
|
+
function AudioVolumeControl() {
|
|
29
|
+
return /* @__PURE__ */ jsxs(VolumeSlider.Root, { className: "group relative hidden h-9 w-20 cursor-pointer touch-none select-none items-center outline-none sm:inline-flex", children: [
|
|
30
|
+
/* @__PURE__ */ jsx(VolumeSlider.Track, { className: "relative h-[4px] w-full rounded-full bg-accent group-data-[filled]/root:bg-primary-foreground/30", children: /* @__PURE__ */ jsx(VolumeSlider.TrackFill, { className: "absolute h-full w-[var(--slider-fill)] rounded-full bg-primary group-data-[filled]/root:bg-primary-foreground" }) }),
|
|
31
|
+
/* @__PURE__ */ jsx(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" })
|
|
32
|
+
] });
|
|
33
|
+
}
|
|
34
|
+
function AudioSeekBar() {
|
|
35
|
+
return /* @__PURE__ */ jsxs(TimeSlider.Root, { className: "group relative inline-flex h-9 w-full cursor-pointer touch-none select-none items-center outline-none", children: [
|
|
36
|
+
/* @__PURE__ */ jsxs(TimeSlider.Track, { className: "relative h-[4px] w-full rounded-full bg-accent group-data-[filled]/root:bg-primary-foreground/30", children: [
|
|
37
|
+
/* @__PURE__ */ jsx(TimeSlider.Progress, { className: "absolute h-full w-[var(--slider-progress)] rounded-full bg-accent-foreground/20 group-data-[filled]/root:bg-primary-foreground/20" }),
|
|
38
|
+
/* @__PURE__ */ jsx(TimeSlider.TrackFill, { className: "absolute h-full w-[var(--slider-fill)] rounded-full bg-primary group-data-[filled]/root:bg-primary-foreground" })
|
|
39
|
+
] }),
|
|
40
|
+
/* @__PURE__ */ jsx(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" }),
|
|
41
|
+
/* @__PURE__ */ jsx(TimeSlider.Preview, { className: "pointer-events-none flex flex-col items-center opacity-0 transition-opacity duration-200 data-[visible]:opacity-100", children: /* @__PURE__ */ jsx(TimeSlider.Value, { className: "rounded bg-popover px-1.5 py-0.5 text-[11px] font-mono text-popover-foreground border border-border shadow-sm" }) })
|
|
42
|
+
] });
|
|
43
|
+
}
|
|
44
|
+
function AudioTimeDisplay() {
|
|
45
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 text-xs font-mono text-muted-foreground tabular-nums group-data-[filled]:text-primary-foreground/80", children: [
|
|
46
|
+
/* @__PURE__ */ jsx(Time, { type: "current" }),
|
|
47
|
+
/* @__PURE__ */ jsx("span", { children: "/" }),
|
|
48
|
+
/* @__PURE__ */ jsx(Time, { type: "duration" })
|
|
49
|
+
] });
|
|
50
|
+
}
|
|
51
|
+
function AudioSpeedControl() {
|
|
52
|
+
const playbackRate = useMediaState("playbackRate");
|
|
53
|
+
const remote = useMediaRemote();
|
|
54
|
+
const [open, setOpen] = React.useState(false);
|
|
55
|
+
const rates = [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2];
|
|
56
|
+
return /* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
57
|
+
/* @__PURE__ */ jsx(
|
|
58
|
+
"button",
|
|
59
|
+
{
|
|
60
|
+
type: "button",
|
|
61
|
+
onClick: () => setOpen(!open),
|
|
62
|
+
className: controlBtnClass,
|
|
63
|
+
children: playbackRate === 1 ? /* @__PURE__ */ jsx(CycleIcon, { icon: Gauge, size: "sm", decorative: true, className: outlineIconClass }) : /* @__PURE__ */ jsxs("span", { className: "text-xs font-mono font-semibold text-foreground group-data-[filled]:text-primary-foreground", children: [
|
|
64
|
+
playbackRate,
|
|
65
|
+
"x"
|
|
66
|
+
] })
|
|
67
|
+
}
|
|
68
|
+
),
|
|
69
|
+
open && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
70
|
+
/* @__PURE__ */ jsx("div", { className: "fixed inset-0 z-40", onClick: () => setOpen(false) }),
|
|
71
|
+
/* @__PURE__ */ jsx("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", children: rates.map((rate) => /* @__PURE__ */ jsxs(
|
|
72
|
+
"button",
|
|
73
|
+
{
|
|
74
|
+
type: "button",
|
|
75
|
+
onClick: () => {
|
|
76
|
+
remote.changePlaybackRate(rate);
|
|
77
|
+
setOpen(false);
|
|
78
|
+
},
|
|
79
|
+
className: cn(
|
|
80
|
+
"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",
|
|
81
|
+
playbackRate === rate && "text-popover-foreground font-medium"
|
|
82
|
+
),
|
|
83
|
+
children: [
|
|
84
|
+
/* @__PURE__ */ jsx("span", { className: "size-4 flex items-center justify-center", children: playbackRate === rate && /* @__PURE__ */ jsx(CycleIcon, { icon: Check, size: "2xs", decorative: true, className: "text-popover-foreground" }) }),
|
|
85
|
+
/* @__PURE__ */ jsx("span", { className: "font-mono", children: rate === 1 ? "Normal" : `${rate}x` })
|
|
86
|
+
]
|
|
87
|
+
},
|
|
88
|
+
rate
|
|
89
|
+
)) })
|
|
90
|
+
] })
|
|
91
|
+
] });
|
|
92
|
+
}
|
|
93
|
+
function AudioPlayer({
|
|
94
|
+
src,
|
|
95
|
+
title,
|
|
96
|
+
subtitle,
|
|
97
|
+
coverArt,
|
|
98
|
+
coverArtAlt = "",
|
|
99
|
+
variant = "default",
|
|
100
|
+
filled = false,
|
|
101
|
+
autoPlay = false,
|
|
102
|
+
muted = false,
|
|
103
|
+
loop = false,
|
|
104
|
+
showSpeed = true,
|
|
105
|
+
className
|
|
106
|
+
}) {
|
|
107
|
+
const player = React.useRef(null);
|
|
108
|
+
if (variant === "card") {
|
|
109
|
+
return /* @__PURE__ */ jsxs(
|
|
110
|
+
MediaPlayer,
|
|
111
|
+
{
|
|
112
|
+
ref: player,
|
|
113
|
+
src,
|
|
114
|
+
autoPlay,
|
|
115
|
+
muted,
|
|
116
|
+
loop,
|
|
117
|
+
viewType: "audio",
|
|
118
|
+
"data-filled": filled ? "" : void 0,
|
|
119
|
+
style: filled ? { "--primary-foreground": "var(--secondary-foreground)" } : void 0,
|
|
120
|
+
className: cn(
|
|
121
|
+
"group/root group !block w-full rounded-xl border border-border bg-card p-4 shadow-sm md:p-6",
|
|
122
|
+
className
|
|
123
|
+
),
|
|
124
|
+
children: [
|
|
125
|
+
/* @__PURE__ */ jsx(MediaProvider, { className: "!hidden" }),
|
|
126
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-4 mb-4 md:gap-5 md:mb-6", children: [
|
|
127
|
+
coverArt && /* @__PURE__ */ jsx(
|
|
128
|
+
"img",
|
|
129
|
+
{
|
|
130
|
+
src: coverArt,
|
|
131
|
+
alt: coverArtAlt,
|
|
132
|
+
className: "size-16 shrink-0 rounded-lg object-cover bg-muted md:size-24 md:rounded-xl"
|
|
133
|
+
}
|
|
134
|
+
),
|
|
135
|
+
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-col justify-center", children: [
|
|
136
|
+
/* @__PURE__ */ jsx("p", { className: cn(
|
|
137
|
+
"truncate text-sm font-semibold md:text-base",
|
|
138
|
+
filled ? "text-primary-foreground" : "text-card-foreground"
|
|
139
|
+
), children: title }),
|
|
140
|
+
subtitle && /* @__PURE__ */ jsx("p", { className: cn(
|
|
141
|
+
"truncate text-xs md:text-sm md:mt-0.5",
|
|
142
|
+
filled ? "text-primary-foreground/70" : "text-muted-foreground"
|
|
143
|
+
), children: subtitle })
|
|
144
|
+
] })
|
|
145
|
+
] }),
|
|
146
|
+
/* @__PURE__ */ jsx("div", { className: "flex w-full items-center", children: /* @__PURE__ */ jsx(AudioSeekBar, {}) }),
|
|
147
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-0.5 -mt-1 mb-1 md:mb-2", children: [
|
|
148
|
+
/* @__PURE__ */ jsx("div", { className: cn(
|
|
149
|
+
"text-[11px] font-mono tabular-nums md:text-xs",
|
|
150
|
+
filled ? "text-primary-foreground/80" : "text-muted-foreground"
|
|
151
|
+
), children: /* @__PURE__ */ jsx(Time, { type: "current" }) }),
|
|
152
|
+
/* @__PURE__ */ jsx("div", { className: cn(
|
|
153
|
+
"text-[11px] font-mono tabular-nums md:text-xs",
|
|
154
|
+
filled ? "text-primary-foreground/80" : "text-muted-foreground"
|
|
155
|
+
), children: /* @__PURE__ */ jsx(Time, { type: "duration" }) })
|
|
156
|
+
] }),
|
|
157
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 md:gap-2", children: [
|
|
158
|
+
/* @__PURE__ */ jsx(AudioSeekBackwardControl, {}),
|
|
159
|
+
/* @__PURE__ */ jsx(AudioPlayControl, {}),
|
|
160
|
+
/* @__PURE__ */ jsx(AudioSeekForwardControl, {}),
|
|
161
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1" }),
|
|
162
|
+
showSpeed && /* @__PURE__ */ jsx(AudioSpeedControl, {}),
|
|
163
|
+
/* @__PURE__ */ jsx(AudioMuteControl, {}),
|
|
164
|
+
/* @__PURE__ */ jsx(AudioVolumeControl, {})
|
|
165
|
+
] })
|
|
166
|
+
]
|
|
167
|
+
}
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
return /* @__PURE__ */ jsxs(
|
|
171
|
+
MediaPlayer,
|
|
172
|
+
{
|
|
173
|
+
ref: player,
|
|
174
|
+
src,
|
|
175
|
+
autoPlay,
|
|
176
|
+
muted,
|
|
177
|
+
loop,
|
|
178
|
+
viewType: "audio",
|
|
179
|
+
"data-filled": filled ? "" : void 0,
|
|
180
|
+
style: filled ? { "--primary-foreground": "var(--secondary-foreground)" } : void 0,
|
|
181
|
+
className: cn(
|
|
182
|
+
"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",
|
|
183
|
+
className
|
|
184
|
+
),
|
|
185
|
+
children: [
|
|
186
|
+
/* @__PURE__ */ jsx(MediaProvider, { className: "!hidden" }),
|
|
187
|
+
/* @__PURE__ */ jsx(AudioSeekBackwardControl, {}),
|
|
188
|
+
/* @__PURE__ */ jsx(AudioPlayControl, {}),
|
|
189
|
+
/* @__PURE__ */ jsx(AudioSeekForwardControl, {}),
|
|
190
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 px-1", children: /* @__PURE__ */ jsx(AudioSeekBar, {}) }),
|
|
191
|
+
/* @__PURE__ */ jsx(AudioTimeDisplay, {}),
|
|
192
|
+
showSpeed && /* @__PURE__ */ jsx(AudioSpeedControl, {}),
|
|
193
|
+
/* @__PURE__ */ jsx(AudioMuteControl, {}),
|
|
194
|
+
/* @__PURE__ */ jsx(AudioVolumeControl, {})
|
|
195
|
+
]
|
|
196
|
+
}
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
export { AudioPlayer };
|
|
201
|
+
//# sourceMappingURL=chunk-VECLN5AT.js.map
|
|
202
|
+
//# sourceMappingURL=chunk-VECLN5AT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/ui/audio-player.tsx"],"names":[],"mappings":"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","file":"chunk-VECLN5AT.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\"\n\n/* ─── Types ─── */\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 className?: string\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\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 ? \"Normal\" : `${rate}x`}</span>\n </button>\n ))}\n </div>\n </>\n )}\n </div>\n )\n}\n\n/* ─── Main component ─── */\n\nexport function AudioPlayer({\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 className,\n}: AudioPlayerProps) {\n const player = React.useRef<MediaPlayerInstance>(null)\n\n if (variant === \"card\") {\n return (\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 >\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 text-sm font-semibold md:text-base\",\n filled ? \"text-primary-foreground\" : \"text-card-foreground\"\n )}>{title}</p>\n {subtitle && (\n <p className={cn(\n \"truncate text-xs md:text-sm md:mt-0.5\",\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 )\n }\n\n // Default variant (compact bar)\n return (\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 >\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 )\n}\n"]}
|