@twick/studio 0.15.16 → 0.15.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +14 -14
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["../../../node_modules/.pnpm/lucide-react@0.511.0_react@18.3.1/node_modules/lucide-react/dist/esm/shared/src/utils.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@18.3.1/node_modules/lucide-react/dist/esm/defaultAttributes.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@18.3.1/node_modules/lucide-react/dist/esm/Icon.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@18.3.1/node_modules/lucide-react/dist/esm/createLucideIcon.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/align-center.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/align-left.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/align-right.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/bold.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/chevron-down.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/chevron-right.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/circle-check.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/circle-x.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/circle.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/clapperboard.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/download.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/file.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/image.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/italic.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/loader-circle.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/message-square.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/music-2.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/music.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/pause.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/play.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/plus.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/rectangle-horizontal.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/rectangle-vertical.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/ruler.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/save.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/scissors.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/sparkles.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/square.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/trash-2.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/type.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/upload.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/video.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/volume-2.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/volume-x.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@18.3.1/node_modules/lucide-react/dist/esm/icons/wand-sparkles.js","../src/components/toolbar.tsx","../src/components/header.tsx","../src/hooks/use-studio-manager.tsx","../src/components/shared/media-manager.ts","../src/components/shared/url-input.tsx","../src/context/media-context.tsx","../src/hooks/use-media-panel.ts","../src/hooks/use-audio-preview.ts","../src/components/panel/audio-panel.tsx","../src/components/container/audio-panel-container.tsx","../src/components/panel/image-panel.tsx","../src/components/container/image-panel-container.tsx","../src/hooks/use-video-preview.ts","../src/components/panel/video-panel.tsx","../src/components/container/video-panel-container.tsx","../src/components/panel/text-panel.tsx","../src/hooks/use-text-panel.ts","../src/components/container/text-panel-container.tsx","../src/components/panel/rect-panel.tsx","../src/hooks/use-rect-panel.ts","../src/components/container/rect-panel-container.tsx","../src/components/panel/circle-panel.tsx","../src/hooks/use-circle-panel.ts","../src/components/container/circle-panel-container.tsx","../src/components/panel/captions-panel.tsx","../src/helpers/constant.ts","../src/hooks/use-captions-panel.ts","../src/components/container/captions-panel-container.tsx","../src/components/container/element-panel-container.tsx","../src/components/properties/property-row.tsx","../src/components/shared/accordion-item.tsx","../src/components/properties/element-props.tsx","../src/components/properties/text-effects.tsx","../src/components/properties/animation.tsx","../src/helpers/volume-db.ts","../src/components/properties/playback-props.tsx","../../media-utils/dist/index.mjs","../src/components/properties/generate-captions.tsx","../src/components/properties/text-props.tsx","../src/components/container/properties-panel-container.tsx","../src/hooks/use-studio-operation.ts","../src/components/twick-studio.tsx","../src/hooks/use-generate-captions.ts"],"sourcesContent":["/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst toKebabCase = (string) => string.replace(/([a-z0-9])([A-Z])/g, \"$1-$2\").toLowerCase();\nconst toCamelCase = (string) => string.replace(\n /^([A-Z])|[\\s-_]+(\\w)/g,\n (match, p1, p2) => p2 ? p2.toUpperCase() : p1.toLowerCase()\n);\nconst toPascalCase = (string) => {\n const camelCase = toCamelCase(string);\n return camelCase.charAt(0).toUpperCase() + camelCase.slice(1);\n};\nconst mergeClasses = (...classes) => classes.filter((className, index, array) => {\n return Boolean(className) && className.trim() !== \"\" && array.indexOf(className) === index;\n}).join(\" \").trim();\nconst hasA11yProp = (props) => {\n for (const prop in props) {\n if (prop.startsWith(\"aria-\") || prop === \"role\" || prop === \"title\") {\n return true;\n }\n }\n};\n\nexport { hasA11yProp, mergeClasses, toCamelCase, toKebabCase, toPascalCase };\n//# sourceMappingURL=utils.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nvar defaultAttributes = {\n xmlns: \"http://www.w3.org/2000/svg\",\n width: 24,\n height: 24,\n viewBox: \"0 0 24 24\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeWidth: 2,\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\"\n};\n\nexport { defaultAttributes as default };\n//# sourceMappingURL=defaultAttributes.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { forwardRef, createElement } from 'react';\nimport defaultAttributes from './defaultAttributes.js';\nimport { mergeClasses, hasA11yProp } from './shared/src/utils.js';\n\nconst Icon = forwardRef(\n ({\n color = \"currentColor\",\n size = 24,\n strokeWidth = 2,\n absoluteStrokeWidth,\n className = \"\",\n children,\n iconNode,\n ...rest\n }, ref) => createElement(\n \"svg\",\n {\n ref,\n ...defaultAttributes,\n width: size,\n height: size,\n stroke: color,\n strokeWidth: absoluteStrokeWidth ? Number(strokeWidth) * 24 / Number(size) : strokeWidth,\n className: mergeClasses(\"lucide\", className),\n ...!children && !hasA11yProp(rest) && { \"aria-hidden\": \"true\" },\n ...rest\n },\n [\n ...iconNode.map(([tag, attrs]) => createElement(tag, attrs)),\n ...Array.isArray(children) ? children : [children]\n ]\n )\n);\n\nexport { Icon as default };\n//# sourceMappingURL=Icon.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { forwardRef, createElement } from 'react';\nimport { mergeClasses, toKebabCase, toPascalCase } from './shared/src/utils.js';\nimport Icon from './Icon.js';\n\nconst createLucideIcon = (iconName, iconNode) => {\n const Component = forwardRef(\n ({ className, ...props }, ref) => createElement(Icon, {\n ref,\n iconNode,\n className: mergeClasses(\n `lucide-${toKebabCase(toPascalCase(iconName))}`,\n `lucide-${iconName}`,\n className\n ),\n ...props\n })\n );\n Component.displayName = toPascalCase(iconName);\n return Component;\n};\n\nexport { createLucideIcon as default };\n//# sourceMappingURL=createLucideIcon.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M17 12H7\", key: \"16if0g\" }],\n [\"path\", { d: \"M19 18H5\", key: \"18s9l3\" }],\n [\"path\", { d: \"M21 6H3\", key: \"1jwq7v\" }]\n];\nconst AlignCenter = createLucideIcon(\"align-center\", __iconNode);\n\nexport { __iconNode, AlignCenter as default };\n//# sourceMappingURL=align-center.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M15 12H3\", key: \"6jk70r\" }],\n [\"path\", { d: \"M17 18H3\", key: \"1amg6g\" }],\n [\"path\", { d: \"M21 6H3\", key: \"1jwq7v\" }]\n];\nconst AlignLeft = createLucideIcon(\"align-left\", __iconNode);\n\nexport { __iconNode, AlignLeft as default };\n//# sourceMappingURL=align-left.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M21 12H9\", key: \"dn1m92\" }],\n [\"path\", { d: \"M21 18H7\", key: \"1ygte8\" }],\n [\"path\", { d: \"M21 6H3\", key: \"1jwq7v\" }]\n];\nconst AlignRight = createLucideIcon(\"align-right\", __iconNode);\n\nexport { __iconNode, AlignRight as default };\n//# sourceMappingURL=align-right.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n { d: \"M6 12h9a4 4 0 0 1 0 8H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h7a4 4 0 0 1 0 8\", key: \"mg9rjx\" }\n ]\n];\nconst Bold = createLucideIcon(\"bold\", __iconNode);\n\nexport { __iconNode, Bold as default };\n//# sourceMappingURL=bold.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [[\"path\", { d: \"m6 9 6 6 6-6\", key: \"qrunsl\" }]];\nconst ChevronDown = createLucideIcon(\"chevron-down\", __iconNode);\n\nexport { __iconNode, ChevronDown as default };\n//# sourceMappingURL=chevron-down.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [[\"path\", { d: \"m9 18 6-6-6-6\", key: \"mthhwq\" }]];\nconst ChevronRight = createLucideIcon(\"chevron-right\", __iconNode);\n\nexport { __iconNode, ChevronRight as default };\n//# sourceMappingURL=chevron-right.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"path\", { d: \"m9 12 2 2 4-4\", key: \"dzmm74\" }]\n];\nconst CircleCheck = createLucideIcon(\"circle-check\", __iconNode);\n\nexport { __iconNode, CircleCheck as default };\n//# sourceMappingURL=circle-check.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"path\", { d: \"m15 9-6 6\", key: \"1uzhvr\" }],\n [\"path\", { d: \"m9 9 6 6\", key: \"z0biqf\" }]\n];\nconst CircleX = createLucideIcon(\"circle-x\", __iconNode);\n\nexport { __iconNode, CircleX as default };\n//# sourceMappingURL=circle-x.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [[\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }]];\nconst Circle = createLucideIcon(\"circle\", __iconNode);\n\nexport { __iconNode, Circle as default };\n//# sourceMappingURL=circle.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n { d: \"M20.2 6 3 11l-.9-2.4c-.3-1.1.3-2.2 1.3-2.5l13.5-4c1.1-.3 2.2.3 2.5 1.3Z\", key: \"1tn4o7\" }\n ],\n [\"path\", { d: \"m6.2 5.3 3.1 3.9\", key: \"iuk76l\" }],\n [\"path\", { d: \"m12.4 3.4 3.1 4\", key: \"6hsd6n\" }],\n [\"path\", { d: \"M3 11h18v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2Z\", key: \"ltgou9\" }]\n];\nconst Clapperboard = createLucideIcon(\"clapperboard\", __iconNode);\n\nexport { __iconNode, Clapperboard as default };\n//# sourceMappingURL=clapperboard.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M12 15V3\", key: \"m9g1x1\" }],\n [\"path\", { d: \"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\", key: \"ih7n3h\" }],\n [\"path\", { d: \"m7 10 5 5 5-5\", key: \"brsn70\" }]\n];\nconst Download = createLucideIcon(\"download\", __iconNode);\n\nexport { __iconNode, Download as default };\n//# sourceMappingURL=download.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z\", key: \"1rqfz7\" }],\n [\"path\", { d: \"M14 2v4a2 2 0 0 0 2 2h4\", key: \"tnqrlb\" }]\n];\nconst File = createLucideIcon(\"file\", __iconNode);\n\nexport { __iconNode, File as default };\n//# sourceMappingURL=file.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", ry: \"2\", key: \"1m3agn\" }],\n [\"circle\", { cx: \"9\", cy: \"9\", r: \"2\", key: \"af1f0g\" }],\n [\"path\", { d: \"m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21\", key: \"1xmnt7\" }]\n];\nconst Image = createLucideIcon(\"image\", __iconNode);\n\nexport { __iconNode, Image as default };\n//# sourceMappingURL=image.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"line\", { x1: \"19\", x2: \"10\", y1: \"4\", y2: \"4\", key: \"15jd3p\" }],\n [\"line\", { x1: \"14\", x2: \"5\", y1: \"20\", y2: \"20\", key: \"bu0au3\" }],\n [\"line\", { x1: \"15\", x2: \"9\", y1: \"4\", y2: \"20\", key: \"uljnxc\" }]\n];\nconst Italic = createLucideIcon(\"italic\", __iconNode);\n\nexport { __iconNode, Italic as default };\n//# sourceMappingURL=italic.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [[\"path\", { d: \"M21 12a9 9 0 1 1-6.219-8.56\", key: \"13zald\" }]];\nconst LoaderCircle = createLucideIcon(\"loader-circle\", __iconNode);\n\nexport { __iconNode, LoaderCircle as default };\n//# sourceMappingURL=loader-circle.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\", key: \"1lielz\" }]\n];\nconst MessageSquare = createLucideIcon(\"message-square\", __iconNode);\n\nexport { __iconNode, MessageSquare as default };\n//# sourceMappingURL=message-square.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"circle\", { cx: \"8\", cy: \"18\", r: \"4\", key: \"1fc0mg\" }],\n [\"path\", { d: \"M12 18V2l7 4\", key: \"g04rme\" }]\n];\nconst Music2 = createLucideIcon(\"music-2\", __iconNode);\n\nexport { __iconNode, Music2 as default };\n//# sourceMappingURL=music-2.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M9 18V5l12-2v13\", key: \"1jmyc2\" }],\n [\"circle\", { cx: \"6\", cy: \"18\", r: \"3\", key: \"fqmcym\" }],\n [\"circle\", { cx: \"18\", cy: \"16\", r: \"3\", key: \"1hluhg\" }]\n];\nconst Music = createLucideIcon(\"music\", __iconNode);\n\nexport { __iconNode, Music as default };\n//# sourceMappingURL=music.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"rect\", { x: \"14\", y: \"4\", width: \"4\", height: \"16\", rx: \"1\", key: \"zuxfzm\" }],\n [\"rect\", { x: \"6\", y: \"4\", width: \"4\", height: \"16\", rx: \"1\", key: \"1okwgv\" }]\n];\nconst Pause = createLucideIcon(\"pause\", __iconNode);\n\nexport { __iconNode, Pause as default };\n//# sourceMappingURL=pause.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [[\"polygon\", { points: \"6 3 20 12 6 21 6 3\", key: \"1oa8hb\" }]];\nconst Play = createLucideIcon(\"play\", __iconNode);\n\nexport { __iconNode, Play as default };\n//# sourceMappingURL=play.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M5 12h14\", key: \"1ays0h\" }],\n [\"path\", { d: \"M12 5v14\", key: \"s699le\" }]\n];\nconst Plus = createLucideIcon(\"plus\", __iconNode);\n\nexport { __iconNode, Plus as default };\n//# sourceMappingURL=plus.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"rect\", { width: \"20\", height: \"12\", x: \"2\", y: \"6\", rx: \"2\", key: \"9lu3g6\" }]\n];\nconst RectangleHorizontal = createLucideIcon(\"rectangle-horizontal\", __iconNode);\n\nexport { __iconNode, RectangleHorizontal as default };\n//# sourceMappingURL=rectangle-horizontal.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"rect\", { width: \"12\", height: \"20\", x: \"6\", y: \"2\", rx: \"2\", key: \"1oxtiu\" }]\n];\nconst RectangleVertical = createLucideIcon(\"rectangle-vertical\", __iconNode);\n\nexport { __iconNode, RectangleVertical as default };\n//# sourceMappingURL=rectangle-vertical.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M21.3 15.3a2.4 2.4 0 0 1 0 3.4l-2.6 2.6a2.4 2.4 0 0 1-3.4 0L2.7 8.7a2.41 2.41 0 0 1 0-3.4l2.6-2.6a2.41 2.41 0 0 1 3.4 0Z\",\n key: \"icamh8\"\n }\n ],\n [\"path\", { d: \"m14.5 12.5 2-2\", key: \"inckbg\" }],\n [\"path\", { d: \"m11.5 9.5 2-2\", key: \"fmmyf7\" }],\n [\"path\", { d: \"m8.5 6.5 2-2\", key: \"vc6u1g\" }],\n [\"path\", { d: \"m17.5 15.5 2-2\", key: \"wo5hmg\" }]\n];\nconst Ruler = createLucideIcon(\"ruler\", __iconNode);\n\nexport { __iconNode, Ruler as default };\n//# sourceMappingURL=ruler.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z\",\n key: \"1c8476\"\n }\n ],\n [\"path\", { d: \"M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7\", key: \"1ydtos\" }],\n [\"path\", { d: \"M7 3v4a1 1 0 0 0 1 1h7\", key: \"t51u73\" }]\n];\nconst Save = createLucideIcon(\"save\", __iconNode);\n\nexport { __iconNode, Save as default };\n//# sourceMappingURL=save.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"circle\", { cx: \"6\", cy: \"6\", r: \"3\", key: \"1lh9wr\" }],\n [\"path\", { d: \"M8.12 8.12 12 12\", key: \"1alkpv\" }],\n [\"path\", { d: \"M20 4 8.12 15.88\", key: \"xgtan2\" }],\n [\"circle\", { cx: \"6\", cy: \"18\", r: \"3\", key: \"fqmcym\" }],\n [\"path\", { d: \"M14.8 14.8 20 20\", key: \"ptml3r\" }]\n];\nconst Scissors = createLucideIcon(\"scissors\", __iconNode);\n\nexport { __iconNode, Scissors as default };\n//# sourceMappingURL=scissors.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z\",\n key: \"4pj2yx\"\n }\n ],\n [\"path\", { d: \"M20 3v4\", key: \"1olli1\" }],\n [\"path\", { d: \"M22 5h-4\", key: \"1gvqau\" }],\n [\"path\", { d: \"M4 17v2\", key: \"vumght\" }],\n [\"path\", { d: \"M5 18H3\", key: \"zchphs\" }]\n];\nconst Sparkles = createLucideIcon(\"sparkles\", __iconNode);\n\nexport { __iconNode, Sparkles as default };\n//# sourceMappingURL=sparkles.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", key: \"afitv7\" }]\n];\nconst Square = createLucideIcon(\"square\", __iconNode);\n\nexport { __iconNode, Square as default };\n//# sourceMappingURL=square.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M3 6h18\", key: \"d0wm0j\" }],\n [\"path\", { d: \"M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6\", key: \"4alrt4\" }],\n [\"path\", { d: \"M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2\", key: \"v07s0e\" }],\n [\"line\", { x1: \"10\", x2: \"10\", y1: \"11\", y2: \"17\", key: \"1uufr5\" }],\n [\"line\", { x1: \"14\", x2: \"14\", y1: \"11\", y2: \"17\", key: \"xtxkd\" }]\n];\nconst Trash2 = createLucideIcon(\"trash-2\", __iconNode);\n\nexport { __iconNode, Trash2 as default };\n//# sourceMappingURL=trash-2.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M12 4v16\", key: \"1654pz\" }],\n [\"path\", { d: \"M4 7V5a1 1 0 0 1 1-1h14a1 1 0 0 1 1 1v2\", key: \"e0r10z\" }],\n [\"path\", { d: \"M9 20h6\", key: \"s66wpe\" }]\n];\nconst Type = createLucideIcon(\"type\", __iconNode);\n\nexport { __iconNode, Type as default };\n//# sourceMappingURL=type.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M12 3v12\", key: \"1x0j5s\" }],\n [\"path\", { d: \"m17 8-5-5-5 5\", key: \"7q97r8\" }],\n [\"path\", { d: \"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\", key: \"ih7n3h\" }]\n];\nconst Upload = createLucideIcon(\"upload\", __iconNode);\n\nexport { __iconNode, Upload as default };\n//# sourceMappingURL=upload.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"m16 13 5.223 3.482a.5.5 0 0 0 .777-.416V7.87a.5.5 0 0 0-.752-.432L16 10.5\",\n key: \"ftymec\"\n }\n ],\n [\"rect\", { x: \"2\", y: \"6\", width: \"14\", height: \"12\", rx: \"2\", key: \"158x01\" }]\n];\nconst Video = createLucideIcon(\"video\", __iconNode);\n\nexport { __iconNode, Video as default };\n//# sourceMappingURL=video.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M11 4.702a.705.705 0 0 0-1.203-.498L6.413 7.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.705.705 0 0 0 11 19.298z\",\n key: \"uqj9uw\"\n }\n ],\n [\"path\", { d: \"M16 9a5 5 0 0 1 0 6\", key: \"1q6k2b\" }],\n [\"path\", { d: \"M19.364 18.364a9 9 0 0 0 0-12.728\", key: \"ijwkga\" }]\n];\nconst Volume2 = createLucideIcon(\"volume-2\", __iconNode);\n\nexport { __iconNode, Volume2 as default };\n//# sourceMappingURL=volume-2.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M11 4.702a.705.705 0 0 0-1.203-.498L6.413 7.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.705.705 0 0 0 11 19.298z\",\n key: \"uqj9uw\"\n }\n ],\n [\"line\", { x1: \"22\", x2: \"16\", y1: \"9\", y2: \"15\", key: \"1ewh16\" }],\n [\"line\", { x1: \"16\", x2: \"22\", y1: \"9\", y2: \"15\", key: \"5ykzw1\" }]\n];\nconst VolumeX = createLucideIcon(\"volume-x\", __iconNode);\n\nexport { __iconNode, VolumeX as default };\n//# sourceMappingURL=volume-x.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"m21.64 3.64-1.28-1.28a1.21 1.21 0 0 0-1.72 0L2.36 18.64a1.21 1.21 0 0 0 0 1.72l1.28 1.28a1.2 1.2 0 0 0 1.72 0L21.64 5.36a1.2 1.2 0 0 0 0-1.72\",\n key: \"ul74o6\"\n }\n ],\n [\"path\", { d: \"m14 7 3 3\", key: \"1r5n42\" }],\n [\"path\", { d: \"M5 6v4\", key: \"ilb8ba\" }],\n [\"path\", { d: \"M19 14v4\", key: \"blhpug\" }],\n [\"path\", { d: \"M10 2v2\", key: \"7u0qdc\" }],\n [\"path\", { d: \"M7 8H3\", key: \"zfb6yr\" }],\n [\"path\", { d: \"M21 16h-4\", key: \"1cnmox\" }],\n [\"path\", { d: \"M11 3H9\", key: \"1obp7u\" }]\n];\nconst WandSparkles = createLucideIcon(\"wand-sparkles\", __iconNode);\n\nexport { __iconNode, WandSparkles as default };\n//# sourceMappingURL=wand-sparkles.js.map\n","/**\n * Toolbar Component\n * \n * A vertical toolbar that provides quick access to different editing tools\n * and media types. Displays icons with labels and optional keyboard shortcuts.\n * \n * @component\n * @param {Object} props\n * @param {string} props.selectedTool - Currently selected tool ID\n * @param {(tool: string) => void} props.setSelectedTool - Callback to update selected tool\n * \n * @example\n * ```tsx\n * <Toolbar\n * selectedTool=\"text\"\n * setSelectedTool={(tool) => console.log(`Selected ${tool}`)}\n * />\n * ```\n */\n\nimport { \n Type, \n Upload, \n Video,\n Image, \n Music,\n Circle,\n MessageSquare,\n Plus,\n Square,\n} from 'lucide-react'\nimport type { ToolCategory } from '../types'\n\nconst toolCategories: ToolCategory[] = [\n { id: 'video', name: 'Video', icon: 'Video', description: 'Add a video element' },\n { id: 'image', name: 'Image', icon: 'Image', description: 'Add an image element' },\n { id: 'audio', name: 'Audio', icon: 'Audio', description: 'Add an audio element' },\n { id: 'text', name: 'Text', icon: 'Type', description: 'Add text elements' },\n { id: 'circle', name: 'Circle', icon: 'Circle', description: 'Add a circle element'},\n { id: 'rect', name: 'Rect', icon: 'Rect', description: 'Add a rectangle element' },\n { id: 'caption', name: 'Caption', icon: 'MessageSquare', description: 'Manage captions'},\n]\n\nconst getIcon = (iconName: string) => {\n switch (iconName) {\n case 'Plus': return Plus\n case 'Type': return Type\n case 'Upload': return Upload\n case 'Square': return Square\n case 'Image': return Image\n case 'Video': return Video\n case 'Audio': return Music\n case 'Circle': return Circle\n case 'Rect': return Square\n case 'MessageSquare': return MessageSquare\n default: return Plus\n }\n}\n\nexport function Toolbar({ selectedTool, setSelectedTool }: { selectedTool: string, setSelectedTool: (tool: string) => void }) {\n\n const handleToolSelect = (toolId: string) => {\n setSelectedTool(toolId)\n }\n\n return (\n <div className=\"sidebar\">\n {/* Main Tools */}\n {toolCategories.map((tool) => {\n const Icon = getIcon(tool.icon)\n const isSelected = selectedTool === tool.id\n \n const tooltipText = `${tool.name}${tool.shortcut ? ` (${tool.shortcut})` : ''}`;\n return (\n <div\n key={tool.id}\n onClick={() => handleToolSelect(tool.id)}\n className={`toolbar-btn ${isSelected ? 'active' : ''}`}\n title={tooltipText}\n data-tooltip={tooltipText}\n >\n <Icon className=\"icon-sm\" />\n <span className=\"toolbar-label\">\n {tool.name}\n </span>\n </div>\n )\n })}\n </div>\n )\n}\n","/**\n * StudioHeader Component\n *\n * The top header bar of the studio interface. Contains the studio logo,\n * orientation controls, and action divs for saving and exporting.\n *\n * @component\n * @param {Object} props\n * @param {(resolution: Size) => void} props.setVideoResolution - Callback to update canvas resolution\n *\n * @example\n * ```tsx\n * <StudioHeader\n * setVideoResolution={(size) => console.log(`New size: ${size.width}x${size.height}`)}\n * />\n * ```\n */\n\nimport type { Size } from \"@twick/timeline\";\nimport { Save, Download, Clapperboard, File, Plus, RectangleVertical, RectangleHorizontal } from \"lucide-react\";\nimport { useEffect, useState } from \"react\";\n\ninterface StudioHeaderProps {\n setVideoResolution: (resolution: Size) => void;\n onNewProject: () => void;\n onLoadProject: () => void;\n onSaveProject: () => void;\n onExportVideo: () => void;\n}\nexport const StudioHeader = ({\n setVideoResolution,\n onNewProject,\n onLoadProject,\n onSaveProject,\n onExportVideo,\n}: StudioHeaderProps) => {\n const [orientation, setOrientation] = useState<\"horizontal\" | \"vertical\">(\n \"vertical\"\n );\n\n useEffect(() => {\n const orientation = localStorage.getItem(\"orientation\");\n if (orientation) {\n setOrientation(orientation as \"horizontal\" | \"vertical\");\n }\n }, []);\n\n const handleOrientationChange = (nextOrientation: \"horizontal\" | \"vertical\") => {\n if (nextOrientation === orientation) return;\n\n const confirmMessage =\n \"Changing orientation will create a new project with the new resolution. Do you want to continue?\";\n\n if (!window.confirm(confirmMessage)) {\n return;\n }\n\n // Create a fresh project for the new resolution\n onNewProject();\n setOrientation(nextOrientation);\n };\n\n useEffect(() => {\n if (orientation === \"horizontal\") {\n localStorage.setItem(\"orientation\", \"horizontal\");\n setVideoResolution({ width: 1280, height: 720 });\n } else {\n localStorage.setItem(\"orientation\", \"vertical\");\n setVideoResolution({ width: 720, height: 1280 });\n }\n }, [orientation]);\n\n return (\n <header className=\"header\">\n <div className=\"flex-container\">\n <Clapperboard className=\"icon-lg accent-purple\" />\n <h1 className=\"text-gradient\">\n Twick Studio\n </h1>\n <div className=\"header-separator\"></div>\n <div className=\"flex-container\" style={{ gap: \"0.5rem\" }}>\n <span className=\"text-sm opacity-80\">Orientation</span>\n <button\n className={`btn-ghost ${orientation === \"vertical\" ? \"btn-primary\" : \"\"}`}\n title=\"Portrait (720×1280)\"\n onClick={() => handleOrientationChange(\"vertical\")}\n >\n <RectangleVertical className=\"icon-sm\" />\n\n </button>\n <button\n className={`btn-ghost ${orientation === \"horizontal\" ? \"btn-primary\" : \"\"}`}\n title=\"Landscape (1280×720)\"\n onClick={() => handleOrientationChange(\"horizontal\")}\n >\n <RectangleHorizontal className=\"icon-sm\" />\n\n </button>\n </div>\n </div>\n <div className=\"flex-container\">\n <button\n className=\"btn-ghost\"\n title=\"New Project\"\n onClick={onNewProject}\n >\n <Plus className=\"icon-sm\" />\n New Project\n </button>\n <button\n className=\"btn-ghost\"\n title=\"Load Project\"\n onClick={onLoadProject}\n >\n <File className=\"icon-sm\" />\n Load Project\n </button>\n <button\n className=\"btn-ghost\"\n title=\"Save Draft\"\n onClick={onSaveProject}\n >\n <Save className=\"icon-sm\" />\n Save Draft\n </button>\n <button\n className=\"btn-primary\"\n title=\"Export\"\n onClick={onExportVideo}\n >\n <Download className=\"icon-sm\" />\n Export\n </button>\n </div>\n </header>\n );\n};\n\nexport default StudioHeader;\n","/**\n * useStudioManager Hook\n *\n * A custom hook that manages the studio's state and operations.\n * Handles tool selection, element management, and timeline interactions.\n *\n * @returns {Object} Studio manager methods and state\n * @property {string} selectedTool - Currently selected tool ID\n * @property {(tool: string) => void} setSelectedTool - Update selected tool\n * @property {TrackElement | null} selectedElement - Currently selected timeline element\n * @property {(element: TrackElement) => void} addElement - Add element to timeline\n * @property {(element: TrackElement) => void} updateElement - Update existing element\n *\n * @example\n * ```tsx\n * const {\n * selectedTool,\n * setSelectedTool,\n * selectedElement,\n * addElement,\n * updateElement\n * } = useStudioManager();\n * ```\n */\n\nimport { Track, TrackElement, useTimelineContext } from \"@twick/timeline\";\nimport { useEditorManager } from \"@twick/video-editor\";\nimport { useEffect, useRef, useState } from \"react\";\n\nexport const useStudioManager = () => {\n const [selectedProp, setSelectedProp] = useState(\"element-props\");\n\n const { selectedItem } = useTimelineContext();\n\n const { addElement, updateElement } = useEditorManager();\n\n const selectedElement =\n selectedItem instanceof TrackElement ? selectedItem : null;\n\n const [selectedTool, setSelectedTool] = useState<string>(\"none\");\n\n const isToolChanged = useRef(false);\n\n useEffect(() => {\n if (selectedItem instanceof TrackElement) {\n setSelectedTool(selectedItem.getType());\n isToolChanged.current = true;\n } else if (selectedItem instanceof Track) {\n // do-nothing\n } else {\n setSelectedTool(\"video\");\n }\n }, [selectedItem]);\n\n return {\n selectedProp,\n setSelectedProp,\n selectedTool,\n setSelectedTool,\n selectedElement,\n addElement,\n updateElement,\n };\n};\n","import { BrowserMediaManager } from \"@twick/video-editor\";\nimport type { MediaItem } from \"@twick/video-editor\";\n\nclass MediaManagerSingleton {\n private static instance: BrowserMediaManager | null = null;\n private static initializationPromise: Promise<void> | null = null;\n private static isInitialized = false;\n\n private constructor() {}\n\n public static getInstance(): BrowserMediaManager {\n if (!MediaManagerSingleton.instance) {\n MediaManagerSingleton.instance = new BrowserMediaManager();\n }\n return MediaManagerSingleton.instance;\n }\n\n public static async initializeDefaults(): Promise<void> {\n // If already initialized, return immediately\n if (MediaManagerSingleton.isInitialized) {\n return;\n }\n\n // If initialization is in progress, wait for it to complete\n if (MediaManagerSingleton.initializationPromise) {\n await MediaManagerSingleton.initializationPromise;\n return;\n }\n\n // Create and store the promise immediately to prevent concurrent initialization\n // This must be synchronous to prevent race conditions\n let resolvePromise: () => void;\n let rejectPromise: (error: any) => void;\n \n MediaManagerSingleton.initializationPromise = new Promise<void>((resolve, reject) => {\n resolvePromise = resolve;\n rejectPromise = reject;\n });\n\n // Start initialization asynchronously\n (async () => {\n try {\n await MediaManagerSingleton.doInitializeDefaults();\n MediaManagerSingleton.isInitialized = true;\n resolvePromise!();\n } catch (error) {\n MediaManagerSingleton.initializationPromise = null;\n rejectPromise!(error);\n }\n })();\n \n return MediaManagerSingleton.initializationPromise;\n }\n\n private static async doInitializeDefaults(): Promise<void> {\n const manager = MediaManagerSingleton.getInstance();\n \n // Default video URLs\n const defaultVideos = [\n {\n name: \"Mountain Road\",\n url: \"https://videos.pexels.com/video-files/31708803/13510402_1080_1920_30fps.mp4\",\n type: \"video\",\n metadata: {\n name: \"Mountain Road\",\n source: \"pexels\",\n },\n },\n {\n name: \"Vase\",\n url: \"https://videos.pexels.com/video-files/4622990/4622990-uhd_1440_2560_30fps.mp4\",\n type: \"video\",\n metadata: {\n name: \"Vase\",\n source: \"pexels\",\n },\n },\n ] as Omit<MediaItem, \"id\">[];\n\n // Default image URLs\n const defaultImages = [\n {\n name: \"Mountain Road\",\n url: \"https://images.pexels.com/photos/1955134/pexels-photo-1955134.jpeg\",\n type: \"image\",\n metadata: {\n name: \"Mountain Road\",\n source: \"pexels\",\n },\n },\n {\n name: \"Waterfall\",\n url: \"https://images.pexels.com/photos/358457/pexels-photo-358457.jpeg\",\n type: \"image\",\n metadata: {\n name: \"Waterfall\",\n source: \"pexels\",\n },\n },\n ] as Omit<MediaItem, \"id\">[];\n\n // Default audio URLs\n const defaultAudios = [\n {\n name: \"Audio 1\",\n url: \"https://cdn.pixabay.com/audio/2022/03/14/audio_782eeb590e.mp3\",\n type: \"audio\",\n metadata: {\n name: \"Audio 1\",\n source: \"pixabay\",\n },\n },\n {\n name: \"Audio 2\",\n url: \"https://cdn.pixabay.com/audio/2025/01/24/audio_24048c78b6.mp3\",\n type: \"audio\",\n metadata: {\n name: \"Audio 2\",\n source: \"pixabay\",\n },\n },\n ] as Omit<MediaItem, \"id\">[];\n\n try {\n // Check if default videos already exist in the database\n const existingVideos = await manager.search({\n type: \"video\",\n query: \"\",\n });\n\n // Check if we already have the default videos by URL\n const existingVideoUrls = new Set(existingVideos.map((v) => v.url));\n const videosToAdd = defaultVideos.filter(\n (video) => !existingVideoUrls.has(video.url)\n );\n\n // Add default videos if they don't exist (check again right before adding to prevent race conditions)\n if (videosToAdd.length > 0) {\n // Double-check to prevent duplicates in case of race conditions\n const finalCheck = await manager.search({\n type: \"video\",\n query: \"\",\n });\n const finalVideoUrls = new Set(finalCheck.map((v) => v.url));\n const finalVideosToAdd = videosToAdd.filter(\n (video) => !finalVideoUrls.has(video.url)\n );\n \n if (finalVideosToAdd.length > 0) {\n await manager.addItems(finalVideosToAdd);\n }\n }\n\n // Check if default images already exist in the database\n const existingImages = await manager.search({\n type: \"image\",\n query: \"\",\n });\n\n // Check if we already have the default images by URL\n const existingImageUrls = new Set(existingImages.map((img) => img.url));\n const imagesToAdd = defaultImages.filter(\n (image) => !existingImageUrls.has(image.url)\n );\n\n // Add default images if they don't exist (check again right before adding)\n if (imagesToAdd.length > 0) {\n // Double-check to prevent duplicates in case of race conditions\n const finalCheck = await manager.search({\n type: \"image\",\n query: \"\",\n });\n const finalImageUrls = new Set(finalCheck.map((img) => img.url));\n const finalImagesToAdd = imagesToAdd.filter(\n (image) => !finalImageUrls.has(image.url)\n );\n \n if (finalImagesToAdd.length > 0) {\n await manager.addItems(finalImagesToAdd);\n }\n }\n\n // Check if default audio files already exist in the database\n const existingAudios = await manager.search({\n type: \"audio\",\n query: \"\",\n });\n\n // Check if we already have the default audio files by URL\n const existingAudioUrls = new Set(existingAudios.map((a) => a.url));\n const audiosToAdd = defaultAudios.filter(\n (audio) => !existingAudioUrls.has(audio.url)\n );\n\n // Add default audio files if they don't exist (check again right before adding)\n if (audiosToAdd.length > 0) {\n // Double-check to prevent duplicates in case of race conditions\n const finalCheck = await manager.search({\n type: \"audio\",\n query: \"\",\n });\n const finalAudioUrls = new Set(finalCheck.map((a) => a.url));\n const finalAudiosToAdd = audiosToAdd.filter(\n (audio) => !finalAudioUrls.has(audio.url)\n );\n \n if (finalAudiosToAdd.length > 0) {\n await manager.addItems(finalAudiosToAdd);\n }\n }\n } catch (error) {\n // Error is handled in initializeDefaults, just re-throw it\n throw error;\n }\n }\n}\n\n// Export a function to get the singleton instance\nexport const getMediaManager = () => MediaManagerSingleton.getInstance();\n\n// Export a function to initialize default videos\nexport const initializeDefaultVideos = () => MediaManagerSingleton.initializeDefaults(); ","import { useState } from \"react\";\nimport { Plus } from \"lucide-react\";\n\ntype MediaType = \"video\" | \"audio\" | \"image\";\n\nconst EXTENSIONS: Record<MediaType, string[]> = {\n video: [\"mp4\", \"webm\", \"ogg\", \"mov\", \"mkv\", \"m3u8\"],\n audio: [\"mp3\", \"wav\", \"ogg\", \"m4a\", \"aac\", \"flac\"],\n image: [\"jpg\", \"jpeg\", \"png\", \"gif\", \"webp\", \"svg\"],\n};\n\nfunction isValidUrl(url: string) {\n try {\n // eslint-disable-next-line no-new\n new URL(url);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction matchesType(url: string, type: MediaType) {\n const pathname = (() => {\n try {\n return new URL(url).pathname.toLowerCase();\n } catch {\n return url.toLowerCase();\n }\n })();\n const ext = pathname.split(\".\").pop() || \"\";\n return EXTENSIONS[type].includes(ext);\n}\n\n// (name extraction removed; naming handled by caller if needed)\n\nexport default function UrlInput({\n type,\n onSubmit,\n}: {\n type: MediaType;\n onSubmit: (url: string) => void;\n}) {\n const [url, setUrl] = useState(\"\");\n const [error, setError] = useState<string>(\"\");\n\n const tryAdd = async () => {\n const trimmed = url.trim();\n if (!trimmed) return;\n\n if (!isValidUrl(trimmed)) {\n setError(\"Enter a valid URL\");\n return;\n }\n\n if (!matchesType(trimmed, type)) {\n setError(`URL must be a ${type} (${EXTENSIONS[type].join(\", \")})`);\n return;\n }\n\n setError(\"\");\n\n onSubmit(trimmed);\n setUrl(\"\");\n };\n\n const onKeyDown: React.KeyboardEventHandler<HTMLInputElement> = (e) => {\n if (e.key === \"Enter\") {\n e.preventDefault();\n void tryAdd();\n }\n };\n\n return (\n <div>\n <div className=\"flex-container\">\n <input\n type=\"url\"\n placeholder={`Paste ${type} URL...`}\n value={url}\n onChange={(e) => setUrl(e.target.value)}\n onKeyDown={onKeyDown}\n className=\"input w-full\"\n />\n <button\n className=\"btn-ghost\"\n onClick={() => void tryAdd()}\n aria-label={`Add ${type} by URL`}\n >\n <Plus size={16} />\n </button>\n </div>\n {error ? <span className=\"text-error\">{error}</span> : null}\n </div>\n );\n}\n","import { createContext, useContext, useEffect, useState, ReactNode } from \"react\";\nimport type { MediaItem } from \"@twick/video-editor\";\nimport { getMediaManager, initializeDefaultVideos } from \"../components/shared\";\n\ntype MediaType = \"video\" | \"audio\" | \"image\";\n\ninterface MediaState {\n items: MediaItem[];\n searchQuery: string;\n isLoading: boolean;\n}\n\ninterface MediaContextType {\n videoState: MediaState;\n audioState: MediaState;\n imageState: MediaState;\n setSearchQuery: (type: MediaType, query: string) => void;\n addItem: (type: MediaType, item: MediaItem) => void;\n}\n\nconst initialMediaState: MediaState = {\n items: [],\n searchQuery: \"\",\n isLoading: false,\n};\n\nconst MediaContext = createContext<MediaContextType | null>(null);\n\nexport function MediaProvider({ children }: { children: ReactNode }) {\n const [videoState, setVideoState] = useState<MediaState>(initialMediaState);\n const [audioState, setAudioState] = useState<MediaState>(initialMediaState);\n const [imageState, setImageState] = useState<MediaState>(initialMediaState);\n const mediaManager = getMediaManager();\n\n const getStateAndSetter = (type: MediaType): [MediaState, (state: MediaState) => void] => {\n switch (type) {\n case \"video\":\n return [videoState, setVideoState];\n case \"audio\":\n return [audioState, setAudioState];\n case \"image\":\n return [imageState, setImageState];\n }\n };\n\n const loadItems = async (type: MediaType, query: string) => {\n const [state, setState] = getStateAndSetter(type);\n \n setState({ ...state, isLoading: true });\n try {\n const results = await mediaManager.search({\n query,\n type,\n });\n setState({\n items: results,\n searchQuery: query,\n isLoading: false,\n });\n } catch (error) {\n console.error(`Error loading ${type} items:`, error);\n setState({\n ...state,\n isLoading: false,\n });\n }\n };\n\n // Initialize default videos and load initial data for each type\n useEffect(() => {\n const initialize = async () => {\n // Initialize default videos first\n await initializeDefaultVideos();\n // Then load all media items\n loadItems(\"video\", \"\");\n loadItems(\"audio\", \"\");\n loadItems(\"image\", \"\");\n };\n initialize();\n }, []);\n\n const setSearchQuery = (type: MediaType, query: string) => {\n const [state, setState] = getStateAndSetter(type);\n setState({ ...state, searchQuery: query });\n loadItems(type, query);\n };\n\n const addItem = (type: MediaType, newItem: MediaItem) => {\n const [state, setState] = getStateAndSetter(type);\n setState({\n ...state,\n items: [...state.items, newItem],\n });\n };\n\n return (\n <MediaContext.Provider\n value={{\n videoState,\n audioState,\n imageState,\n setSearchQuery,\n addItem,\n }}\n >\n {children}\n </MediaContext.Provider>\n );\n}\n\nexport function useMedia(type: MediaType) {\n const context = useContext(MediaContext);\n if (!context) {\n throw new Error(\"useMedia must be used within a MediaProvider\");\n }\n\n const state = context[`${type}State`];\n return {\n items: state.items,\n searchQuery: state.searchQuery,\n isLoading: state.isLoading,\n setSearchQuery: (query: string) => context.setSearchQuery(type, query),\n addItem: (item: MediaItem) => context.addItem(type, item),\n };\n}\n","import {\n TrackElement,\n VideoElement,\n AudioElement,\n ImageElement,\n Size,\n} from \"@twick/timeline\";\nimport type { MediaItem } from \"@twick/video-editor\";\nimport { getMediaManager } from \"../components/shared\";\nimport { useMedia } from \"../context/media-context\";\n\nexport interface MediaPanelState {\n items: MediaItem[];\n searchQuery: string;\n isLoading: boolean;\n acceptFileTypes: string[];\n}\n\nexport interface MediaPanelActions {\n setSearchQuery: (query: string) => void;\n handleSelection: (item: MediaItem, forceAdd?: boolean) => void;\n handleFileUpload: (fileData: { file: File; blobUrl: string }) => void;\n}\n\nexport type MediaType = \"video\" | \"audio\" | \"image\";\n\nconst mediaConfigs = {\n video: {\n acceptFileTypes: [\"video/*\"] as string[],\n createElement: (url: string, parentSize: Size) =>\n new VideoElement(url, parentSize),\n updateElement: async (element: TrackElement, url: string) => {\n if (element instanceof VideoElement) {\n element.setSrc(url);\n await element.updateVideoMeta();\n }\n },\n },\n audio: {\n acceptFileTypes: [\"audio/*\"] as string[],\n createElement: (url: string, _parentSize: Size) => new AudioElement(url),\n updateElement: async (element: TrackElement, url: string) => {\n if (element instanceof AudioElement) {\n element.setSrc(url);\n await element.updateAudioMeta();\n }\n },\n },\n image: {\n acceptFileTypes: [\"image/*\"] as string[],\n createElement: (url: string, parentSize: Size) =>\n new ImageElement(url, parentSize),\n updateElement: async (element: TrackElement, url: string) => {\n if (element instanceof ImageElement) {\n element.setSrc(url);\n await element.updateImageMeta();\n }\n },\n },\n};\n\nexport const useMediaPanel = (\n type: MediaType,\n {\n selectedElement,\n addElement,\n updateElement,\n }: {\n selectedElement: TrackElement | null;\n addElement: (element: TrackElement) => void;\n updateElement: (element: TrackElement) => void;\n },\n videoResolution: Size\n): MediaPanelState & MediaPanelActions => {\n const { items, searchQuery, setSearchQuery, addItem, isLoading } =\n useMedia(type);\n const mediaManager = getMediaManager();\n\n const handleSelection = async (item: MediaItem, forceAdd?: boolean) => {\n const config = mediaConfigs[type];\n if (forceAdd) {\n const element = config.createElement(item.url, videoResolution);\n addElement(element);\n } else {\n if (selectedElement) {\n await config.updateElement(selectedElement, item.url);\n updateElement(selectedElement);\n } else {\n const element = config.createElement(item.url, videoResolution);\n addElement(element);\n }\n }\n };\n\n const handleFileUpload = async (fileData: {\n file: File;\n blobUrl: string;\n }) => {\n const arrayBuffer = await fileData.file.arrayBuffer();\n const newItem = await mediaManager.addItem({\n name: fileData.file.name,\n url: fileData.blobUrl,\n type,\n arrayBuffer,\n metadata: {\n name: fileData.file.name,\n size: fileData.file.size,\n type: fileData.file.type,\n },\n });\n addItem(newItem);\n };\n\n const config = mediaConfigs[type];\n return {\n items,\n searchQuery,\n setSearchQuery,\n handleSelection,\n handleFileUpload,\n isLoading,\n acceptFileTypes: config.acceptFileTypes,\n };\n};\n","import { useState, useCallback, useRef, useEffect } from 'react';\nimport type { MediaItem } from '@twick/video-editor';\n\nexport interface AudioPreviewState {\n playingAudio: string | null; // ID of currently playing audio\n audioElement: HTMLAudioElement | null;\n}\n\nexport interface AudioPreviewActions {\n togglePlayPause: (item: MediaItem) => void;\n stopPlayback: () => void;\n}\n\nexport const useAudioPreview = (): AudioPreviewState & AudioPreviewActions => {\n const [playingAudio, setPlayingAudio] = useState<string | null>(null);\n const audioRef = useRef<HTMLAudioElement | null>(null);\n\n // Cleanup audio element on unmount\n useEffect(() => {\n return () => {\n if (audioRef.current) {\n audioRef.current.pause();\n audioRef.current = null;\n }\n };\n }, []);\n\n const stopPlayback = useCallback(() => {\n if (audioRef.current) {\n audioRef.current.pause();\n audioRef.current = null;\n }\n setPlayingAudio(null);\n }, []);\n\n const togglePlayPause = useCallback((item: MediaItem) => {\n // If we're already playing this audio, stop it\n if (playingAudio === item.id) {\n stopPlayback();\n return;\n }\n\n // Stop any currently playing audio\n stopPlayback();\n\n // Start playing the new audio\n const audio = new Audio(item.url);\n audio.addEventListener('ended', stopPlayback);\n audio.play();\n audioRef.current = audio;\n setPlayingAudio(item.id);\n }, [playingAudio, stopPlayback]);\n\n return {\n playingAudio,\n audioElement: audioRef.current,\n togglePlayPause,\n stopPlayback,\n };\n};\n","/**\n * AudioPanel Component\n * \n * A panel for managing audio elements in the studio. Provides functionality\n * for searching, uploading, previewing, and adding audio files to the timeline.\n * \n * @component\n * @param {Object} props\n * @param {MediaItem[]} props.items - List of audio items to display\n * @param {string} props.searchQuery - Current search query\n * @param {string | null} props.playingAudio - ID of currently playing audio, if any\n * @param {(query: string) => void} props.onSearchChange - Handle search query changes\n * @param {(item: MediaItem) => void} props.onItemSelect - Handle audio item selection\n * @param {(item: MediaItem) => void} props.onPlayPause - Toggle audio preview playback\n * @param {(data: { file: File; blobUrl: string }) => void} props.onFileUpload - Handle file uploads\n * \n * @example\n * ```tsx\n * <AudioPanel\n * items={audioItems}\n * searchQuery=\"\"\n * playingAudio={null}\n * onSearchChange={setSearchQuery}\n * onItemSelect={handleSelect}\n * onPlayPause={togglePlayback}\n * onFileUpload={handleUpload}\n * />\n * ```\n */\n\nimport { Wand2, Plus, Volume2, Play, Pause } from \"lucide-react\";\nimport { TIMELINE_DROP_MEDIA_TYPE } from \"@twick/video-editor\";\nimport UrlInput from \"../shared/url-input\";\nimport type { AudioPanelProps } from \"../../types/media-panel\";\nimport { useAudioPreview } from \"../../hooks/use-audio-preview\";\n\n\nexport const AudioPanel = ({\n items,\n onItemSelect,\n onUrlAdd,\n}: AudioPanelProps) => {\n const { playingAudio, togglePlayPause } = useAudioPreview();\n return (\n <div className=\"panel-container\">\n <div className=\"panel-title\">Audio Library</div>\n\n {/* Add by URL */}\n <div className=\"panel-section\">\n <UrlInput type=\"audio\" onSubmit={onUrlAdd} />\n </div>\n\n {/* Upload */}\n {/* <div className=\"flex panel-section\">\n <FileInput\n id=\"audio-upload\"\n acceptFileTypes={acceptFileTypes}\n onFileLoad={onFileUpload}\n buttonText=\"Import media\"\n className=\"btn-primary w-full\"\n icon={<Upload className=\"icon-sm\" />}\n />\n </div> */}\n\n {/* Audio List */}\n <div className=\"media-content\">\n <div className=\"media-list\">\n {(items || []).map((item) => (\n <div\n key={item.id}\n draggable\n onDoubleClick={() => onItemSelect(item)}\n onDragStart={(e) => {\n e.dataTransfer.setData(\n TIMELINE_DROP_MEDIA_TYPE,\n JSON.stringify({ type: \"audio\", url: item.url })\n );\n e.dataTransfer.effectAllowed = \"copy\";\n }}\n className=\"media-list-item media-item-draggable\"\n >\n {/* Audio Info */}\n <div className=\"media-list-content\">\n {/* Play/Pause button */}\n <button\n onClick={(e) => {\n e.stopPropagation();\n togglePlayPause(item);\n }}\n className=\"media-action-btn\"\n >\n {playingAudio === item.id ? (\n <Pause className=\"icon-sm\" />\n ) : (\n <Play className=\"icon-sm\" />\n )}\n </button>\n\n {/* Audio Icon */}\n <div className={`media-list-icon ${playingAudio === item.id ? 'active' : ''}`}>\n <Volume2 className=\"icon-sm\" />\n </div>\n\n {/* Audio Title */}\n <div className=\"media-list-title\">\n {item.metadata?.title || item.metadata?.name}\n </div>\n\n {/* Quick Add button */}\n <button\n onClick={(e) => {\n e.stopPropagation();\n onItemSelect(item, true);\n }}\n className=\"media-action-btn\"\n >\n <Plus className=\"icon-sm\" />\n </button>\n </div>\n </div>\n ))}\n </div>\n\n {/* Empty state */}\n {items.length === 0 && (\n <div className=\"empty-state\">\n <div className=\"empty-state-content\">\n <Wand2 className=\"empty-state-icon\" />\n <p className=\"empty-state-text\">No audio files found</p>\n </div>\n </div>\n )}\n </div>\n </div>\n );\n};","import { useMediaPanel } from \"../../hooks/use-media-panel\";\nimport { AudioPanel } from \"../panel/audio-panel\";\nimport type { PanelProps } from \"../../types\";\nimport { useMedia } from \"../../context/media-context\";\nimport { getMediaManager } from \"../shared\";\n\nexport const AudioPanelContainer = (props: PanelProps) => {\n const { addItem } = useMedia(\"audio\");\n const mediaManager = getMediaManager();\n const {\n items,\n searchQuery,\n setSearchQuery,\n handleSelection,\n handleFileUpload,\n isLoading,\n acceptFileTypes,\n } = useMediaPanel(\"audio\", {\n selectedElement: props.selectedElement ?? null,\n addElement: props.addElement!,\n updateElement: props.updateElement!,\n },\n props.videoResolution);\n\n const onUrlAdd = async (url: string) => {\n const nameFromUrl = (() => {\n try {\n const u = new URL(url);\n const parts = u.pathname.split(\"/\").filter(Boolean);\n return decodeURIComponent(parts[parts.length - 1] || url);\n } catch {\n return url;\n }\n })();\n\n const newItem = await mediaManager.addItem({\n name: nameFromUrl,\n url,\n type: \"audio\",\n metadata: { source: \"url\" },\n });\n addItem(newItem);\n };\n\n return (\n <AudioPanel\n items={items}\n searchQuery={searchQuery}\n onSearchChange={setSearchQuery}\n onItemSelect={handleSelection}\n onFileUpload={handleFileUpload}\n isLoading={isLoading}\n acceptFileTypes={acceptFileTypes}\n onUrlAdd={onUrlAdd}\n />\n );\n};\n","/**\n * ImagePanel Component\n *\n * A panel for managing image elements in the studio. Provides functionality\n * for searching, uploading, previewing, and adding image files to the timeline.\n * Features a grid layout with image thumbnails and hover actions.\n *\n * @component\n * @param {Object} props\n * @param {MediaItem[]} props.items - List of image items to display\n * @param {string} props.searchQuery - Current search query\n * @param {(query: string) => void} props.setSearchQuery - Handle search query changes\n * @param {(item: MediaItem) => void} props.handleSelection - Handle image item selection\n * @param {(data: { file: File; blobUrl: string }) => void} props.handleFileUpload - Handle file uploads\n *\n * @example\n * ```tsx\n * <ImagePanel\n * items={imageItems}\n * searchQuery=\"\"\n * setSearchQuery={setSearchQuery}\n * handleSelection={handleSelect}\n * handleFileUpload={handleUpload}\n * />\n * ```\n */\n\nimport { Wand2, Plus } from \"lucide-react\";\nimport type { MediaItem } from \"@twick/video-editor\";\nimport { TIMELINE_DROP_MEDIA_TYPE } from \"@twick/video-editor\";\nimport type { ImagePanelProps } from \"../../types/media-panel\";\nimport UrlInput from \"../shared/url-input\";\n\nexport function ImagePanel({\n items,\n onItemSelect,\n onUrlAdd,\n}: ImagePanelProps) {\n return (\n <div className=\"panel-container\">\n <div className=\"panel-title\">Image Library</div>\n\n {/* Add by URL */}\n <div className=\"panel-section\">\n <UrlInput type=\"image\" onSubmit={onUrlAdd} />\n </div>\n {/* Upload */}\n {/* <div className=\"flex panel-section\">\n <FileInput\n id=\"image-upload\"\n acceptFileTypes={acceptFileTypes}\n onFileLoad={onFileUpload}\n buttonText=\"Import media\"\n className=\"btn-primary w-full\"\n icon={<Upload className=\"icon-sm\" />}\n />\n </div> */}\n\n {/* Media Grid */}\n <div className=\"media-content\">\n <div className=\"media-grid\">\n {(items || []).map((item: MediaItem) => (\n <div\n key={item.id}\n draggable\n onDoubleClick={() => onItemSelect(item)}\n onDragStart={(e) => {\n e.dataTransfer.setData(\n TIMELINE_DROP_MEDIA_TYPE,\n JSON.stringify({ type: \"image\", url: item.url })\n );\n e.dataTransfer.effectAllowed = \"copy\";\n }}\n className=\"media-item media-item-draggable\"\n >\n <img src={item.url} alt=\"\" className=\"media-item-content\" />\n <div className=\"media-actions media-actions-corner\">\n <button\n onClick={(e) => {\n e.stopPropagation();\n onItemSelect(item, true);\n }}\n className=\"media-action-btn\"\n >\n <Plus className=\"icon-sm\" />\n </button>\n </div>\n </div>\n ))}\n </div>\n\n {/* Empty state */}\n {items.length === 0 && (\n <div className=\"empty-state\">\n <div className=\"empty-state-content\">\n <Wand2 className=\"empty-state-icon\" />\n <p className=\"empty-state-text\">No images found</p>\n </div>\n </div>\n )}\n </div>\n </div>\n );\n}\n","import type { PanelProps } from \"../../types\";\nimport { ImagePanel } from \"../panel/image-panel\";\nimport { useMediaPanel } from \"../../hooks/use-media-panel\";\nimport { useMedia } from \"../../context/media-context\";\nimport { getMediaManager } from \"../shared\";\n\nexport function ImagePanelContainer(props: PanelProps) {\n const { addItem } = useMedia(\"image\");\n const mediaManager = getMediaManager();\n const {\n items,\n searchQuery,\n setSearchQuery,\n handleSelection,\n handleFileUpload,\n isLoading,\n acceptFileTypes,\n } = useMediaPanel(\"image\", {\n selectedElement: props.selectedElement ?? null,\n addElement: props.addElement!,\n updateElement: props.updateElement!,\n },\n props.videoResolution);\n\n const onUrlAdd = async (url: string) => {\n const nameFromUrl = (() => {\n try {\n const u = new URL(url);\n const parts = u.pathname.split(\"/\").filter(Boolean);\n return decodeURIComponent(parts[parts.length - 1] || url);\n } catch {\n return url;\n }\n })();\n\n const newItem = await mediaManager.addItem({\n name: nameFromUrl,\n url,\n type: \"image\",\n metadata: { source: \"url\" },\n });\n addItem(newItem);\n };\n\n return (\n <ImagePanel\n items={items}\n searchQuery={searchQuery}\n onSearchChange={setSearchQuery}\n onItemSelect={handleSelection}\n onFileUpload={handleFileUpload}\n isLoading={isLoading}\n acceptFileTypes={acceptFileTypes}\n onUrlAdd={onUrlAdd}\n />\n );\n}\n","import { useState, useCallback, useRef, useEffect } from 'react';\nimport type { MediaItem } from '@twick/video-editor';\n\nexport interface VideoPreviewState {\n playingVideo: string | null; // ID of currently playing video\n videoElement: HTMLVideoElement | null;\n}\n\nexport interface VideoPreviewActions {\n togglePlayPause: (item: MediaItem, videoElement: HTMLVideoElement) => void;\n stopPlayback: () => void;\n}\n\nexport const useVideoPreview = (): VideoPreviewState & VideoPreviewActions => {\n const [playingVideo, setPlayingVideo] = useState<string | null>(null);\n const videoRef = useRef<HTMLVideoElement | null>(null);\n\n // Cleanup video element on unmount\n useEffect(() => {\n return () => {\n if (videoRef.current) {\n videoRef.current.pause();\n videoRef.current = null;\n }\n };\n }, []);\n\n const stopPlayback = useCallback(() => {\n if (videoRef.current) {\n videoRef.current.pause();\n videoRef.current = null;\n }\n setPlayingVideo(null);\n }, []);\n\n const togglePlayPause = useCallback((item: MediaItem, videoElement: HTMLVideoElement) => {\n // If we're already playing this video, pause it\n if (playingVideo === item.id) {\n videoElement.pause();\n stopPlayback();\n return;\n }\n\n // Stop any currently playing video\n stopPlayback();\n\n // Start playing the new video\n videoElement.currentTime = 0; // Reset to start\n videoElement.play();\n videoRef.current = videoElement;\n setPlayingVideo(item.id);\n\n // Add ended event listener\n videoElement.addEventListener('ended', stopPlayback, { once: true });\n }, [playingVideo, stopPlayback]);\n\n return {\n playingVideo,\n videoElement: videoRef.current,\n togglePlayPause,\n stopPlayback,\n };\n};","/**\n * VideoPanel Component\n * \n * A panel for managing video elements in the studio. Provides functionality\n * for searching, uploading, previewing, and adding video files to the timeline.\n * Features a grid layout with video thumbnails and hover actions.\n * \n * @component\n * @param {Object} props\n * @param {MediaItem[]} props.items - List of video items to display\n * @param {string} props.searchQuery - Current search query\n * @param {(query: string) => void} props.setSearchQuery - Handle search query changes\n * @param {(item: MediaItem) => void} props.handleSelection - Handle video item selection\n * @param {(data: { file: File; blobUrl: string }) => void} props.handleFileUpload - Handle file uploads\n * \n * @example\n * ```tsx\n * <VideoPanel\n * items={videoItems}\n * searchQuery=\"\"\n * setSearchQuery={setSearchQuery}\n * handleSelection={handleSelect}\n * handleFileUpload={handleUpload}\n * />\n * ```\n */\n\nimport { Wand2, Plus, Play, Pause } from \"lucide-react\";\nimport type { MediaItem } from \"@twick/video-editor\";\nimport { TIMELINE_DROP_MEDIA_TYPE } from \"@twick/video-editor\";\nimport type { VideoPanelProps } from \"../../types/media-panel\";\nimport { useVideoPreview } from \"../../hooks/use-video-preview\";\nimport UrlInput from \"../shared/url-input\";\n\n\nexport function VideoPanel({\n items,\n onItemSelect,\n onUrlAdd,\n}: VideoPanelProps) {\n const { playingVideo, togglePlayPause } = useVideoPreview();\n return (\n <div className=\"panel-container\">\n <div className=\"panel-title\">Video Library</div>\n\n {/* Add by URL */}\n <div className=\"flex panel-section\">\n <UrlInput type=\"video\" onSubmit={onUrlAdd} />\n </div>\n\n {/* Import Button */}\n {/* <div className=\"flex panel-section\">\n <FileInput\n id=\"video-upload\"\n acceptFileTypes={acceptFileTypes}\n onFileLoad={onFileUpload}\n buttonText=\"Import media\"\n className=\"btn-primary w-full\"\n icon={<Upload className=\"icon-sm\" />}\n />\n </div> */}\n\n {/* Media Grid */}\n <div className=\"media-content\">\n <div className=\"media-grid\">\n {(items || []).map((item: MediaItem) => (\n <div\n key={item.id}\n draggable\n onDoubleClick={() => onItemSelect(item)}\n onDragStart={(e) => {\n e.dataTransfer.setData(\n TIMELINE_DROP_MEDIA_TYPE,\n JSON.stringify({ type: \"video\", url: item.url })\n );\n e.dataTransfer.effectAllowed = \"copy\";\n }}\n className=\"media-item media-item-draggable\"\n >\n <video\n src={item.url}\n poster={item.thumbnail}\n className=\"media-item-content\"\n ref={(el) => {\n if (el) {\n el.addEventListener('ended', () => {\n el.currentTime = 0;\n }, { once: true });\n }\n }}\n />\n\n {/* Duration */}\n {/* <div className=\"media-duration\">\n 0:13\n </div> */}\n\n {/* Corner play/pause control */}\n <div className=\"media-actions media-actions-corner\">\n <button\n onClick={(e) => {\n e.stopPropagation();\n const videoEl =\n e.currentTarget.parentElement?.parentElement?.querySelector(\"video\");\n if (videoEl) {\n togglePlayPause(item, videoEl);\n }\n }}\n className=\"media-action-btn\"\n >\n {playingVideo === item.id ? (\n <Pause className=\"icon-sm\" />\n ) : (\n <Play className=\"icon-sm\" />\n )}\n </button>\n <button\n onClick={(e) => {\n e.stopPropagation();\n onItemSelect(item, true);\n }}\n className=\"media-action-btn\"\n >\n <Plus className=\"icon-sm\" />\n </button>\n </div>\n </div>\n ))}\n </div>\n\n {/* Empty state */}\n {items.length === 0 && (\n <div className=\"empty-state\">\n <div className=\"empty-state-content\">\n <Wand2 className=\"empty-state-icon\" />\n <p className=\"empty-state-text\">No videos found</p>\n </div>\n </div>\n )}\n </div>\n </div>\n );\n}","import type { PanelProps } from \"../../types\";\nimport { VideoPanel } from \"../panel/video-panel\";\nimport { useMediaPanel } from \"../../hooks/use-media-panel\";\nimport { useMedia } from \"../../context/media-context\";\nimport { getMediaManager } from \"../shared\";\n\nexport function VideoPanelContainer(props: PanelProps) {\n const { addItem } = useMedia(\"video\");\n const mediaManager = getMediaManager();\n const {\n items,\n handleSelection,\n handleFileUpload,\n isLoading,\n acceptFileTypes,\n } = useMediaPanel(\"video\", {\n selectedElement: props.selectedElement ?? null,\n addElement: props.addElement!,\n updateElement: props.updateElement!,\n },\n props.videoResolution);\n\n const onUrlAdd = async (url: string) => {\n const nameFromUrl = (() => {\n try {\n const u = new URL(url);\n const parts = u.pathname.split(\"/\").filter(Boolean);\n return decodeURIComponent(parts[parts.length - 1] || url);\n } catch {\n return url;\n }\n })();\n\n const newItem = await mediaManager.addItem({\n name: nameFromUrl,\n url,\n type: \"video\",\n metadata: { source: \"url\" },\n });\n addItem(newItem);\n };\n\n return (\n <VideoPanel\n items={items}\n onItemSelect={handleSelection}\n onFileUpload={handleFileUpload}\n isLoading={isLoading}\n acceptFileTypes={acceptFileTypes}\n onUrlAdd={onUrlAdd}\n />\n );\n}\n","/**\n * TextPanel Component\n * \n * A panel for creating and editing text elements in the studio. Provides comprehensive\n * text styling options including font selection, size, colors, stroke, and shadow effects.\n * \n * @component\n * @param {Object} props\n * @param {string} props.textContent - Text content to display\n * @param {number} props.fontSize - Font size in pixels\n * @param {string} props.selectedFont - Selected font family\n * @param {boolean} props.isBold - Whether text is bold\n * @param {boolean} props.isItalic - Whether text is italic\n * @param {string} props.textColor - Text color in hex format\n * @param {string} props.strokeColor - Stroke color in hex format\n * @param {boolean} props.applyShadow - Whether to apply shadow effect\n * @param {string} props.shadowColor - Shadow color in hex format\n * @param {number} props.strokeWidth - Width of text stroke\n * @param {boolean} props.applyBackground - Whether to apply background behind text\n * @param {string} props.backgroundColor - Background color in hex (when applyBackground is true)\n * @param {number} props.backgroundOpacity - Background opacity 0-1 (when applyBackground is true)\n * @param {string[]} props.fonts - Available font options\n * @param {(text: string) => void} props.setTextContent - Update text content\n * @param {(size: number) => void} props.setFontSize - Update font size\n * @param {(font: string) => void} props.setSelectedFont - Update selected font\n * @param {(bold: boolean) => void} props.setIsBold - Toggle bold style\n * @param {(italic: boolean) => void} props.setIsItalic - Toggle italic style\n * @param {(color: string) => void} props.setTextColor - Update text color\n * @param {(color: string) => void} props.setStrokeColor - Update stroke color\n * @param {(apply: boolean) => void} props.setApplyShadow - Toggle shadow effect\n * @param {(color: string) => void} props.setShadowColor - Update shadow color\n * @param {(width: number) => void} props.setStrokeWidth - Update stroke width\n * @param {(apply: boolean) => void} props.setApplyBackground - Toggle background\n * @param {(color: string) => void} props.setBackgroundColor - Update background color\n * @param {(opacity: number) => void} props.setBackgroundOpacity - Update background opacity\n * @param {() => void} props.handleApplyChanges - Apply text element changes\n * \n * @example\n * ```tsx\n * <TextPanel\n * textContent=\"Sample Text\"\n * fontSize={48}\n * selectedFont=\"Arial\"\n * isBold={false}\n * isItalic={false}\n * textColor=\"#000000\"\n * strokeColor=\"#ffffff\"\n * applyShadow={false}\n * shadowColor=\"#000000\"\n * strokeWidth={0}\n * fonts={[\"Arial\", \"Times New Roman\"]}\n * setTextContent={setText}\n * setFontSize={setSize}\n * // ... other handlers\n * />\n * ```\n */\n\nimport type { TextPanelState, TextPanelActions } from \"../../hooks/use-text-panel\";\n\nexport type TextPanelProps = TextPanelState & TextPanelActions;\n\nexport function TextPanel({\n textContent,\n fontSize,\n selectedFont,\n isBold,\n isItalic,\n textColor,\n strokeColor,\n applyShadow,\n shadowColor,\n strokeWidth,\n applyBackground,\n backgroundColor,\n backgroundOpacity,\n fonts,\n operation,\n setTextContent,\n setFontSize,\n setSelectedFont,\n setIsBold,\n setIsItalic,\n setTextColor,\n setStrokeColor,\n setApplyShadow,\n setShadowColor,\n setStrokeWidth,\n setApplyBackground,\n setBackgroundColor,\n setBackgroundOpacity,\n handleApplyChanges,\n}: TextPanelProps) {\n return (\n <div className=\"panel-container\">\n <div className=\"panel-title\">Text</div>\n {/* Text Content */}\n <div className=\"flex panel-section\">\n <input\n type=\"text\"\n value={textContent}\n placeholder=\"Sample\"\n onChange={(e) => setTextContent(e.target.value)}\n className=\"input-dark\"\n />\n </div>\n\n {/* Font Size */}\n <div className=\"panel-section\">\n <label className=\"label-dark\">Font Size</label>\n <div className=\"slider-container\">\n <input\n type=\"range\"\n min=\"8\"\n max=\"120\"\n value={fontSize}\n onChange={(e) => setFontSize(Number(e.target.value))}\n className=\"slider-purple\"\n />\n <span className=\"slider-value\">{fontSize}px</span>\n </div>\n </div>\n\n {/* Font */}\n <div className=\"panel-section\">\n <label className=\"label-dark\">Font</label>\n <div className=\"font-controls\">\n <select\n value={selectedFont}\n onChange={(e) => setSelectedFont(e.target.value)}\n className=\"select-dark\"\n >\n {fonts.map((font) => (\n <option key={font} value={font}>\n {font}\n </option>\n ))}\n </select>\n <button\n onClick={() => setIsBold(!isBold)}\n className={`btn-icon ${isBold ? 'btn-icon-active' : ''}`}\n >\n B\n </button>\n <button\n onClick={() => setIsItalic(!isItalic)}\n className={`btn-icon ${isItalic ? 'btn-icon-active' : ''}`}\n >\n I\n </button>\n </div>\n </div>\n\n {/* Colors */}\n <div className=\"panel-section\">\n <label className=\"label-dark\">Colors</label>\n <div className=\"color-section\">\n {/* Text Color */}\n <div className=\"color-control\">\n <label className=\"label-small\">Text Color</label>\n <div className=\"color-inputs\">\n <input\n type=\"color\"\n value={textColor}\n onChange={(e) => setTextColor(e.target.value)}\n className=\"color-picker\"\n />\n <input\n type=\"text\"\n value={textColor}\n onChange={(e) => setTextColor(e.target.value)}\n className=\"color-text\"\n />\n </div>\n </div>\n\n {/* Stroke Color */}\n <div className=\"color-control\">\n <label className=\"label-small\">Stroke Color</label>\n <div className=\"color-inputs\">\n <input\n type=\"color\"\n value={strokeColor}\n onChange={(e) => setStrokeColor(e.target.value)}\n className=\"color-picker\"\n />\n <input\n type=\"text\"\n value={strokeColor}\n onChange={(e) => setStrokeColor(e.target.value)}\n className=\"color-text\"\n />\n </div>\n </div>\n\n {/* Apply Shadow */}\n <div className=\"checkbox-control\">\n <label className=\"checkbox-label\">\n <input\n type=\"checkbox\"\n checked={applyShadow}\n onChange={(e) => setApplyShadow(e.target.checked)}\n className=\"checkbox-purple\"\n />\n Apply Shadow\n </label>\n </div>\n\n {/* Shadow Color - Only shown when shadow is enabled */}\n {applyShadow && (\n <div className=\"color-control\">\n <label className=\"label-small\">Shadow Color</label>\n <div className=\"color-inputs\">\n <input\n type=\"color\"\n value={shadowColor}\n onChange={(e) => setShadowColor(e.target.value)}\n className=\"color-picker\"\n />\n <input\n type=\"text\"\n value={shadowColor}\n onChange={(e) => setShadowColor(e.target.value)}\n className=\"color-text\"\n />\n </div>\n </div>\n )}\n </div>\n </div>\n\n {/* Stroke Width */}\n <div className=\"panel-section\">\n <label className=\"label-dark\">Stroke Width</label>\n <div className=\"slider-container\">\n <input\n type=\"range\"\n min=\"0\"\n max=\"2\"\n step={0.1}\n value={strokeWidth}\n onChange={(e) => setStrokeWidth(Number(e.target.value))}\n className=\"slider-purple\"\n />\n <span className=\"slider-value\">{strokeWidth}</span>\n </div>\n </div>\n\n {/* Background (optional) */}\n <div className=\"panel-section\">\n <label className=\"label-dark\">Background</label>\n <div className=\"color-section\">\n <div className=\"checkbox-control\">\n <label className=\"checkbox-label\">\n <input\n type=\"checkbox\"\n checked={applyBackground}\n onChange={(e) => setApplyBackground(e.target.checked)}\n className=\"checkbox-purple\"\n />\n Apply Background\n </label>\n </div>\n {applyBackground && (\n <>\n <div className=\"color-control\">\n <label className=\"label-small\">Background Color</label>\n <div className=\"color-inputs\">\n <input\n type=\"color\"\n value={backgroundColor}\n onChange={(e) => setBackgroundColor(e.target.value)}\n className=\"color-picker\"\n />\n <input\n type=\"text\"\n value={backgroundColor}\n onChange={(e) => setBackgroundColor(e.target.value)}\n className=\"color-text\"\n />\n </div>\n </div>\n <div className=\"panel-section\">\n <label className=\"label-small\">Background Opacity</label>\n <div className=\"slider-container\">\n <input\n type=\"range\"\n min=\"0\"\n max=\"1\"\n step={0.1}\n value={backgroundOpacity}\n onChange={(e) => setBackgroundOpacity(Number(e.target.value))}\n className=\"slider-purple\"\n />\n <span className=\"slider-value\">{Math.round(backgroundOpacity * 100)}%</span>\n </div>\n </div>\n </>\n )}\n </div>\n </div>\n\n {/* Operation button (only for creation, not edits) */}\n {operation !== \"Apply Changes\" && (\n <div className=\"flex panel-section\">\n <button onClick={handleApplyChanges} className=\"btn-primary w-full\">\n {operation}\n </button>\n </div>\n )}\n </div>\n );\n}","import { useEffect, useState } from \"react\";\nimport { TextElement, TrackElement, type TextAlign } from \"@twick/timeline\";\nimport { AVAILABLE_TEXT_FONTS } from \"@twick/video-editor\";\n\nexport const DEFAULT_TEXT_PROPS = {\n text: \"Sample\",\n fontSize: 48,\n fontFamily: \"Poppins\",\n fontWeight: 400,\n fontStyle: \"normal\",\n textColor: \"#ffffff\",\n strokeColor: \"#4d4d4d\",\n strokeWidth: 0,\n applyShadow: false,\n shadowColor: \"#000000\",\n textAlign: \"center\" as TextAlign,\n shadowOffset: [0, 0],\n shadowBlur: 2,\n shadowOpacity: 1.0,\n};\n\nexport interface TextPanelState {\n textContent: string;\n fontSize: number;\n selectedFont: string;\n isBold: boolean;\n isItalic: boolean;\n textColor: string;\n strokeColor: string;\n applyShadow: boolean;\n shadowColor: string;\n strokeWidth: number;\n applyBackground: boolean;\n backgroundColor: string;\n backgroundOpacity: number;\n fonts: string[];\n operation: string;\n}\n\nexport interface TextPanelActions {\n setTextContent: (text: string) => void;\n setFontSize: (size: number) => void;\n setSelectedFont: (font: string) => void;\n setIsBold: (bold: boolean) => void;\n setIsItalic: (italic: boolean) => void;\n setTextColor: (color: string) => void;\n setStrokeColor: (color: string) => void;\n setApplyShadow: (shadow: boolean) => void;\n setShadowColor: (color: string) => void;\n setStrokeWidth: (width: number) => void;\n setApplyBackground: (apply: boolean) => void;\n setBackgroundColor: (color: string) => void;\n setBackgroundOpacity: (opacity: number) => void;\n handleApplyChanges: () => void;\n}\n\nexport const useTextPanel = ({\n selectedElement,\n addElement,\n updateElement,\n}: {\n selectedElement: TrackElement | null;\n addElement: (element: TrackElement) => void;\n updateElement: (element: TrackElement) => void;\n}): TextPanelState & TextPanelActions => {\n const [textContent, setTextContent] = useState(DEFAULT_TEXT_PROPS.text);\n const [fontSize, setFontSize] = useState(DEFAULT_TEXT_PROPS.fontSize);\n const [selectedFont, setSelectedFont] = useState(DEFAULT_TEXT_PROPS.fontFamily);\n const [isBold, setIsBold] = useState(DEFAULT_TEXT_PROPS.fontWeight === 700);\n const [isItalic, setIsItalic] = useState(DEFAULT_TEXT_PROPS.fontStyle === \"italic\");\n const [textColor, setTextColor] = useState(DEFAULT_TEXT_PROPS.textColor);\n const [strokeColor, setStrokeColor] = useState(DEFAULT_TEXT_PROPS.strokeColor);\n const [applyShadow, setApplyShadow] = useState(DEFAULT_TEXT_PROPS.applyShadow);\n const [shadowColor, setShadowColor] = useState(DEFAULT_TEXT_PROPS.shadowColor);\n const [strokeWidth, setStrokeWidth] = useState(DEFAULT_TEXT_PROPS.strokeWidth);\n const [applyBackground, setApplyBackground] = useState(false);\n const [backgroundColor, setBackgroundColor] = useState(\"#FACC15\");\n const [backgroundOpacity, setBackgroundOpacity] = useState(1);\n\n const fonts = Object.values(AVAILABLE_TEXT_FONTS);\n\n const applyLiveChangesToExistingText = (overrides: Partial<TextPanelState> = {}) => {\n if (!(selectedElement instanceof TextElement)) {\n return;\n }\n\n const textElement = selectedElement;\n\n const nextState: Pick<\n TextPanelState,\n | \"textContent\"\n | \"fontSize\"\n | \"selectedFont\"\n | \"isBold\"\n | \"isItalic\"\n | \"textColor\"\n | \"strokeColor\"\n | \"strokeWidth\"\n | \"applyShadow\"\n | \"shadowColor\"\n | \"applyBackground\"\n | \"backgroundColor\"\n | \"backgroundOpacity\"\n > = {\n textContent,\n fontSize,\n selectedFont,\n isBold,\n isItalic,\n textColor,\n strokeColor,\n strokeWidth,\n applyShadow,\n shadowColor,\n applyBackground,\n backgroundColor,\n backgroundOpacity,\n ...overrides,\n };\n\n textElement.setText(nextState.textContent);\n textElement.setFontSize(nextState.fontSize);\n textElement.setFontFamily(nextState.selectedFont);\n textElement.setFontWeight(nextState.isBold ? 700 : 400);\n textElement.setFontStyle(nextState.isItalic ? \"italic\" : \"normal\");\n textElement.setFill(nextState.textColor);\n textElement.setStrokeColor(nextState.strokeColor);\n textElement.setLineWidth(nextState.strokeWidth);\n textElement.setTextAlign(DEFAULT_TEXT_PROPS.textAlign);\n\n const nextProps = { ...textElement.getProps() };\n\n if (nextState.applyShadow) {\n nextProps.shadowColor = nextState.shadowColor;\n nextProps.shadowOffset = DEFAULT_TEXT_PROPS.shadowOffset;\n nextProps.shadowBlur = DEFAULT_TEXT_PROPS.shadowBlur;\n nextProps.shadowOpacity = DEFAULT_TEXT_PROPS.shadowOpacity;\n } else {\n nextProps.shadowColor = undefined;\n nextProps.shadowOffset = undefined;\n nextProps.shadowBlur = undefined;\n nextProps.shadowOpacity = undefined;\n }\n\n if (nextState.applyBackground) {\n nextProps.backgroundColor = nextState.backgroundColor;\n nextProps.backgroundOpacity = nextState.backgroundOpacity;\n } else {\n nextProps.backgroundColor = undefined;\n nextProps.backgroundOpacity = undefined;\n }\n\n textElement.setProps(nextProps);\n updateElement(textElement);\n };\n\n const handleTextContentChange = (text: string) => {\n setTextContent(text);\n applyLiveChangesToExistingText({ textContent: text });\n };\n\n const handleFontSizeChange = (size: number) => {\n setFontSize(size);\n applyLiveChangesToExistingText({ fontSize: size });\n };\n\n const handleSelectedFontChange = (font: string) => {\n setSelectedFont(font);\n applyLiveChangesToExistingText({ selectedFont: font });\n };\n\n const handleIsBoldChange = (bold: boolean) => {\n setIsBold(bold);\n applyLiveChangesToExistingText({ isBold: bold });\n };\n\n const handleIsItalicChange = (italic: boolean) => {\n setIsItalic(italic);\n applyLiveChangesToExistingText({ isItalic: italic });\n };\n\n const handleTextColorChange = (color: string) => {\n setTextColor(color);\n applyLiveChangesToExistingText({ textColor: color });\n };\n\n const handleStrokeColorChange = (color: string) => {\n setStrokeColor(color);\n applyLiveChangesToExistingText({ strokeColor: color });\n };\n\n const handleStrokeWidthChange = (width: number) => {\n setStrokeWidth(width);\n applyLiveChangesToExistingText({ strokeWidth: width });\n };\n\n const handleApplyShadowChange = (shadow: boolean) => {\n setApplyShadow(shadow);\n applyLiveChangesToExistingText({ applyShadow: shadow });\n };\n\n const handleShadowColorChange = (color: string) => {\n setShadowColor(color);\n applyLiveChangesToExistingText({ shadowColor: color });\n };\n\n const handleApplyBackgroundChange = (apply: boolean) => {\n setApplyBackground(apply);\n applyLiveChangesToExistingText({ applyBackground: apply });\n };\n\n const handleBackgroundColorChange = (color: string) => {\n setBackgroundColor(color);\n applyLiveChangesToExistingText({ backgroundColor: color });\n };\n\n const handleBackgroundOpacityChange = (opacity: number) => {\n setBackgroundOpacity(opacity);\n applyLiveChangesToExistingText({ backgroundOpacity: opacity });\n };\n\n const handleApplyChanges = async () => {\n // For existing text elements, changes are already applied live via the handlers above.\n // The apply button is only meaningful when creating a new text element.\n if (selectedElement instanceof TextElement) {\n return;\n }\n\n const textElement = new TextElement(textContent)\n .setFontSize(fontSize)\n .setFontFamily(selectedFont)\n .setFontWeight(isBold ? 700 : 400)\n .setFontStyle(isItalic ? \"italic\" : \"normal\")\n .setFill(textColor)\n .setStrokeColor(strokeColor)\n .setLineWidth(strokeWidth)\n .setTextAlign(\"center\");\n\n const nextProps = { ...textElement.getProps() };\n if (applyShadow) {\n nextProps.shadowColor = shadowColor;\n nextProps.shadowOffset = DEFAULT_TEXT_PROPS.shadowOffset;\n nextProps.shadowBlur = DEFAULT_TEXT_PROPS.shadowBlur;\n nextProps.shadowOpacity = DEFAULT_TEXT_PROPS.shadowOpacity;\n }\n if (applyBackground) {\n nextProps.backgroundColor = backgroundColor;\n nextProps.backgroundOpacity = backgroundOpacity;\n }\n textElement.setProps(nextProps);\n await addElement(textElement);\n };\n\n useEffect(() => {\n if (selectedElement instanceof TextElement) {\n setTextContent(selectedElement.getText());\n const textProps = selectedElement.getProps();\n setSelectedFont(textProps.fontFamily ?? DEFAULT_TEXT_PROPS.fontFamily);\n setFontSize(textProps.fontSize ?? DEFAULT_TEXT_PROPS.fontSize);\n setIsBold(textProps.fontWeight === 700);\n setIsItalic(textProps.fontStyle === \"italic\");\n setTextColor(textProps.fill ?? DEFAULT_TEXT_PROPS.textColor);\n setStrokeColor(textProps.stroke ?? DEFAULT_TEXT_PROPS.strokeColor);\n setStrokeWidth(textProps.lineWidth ?? DEFAULT_TEXT_PROPS.strokeWidth);\n const hasShadow = textProps.shadowColor !== undefined;\n setApplyShadow(hasShadow);\n if (hasShadow) {\n setShadowColor(textProps.shadowColor ?? DEFAULT_TEXT_PROPS.shadowColor);\n }\n const hasBackground = textProps.backgroundColor != null && textProps.backgroundColor !== \"\";\n setApplyBackground(hasBackground);\n if (hasBackground) {\n setBackgroundColor(textProps.backgroundColor ?? \"#FACC15\");\n setBackgroundOpacity(textProps.backgroundOpacity ?? 1);\n }\n } else {\n setTextContent(DEFAULT_TEXT_PROPS.text);\n setFontSize(DEFAULT_TEXT_PROPS.fontSize);\n setSelectedFont(DEFAULT_TEXT_PROPS.fontFamily);\n setIsBold(DEFAULT_TEXT_PROPS.fontWeight === 700);\n setIsItalic(DEFAULT_TEXT_PROPS.fontStyle === \"italic\");\n setTextColor(DEFAULT_TEXT_PROPS.textColor);\n setStrokeColor(DEFAULT_TEXT_PROPS.strokeColor);\n setStrokeWidth(DEFAULT_TEXT_PROPS.strokeWidth);\n setApplyShadow(DEFAULT_TEXT_PROPS.applyShadow);\n setShadowColor(DEFAULT_TEXT_PROPS.shadowColor);\n setApplyBackground(false);\n setBackgroundColor(\"#FACC15\");\n setBackgroundOpacity(1);\n }\n }, [selectedElement]);\n\n return {\n textContent,\n fontSize,\n selectedFont,\n isBold,\n isItalic,\n textColor,\n strokeColor,\n applyShadow,\n shadowColor,\n strokeWidth,\n fonts,\n operation: selectedElement instanceof TextElement ? \"Apply Changes\": \"Add Text\",\n setTextContent: handleTextContentChange,\n setFontSize: handleFontSizeChange,\n setSelectedFont: handleSelectedFontChange,\n setIsBold: handleIsBoldChange,\n setIsItalic: handleIsItalicChange,\n setTextColor: handleTextColorChange,\n setStrokeColor: handleStrokeColorChange,\n setApplyShadow: handleApplyShadowChange,\n setShadowColor: handleShadowColorChange,\n setStrokeWidth: handleStrokeWidthChange,\n applyBackground,\n backgroundColor,\n backgroundOpacity,\n setApplyBackground: handleApplyBackgroundChange,\n setBackgroundColor: handleBackgroundColorChange,\n setBackgroundOpacity: handleBackgroundOpacityChange,\n handleApplyChanges,\n };\n};\n","import { TrackElement } from \"@twick/timeline\";\nimport { TextPanel } from \"../panel/text-panel\";\nimport { useTextPanel } from \"../../hooks/use-text-panel\";\n\ninterface TextPanelContainerProps {\n selectedElement: TrackElement | null;\n addElement: (element: TrackElement) => void;\n updateElement: (element: TrackElement) => void;\n}\n\nexport function TextPanelContainer(props: TextPanelContainerProps) {\n const textPanelProps = useTextPanel(props);\n return <TextPanel {...textPanelProps} />;\n}\n","/**\n * RectPanel Component\n * \n * A panel for creating and editing rectangle shapes in the studio. Provides controls\n * for adjusting corner radius, fill color, opacity, stroke color, and line width.\n * \n * @component\n * @param {Object} props\n * @param {number} props.cornerRadius - Corner radius in pixels\n * @param {string} props.fillColor - Fill color in hex format\n * @param {string} props.strokeColor - Stroke color in hex format\n * @param {number} props.lineWidth - Stroke width in pixels\n * @param {(radius: number) => void} props.setCornerRadius - Update corner radius\n * @param {(color: string) => void} props.setFillColor - Update fill color\n * @param {(opacity: number) => void} props.setOpacity - Update opacity\n * @param {(color: string) => void} props.setStrokeColor - Update stroke color\n * @param {(width: number) => void} props.setLineWidth - Update line width\n * @param {() => void} props.handleApplyChanges - Apply rectangle element changes\n * \n * @example\n * ```tsx\n * <RectPanel\n * cornerRadius={10}\n * fillColor=\"#ff0000\"\n * opacity={100}\n * strokeColor=\"#000000\"\n * lineWidth={2}\n * setCornerRadius={setRadius}\n * setFillColor={setFill}\n * setOpacity={setOpacity}\n * setStrokeColor={setStroke}\n * setLineWidth={setWidth}\n * handleApplyChanges={applyChanges}\n * />\n * ```\n */\n\nimport type { RectPanelState, RectPanelActions } from \"../../hooks/use-rect-panel\";\n\nexport type RectPanelProps = RectPanelState & RectPanelActions;\n\nexport function RectPanel({\n cornerRadius,\n fillColor,\n strokeColor,\n lineWidth,\n operation,\n setCornerRadius,\n setFillColor,\n setStrokeColor,\n setLineWidth,\n handleApplyChanges,\n}: RectPanelProps) {\n return (\n <div className=\"panel-container\">\n <div className=\"panel-title\">Rectangle</div>\n {/* Corner Radius */}\n <div className=\"panel-section\">\n <label className=\"label-dark\">Corner Radius</label>\n <div className=\"slider-container\">\n <input\n type=\"range\"\n min=\"0\"\n max=\"100\"\n value={cornerRadius}\n onChange={(e) => setCornerRadius(Number(e.target.value))}\n className=\"slider-purple\"\n />\n <span className=\"slider-value\">{cornerRadius}px</span>\n </div>\n </div>\n\n {/* Fill Color */}\n <div className=\"panel-section\">\n <label className=\"label-dark\">Fill Color</label>\n <div className=\"color-inputs\">\n <input\n type=\"color\"\n value={fillColor}\n onChange={(e) => setFillColor(e.target.value)}\n className=\"color-picker\"\n />\n <input\n type=\"text\"\n value={fillColor}\n onChange={(e) => setFillColor(e.target.value)}\n className=\"color-text\"\n />\n </div>\n </div>\n\n {/* Stroke Color */}\n <div className=\"panel-section\">\n <label className=\"label-dark\">Stroke Color</label>\n <div className=\"color-inputs\">\n <input\n type=\"color\"\n value={strokeColor}\n onChange={(e) => setStrokeColor(e.target.value)}\n className=\"color-picker\"\n />\n <input\n type=\"text\"\n value={strokeColor}\n onChange={(e) => setStrokeColor(e.target.value)}\n className=\"color-text\"\n />\n </div>\n </div>\n\n {/* Line Width */}\n <div className=\"panel-section\">\n <label className=\"label-dark\">Line Width</label>\n <div className=\"slider-container\">\n <input\n type=\"range\"\n min=\"0\"\n max=\"20\"\n value={lineWidth}\n onChange={(e) => setLineWidth(Number(e.target.value))}\n className=\"slider-purple\"\n />\n <span className=\"slider-value\">{lineWidth}px</span>\n </div>\n </div>\n\n {/* Operation button (only for creation, not edits) */}\n {operation !== \"Apply Changes\" && (\n <div className=\"flex panel-section\">\n <button\n onClick={handleApplyChanges}\n className=\"btn-primary w-full\"\n >\n {operation}\n </button>\n </div>\n )}\n </div>\n );\n}","import { useEffect, useState } from \"react\";\nimport { RectElement, TrackElement } from \"@twick/timeline\";\n\nexport const DEFAULT_RECT_PROPS = {\n cornerRadius: 0,\n fillColor: \"#3b82f6\",\n // UI uses 0–100%; element opacity is 0–1\n opacity: 100,\n strokeColor: \"#000000\",\n lineWidth: 0,\n};\n\nexport interface RectPanelState {\n cornerRadius: number;\n fillColor: string;\n opacity: number;\n strokeColor: string;\n lineWidth: number;\n operation: string;\n}\n\nexport interface RectPanelActions {\n setCornerRadius: (radius: number) => void;\n setFillColor: (color: string) => void;\n setOpacity: (opacity: number) => void;\n setStrokeColor: (color: string) => void;\n setLineWidth: (width: number) => void;\n handleApplyChanges: () => void;\n}\n\nexport const useRectPanel = ({\n selectedElement,\n addElement,\n updateElement,\n}: {\n selectedElement: TrackElement | null;\n addElement: (element: TrackElement) => void;\n updateElement: (element: TrackElement) => void;\n}): RectPanelState & RectPanelActions => {\n const [cornerRadius, setCornerRadius] = useState(DEFAULT_RECT_PROPS.cornerRadius);\n const [fillColor, setFillColor] = useState(DEFAULT_RECT_PROPS.fillColor);\n // Stored as percentage 0–100 for the UI slider\n const [opacity, setOpacity] = useState(DEFAULT_RECT_PROPS.opacity);\n const [strokeColor, setStrokeColor] = useState(DEFAULT_RECT_PROPS.strokeColor);\n const [lineWidth, setLineWidth] = useState(DEFAULT_RECT_PROPS.lineWidth);\n\n const applyLiveChangesToExistingRect = (overrides: Partial<RectPanelState> = {}) => {\n if (!(selectedElement instanceof RectElement)) {\n return;\n }\n\n const rectElement = selectedElement;\n const nextCornerRadius = overrides.cornerRadius ?? cornerRadius;\n const nextFillColor = overrides.fillColor ?? fillColor;\n const nextOpacityPercent = overrides.opacity ?? opacity;\n const nextStrokeColor = overrides.strokeColor ?? strokeColor;\n const nextLineWidth = overrides.lineWidth ?? lineWidth;\n\n rectElement.setCornerRadius(nextCornerRadius);\n rectElement.setFill(nextFillColor);\n // Element expects 0–1 opacity\n rectElement.setOpacity(nextOpacityPercent / 100);\n rectElement.setStrokeColor(nextStrokeColor);\n rectElement.setLineWidth(nextLineWidth);\n\n updateElement?.(rectElement);\n };\n\n const handleCornerRadiusChange = (radius: number) => {\n setCornerRadius(radius);\n applyLiveChangesToExistingRect({ cornerRadius: radius });\n };\n\n const handleFillColorChange = (color: string) => {\n setFillColor(color);\n applyLiveChangesToExistingRect({ fillColor: color });\n };\n\n const handleOpacityChange = (nextOpacity: number) => {\n setOpacity(nextOpacity);\n applyLiveChangesToExistingRect({ opacity: nextOpacity });\n };\n\n const handleStrokeColorChange = (color: string) => {\n setStrokeColor(color);\n applyLiveChangesToExistingRect({ strokeColor: color });\n };\n\n const handleLineWidthChange = (width: number) => {\n setLineWidth(width);\n applyLiveChangesToExistingRect({ lineWidth: width });\n };\n\n const handleApplyChanges = () => {\n // For existing rectangles, changes are already applied live via the handlers above.\n // The apply button is only meaningful when creating a new rectangle.\n if (selectedElement instanceof RectElement) {\n return;\n }\n\n const rectElement = new RectElement(fillColor, { width: 200, height: 200 })\n .setCornerRadius(cornerRadius)\n // Element expects 0–1 opacity; UI stores 0–100\n .setOpacity(opacity / 100)\n .setStrokeColor(strokeColor)\n .setLineWidth(lineWidth);\n\n addElement?.(rectElement);\n };\n\n useEffect(() => {\n if (selectedElement instanceof RectElement) {\n setCornerRadius(selectedElement.getCornerRadius() ?? DEFAULT_RECT_PROPS.cornerRadius);\n setFillColor(selectedElement.getFill() ?? DEFAULT_RECT_PROPS.fillColor);\n const elementOpacity = selectedElement.getOpacity();\n // Convert 0–1 element opacity into 0–100 UI percentage\n setOpacity(elementOpacity != null ? elementOpacity * 100 : DEFAULT_RECT_PROPS.opacity);\n setStrokeColor(selectedElement.getStrokeColor() ?? DEFAULT_RECT_PROPS.strokeColor);\n setLineWidth(selectedElement.getLineWidth() ?? DEFAULT_RECT_PROPS.lineWidth);\n }\n }, [selectedElement]);\n\n return {\n cornerRadius,\n fillColor,\n opacity,\n strokeColor,\n lineWidth,\n operation: selectedElement instanceof RectElement ? \"Apply Changes\": \"Add Rectangle\",\n setCornerRadius: handleCornerRadiusChange,\n setFillColor: handleFillColorChange,\n setOpacity: handleOpacityChange,\n setStrokeColor: handleStrokeColorChange,\n setLineWidth: handleLineWidthChange,\n handleApplyChanges,\n };\n};\n","import type { PanelProps } from \"../../types\";\nimport { RectPanel } from \"../panel/rect-panel\";\nimport { useRectPanel } from \"../../hooks/use-rect-panel\";\n\nexport function RectPanelContainer(props: PanelProps) {\n const rectPanelProps = useRectPanel({\n selectedElement: props.selectedElement ?? null,\n addElement: props.addElement!,\n updateElement: props.updateElement!,\n });\n return <RectPanel {...rectPanelProps} />;\n}\n","/**\n * CirclePanel Component\n *\n * A panel for creating and editing circle shapes in the studio. Provides controls\n * for adjusting radius, fill color, opacity, stroke color, and line width.\n *\n * @component\n * @param {Object} props\n * @param {number} props.radius - Circle radius in pixels\n * @param {string} props.fillColor - Fill color in hex format\n * @param {string} props.strokeColor - Stroke color in hex format\n * @param {number} props.lineWidth - Stroke width in pixels\n * @param {(radius: number) => void} props.setRadius - Update circle radius\n * @param {(color: string) => void} props.setFillColor - Update fill color\n * @param {(opacity: number) => void} props.setOpacity - Update opacity\n * @param {(color: string) => void} props.setStrokeColor - Update stroke color\n * @param {(width: number) => void} props.setLineWidth - Update line width\n * @param {() => void} props.handleApplyChanges - Apply circle element changes\n *\n * @example\n * ```tsx\n * <CirclePanel\n * radius={50}\n * fillColor=\"#ff0000\"\n * opacity={100}\n * strokeColor=\"#000000\"\n * lineWidth={2}\n * setRadius={setRadius}\n * setFillColor={setFill}\n * setOpacity={setOpacity}\n * setStrokeColor={setStroke}\n * setLineWidth={setWidth}\n * handleApplyChanges={applyChanges}\n * />\n * ```\n */\n\nimport type {\n CirclePanelState,\n CirclePanelActions,\n} from \"../../hooks/use-circle-panel\";\n\nexport type CirclePanelProps = CirclePanelState & CirclePanelActions;\n\nexport function CirclePanel({\n radius,\n fillColor,\n strokeColor,\n lineWidth,\n operation,\n setRadius,\n setFillColor,\n setStrokeColor,\n setLineWidth,\n handleApplyChanges,\n}: CirclePanelProps) {\n return (\n <div className=\"panel-container\">\n <div className=\"panel-title\">Circle</div>\n {/* Radius */}\n <div className=\"panel-section\">\n <label className=\"label-dark\">Radius</label>\n <div className=\"slider-container\">\n <input\n type=\"range\"\n min=\"10\"\n max=\"300\"\n value={radius}\n onChange={(e) => setRadius(Number(e.target.value))}\n className=\"slider-purple\"\n />\n <span className=\"slider-value\">{radius}px</span>\n </div>\n </div>\n\n {/* Fill Color */}\n <div className=\"panel-section\">\n <label className=\"label-dark\">Fill Color</label>\n <div className=\"color-inputs\">\n <input\n type=\"color\"\n value={fillColor}\n onChange={(e) => setFillColor(e.target.value)}\n className=\"color-picker\"\n />\n <input\n type=\"text\"\n value={fillColor}\n onChange={(e) => setFillColor(e.target.value)}\n className=\"color-text\"\n />\n </div>\n </div>\n\n\n {/* Stroke Color */}\n <div className=\"panel-section\">\n <label className=\"label-dark\">Stroke Color</label>\n <div className=\"color-inputs\">\n <input\n type=\"color\"\n value={strokeColor}\n onChange={(e) => setStrokeColor(e.target.value)}\n className=\"color-picker\"\n />\n <input\n type=\"text\"\n value={strokeColor}\n onChange={(e) => setStrokeColor(e.target.value)}\n className=\"color-text\"\n />\n </div>\n </div>\n\n {/* Line Width */}\n <div className=\"panel-section\">\n <label className=\"label-dark\">Line Width</label>\n <div className=\"slider-container\">\n <input\n type=\"range\"\n min=\"0\"\n max=\"20\"\n value={lineWidth}\n onChange={(e) => setLineWidth(Number(e.target.value))}\n className=\"slider-purple\"\n />\n <span className=\"slider-value\">{lineWidth}px</span>\n </div>\n </div>\n\n {/* Operation button (only for creation, not edits) */}\n {operation !== \"Apply Changes\" && (\n <div className=\"flex panel-section\">\n <button onClick={handleApplyChanges} className=\"btn-primary w-full\">\n {operation}\n </button>\n </div>\n )}\n </div>\n );\n}\n","import { useEffect, useState } from \"react\";\nimport { CircleElement, TrackElement } from \"@twick/timeline\";\n\nexport const DEFAULT_CIRCLE_PROPS = {\n radius: 50,\n fillColor: \"#3b82f6\",\n // UI uses 0–100%; element opacity is 0–1\n opacity: 100,\n strokeColor: \"#000000\",\n lineWidth: 0,\n};\n\nexport interface CirclePanelState {\n radius: number;\n fillColor: string;\n opacity: number;\n strokeColor: string;\n lineWidth: number;\n operation: string;\n}\n\nexport interface CirclePanelActions {\n setRadius: (radius: number) => void;\n setFillColor: (color: string) => void;\n setOpacity: (opacity: number) => void;\n setStrokeColor: (color: string) => void;\n setLineWidth: (width: number) => void;\n handleApplyChanges: () => void;\n}\n\nexport const useCirclePanel = ({\n selectedElement,\n addElement,\n updateElement,\n}: {\n selectedElement: TrackElement | null;\n addElement: (element: TrackElement) => void;\n updateElement: (element: TrackElement) => void;\n}): CirclePanelState & CirclePanelActions => {\n const [radius, setRadius] = useState(DEFAULT_CIRCLE_PROPS.radius);\n const [fillColor, setFillColor] = useState(DEFAULT_CIRCLE_PROPS.fillColor);\n // Stored as percentage 0–100 for the UI slider\n const [opacity, setOpacity] = useState(DEFAULT_CIRCLE_PROPS.opacity);\n const [strokeColor, setStrokeColor] = useState(DEFAULT_CIRCLE_PROPS.strokeColor);\n const [lineWidth, setLineWidth] = useState(DEFAULT_CIRCLE_PROPS.lineWidth);\n\n const applyLiveChangesToExistingCircle = (overrides: Partial<CirclePanelState> = {}) => {\n if (!(selectedElement instanceof CircleElement)) {\n return;\n }\n\n const circleElement = selectedElement;\n const nextRadius = overrides.radius ?? radius;\n const nextFillColor = overrides.fillColor ?? fillColor;\n const nextOpacityPercent = overrides.opacity ?? opacity;\n const nextStrokeColor = overrides.strokeColor ?? strokeColor;\n const nextLineWidth = overrides.lineWidth ?? lineWidth;\n\n circleElement.setRadius(nextRadius);\n circleElement.setFill(nextFillColor);\n // Element expects 0–1 opacity\n circleElement.setOpacity(nextOpacityPercent / 100);\n circleElement.setStrokeColor(nextStrokeColor);\n circleElement.setLineWidth(nextLineWidth);\n\n updateElement?.(circleElement);\n };\n\n const handleRadiusChange = (nextRadius: number) => {\n setRadius(nextRadius);\n applyLiveChangesToExistingCircle({ radius: nextRadius });\n };\n\n const handleFillColorChange = (color: string) => {\n setFillColor(color);\n applyLiveChangesToExistingCircle({ fillColor: color });\n };\n\n const handleOpacityChange = (nextOpacity: number) => {\n setOpacity(nextOpacity);\n applyLiveChangesToExistingCircle({ opacity: nextOpacity });\n };\n\n const handleStrokeColorChange = (color: string) => {\n setStrokeColor(color);\n applyLiveChangesToExistingCircle({ strokeColor: color });\n };\n\n const handleLineWidthChange = (width: number) => {\n setLineWidth(width);\n applyLiveChangesToExistingCircle({ lineWidth: width });\n };\n\n const handleApplyChanges = () => {\n // For existing circles, changes are already applied live via the handlers above.\n // The apply button is only meaningful when creating a new circle.\n if (selectedElement instanceof CircleElement) {\n return;\n }\n\n const circleElement = new CircleElement(fillColor, radius)\n // Element expects 0–1 opacity; UI stores 0–100\n .setOpacity(opacity / 100)\n .setStrokeColor(strokeColor)\n .setLineWidth(lineWidth);\n\n addElement?.(circleElement);\n };\n\n useEffect(() => {\n if (selectedElement instanceof CircleElement) {\n setRadius(selectedElement.getRadius() ?? DEFAULT_CIRCLE_PROPS.radius);\n setFillColor(selectedElement.getFill() ?? DEFAULT_CIRCLE_PROPS.fillColor);\n const elementOpacity = selectedElement.getOpacity();\n // Convert 0–1 element opacity into 0–100 UI percentage\n setOpacity(elementOpacity != null ? elementOpacity * 100 : DEFAULT_CIRCLE_PROPS.opacity);\n setStrokeColor(selectedElement.getStrokeColor() ?? DEFAULT_CIRCLE_PROPS.strokeColor);\n setLineWidth(selectedElement.getLineWidth() ?? DEFAULT_CIRCLE_PROPS.lineWidth);\n }\n }, [selectedElement]);\n\n return {\n radius,\n fillColor,\n opacity,\n strokeColor,\n lineWidth,\n operation: selectedElement instanceof CircleElement ? \"Apply Changes\": \"Add Circle\",\n setRadius: handleRadiusChange,\n setFillColor: handleFillColorChange,\n setOpacity: handleOpacityChange,\n setStrokeColor: handleStrokeColorChange,\n setLineWidth: handleLineWidthChange,\n handleApplyChanges,\n };\n};\n","import type { PanelProps } from \"../../types\";\nimport { CirclePanel } from \"../panel/circle-panel\";\nimport { useCirclePanel } from \"../../hooks/use-circle-panel\";\n\nexport function CirclePanelContainer(props: PanelProps) {\n const circlePanelProps = useCirclePanel({\n selectedElement: props.selectedElement ?? null,\n addElement: props.addElement!,\n updateElement: props.updateElement!,\n });\n return <CirclePanel {...circlePanelProps} />;\n}","/**\n * CaptionsPanel Component\n *\n * A presentational panel for managing caption entries in the studio.\n * Renders a list of caption items, each with a text input and two actions:\n * Split and Delete. A single Add button appears below the list.\n *\n * State is controlled by the parent via props; this component is stateless.\n *\n * Entry shape (CaptionEntry):\n * - `s`: start time (seconds)\n * - `e`: end time (seconds)\n * - `t`: caption text\n *\n * Props:\n * - `captions`: CaptionEntry[] — ordered list of captions\n * - `addCaption()`: add a new caption at the end\n * - `splitCaption(index)`: split the caption at `index`\n * - `deleteCaption(index)`: remove the caption at `index`\n * - `updateCaption(index, caption)`: update the caption at `index`\n *\n * @component\n * @example\n * ```tsx\n * <CaptionsPanel\n * captions={captions}\n * addCaption={addCaption}\n * splitCaption={splitCaption}\n * deleteCaption={deleteCaption}\n * updateCaption={updateCaption}\n * />\n * ```\n */\n\nimport { Trash2, Scissors } from \"lucide-react\";\n\ninterface CaptionEntry {\n s: number;\n e: number;\n t: string; \n}\n\nexport function CaptionsPanel({\n captions,\n addCaption,\n splitCaption,\n deleteCaption,\n updateCaption,\n}: {\n captions: CaptionEntry[];\n addCaption: () => void;\n splitCaption: (index: number) => void;\n deleteCaption: (index: number) => void;\n updateCaption: (index: number, caption: CaptionEntry) => void;\n}) {\n\n return (\n <div className=\"panel-container\">\n <h3 className=\"panel-title\">Captions</h3>\n\n {/* Caption Entries */}\n {captions.map((caption, i) => (\n <div\n key={i}\n className=\"panel-section gap-2\"\n >\n {/* Caption Text Input */}\n <div>\n <input\n type=\"text\"\n placeholder=\"Enter caption text\"\n value={caption.t}\n onChange={(e) => updateCaption(i, { ...caption, t: e.target.value })}\n className=\"input-dark\"\n />\n </div>\n\n {/* Action Buttons (bottom-right) */}\n <div className=\"flex-container justify-between\">\n <button\n onClick={() => splitCaption(i)}\n className=\"btn-ghost\"\n title=\"Split caption\"\n >\n <Scissors className=\"icon-sm\" />\n </button>\n <button\n onClick={() => deleteCaption(i)}\n className=\"btn-ghost\"\n title=\"Delete caption\"\n >\n <Trash2 className=\"icon-sm\" color=\"var(--color-red-500)\"/>\n </button>\n </div>\n </div>\n ))}\n\n {/* Common Add Button */}\n <div className=\"panel-section\">\n <button onClick={addCaption} className=\"btn-primary w-full\" title=\"Add caption\">\n Add\n </button>\n </div>\n </div>\n );\n}\n","import { CAPTION_STYLE } from \"@twick/timeline\";\n\nexport const CAPTION_PROPS = {\n [CAPTION_STYLE.WORD_BG_HIGHLIGHT]: {\n font: {\n size: 46,\n weight: 700,\n family: \"Bangers\",\n },\n colors: {\n text: \"#ffffff\",\n highlight: \"#ff4081\",\n bgColor: \"#444444\",\n },\n lineWidth: 0.35,\n stroke: \"#000000\",\n fontWeight: 700,\n shadowOffset: [-3, 3],\n shadowColor: \"#000000\",\n },\n [CAPTION_STYLE.WORD_BY_WORD]: {\n font: {\n size: 46,\n weight: 700,\n family: \"Bangers\",\n },\n colors: {\n text: \"#ffffff\",\n highlight: \"#ff4081\",\n bgColor: \"#444444\",\n }, \n lineWidth: 0.35,\n stroke: \"#000000\",\n shadowOffset: [-2, 2],\n shadowColor: \"#000000\",\n shadowBlur: 5,\n },\n [CAPTION_STYLE.WORD_BY_WORD_WITH_BG]: {\n font: {\n size: 46,\n weight: 700,\n family: \"Bangers\",\n },\n colors: {\n text: \"#ffffff\",\n highlight: \"#ff4081\",\n bgColor: \"#444444\",\n },\n lineWidth: 0.35,\n shadowOffset: [-2, 2],\n shadowColor: \"#000000\",\n shadowBlur: 5,\n }\n };","import { useState, useEffect, useRef } from \"react\";\nimport {\n CAPTION_STYLE,\n CaptionElement,\n Track,\n useTimelineContext,\n} from \"@twick/timeline\";\nimport { CAPTION_PROPS } from \"../helpers/constant\";\n\ninterface CaptionEntry {\n s: number;\n e: number;\n t: string;\n}\n\nexport const useCaptionsPanel = () => {\n const [captions, setCaptions] = useState<CaptionEntry[]>([]);\n const captionsTrack = useRef<Track | null>(null);\n const { editor } = useTimelineContext();\n\n const fetchCaptions = async () => {\n const editorCaptionsTrack = editor.getCaptionsTrack();\n if (editorCaptionsTrack) {\n captionsTrack.current = editorCaptionsTrack;\n setCaptions(\n editorCaptionsTrack.getElements().map((element) => ({\n s: element.getStart(),\n e: element.getEnd(),\n t: (element as CaptionElement).getText(),\n }))\n );\n }\n };\n\n useEffect(() => {\n fetchCaptions();\n }, []);\n\n const checkCaptionsTrack = () => {\n if (!captionsTrack.current) {\n captionsTrack.current = editor.addTrack(\"Caption\", \"caption\");\n const props: Record<string, any> = {\n capStyle: CAPTION_STYLE.WORD_BG_HIGHLIGHT,\n ...CAPTION_PROPS[CAPTION_STYLE.WORD_BG_HIGHLIGHT],\n x: 0,\n y: 200,\n applyToAll: true,\n };\n captionsTrack.current?.setProps(props);\n }\n };\n\n const addCaption = () => {\n const newCaption: CaptionEntry = { s: 0, e: 0, t: \"New Caption\" };\n if (captions.length > 0) {\n newCaption.s = captions[captions.length - 1].e;\n }\n newCaption.e = newCaption.s + 1;\n setCaptions([...captions, newCaption]);\n checkCaptionsTrack();\n const captionElement = new CaptionElement(\n newCaption.t,\n newCaption.s,\n newCaption.e\n );\n editor.addElementToTrack(captionsTrack.current as Track, captionElement);\n };\n\n const splitCaption = async (index: number) => {\n if (captionsTrack.current) {\n const element = captionsTrack.current.getElements()[\n index\n ] as CaptionElement;\n const splitResult = await editor.splitElement(\n element,\n element.getStart() + element.getDuration() / 2\n );\n if (splitResult.success) {\n fetchCaptions();\n }\n }\n };\n\n const deleteCaption = (index: number) => {\n setCaptions(captions.filter((_, i) => i !== index));\n if (captionsTrack.current) {\n editor.removeElement(captionsTrack.current.getElements()[index]);\n }\n };\n\n const updateCaption = (index: number, caption: CaptionEntry) => {\n setCaptions(captions.map((sub, i) => (i === index ? caption : sub)));\n if (captionsTrack.current) {\n const element = captionsTrack.current.getElements()[\n index\n ] as CaptionElement;\n element.setText(caption.t);\n editor.updateElement(element);\n }\n };\n\n return {\n captions,\n addCaption,\n splitCaption,\n deleteCaption,\n updateCaption,\n };\n};\n","import { CaptionsPanel } from \"../panel/captions-panel\";\nimport { useCaptionsPanel } from \"../../hooks/use-captions-panel\";\n\nexport function CaptionsPanelContainer() {\n const captionsPanelProps = useCaptionsPanel();\n return <CaptionsPanel {...captionsPanelProps} />;\n}","import React from \"react\";\nimport { Size, TrackElement } from \"@twick/timeline\";\nimport { AudioPanelContainer } from \"./audio-panel-container\";\nimport { ImagePanelContainer } from \"./image-panel-container\";\nimport { VideoPanelContainer } from \"./video-panel-container\";\nimport { TextPanelContainer } from \"./text-panel-container\";\nimport { RectPanelContainer } from \"./rect-panel-container\";\nimport { CirclePanelContainer } from \"./circle-panel-container\";\nimport { Wand2 } from \"lucide-react\";\nimport { CaptionsPanelContainer } from \"./captions-panel-container\";\n\n/**\n * Props interface for the ElementPanelContainer component.\n * Defines the configuration and callback functions for element management.\n */\ninterface ElementPanelContainerProps {\n selectedTool: string;\n selectedElement: TrackElement | null;\n videoResolution: Size;\n setSelectedTool: (tool: string) => void;\n addElement: (element: TrackElement) => void;\n updateElement: (element: TrackElement) => void;\n}\n\n/**\n * ElementPanelContainer component that renders the appropriate element panel\n * based on the currently selected tool. Provides a unified interface for\n * managing different types of timeline elements including media, text, shapes,\n * and captions. Shows an empty state when no tool is selected.\n *\n * @param props - Component props for element panel configuration\n * @returns JSX element containing the appropriate element panel or empty state\n * \n * @example\n * ```tsx\n * <ElementPanelContainer\n * selectedTool=\"text\"\n * selectedElement={currentElement}\n * videoResolution={{ width: 1920, height: 1080 }}\n * setSelectedTool={setTool}\n * addElement={addToTimeline}\n * updateElement={updateInTimeline}\n * />\n * ```\n */\nconst ElementPanelContainer = ({\n selectedTool,\n videoResolution,\n selectedElement,\n addElement,\n updateElement,\n}: ElementPanelContainerProps): React.ReactElement => {\n const addNewElement = async (element: TrackElement) => {\n await addElement(element);\n };\n\n // Render appropriate library based on selected tool\n const renderLibrary = () => {\n switch (selectedTool) {\n case \"image\":\n return (\n <ImagePanelContainer\n videoResolution={videoResolution}\n selectedElement={selectedElement}\n addElement={addNewElement}\n updateElement={updateElement}\n />\n );\n case \"audio\":\n return (\n <AudioPanelContainer\n videoResolution={videoResolution}\n selectedElement={selectedElement}\n addElement={addNewElement}\n updateElement={updateElement}\n />\n );\n case \"video\":\n return (\n <VideoPanelContainer\n videoResolution={videoResolution}\n selectedElement={selectedElement}\n addElement={addNewElement}\n updateElement={updateElement}\n />\n );\n case \"text\":\n return (\n <TextPanelContainer\n selectedElement={selectedElement}\n addElement={addNewElement}\n updateElement={updateElement}\n />\n );\n case \"rect\":\n return (\n <RectPanelContainer\n videoResolution={videoResolution}\n selectedElement={selectedElement}\n addElement={addNewElement}\n updateElement={updateElement}\n />\n );\n case \"circle\":\n return (\n <CirclePanelContainer\n videoResolution={videoResolution}\n selectedElement={selectedElement}\n addElement={addNewElement}\n updateElement={updateElement}\n />\n );\n case \"caption\":\n return <CaptionsPanelContainer />;\n default:\n return (\n <div className=\"panel-container\">\n <div className=\"empty-state\">\n <div className=\"empty-state-content\">\n <Wand2 className=\"empty-state-icon\" />\n <p className=\"empty-state-text\">Select an element from toolbar</p>\n </div>\n </div>\n </div>\n );\n }\n };\n\n return renderLibrary();\n};\n\nexport default ElementPanelContainer;\n","import type { ReactNode } from \"react\";\n\ninterface PropertyRowProps {\n label: string;\n children: ReactNode;\n /** Optional secondary label/value on the right (e.g. units, current value) */\n secondary?: ReactNode;\n}\n\nexport function PropertyRow({ label, children, secondary }: PropertyRowProps) {\n return (\n <div className=\"property-row\">\n <div className=\"property-row-label\">\n <span className=\"property-label\">{label}</span>\n </div>\n <div className=\"property-row-control\">\n {children}\n </div>\n {secondary && (\n <div className=\"property-row-secondary\">\n {secondary}\n </div>\n )}\n </div>\n );\n}\n\n","import { ChevronDown, ChevronRight } from \"lucide-react\";\n\ninterface AccordionItemProps {\n title: string;\n icon: React.ReactNode;\n children: React.ReactNode;\n isOpen: boolean;\n onToggle: () => void;\n}\n\nexport function AccordionItem({ title, icon, children, isOpen, onToggle }: AccordionItemProps) {\n return (\n <div className=\"accordion-item\">\n <div\n onClick={onToggle}\n className=\"accordion-header\"\n >\n <div className=\"flex-container\">\n <div className=\"accent-purple\">\n {icon}\n </div>\n <span className=\"property-title\">{title}</span>\n </div>\n {isOpen ? (\n <ChevronDown className=\"icon-sm accent-purple\" />\n ) : (\n <ChevronRight className=\"icon-sm accent-purple\" />\n )}\n </div>\n <div\n className={`accordion-content ${isOpen ? 'expanded' : ''}`}\n >\n <div className=\"accordion-panel\">\n {children}\n </div>\n </div>\n </div>\n );\n}\n","import { RectElement, CircleElement, TrackElement } from \"@twick/timeline\";\n// Dimensions in inspector: Rect and Circle only. Image/Video resize via canvas (dimensions deferred).\nimport type { PropertiesPanelProps } from \"../../types\";\nimport { PropertyRow } from \"./property-row\";\nimport { Ruler } from \"lucide-react\";\nimport { AccordionItem } from \"../shared/accordion-item\";\nimport { useState } from \"react\";\n\nexport function ElementProps({ selectedElement, updateElement }: PropertiesPanelProps) {\n const opacity = selectedElement?.getOpacity() || 1;\n const rotation = selectedElement?.getRotation() || 0;\n const position = selectedElement?.getPosition() || { x: 0, y: 0 };\n\n const handleRotationChange = (rotation: number) => {\n if (selectedElement) {\n selectedElement.setRotation(rotation);\n updateElement?.(selectedElement as TrackElement);\n }\n }\n\n const handleOpacityChange = (opacity: number) => {\n if (selectedElement) {\n selectedElement.setOpacity(opacity);\n updateElement?.(selectedElement as TrackElement);\n }\n }\n const handlePositionChange = (props: Record<string, any>) => {\n if (selectedElement) {\n selectedElement.setPosition({ x: props.x ?? 0, y: props.y ?? 0 });\n updateElement?.(selectedElement as TrackElement);\n }\n }\n\n const handleDimensionsChange = (width?: number, height?: number) => {\n if (!selectedElement) return;\n if (selectedElement instanceof RectElement) {\n const size = selectedElement.getSize();\n selectedElement.setSize({ width: width ?? size.width, height: height ?? size.height });\n updateElement?.(selectedElement as TrackElement);\n } else if (selectedElement instanceof CircleElement) {\n const dims = {\n width: selectedElement.getRadius() * 2,\n height: selectedElement.getRadius() * 2,\n };\n const newDiameter =\n width !== undefined && width !== dims.width ? width : (height ?? dims.height);\n selectedElement.setRadius(newDiameter / 2);\n updateElement?.(selectedElement as TrackElement);\n }\n }\n\n const hasShapeDimensions =\n selectedElement instanceof RectElement || selectedElement instanceof CircleElement;\n\n let dimensions: { width: number; height: number } | null = null;\n if (selectedElement instanceof RectElement) {\n dimensions = selectedElement.getSize();\n } else if (selectedElement instanceof CircleElement) {\n const r = selectedElement.getRadius();\n dimensions = { width: r * 2, height: r * 2 };\n }\n\n const [isTransformOpen, setIsTransformOpen] = useState(false);\n\n return (\n <div className=\"panel-container\">\n <div className=\"panel-title\">Properties</div>\n\n <AccordionItem\n title=\"Transform\"\n icon={<Ruler className=\"icon-sm\" />}\n isOpen={isTransformOpen}\n onToggle={() => setIsTransformOpen((open) => !open)}\n >\n <div className=\"properties-group\">\n <div className=\"property-section\">\n <PropertyRow label=\"Position X\">\n <input\n type=\"number\"\n value={position.x ?? 0}\n onChange={(e) =>\n handlePositionChange({ x: Number(e.target.value) })\n }\n className=\"input-dark\"\n />\n </PropertyRow>\n <PropertyRow label=\"Position Y\">\n <input\n type=\"number\"\n value={position.y ?? 0}\n onChange={(e) =>\n handlePositionChange({ y: Number(e.target.value) })\n }\n className=\"input-dark\"\n />\n </PropertyRow>\n </div>\n\n {/* Dimensions - for rect, circle only; image/video resize via canvas */}\n {hasShapeDimensions && dimensions && (\n <div className=\"property-section\">\n <PropertyRow label=\"Width\">\n <input\n type=\"number\"\n min={1}\n value={Math.round(dimensions.width)}\n onChange={(e) =>\n handleDimensionsChange(\n Number(e.target.value),\n dimensions!.height\n )\n }\n className=\"input-dark\"\n />\n </PropertyRow>\n <PropertyRow label=\"Height\">\n <input\n type=\"number\"\n min={1}\n value={Math.round(dimensions.height)}\n onChange={(e) =>\n handleDimensionsChange(\n dimensions!.width,\n Number(e.target.value)\n )\n }\n className=\"input-dark\"\n />\n </PropertyRow>\n </div>\n )}\n\n {/* Opacity */}\n <div className=\"property-section\">\n <PropertyRow\n label=\"Opacity\"\n secondary={\n <span>\n {Math.round((opacity ?? 1) * 100)}\n %\n </span>\n }\n >\n <input\n type=\"range\"\n min=\"0\"\n max=\"100\"\n value={(opacity ?? 1) * 100}\n onChange={(e) =>\n handleOpacityChange(Number(e.target.value) / 100)\n }\n className=\"slider-purple\"\n />\n </PropertyRow>\n </div>\n\n {/* Rotation */}\n <div className=\"property-section\">\n <PropertyRow\n label=\"Rotation\"\n secondary={\n <span>\n {Math.round(rotation ?? 0)}\n °\n </span>\n }\n >\n <input\n type=\"range\"\n min=\"0\"\n max=\"360\"\n value={rotation ?? 0}\n onChange={(e) => handleRotationChange(Number(e.target.value))}\n className=\"slider-purple\"\n />\n </PropertyRow>\n </div>\n </div>\n </AccordionItem>\n </div>\n );\n}\n","import { TEXT_EFFECTS } from \"@twick/video-editor\";\nimport { ElementTextEffect, TextElement } from \"@twick/timeline\";\nimport type { PropertiesPanelProps } from \"../../types\";\nimport { AccordionItem } from \"../shared/accordion-item\";\nimport { PropertyRow } from \"./property-row\";\nimport { SparklesIcon } from \"lucide-react\";\nimport { useState } from \"react\";\n\nexport function TextEffects({\n selectedElement,\n updateElement,\n}: PropertiesPanelProps) {\n if (!(selectedElement instanceof TextElement)) return null;\n\n const currentEffect = selectedElement.getTextEffect();\n\n const handleUpdateEffect = (props: {\n name?: string;\n delay?: number;\n duration?: number;\n bufferTime?: number;\n }) => {\n if (!selectedElement || !(selectedElement instanceof TextElement)) return;\n\n let effect = currentEffect;\n\n // If name is provided and empty, remove effect\n if (props.name === \"\") {\n selectedElement.setTextEffect(undefined);\n updateElement?.(selectedElement);\n return;\n }\n\n // Create new effect if none exists or name is changing\n if (!effect || (props.name && props.name !== effect.getName())) {\n effect = new ElementTextEffect(\n props.name || currentEffect?.getName() || TEXT_EFFECTS[0].name\n );\n // Set default values for new effect\n effect.setDelay(0);\n effect.setDuration(1);\n effect.setBufferTime(0.1);\n }\n\n // Update effect properties\n if (props.delay !== undefined) effect.setDelay(props.delay);\n if (props.duration !== undefined) effect.setDuration(props.duration);\n if (props.bufferTime !== undefined) effect.setBufferTime(props.bufferTime);\n\n // Update element with new/modified effect\n selectedElement.setTextEffect(effect);\n updateElement?.(selectedElement);\n };\n\n const [isEffectsOpen, setIsEffectsOpen] = useState(false);\n\n return (\n <div className=\"panel-container\">\n <div className=\"panel-title\">Text Effects</div>\n <AccordionItem\n title=\"Effects\"\n icon={<SparklesIcon className=\"icon-sm\" />}\n isOpen={isEffectsOpen}\n onToggle={() => setIsEffectsOpen((open) => !open)}\n >\n <div className=\"properties-group\">\n {/* Text Effect Selection */}\n <div className=\"property-section\">\n <PropertyRow label=\"Preset\">\n <select\n value={currentEffect?.getName() || \"\"}\n onChange={(e) => handleUpdateEffect({ name: e.target.value })}\n className=\"select-dark w-full\"\n >\n <option value=\"\">No Effect</option>\n {TEXT_EFFECTS.map((effect) => (\n <option key={effect.name} value={effect.name}>\n {effect.name.charAt(0).toUpperCase() + effect.name.slice(1)}\n </option>\n ))}\n </select>\n </PropertyRow>\n </div>\n\n {/* Text Effect Options */}\n {currentEffect && (\n <>\n {/* Delay */}\n <div className=\"property-section\">\n <PropertyRow label=\"Delay (s)\">\n <input\n type=\"number\"\n min=\"0\"\n max=\"5\"\n step=\"0.1\"\n value={currentEffect.getDelay() ?? 0}\n onChange={(e) =>\n handleUpdateEffect({ delay: Number(e.target.value) })\n }\n className=\"input-dark\"\n />\n </PropertyRow>\n </div>\n\n {/* Duration */}\n <div className=\"property-section\">\n <PropertyRow label=\"Duration (s)\">\n <input\n type=\"number\"\n min=\"0.1\"\n max=\"10\"\n step=\"0.1\"\n value={currentEffect.getDuration() ?? 1}\n onChange={(e) =>\n handleUpdateEffect({ duration: Number(e.target.value) })\n }\n className=\"input-dark\"\n />\n </PropertyRow>\n </div>\n\n {/* Buffer Time */}\n <div className=\"property-section\">\n <PropertyRow label=\"Buffer (s)\">\n <input\n type=\"number\"\n min=\"0.05\"\n max=\"1\"\n step=\"0.05\"\n value={currentEffect.getBufferTime() ?? 0.1}\n onChange={(e) =>\n handleUpdateEffect({\n bufferTime: Number(e.target.value),\n })\n }\n className=\"input-dark\"\n />\n </PropertyRow>\n </div>\n </>\n )}\n </div>\n </AccordionItem>\n </div>\n );\n}\n","import { ANIMATIONS } from \"@twick/video-editor\";\nimport { ElementAnimation, TrackElement } from \"@twick/timeline\";\nimport type { PropertiesPanelProps } from \"../../types\";\n\nexport function Animation({\n selectedElement,\n updateElement,\n}: PropertiesPanelProps) {\n if (!(selectedElement instanceof TrackElement)) return null;\n\n const currentAnimation = selectedElement?.getAnimation();\n\n const handleUpdateAnimation = (props: {\n name?: string;\n interval?: number;\n duration?: number;\n intensity?: number;\n animate?: \"enter\" | \"exit\" | \"both\";\n mode?: \"in\" | \"out\";\n direction?: \"up\" | \"down\" | \"left\" | \"right\" | \"center\";\n }) => {\n if (!selectedElement) return;\n\n let animation = currentAnimation;\n\n // If name is provided and empty, remove animation\n if (props.name === \"\") {\n selectedElement.setAnimation(undefined);\n updateElement?.(selectedElement);\n return;\n }\n\n // Find animation definition\n const animationDef = ANIMATIONS.find(\n (a) => a.name === (props.name || currentAnimation?.getName())\n );\n if (!animationDef) return;\n\n // Create new animation if none exists or name is changing\n if (!animation || (props.name && props.name !== animation.getName())) {\n animation = new ElementAnimation(\n props.name || currentAnimation?.getName() || ANIMATIONS[0].name\n );\n // Set default values for new animation\n animation.setInterval(animationDef.interval || 1);\n animation.setDuration(animationDef.duration || 1);\n animation.setIntensity(animationDef.intensity || 1);\n animation.setAnimate(animationDef.animate || \"enter\");\n if (animationDef.mode) animation.setMode(animationDef.mode);\n if (animationDef.direction)\n animation.setDirection(animationDef.direction);\n }\n\n // Update animation properties with validation\n if (props.interval !== undefined) {\n const [min, max] = animationDef.options?.interval || [0.1, 5];\n animation.setInterval(Math.min(Math.max(props.interval, min), max));\n }\n if (props.duration !== undefined) {\n const [min, max] = animationDef.options?.duration || [0.1, 5];\n animation.setDuration(Math.min(Math.max(props.duration, min), max));\n }\n if (props.intensity !== undefined) {\n const [min, max] = animationDef.options?.intensity || [0.1, 2];\n animation.setIntensity(Math.min(Math.max(props.intensity, min), max));\n }\n if (\n props.animate &&\n animationDef.options?.animate?.includes(props.animate)\n ) {\n animation.setAnimate(props.animate);\n }\n if (props.mode && animationDef.options?.mode?.includes(props.mode)) {\n animation.setMode(props.mode);\n }\n if (\n props.direction &&\n animationDef.options?.direction?.includes(props.direction)\n ) {\n animation.setDirection(props.direction);\n }\n\n // Update element with new/modified animation\n selectedElement.setAnimation(animation);\n updateElement?.(selectedElement);\n };\n\n return (\n <div className=\"panel-container\">\n <div className=\"panel-title\">Animations</div>\n {/* Animation Selection */}\n <div className=\"panel-section\">\n <label className=\"label-dark\">Type</label>\n <select\n value={currentAnimation?.getName() || \"\"}\n onChange={(e) => handleUpdateAnimation({ name: e.target.value })}\n className=\"select-dark w-full\"\n >\n <option value=\"\">No Animation</option>\n {ANIMATIONS.map((animation) => (\n <option key={animation.name} value={animation.name}>\n {animation.name.charAt(0).toUpperCase() + animation.name.slice(1)}\n </option>\n ))}\n </select>\n </div>\n\n {/* Animation Options */}\n {currentAnimation && (\n <>\n {/* Get current animation definition */}\n {(() => {\n const animationDef = ANIMATIONS.find(\n (a) => a.name === currentAnimation.getName()\n );\n if (!animationDef || !animationDef.options) return null;\n\n return (\n <>\n {/* Animate */}\n {animationDef.options?.animate && (\n <div className=\"panel-section\">\n <label className=\"label-dark\">When to Animate</label>\n <select\n value={currentAnimation.getAnimate()}\n onChange={(e) =>\n handleUpdateAnimation({\n animate: e.target.value as\n | \"enter\"\n | \"exit\"\n | \"both\",\n })\n }\n className=\"select-dark w-full\"\n >\n {animationDef.options?.animate.map((option) => (\n <option key={option} value={option}>\n {option.charAt(0).toUpperCase() + option.slice(1)}\n </option>\n ))}\n </select>\n </div>\n )}\n\n {/* Direction */}\n {animationDef.options?.direction && (\n <div className=\"panel-section\">\n <label className=\"label-dark\">Direction</label>\n <select\n value={currentAnimation.getDirection()}\n onChange={(e) =>\n handleUpdateAnimation({\n direction: e.target.value as\n | \"up\"\n | \"down\"\n | \"left\"\n | \"right\"\n | \"center\",\n })\n }\n className=\"select-dark w-full\"\n >\n {animationDef.options?.direction.map((option) => (\n <option key={option} value={option}>\n {option.charAt(0).toUpperCase() + option.slice(1)}\n </option>\n ))}\n </select>\n </div>\n )}\n\n {/* Mode */}\n {animationDef.options?.mode && (\n <div className=\"panel-section\">\n <label className=\"label-dark\">Mode</label>\n <select\n value={currentAnimation.getMode()}\n onChange={(e) =>\n handleUpdateAnimation({\n mode: e.target.value as \"in\" | \"out\",\n })\n }\n className=\"select-dark w-full\"\n >\n {animationDef.options?.mode.map((option) => (\n <option key={option} value={option}>\n {option.charAt(0).toUpperCase() + option.slice(1)}\n </option>\n ))}\n </select>\n </div>\n )}\n\n {/* Duration */}\n {animationDef.options?.duration && (\n <div className=\"panel-section\">\n <label className=\"label-dark\">Duration (seconds)</label>\n <div className=\"slider-container\">\n <input\n type=\"range\"\n min={animationDef.options?.duration[0]}\n max={animationDef.options?.duration[1]}\n step=\"0.1\"\n value={currentAnimation.getDuration()}\n onChange={(e) =>\n handleUpdateAnimation({\n duration: Number(e.target.value),\n })\n }\n className=\"slider-purple\"\n />\n <span className=\"slider-value\">{currentAnimation.getDuration()}</span>\n </div>\n </div>\n )}\n\n {/* Interval */}\n {animationDef.options?.interval && (\n <div className=\"panel-section\">\n <label className=\"label-dark\">Interval (seconds)</label>\n <div className=\"slider-container\">\n <input\n type=\"range\"\n min={animationDef.options?.interval[0]}\n max={animationDef.options?.interval[1]}\n step=\"0.1\"\n value={currentAnimation.getInterval()}\n onChange={(e) =>\n handleUpdateAnimation({\n interval: Number(e.target.value),\n })\n }\n className=\"slider-purple\"\n />\n <span className=\"slider-value\">{currentAnimation.getInterval()}</span>\n </div>\n </div>\n )}\n\n {/* Intensity */}\n {animationDef.options?.intensity && (\n <div className=\"panel-section\">\n <label className=\"label-dark\">Intensity</label>\n <div className=\"slider-container\">\n <input\n type=\"range\"\n min={animationDef.options?.intensity[0]}\n max={animationDef.options?.intensity[1]}\n step=\"0.1\"\n value={currentAnimation.getIntensity()}\n onChange={(e) =>\n handleUpdateAnimation({\n intensity: Number(e.target.value),\n })\n }\n className=\"slider-purple\"\n />\n <span className=\"slider-value\">{currentAnimation.getIntensity()}</span>\n </div>\n </div>\n )}\n </>\n );\n })()}\n </>\n )}\n </div>\n );\n}\n","/**\n * Volume conversion between linear (0-1) and dB scale.\n * Used for PlaybackPropsPanel to match professional audio tools (e.g. -60 dB to +6 dB).\n *\n * Formula: dB = 20 * log10(linear)\n * - 0 dB = 1.0 linear (full volume)\n * - -60 dB ≈ 0.001 linear (effectively mute)\n * - +6 dB ≈ 2.0 linear (amplification)\n */\n\nconst MIN_DB = -60;\nconst MAX_DB = 6;\n\n/**\n * Convert linear volume (0 to ~2) to dB.\n * Returns MIN_DB for linear <= 0 to avoid -Infinity.\n */\nexport function linearToDb(linear: number): number {\n if (linear <= 0) return MIN_DB;\n const db = 20 * Math.log10(linear);\n return Math.max(MIN_DB, Math.min(MAX_DB, db));\n}\n\n/**\n * Convert dB to linear volume.\n * Returns 0 for dB <= MIN_DB (mute).\n */\nexport function dbToLinear(db: number): number {\n if (db <= MIN_DB) return 0;\n const linear = Math.pow(10, db / 20);\n return Math.min(linear, Math.pow(10, MAX_DB / 20));\n}\n\nexport { MIN_DB, MAX_DB };\n","import { linearToDb, dbToLinear, MIN_DB, MAX_DB } from \"../../helpers/volume-db\";\nimport type { PropertiesPanelProps } from \"../../types\";\nimport { AccordionItem } from \"../shared/accordion-item\";\nimport { PropertyRow } from \"./property-row\";\nimport { Music2 } from \"lucide-react\";\nimport { useState } from \"react\";\n\nconst PLAYBACK_RATE_MIN = 0.25;\nconst PLAYBACK_RATE_MAX = 2;\nconst PLAYBACK_RATE_STEP = 0.25;\n\nexport function PlaybackPropsPanel({\n selectedElement,\n updateElement,\n}: PropertiesPanelProps) {\n const elementProps = selectedElement?.getProps() || {};\n const volumeLinear = elementProps.volume ?? 1;\n const volumeDb = linearToDb(volumeLinear);\n const playbackRate = elementProps.playbackRate ?? 1;\n\n const handleUpdateElement = (props: Record<string, any>) => {\n if (selectedElement) {\n updateElement?.(selectedElement?.setProps({ ...elementProps, ...props }));\n }\n };\n\n const handleVolumeDbChange = (db: number) => {\n handleUpdateElement({ volume: dbToLinear(db) });\n };\n\n const handlePlaybackRateChange = (rate: number) => {\n handleUpdateElement({ playbackRate: rate });\n };\n\n const [isPlaybackOpen, setIsPlaybackOpen] = useState(false);\n\n return (\n <div className=\"panel-container\">\n <div className=\"panel-title\">Playback</div>\n <AccordionItem\n title=\"Playback\"\n icon={<Music2 className=\"icon-sm\" />}\n isOpen={isPlaybackOpen}\n onToggle={() => setIsPlaybackOpen((open) => !open)}\n >\n <div className=\"properties-group\">\n {/* Playback rate */}\n <div className=\"property-section\">\n <PropertyRow\n label=\"Playback rate\"\n secondary={<span>{playbackRate}×</span>}\n >\n <input\n type=\"range\"\n min={PLAYBACK_RATE_MIN}\n max={PLAYBACK_RATE_MAX}\n step={PLAYBACK_RATE_STEP}\n value={playbackRate}\n onChange={(e) =>\n handlePlaybackRateChange(Number(e.target.value))\n }\n className=\"slider-purple\"\n />\n </PropertyRow>\n </div>\n\n {/* Volume (dB) */}\n <div className=\"property-section\">\n <PropertyRow\n label=\"Volume\"\n secondary={\n <span>\n {volumeDb <= MIN_DB ? \"−∞\" : `${Math.round(volumeDb)} dB`}\n </span>\n }\n >\n <input\n type=\"range\"\n min={MIN_DB}\n max={MAX_DB}\n step={1}\n value={volumeDb}\n onChange={(e) =>\n handleVolumeDbChange(Number(e.target.value))\n }\n className=\"slider-purple\"\n />\n </PropertyRow>\n </div>\n </div>\n </AccordionItem>\n </div>\n );\n}\n","const imageDimensionsCache = {};\nconst videoMetaCache = {};\nconst audioDurationCache = {};\n\nconst getAudioDuration = (audioSrc) => {\n if (audioDurationCache[audioSrc]) {\n return Promise.resolve(audioDurationCache[audioSrc]);\n }\n return new Promise((resolve, reject) => {\n const audio = document.createElement(\"audio\");\n audio.preload = \"metadata\";\n const isSafeUrl = /^(https?:|blob:|data:audio\\/)/i.test(audioSrc);\n if (!isSafeUrl) {\n throw new Error(\"Unsafe audio source URL\");\n }\n audio.src = audioSrc;\n audio.onloadedmetadata = () => {\n const duration = audio.duration;\n audioDurationCache[audioSrc] = duration;\n resolve(duration);\n };\n audio.onerror = () => {\n reject(new Error(\"Failed to load audio metadata\"));\n };\n });\n};\n\nconst concurrencyLimit = 5;\nlet activeCount = 0;\nconst queue = [];\nfunction runNext() {\n if (queue.length === 0 || activeCount >= concurrencyLimit) return;\n const next = queue.shift();\n if (next) {\n activeCount++;\n next();\n }\n}\nfunction limit(fn) {\n return new Promise((resolve, reject) => {\n const task = () => {\n fn().then(resolve).catch(reject).finally(() => {\n activeCount--;\n runNext();\n });\n };\n if (activeCount < concurrencyLimit) {\n activeCount++;\n task();\n } else {\n queue.push(task);\n }\n });\n}\n\nconst loadImageDimensions = (url) => {\n return new Promise((resolve, reject) => {\n if (typeof document === \"undefined\") {\n reject(new Error(\"getImageDimensions() is only available in the browser.\"));\n return;\n }\n const img = new Image();\n img.onload = () => {\n resolve({ width: img.naturalWidth, height: img.naturalHeight });\n };\n img.onerror = reject;\n img.src = url;\n });\n};\nconst getImageDimensions = (url) => {\n if (imageDimensionsCache[url]) {\n return Promise.resolve(imageDimensionsCache[url]);\n }\n return limit(() => loadImageDimensions(url)).then((dimensions) => {\n imageDimensionsCache[url] = dimensions;\n return dimensions;\n });\n};\n\nconst getVideoMeta = (videoSrc) => {\n if (videoMetaCache[videoSrc]) {\n return Promise.resolve(videoMetaCache[videoSrc]);\n }\n return new Promise((resolve, reject) => {\n const isSafeUrl = /^(https?:|blob:|data:video\\/)/i.test(videoSrc);\n if (!isSafeUrl) {\n reject(new Error(\"Unsafe video source URL\"));\n return;\n }\n const tryLoadVideo = (useCors) => {\n const video = document.createElement(\"video\");\n video.preload = \"metadata\";\n video.crossOrigin = useCors ? \"anonymous\" : null;\n video.src = videoSrc;\n video.onloadedmetadata = () => {\n const meta = {\n width: video.videoWidth,\n height: video.videoHeight,\n duration: video.duration\n };\n videoMetaCache[videoSrc] = meta;\n resolve(meta);\n };\n video.onerror = () => {\n if (useCors) {\n video.src = \"\";\n tryLoadVideo(false);\n } else {\n reject(new Error(\"Failed to load video metadata. This may be due to CORS restrictions or an invalid video URL.\"));\n }\n };\n };\n tryLoadVideo(true);\n });\n};\n\nconst getThumbnail = async (videoUrl, seekTime = 0.1, playbackRate = 1) => {\n return new Promise((resolve, reject) => {\n const tryLoadThumbnail = (useCors) => {\n const video = document.createElement(\"video\");\n video.crossOrigin = useCors ? \"anonymous\" : null;\n video.muted = true;\n video.playsInline = true;\n video.autoplay = false;\n video.preload = \"auto\";\n video.playbackRate = playbackRate;\n video.style.position = \"absolute\";\n video.style.left = \"-9999px\";\n video.style.top = \"-9999px\";\n video.style.width = \"1px\";\n video.style.height = \"1px\";\n video.style.opacity = \"0\";\n video.style.pointerEvents = \"none\";\n video.style.zIndex = \"-1\";\n let timeoutId;\n const cleanup = () => {\n if (video.parentNode) video.remove();\n if (timeoutId) clearTimeout(timeoutId);\n };\n const handleError = () => {\n cleanup();\n if (useCors) {\n tryLoadThumbnail(false);\n } else {\n reject(new Error(`Failed to load video: ${video.error?.message || \"Unknown error. This may be due to CORS restrictions or an invalid video URL.\"}`));\n }\n };\n const handleSeeked = () => {\n try {\n video.pause();\n const canvas = document.createElement(\"canvas\");\n const width = video.videoWidth || 640;\n const height = video.videoHeight || 360;\n canvas.width = width;\n canvas.height = height;\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) {\n cleanup();\n reject(new Error(\"Failed to get canvas context\"));\n return;\n }\n ctx.drawImage(video, 0, 0, width, height);\n try {\n const dataUrl = canvas.toDataURL(\"image/jpeg\", 0.8);\n cleanup();\n resolve(dataUrl);\n } catch {\n canvas.toBlob((blob) => {\n if (!blob) {\n cleanup();\n reject(new Error(\"Failed to create Blob\"));\n return;\n }\n const blobUrl = URL.createObjectURL(blob);\n cleanup();\n resolve(blobUrl);\n }, \"image/jpeg\", 0.8);\n }\n } catch (err) {\n cleanup();\n reject(new Error(`Error creating thumbnail: ${err}`));\n }\n };\n video.addEventListener(\"error\", handleError, { once: true });\n video.addEventListener(\"seeked\", handleSeeked, { once: true });\n video.addEventListener(\"loadedmetadata\", () => {\n const playPromise = video.play();\n if (playPromise !== void 0) {\n playPromise.then(() => {\n video.currentTime = seekTime || 0.1;\n }).catch(() => {\n video.currentTime = seekTime || 0.1;\n });\n } else {\n video.currentTime = seekTime || 0.1;\n }\n }, { once: true });\n timeoutId = window.setTimeout(() => {\n cleanup();\n reject(new Error(\"Video loading timed out\"));\n }, 15e3);\n video.src = videoUrl;\n document.body.appendChild(video);\n };\n tryLoadThumbnail(true);\n });\n};\n\nclass LRUCache {\n constructor(maxSize = 100) {\n if (maxSize <= 0) {\n throw new Error(\"maxSize must be greater than 0\");\n }\n this.maxSize = maxSize;\n this.cache = /* @__PURE__ */ new Map();\n }\n /**\n * Get a value from the cache.\n * Moves the item to the end (most recently used).\n */\n get(key) {\n const value = this.cache.get(key);\n if (value === void 0) {\n return void 0;\n }\n this.cache.delete(key);\n this.cache.set(key, value);\n return value;\n }\n /**\n * Set a value in the cache.\n * If cache is full, removes the least recently used item.\n */\n set(key, value) {\n if (this.cache.has(key)) {\n this.cache.delete(key);\n } else if (this.cache.size >= this.maxSize) {\n const firstKey = this.cache.keys().next().value;\n if (firstKey !== void 0) {\n this.cache.delete(firstKey);\n }\n }\n this.cache.set(key, value);\n }\n /**\n * Check if a key exists in the cache.\n */\n has(key) {\n return this.cache.has(key);\n }\n /**\n * Delete a key from the cache.\n */\n delete(key) {\n return this.cache.delete(key);\n }\n /**\n * Clear all entries from the cache.\n */\n clear() {\n this.cache.clear();\n }\n /**\n * Get the current size of the cache.\n */\n get size() {\n return this.cache.size;\n }\n}\n\nclass VideoFrameExtractor {\n constructor(options = {}) {\n this.frameCache = new LRUCache(\n options.maxCacheSize ?? 50\n );\n this.videoElements = /* @__PURE__ */ new Map();\n this.maxVideoElements = options.maxVideoElements ?? 5;\n this.loadTimeout = options.loadTimeout ?? 15e3;\n this.jpegQuality = options.jpegQuality ?? 0.8;\n this.playbackRate = options.playbackRate ?? 1;\n }\n /**\n * Get a frame thumbnail from a video at a specific time.\n * Uses caching and reuses video elements for optimal performance.\n * Uses 0.1s instead of 0 when seekTime is 0, since frames at t=0 are often blank.\n *\n * @param videoUrl - The URL of the video\n * @param seekTime - The time in seconds to extract the frame (0 is treated as 0.1)\n * @returns Promise resolving to a thumbnail image URL (data URL or blob URL)\n */\n async getFrame(videoUrl, seekTime = 0.1) {\n const effectiveSeekTime = seekTime === 0 ? 0.1 : seekTime;\n const cacheKey = this.getCacheKey(videoUrl, effectiveSeekTime);\n const cached = this.frameCache.get(cacheKey);\n if (cached) {\n return cached;\n }\n const videoState = await this.getVideoElement(videoUrl);\n const thumbnail = await this.extractFrame(videoState.video, effectiveSeekTime);\n this.frameCache.set(cacheKey, thumbnail);\n return thumbnail;\n }\n /**\n * Get or create a video element for the given URL.\n * Reuses existing elements and manages cleanup.\n */\n async getVideoElement(videoUrl) {\n let videoState = this.videoElements.get(videoUrl);\n if (videoState && videoState.isReady) {\n videoState.lastUsed = Date.now();\n return videoState;\n }\n if (videoState && videoState.isLoading && videoState.loadPromise) {\n await videoState.loadPromise;\n if (videoState.isReady) {\n videoState.lastUsed = Date.now();\n return videoState;\n }\n }\n if (this.videoElements.size >= this.maxVideoElements) {\n this.cleanupOldVideoElements();\n }\n videoState = await this.createVideoElement(videoUrl);\n this.videoElements.set(videoUrl, videoState);\n videoState.lastUsed = Date.now();\n return videoState;\n }\n /**\n * Create and initialize a new video element.\n */\n async createVideoElement(videoUrl) {\n const video = document.createElement(\"video\");\n video.crossOrigin = \"anonymous\";\n video.muted = true;\n video.playsInline = true;\n video.autoplay = false;\n video.preload = \"auto\";\n video.playbackRate = this.playbackRate;\n video.style.position = \"absolute\";\n video.style.left = \"-9999px\";\n video.style.top = \"-9999px\";\n video.style.width = \"1px\";\n video.style.height = \"1px\";\n video.style.opacity = \"0\";\n video.style.pointerEvents = \"none\";\n video.style.zIndex = \"-1\";\n const state = {\n video,\n isReady: false,\n isLoading: true,\n loadPromise: null,\n lastUsed: Date.now()\n };\n state.loadPromise = new Promise((resolve, reject) => {\n let timeoutId;\n const cleanup = () => {\n if (timeoutId) clearTimeout(timeoutId);\n };\n const handleError = () => {\n cleanup();\n state.isLoading = false;\n reject(new Error(`Failed to load video: ${video.error?.message || \"Unknown error\"}`));\n };\n const handleLoadedMetadata = () => {\n cleanup();\n state.isReady = true;\n state.isLoading = false;\n resolve();\n };\n video.addEventListener(\"error\", handleError, { once: true });\n video.addEventListener(\"loadedmetadata\", handleLoadedMetadata, { once: true });\n timeoutId = window.setTimeout(() => {\n cleanup();\n state.isLoading = false;\n reject(new Error(\"Video loading timed out\"));\n }, this.loadTimeout);\n video.src = videoUrl;\n document.body.appendChild(video);\n });\n try {\n await state.loadPromise;\n } catch (error) {\n if (video.parentNode) {\n video.remove();\n }\n throw error;\n }\n return state;\n }\n /**\n * Extract a frame from a video at the specified time.\n */\n async extractFrame(video, seekTime) {\n return new Promise((resolve, reject) => {\n video.pause();\n const timeThreshold = 0.1;\n if (Math.abs(video.currentTime - seekTime) < timeThreshold) {\n try {\n const canvas = document.createElement(\"canvas\");\n const width = video.videoWidth || 640;\n const height = video.videoHeight || 360;\n canvas.width = width;\n canvas.height = height;\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) {\n reject(new Error(\"Failed to get canvas context\"));\n return;\n }\n ctx.drawImage(video, 0, 0, width, height);\n try {\n const dataUrl = canvas.toDataURL(\"image/jpeg\", this.jpegQuality);\n resolve(dataUrl);\n } catch {\n canvas.toBlob(\n (blob) => {\n if (!blob) {\n reject(new Error(\"Failed to create Blob\"));\n return;\n }\n const blobUrl = URL.createObjectURL(blob);\n resolve(blobUrl);\n },\n \"image/jpeg\",\n this.jpegQuality\n );\n }\n return;\n } catch (err) {\n reject(new Error(`Error creating thumbnail: ${err}`));\n return;\n }\n }\n const handleSeeked = () => {\n try {\n const canvas = document.createElement(\"canvas\");\n const width = video.videoWidth || 640;\n const height = video.videoHeight || 360;\n canvas.width = width;\n canvas.height = height;\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) {\n reject(new Error(\"Failed to get canvas context\"));\n return;\n }\n ctx.drawImage(video, 0, 0, width, height);\n try {\n const dataUrl = canvas.toDataURL(\"image/jpeg\", this.jpegQuality);\n resolve(dataUrl);\n } catch {\n canvas.toBlob(\n (blob) => {\n if (!blob) {\n reject(new Error(\"Failed to create Blob\"));\n return;\n }\n const blobUrl = URL.createObjectURL(blob);\n resolve(blobUrl);\n },\n \"image/jpeg\",\n this.jpegQuality\n );\n }\n } catch (err) {\n reject(new Error(`Error creating thumbnail: ${err}`));\n }\n };\n video.addEventListener(\"seeked\", handleSeeked, { once: true });\n const playPromise = video.play();\n if (playPromise !== void 0) {\n playPromise.then(() => {\n video.currentTime = seekTime;\n }).catch(() => {\n video.currentTime = seekTime;\n });\n } else {\n video.currentTime = seekTime;\n }\n });\n }\n /**\n * Generate cache key for a video URL and seek time.\n */\n getCacheKey(videoUrl, seekTime) {\n const roundedTime = Math.round(seekTime * 100) / 100;\n return `${videoUrl}:${roundedTime}`;\n }\n /**\n * Cleanup least recently used video elements.\n */\n cleanupOldVideoElements() {\n if (this.videoElements.size < this.maxVideoElements) {\n return;\n }\n const entries = Array.from(this.videoElements.entries());\n entries.sort((a, b) => a[1].lastUsed - b[1].lastUsed);\n const toRemove = entries.slice(0, entries.length - this.maxVideoElements + 1);\n for (const [url, state] of toRemove) {\n if (state.video.parentNode) {\n state.video.remove();\n }\n this.videoElements.delete(url);\n }\n }\n /**\n * Clear the frame cache.\n */\n clearCache() {\n this.frameCache.clear();\n }\n /**\n * Remove a specific video element and clear its cached frames.\n */\n removeVideo(videoUrl) {\n const state = this.videoElements.get(videoUrl);\n if (state) {\n if (state.video.parentNode) {\n state.video.remove();\n }\n this.videoElements.delete(videoUrl);\n }\n this.frameCache.clear();\n }\n /**\n * Dispose of all video elements and clear caches.\n * Removes all video elements from the DOM and clears both the frame cache\n * and video element cache. Call this when the extractor is no longer needed\n * to prevent memory leaks.\n */\n dispose() {\n for (const state of this.videoElements.values()) {\n if (state.video.parentNode) {\n state.video.remove();\n }\n }\n this.videoElements.clear();\n this.frameCache.clear();\n }\n}\nlet defaultExtractor = null;\nfunction getDefaultVideoFrameExtractor(options) {\n if (!defaultExtractor) {\n defaultExtractor = new VideoFrameExtractor(options);\n }\n return defaultExtractor;\n}\nasync function getThumbnailCached(videoUrl, seekTime = 0.1, playbackRate) {\n const extractor = getDefaultVideoFrameExtractor(\n playbackRate !== void 0 ? { playbackRate } : void 0\n );\n return extractor.getFrame(videoUrl, seekTime);\n}\n\nconst extractAudio = async ({\n src,\n playbackRate = 1,\n start = 0,\n end\n}) => {\n if (!src) throw new Error(\"src is required\");\n if (playbackRate <= 0) throw new Error(\"playbackRate must be > 0\");\n const isSafeUrl = /^(https?:|blob:|data:)/i.test(src);\n if (!isSafeUrl) throw new Error(\"Unsafe media source URL\");\n const audioBuffer = await fetchAndDecodeAudio(src);\n if (audioBuffer.duration === 0 || audioBuffer.length === 0) {\n throw new Error(\"No audio track found in the media source\");\n }\n if (isAudioSilent(audioBuffer)) {\n throw new Error(\"Audio track is silent (no audio content detected)\");\n }\n const clampedStart = Math.max(0, start || 0);\n const fullDuration = audioBuffer.duration;\n const clampedEnd = Math.min(\n typeof end === \"number\" ? end : fullDuration,\n fullDuration\n );\n if (clampedEnd <= clampedStart)\n throw new Error(\"Invalid range: end must be greater than start\");\n const renderedBuffer = await renderAudioSegment(\n audioBuffer,\n clampedStart,\n clampedEnd,\n playbackRate\n );\n const mp3Blob = await audioBufferToMp3(renderedBuffer);\n return URL.createObjectURL(mp3Blob);\n};\nconst hasAudio = async (src) => {\n if (!src) return false;\n const isSafeUrl = /^(https?:|blob:|data:)/i.test(src);\n if (!isSafeUrl) return false;\n try {\n const audioBuffer = await fetchAndDecodeAudio(src);\n if (audioBuffer.duration === 0 || audioBuffer.length === 0) {\n return false;\n }\n if (isAudioSilent(audioBuffer)) {\n return false;\n }\n return true;\n } catch (error) {\n return false;\n }\n};\nconst stitchAudio = async (segments, totalDuration) => {\n if (!segments || segments.length === 0) {\n throw new Error(\"At least one audio segment is required\");\n }\n const duration = totalDuration || Math.max(...segments.map((s) => s.e));\n const renderedBuffer = await createAudioTimeline(segments, duration);\n const mp3Blob = await audioBufferToMp3(renderedBuffer);\n return URL.createObjectURL(mp3Blob);\n};\nconst fetchAndDecodeAudio = async (src) => {\n const response = await fetch(src);\n if (!response.ok) throw new Error(`Failed to fetch source: ${response.status}`);\n const arrayBuffer = await response.arrayBuffer();\n return decodeAudioData(arrayBuffer);\n};\nconst decodeAudioData = async (arrayBuffer) => {\n const AudioContextCtor = window.AudioContext || window.webkitAudioContext;\n if (!AudioContextCtor) throw new Error(\"Web Audio API not supported\");\n const audioContext = new AudioContextCtor();\n try {\n return await new Promise((resolve, reject) => {\n audioContext.decodeAudioData(\n arrayBuffer.slice(0),\n (buf) => resolve(buf),\n (err) => reject(err || new Error(\"Failed to decode audio: no audio track found or unsupported format\"))\n );\n });\n } finally {\n audioContext.close();\n }\n};\nconst isAudioSilent = (buffer, threshold = 1e-3) => {\n for (let channel = 0; channel < buffer.numberOfChannels; channel++) {\n const channelData = buffer.getChannelData(channel);\n for (let i = 0; i < channelData.length; i += 100) {\n if (Math.abs(channelData[i]) > threshold) {\n return false;\n }\n }\n }\n return true;\n};\nconst renderAudioSegment = async (audioBuffer, start, end, playbackRate) => {\n const OfflineAudioContextCtor = window.OfflineAudioContext || window.webkitOfflineAudioContext;\n if (!OfflineAudioContextCtor) throw new Error(\"OfflineAudioContext not supported\");\n const sampleRate = audioBuffer.sampleRate;\n const numChannels = audioBuffer.numberOfChannels;\n const sourceDuration = end - start;\n const renderedFrames = Math.max(\n 1,\n Math.ceil(sourceDuration / playbackRate * sampleRate)\n );\n const offline = new OfflineAudioContextCtor(numChannels, renderedFrames, sampleRate);\n const sourceNode = offline.createBufferSource();\n sourceNode.buffer = audioBuffer;\n sourceNode.playbackRate.value = playbackRate;\n sourceNode.connect(offline.destination);\n sourceNode.start(0, start, sourceDuration);\n return await offline.startRendering();\n};\nconst createAudioTimeline = async (segments, duration) => {\n const OfflineAudioContextCtor = window.OfflineAudioContext || window.webkitOfflineAudioContext;\n if (!OfflineAudioContextCtor) throw new Error(\"OfflineAudioContext not supported\");\n const sampleRate = 44100;\n const totalFrames = Math.ceil(duration * sampleRate);\n const offline = new OfflineAudioContextCtor(2, totalFrames, sampleRate);\n for (const segment of segments) {\n if (segment.s >= segment.e) continue;\n const volume = segment.volume ?? 1;\n if (volume <= 0) continue;\n try {\n const audioBuffer = await fetchAndDecodeAudio(segment.src);\n const segmentDuration = segment.e - segment.s;\n const sourceDuration = Math.min(segmentDuration, audioBuffer.duration);\n const source = offline.createBufferSource();\n source.buffer = audioBuffer;\n if (volume !== 1) {\n const gainNode = offline.createGain();\n gainNode.gain.value = volume;\n source.connect(gainNode);\n gainNode.connect(offline.destination);\n } else {\n source.connect(offline.destination);\n }\n source.start(segment.s, 0, sourceDuration);\n } catch {\n }\n }\n return await offline.startRendering();\n};\nconst audioBufferToMp3 = async (buffer) => {\n try {\n const wavArrayBuffer = audioBufferToWavArrayBuffer(buffer);\n const pcmBuffer = await decodeAudioData(wavArrayBuffer);\n return await encodePcmToMp3(pcmBuffer);\n } catch (error) {\n return audioBufferToWavBlob(buffer);\n }\n};\nconst audioBufferToWavArrayBuffer = (buffer) => {\n const numChannels = buffer.numberOfChannels;\n const sampleRate = buffer.sampleRate;\n const numFrames = buffer.length;\n const interleaved = interleave(buffer, numChannels, numFrames);\n const bytesPerSample = 2;\n const blockAlign = numChannels * bytesPerSample;\n const byteRate = sampleRate * blockAlign;\n const dataSize = interleaved.length * bytesPerSample;\n const bufferSize = 44 + dataSize;\n const arrayBuffer = new ArrayBuffer(bufferSize);\n const view = new DataView(arrayBuffer);\n writeString(view, 0, \"RIFF\");\n view.setUint32(4, 36 + dataSize, true);\n writeString(view, 8, \"WAVE\");\n writeString(view, 12, \"fmt \");\n view.setUint32(16, 16, true);\n view.setUint16(20, 1, true);\n view.setUint16(22, numChannels, true);\n view.setUint32(24, sampleRate, true);\n view.setUint32(28, byteRate, true);\n view.setUint16(32, blockAlign, true);\n view.setUint16(34, 16, true);\n writeString(view, 36, \"data\");\n view.setUint32(40, dataSize, true);\n floatTo16BitPCM(view, 44, interleaved);\n return arrayBuffer;\n};\nconst encodePcmToMp3 = async (buffer) => {\n const lamejs = await import('./index-CXhwwSX-.mjs').then(n => n.i);\n const channels = buffer.numberOfChannels >= 2 ? 2 : 1;\n const targetSampleRate = 22050;\n const downsampledBuffer = downsampleAudioBuffer(buffer, targetSampleRate);\n const kbps = 48;\n const mp3encoder = new lamejs.default.Mp3Encoder(channels, targetSampleRate, kbps);\n const samplesPerFrame = 1152;\n const leftFloat = downsampledBuffer.getChannelData(0);\n const left = floatTo16(leftFloat);\n let right;\n if (channels === 2) {\n const rightFloat = downsampledBuffer.getChannelData(1);\n right = floatTo16(rightFloat);\n }\n const mp3Chunks = [];\n for (let i = 0; i < left.length; i += samplesPerFrame) {\n const leftChunk = left.subarray(i, Math.min(i + samplesPerFrame, left.length));\n let mp3buf;\n if (channels === 2 && right) {\n const rightChunk = right.subarray(i, Math.min(i + samplesPerFrame, right.length));\n mp3buf = mp3encoder.encodeBuffer(leftChunk, rightChunk);\n } else {\n mp3buf = mp3encoder.encodeBuffer(leftChunk);\n }\n if (mp3buf.length > 0) mp3Chunks.push(mp3buf);\n }\n const end = mp3encoder.flush();\n if (end.length > 0) mp3Chunks.push(end);\n return new Blob(mp3Chunks, { type: \"audio/mpeg\" });\n};\nconst audioBufferToWavBlob = (buffer) => {\n const arrayBuffer = audioBufferToWavArrayBuffer(buffer);\n return new Blob([arrayBuffer], { type: \"audio/wav\" });\n};\nconst downsampleAudioBuffer = (buffer, targetSampleRate) => {\n if (buffer.sampleRate === targetSampleRate) {\n return buffer;\n }\n const ratio = buffer.sampleRate / targetSampleRate;\n const newLength = Math.round(buffer.length / ratio);\n const newBuffer = new AudioContext().createBuffer(\n buffer.numberOfChannels,\n newLength,\n targetSampleRate\n );\n for (let channel = 0; channel < buffer.numberOfChannels; channel++) {\n const oldData = buffer.getChannelData(channel);\n const newData = newBuffer.getChannelData(channel);\n for (let i = 0; i < newLength; i++) {\n const oldIndex = Math.floor(i * ratio);\n newData[i] = oldData[oldIndex];\n }\n }\n return newBuffer;\n};\nconst interleave = (buffer, numChannels, numFrames) => {\n if (numChannels === 1) {\n return buffer.getChannelData(0).slice(0, numFrames);\n }\n const result = new Float32Array(numFrames * numChannels);\n const channelData = [];\n for (let ch = 0; ch < numChannels; ch++) {\n channelData[ch] = buffer.getChannelData(ch);\n }\n let writeIndex = 0;\n for (let i = 0; i < numFrames; i++) {\n for (let ch = 0; ch < numChannels; ch++) {\n result[writeIndex++] = channelData[ch][i];\n }\n }\n return result;\n};\nconst floatTo16BitPCM = (view, offset, input) => {\n let pos = offset;\n for (let i = 0; i < input.length; i++, pos += 2) {\n let s = Math.max(-1, Math.min(1, input[i]));\n view.setInt16(pos, s < 0 ? s * 32768 : s * 32767, true);\n }\n};\nconst floatTo16 = (input) => {\n const output = new Int16Array(input.length);\n for (let i = 0; i < input.length; i++) {\n const s = Math.max(-1, Math.min(1, input[i]));\n output[i] = s < 0 ? s * 32768 : s * 32767;\n }\n return output;\n};\nconst writeString = (view, offset, str) => {\n for (let i = 0; i < str.length; i++) {\n view.setUint8(offset + i, str.charCodeAt(i));\n }\n};\n\nconst getScaledDimensions = (width, height, maxWidth, maxHeight) => {\n if (width <= maxWidth && height <= maxHeight) {\n return {\n width: width % 2 === 0 ? width : width - 1,\n height: height % 2 === 0 ? height : height - 1\n };\n }\n const widthRatio = maxWidth / width;\n const heightRatio = maxHeight / height;\n const scale = Math.min(widthRatio, heightRatio);\n let scaledWidth = Math.round(width * scale);\n let scaledHeight = Math.round(height * scale);\n if (scaledWidth % 2 !== 0) {\n scaledWidth -= 1;\n }\n if (scaledHeight % 2 !== 0) {\n scaledHeight -= 1;\n }\n return {\n width: Math.min(scaledWidth, maxWidth),\n height: Math.min(scaledHeight, maxHeight)\n };\n};\nconst getObjectFitSize = (objectFit, elementSize, containerSize) => {\n const elementAspectRatio = elementSize.width / elementSize.height;\n const containerAspectRatio = containerSize.width / containerSize.height;\n switch (objectFit) {\n case \"contain\":\n if (elementAspectRatio > containerAspectRatio) {\n return {\n width: containerSize.width,\n height: containerSize.width / elementAspectRatio\n };\n } else {\n return {\n width: containerSize.height * elementAspectRatio,\n height: containerSize.height\n };\n }\n case \"cover\":\n if (elementAspectRatio > containerAspectRatio) {\n return {\n width: containerSize.height * elementAspectRatio,\n height: containerSize.height\n };\n } else {\n return {\n width: containerSize.width,\n height: containerSize.width / elementAspectRatio\n };\n }\n case \"fill\":\n return {\n width: containerSize.width,\n height: containerSize.height\n };\n default:\n return {\n width: elementSize.width,\n height: elementSize.height\n };\n }\n};\n\nconst blobUrlToFile = async (blobUrl, fileName) => {\n const response = await fetch(blobUrl);\n const blob = await response.blob();\n return new File([blob], fileName, { type: blob.type });\n};\nconst loadFile = (accept) => {\n return new Promise((resolve, reject) => {\n try {\n const input = document.createElement(\"input\");\n input.type = \"file\";\n input.accept = accept;\n input.style.display = \"none\";\n document.body.appendChild(input);\n const cleanup = () => {\n input.value = \"\";\n document.body.removeChild(input);\n };\n input.onchange = () => {\n const file = input.files && input.files[0];\n cleanup();\n if (!file) {\n reject(new Error(\"No file selected\"));\n return;\n }\n resolve(file);\n };\n input.click();\n } catch (error) {\n reject(error);\n }\n });\n};\nconst saveAsFile = (content, type, name) => {\n const blob = typeof content === \"string\" ? new Blob([content], { type }) : content;\n const url = URL.createObjectURL(blob);\n const a = document.createElement(\"a\");\n a.href = url;\n a.download = name;\n a.click();\n URL.revokeObjectURL(url);\n};\nconst downloadFile = async (url, filename) => {\n try {\n const response = await fetch(url);\n const blob = await response.blob();\n const downloadUrl = window.URL.createObjectURL(blob);\n const link = document.createElement(\"a\");\n link.href = downloadUrl;\n link.download = filename;\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n window.URL.revokeObjectURL(downloadUrl);\n } catch (error) {\n throw error;\n }\n};\n\nconst detectMediaTypeFromUrl = async (url) => {\n try {\n const response = await fetch(url, { method: \"HEAD\" });\n const contentType = response.headers.get(\"Content-Type\");\n if (!contentType) return null;\n if (contentType.startsWith(\"image/\")) return \"image\";\n if (contentType.startsWith(\"video/\")) return \"video\";\n if (contentType.startsWith(\"audio/\")) return \"audio\";\n return null;\n } catch {\n return null;\n }\n};\n\nexport { VideoFrameExtractor, blobUrlToFile, detectMediaTypeFromUrl, downloadFile, extractAudio, getAudioDuration, getDefaultVideoFrameExtractor, getImageDimensions, getObjectFitSize, getScaledDimensions, getThumbnail, getThumbnailCached, getVideoMeta, hasAudio, limit, loadFile, saveAsFile, stitchAudio };\n//# sourceMappingURL=index.mjs.map\n","import { TrackElement, VideoElement } from \"@twick/timeline\";\nimport { useEffect, useState, useRef } from \"react\";\nimport { hasAudio } from \"@twick/media-utils\";\nimport { Loader2, VolumeX, Volume2, CheckCircle2, XCircle } from \"lucide-react\";\nimport { ICaptionGenerationPollingResponse } from \"../../types\";\n\nexport function GenerateCaptionsPanel({\n selectedElement,\n addCaptionsToTimeline,\n onGenerateCaptions,\n getCaptionstatus,\n pollingIntervalMs = 5000,\n}: {\n selectedElement: TrackElement;\n addCaptionsToTimeline: (captions: { s: number; e: number; t: string }[]) => void;\n onGenerateCaptions: (videoElement: VideoElement) => Promise<string | null>;\n getCaptionstatus: (reqId: string) => Promise<ICaptionGenerationPollingResponse>;\n pollingIntervalMs?: number;\n}) {\n const [containsAudio, setContainsAudio] = useState<boolean | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [isGenerating, setIsGenerating] = useState(false);\n const [pollingStatus, setPollingStatus] = useState<\"idle\" | \"polling\" | \"success\" | \"error\">(\"idle\");\n const [errorMessage, setErrorMessage] = useState<string | null>(null);\n const pollingIntervalRef = useRef<NodeJS.Timeout | null>(null);\n const currentReqIdRef = useRef<string | null>(null);\n\n // Cleanup polling on unmount\n useEffect(() => {\n return () => {\n if (pollingIntervalRef.current) {\n clearInterval(pollingIntervalRef.current);\n }\n };\n }, []);\n\n const stopPolling = () => {\n if (pollingIntervalRef.current) {\n clearInterval(pollingIntervalRef.current);\n pollingIntervalRef.current = null;\n }\n };\n\n const startPolling = async (reqId: string) => {\n if (!getCaptionstatus) {\n return;\n }\n setPollingStatus(\"polling\");\n setIsGenerating(true);\n setErrorMessage(null);\n\n const poll = async () => {\n try {\n const response = await getCaptionstatus(reqId);\n\n \n if (response.status === \"completed\") {\n stopPolling();\n setPollingStatus(\"success\");\n setIsGenerating(false);\n \n // Add captions to timeline\n addCaptionsToTimeline(response.captions || []);\n \n // Reset status after 3 seconds\n setTimeout(() => {\n setPollingStatus(\"idle\");\n }, 3000);\n } else if (response.status === \"pending\") {\n // Continue polling - interval will call this again\n } else if (response.status === \"failed\") {\n stopPolling();\n setPollingStatus(\"error\");\n setIsGenerating(false);\n setErrorMessage(response.error || \"Failed to generate captions\");\n console.error(\"Error generating captions:\", response.error);\n }\n } catch (error) {\n stopPolling();\n setPollingStatus(\"error\");\n setIsGenerating(false);\n setErrorMessage(error instanceof Error ? error.message : \"Failed to get caption status\");\n console.error(\"Error polling for captions:\", error);\n }\n };\n\n // Poll immediately, then at configured interval (default 5 seconds)\n await poll();\n pollingIntervalRef.current = setInterval(poll, pollingIntervalMs);\n };\n\n const handleGenerateCaptions = async () => {\n if (!(selectedElement instanceof VideoElement)) {\n return;\n }\n\n setIsGenerating(true);\n setPollingStatus(\"polling\");\n const videoElement = selectedElement as VideoElement;\n \n\n try {\n const reqId = await onGenerateCaptions(videoElement);\n if (!reqId) {\n setPollingStatus(\"error\");\n setIsGenerating(false);\n setErrorMessage(\"Failed to start caption generation\");\n console.error(\"Error generating captions: Failed to start caption generation\");\n return;\n }\n currentReqIdRef.current = reqId;\n await startPolling(reqId);\n } catch (error) {\n setPollingStatus(\"error\");\n setIsGenerating(false);\n setErrorMessage(error instanceof Error ? error.message : \"Failed to start caption generation\");\n console.error(\"Error generating captions:\", error);\n }\n };\n\n const checkAudio = async () => {\n setIsLoading(true);\n if (selectedElement instanceof VideoElement) {\n const videoElement = selectedElement as VideoElement;\n const videoUrl = videoElement.getSrc();\n if (videoUrl) {\n try {\n const hasAudioTrack = await hasAudio(videoUrl);\n setContainsAudio(hasAudioTrack);\n } catch (error) {\n console.error(\"Error checking audio:\", error);\n setContainsAudio(false);\n }\n } else {\n setContainsAudio(false);\n }\n } else {\n setContainsAudio(false);\n }\n setIsLoading(false);\n };\n\n useEffect(() => {\n checkAudio();\n // Reset polling state when element changes\n stopPolling();\n setPollingStatus(\"idle\");\n setIsGenerating(false);\n setErrorMessage(null);\n }, [selectedElement]);\n\n return (\n <div className=\"panel-container\">\n <div className=\"panel-title\">Generate Captions Panel</div>\n \n {/* Loading State */}\n {isLoading && (\n <div className=\"panel-section\">\n <div className=\"empty-state\">\n <div className=\"empty-state-content\">\n <Loader2 className=\"empty-state-icon animate-spin\" />\n <p className=\"empty-state-text\">Checking for audio...</p>\n </div>\n </div>\n </div>\n )}\n\n {/* No Audio State */}\n {!isLoading && containsAudio === false && (\n <div className=\"panel-section\">\n <div className=\"empty-state\">\n <div className=\"empty-state-content\">\n <VolumeX className=\"empty-state-icon\" />\n <p className=\"empty-state-text\">No audio track found in this video</p>\n </div>\n </div>\n </div>\n )}\n\n {/* Audio Present State */}\n {!isLoading && containsAudio === true && pollingStatus === \"idle\" && !isGenerating && (\n <div className=\"panel-section\">\n <div className=\"empty-state\">\n <div className=\"empty-state-content\">\n <Volume2 className=\"empty-state-icon\" />\n <p className=\"empty-state-text\">Audio detected! You can now generate captions</p>\n </div>\n </div>\n </div>\n )}\n\n {/* Polling/Generating State */}\n {!isLoading && isGenerating && pollingStatus === \"polling\" && (\n <div className=\"panel-section\">\n <div className=\"empty-state\">\n <div className=\"empty-state-content\">\n <Loader2 className=\"empty-state-icon animate-spin\" />\n <p className=\"empty-state-text\">Generating captions... Please wait</p>\n </div>\n </div>\n </div>\n )}\n\n {/* Success State */}\n {!isLoading && pollingStatus === \"success\" && (\n <div className=\"panel-section\">\n <div className=\"empty-state\">\n <div className=\"empty-state-content\">\n <CheckCircle2 className=\"empty-state-icon\" color=\"var(--color-green-500)\" />\n <p className=\"empty-state-text\">Captions generated successfully!</p>\n </div>\n </div>\n </div>\n )}\n\n {/* Error State */}\n {!isLoading && pollingStatus === \"error\" && (\n <div className=\"panel-section\">\n <div className=\"empty-state\">\n <div className=\"empty-state-content\">\n <XCircle className=\"empty-state-icon\" color=\"var(--color-red-500)\" />\n <p className=\"empty-state-text\">{errorMessage || \"Failed to generate captions\"}</p>\n </div>\n </div>\n </div>\n )}\n\n {/* Generate Button */}\n {!isLoading && (\n <div className=\"flex panel-section\">\n <button\n onClick={handleGenerateCaptions}\n disabled={!containsAudio || isGenerating}\n className=\"btn-primary w-full\"\n >\n {isGenerating ? \"Generating...\" : \"Generate Captions\"}\n </button>\n </div>\n )}\n </div>\n );\n}\n","import { TextElement } from \"@twick/timeline\";\nimport type { PropertiesPanelProps } from \"../../types\";\nimport { AccordionItem } from \"../shared/accordion-item\";\nimport { PropertyRow } from \"./property-row\";\nimport { Type, AlignLeft, AlignCenter, AlignRight, Bold, Italic } from \"lucide-react\";\nimport { useState } from \"react\";\n\nexport function TextPropsPanel({\n selectedElement,\n updateElement,\n}: PropertiesPanelProps) {\n if (!(selectedElement instanceof TextElement)) return null;\n\n const textProps = selectedElement.getProps() || {};\n\n const [isTypographyOpen, setIsTypographyOpen] = useState(false);\n\n const currentAlign = textProps.textAlign ?? \"center\";\n const currentWeight = textProps.fontWeight ?? 400;\n const isBold = currentWeight >= 600;\n const isItalic = textProps.fontStyle === \"italic\";\n\n const handleUpdate = (patch: Partial<typeof textProps>) => {\n if (!selectedElement) return;\n const next = { ...textProps, ...patch };\n selectedElement.setProps(next);\n updateElement?.(selectedElement);\n };\n\n const toggleBold = () => {\n handleUpdate({ fontWeight: isBold ? 400 : 700 });\n };\n\n const toggleItalic = () => {\n handleUpdate({ fontStyle: isItalic ? \"normal\" : \"italic\" });\n };\n\n const setAlign = (align: \"left\" | \"center\" | \"right\") => {\n handleUpdate({ textAlign: align });\n };\n\n return (\n <div className=\"panel-container\">\n <div className=\"panel-title\">Typography</div>\n <AccordionItem\n title=\"Typography\"\n icon={<Type className=\"icon-sm\" />}\n isOpen={isTypographyOpen}\n onToggle={() => setIsTypographyOpen((open) => !open)}\n >\n <div className=\"properties-group\">\n {/* Font size */}\n <div className=\"property-section\">\n <PropertyRow\n label=\"Font size\"\n secondary={<span>{textProps.fontSize ?? 48}px</span>}\n >\n <input\n type=\"range\"\n min={8}\n max={160}\n value={textProps.fontSize ?? 48}\n onChange={(e) =>\n handleUpdate({ fontSize: Number(e.target.value) })\n }\n className=\"slider-purple\"\n />\n </PropertyRow>\n </div>\n\n {/* Style: bold / italic */}\n <div className=\"property-section\">\n <PropertyRow label=\"Style\">\n <button\n type=\"button\"\n className={`form-btn ${isBold ? \"active\" : \"\"}`}\n onClick={toggleBold}\n title=\"Bold\"\n >\n <Bold className=\"icon-sm\" />\n </button>\n <button\n type=\"button\"\n className={`form-btn ${isItalic ? \"active\" : \"\"}`}\n onClick={toggleItalic}\n title=\"Italic\"\n >\n <Italic className=\"icon-sm\" />\n </button>\n </PropertyRow>\n </div>\n\n {/* Alignment */}\n <div className=\"property-section\">\n <PropertyRow label=\"Align\">\n <button\n type=\"button\"\n className={`form-btn ${currentAlign === \"left\" ? \"active\" : \"\"}`}\n onClick={() => setAlign(\"left\")}\n title=\"Align left\"\n >\n <AlignLeft className=\"icon-sm\" />\n </button>\n <button\n type=\"button\"\n className={`form-btn ${\n currentAlign === \"center\" ? \"active\" : \"\"\n }`}\n onClick={() => setAlign(\"center\")}\n title=\"Align center\"\n >\n <AlignCenter className=\"icon-sm\" />\n </button>\n <button\n type=\"button\"\n className={`form-btn ${\n currentAlign === \"right\" ? \"active\" : \"\"\n }`}\n onClick={() => setAlign(\"right\")}\n title=\"Align right\"\n >\n <AlignRight className=\"icon-sm\" />\n </button>\n </PropertyRow>\n </div>\n\n </div>\n </AccordionItem>\n </div>\n );\n}\n\n","import { ElementProps } from \"../properties/element-props\";\nimport { TextEffects } from \"../properties/text-effects\";\nimport { Animation } from \"../properties/animation\";\nimport { VideoElement, TextElement, AudioElement, type TrackElement, Size } from \"@twick/timeline\";\nimport { PlaybackPropsPanel } from \"../properties/playback-props\";\nimport { GenerateCaptionsPanel } from \"../properties/generate-captions.tsx\";\nimport { TextPropsPanel } from \"../properties/text-props\";\nimport { ICaptionGenerationPollingResponse, CaptionEntry } from \"../../types\";\n\ninterface PropertiesPanelContainerProps {\n selectedElement: TrackElement | null;\n updateElement: (element: TrackElement) => void;\n addCaptionsToTimeline: (captions: CaptionEntry[]) => void;\n onGenerateCaptions: (videoElement: VideoElement) => Promise<string | null>;\n getCaptionstatus: (reqId: string) => Promise<ICaptionGenerationPollingResponse>;\n pollingIntervalMs: number;\n videoResolution: Size;\n}\n\nexport function PropertiesPanelContainer({\n selectedElement,\n updateElement,\n addCaptionsToTimeline,\n onGenerateCaptions,\n getCaptionstatus,\n pollingIntervalMs,\n videoResolution,\n}: PropertiesPanelContainerProps) {\n\n const title = selectedElement instanceof TextElement ? selectedElement.getText() : selectedElement?.getName() || selectedElement?.getType() || \"Element\";\n\n return (\n <aside className=\"properties-panel\" aria-label=\"Element properties inspector\">\n <div className=\"properties-header\">\n {!selectedElement && (\n <h3 className=\"properties-title\">Composition</h3>\n )}\n {selectedElement && selectedElement.getType() === \"caption\" && (\n <h3 className=\"properties-title\">Subtitles are edited from the captions panel</h3>\n )}\n {selectedElement && selectedElement.getType() !== \"caption\" && (\n <h3 className=\"properties-title\">\n {title}\n </h3>\n )}\n </div>\n\n <div className=\"prop-content\">\n {/* Composition inspector when nothing selected */}\n {!selectedElement && (\n <div className=\"panel-container\">\n <div className=\"panel-title\">Canvas & Render</div>\n <div className=\"properties-group\">\n <div className=\"property-section\">\n <span className=\"property-label\">Size</span>\n <span className=\"properties-size-readonly\">\n {videoResolution.width} × {videoResolution.height}\n </span>\n </div>\n </div>\n </div>\n )}\n\n {/* Element inspector when something is selected */}\n {selectedElement && selectedElement.getType() === \"caption\"\n ? null\n : selectedElement && (\n <>\n {(() => {\n const isText = selectedElement instanceof TextElement;\n const isVideo = selectedElement instanceof VideoElement;\n const isAudio = selectedElement instanceof AudioElement;\n\n return (\n <>\n {/* Typography (Text only) */}\n {isText && (\n <TextPropsPanel\n selectedElement={selectedElement}\n updateElement={updateElement}\n />\n )}\n\n {/* Transform – visual elements only (not audio) */}\n {!isAudio && (\n <ElementProps\n selectedElement={selectedElement}\n updateElement={updateElement}\n />\n )}\n\n {/* Playback + Volume – video and audio */}\n {(isVideo || isAudio) && (\n <PlaybackPropsPanel\n selectedElement={selectedElement}\n updateElement={updateElement}\n />\n )}\n\n {/* Text Effects – text only */}\n {isText && (\n <TextEffects\n selectedElement={selectedElement}\n updateElement={updateElement}\n />\n )}\n\n {/* Animations – visual elements only (not audio) */}\n {!isAudio && (\n <Animation\n selectedElement={selectedElement}\n updateElement={updateElement}\n />\n )}\n\n {/* Generate Captions – video only */}\n {isVideo && (\n <GenerateCaptionsPanel\n selectedElement={selectedElement}\n addCaptionsToTimeline={addCaptionsToTimeline}\n onGenerateCaptions={onGenerateCaptions}\n getCaptionstatus={getCaptionstatus}\n pollingIntervalMs={pollingIntervalMs}\n />\n )}\n </>\n );\n })()}\n </>\n )}\n </div>\n </aside>\n );\n}\n","import { PLAYER_STATE, ProjectJSON, useTimelineContext, VideoElement } from \"@twick/timeline\";\nimport { ICaptionGenerationPollingResponse, StudioConfig, CaptionEntry } from \"../types\";\nimport { loadFile, saveAsFile } from \"@twick/media-utils\";\nimport { useState } from \"react\";\nimport { useLivePlayerContext } from \"@twick/live-player\";\n\nconst useStudioOperation = (studioConfig?: StudioConfig) => {\n const { editor, present, videoResolution } = useTimelineContext();\n const { setSeekTime, setPlayerState } = useLivePlayerContext();\n const [projectName, setProjectName] = useState(\"\");\n\n const onNewProject = () => {\n setPlayerState(PLAYER_STATE.PAUSED);\n editor.loadProject({\n tracks: [],\n version: 0,\n });\n setSeekTime(0);\n }\n\n const onLoadProject = async () => {\n let project: ProjectJSON;\n setPlayerState(PLAYER_STATE.PAUSED);\n if (studioConfig?.loadProject) {\n project = await studioConfig.loadProject();\n } else {\n const file = await loadFile(\"application/json\");\n const text = await file.text();\n setProjectName(file.name);\n project = JSON.parse(text);\n }\n editor.loadProject(project);\n setSeekTime(0.01);\n };\n\n const onSaveProject = async () => {\n let fileName;\n if (projectName) {\n fileName = projectName;\n } else {\n fileName = prompt(\"Enter the name of the project\") || \"untitled-project\";\n fileName = fileName + \".json\";\n setProjectName(fileName);\n }\n if (studioConfig?.saveProject && present) {\n await studioConfig.saveProject(present, fileName);\n } else {\n const file = await saveAsFile(\n JSON.stringify(present),\n \"application/json\",\n fileName\n );\n if (file) {\n console.log(\"File saved\", file);\n }\n }\n };\n\n const onExportVideo = async () => {\n if (studioConfig?.exportVideo && present) {\n await studioConfig.exportVideo(present, {\n outFile: \"output.mp4\",\n fps: 30,\n resolution: {\n width: videoResolution.width,\n height: videoResolution.height,\n },\n });\n } else {\n alert(\"Export video not supported in demo mode\");\n }\n };\n\n\n\n /**\n * Generates captions using the new polling-based service\n * Returns a function that can be called to start the generation process\n */\n const onGenerateCaptions = async (videoElement: VideoElement) => {\n // Use new polling-based service if available\n if (studioConfig?.captionGenerationService) {\n const service = studioConfig.captionGenerationService;\n const reqId = await service.generateCaptions(videoElement, present as ProjectJSON);\n return reqId;\n }\n alert(\"Generate captions not supported in demo mode\");\n return null;\n };\n\n const addCaptionsToTimeline = (captions: CaptionEntry[]) => {\n const updatedProjectJSON = studioConfig?.captionGenerationService?.updateProjectWithCaptions(captions);\n if (updatedProjectJSON) {\n editor.loadProject(updatedProjectJSON);\n }\n }\n\n const getCaptionstatus = async (reqId: string) => {\n if (studioConfig?.captionGenerationService) {\n const service = studioConfig.captionGenerationService;\n return await service.getRequestStatus(reqId);\n }\n return {\n status: \"failed\",\n error: \"Caption generation service not found\",\n } as ICaptionGenerationPollingResponse;\n }\n\n return { \n onLoadProject, \n onSaveProject, \n onExportVideo, \n onNewProject,\n onGenerateCaptions,\n addCaptionsToTimeline,\n getCaptionstatus,\n };\n};\n\nexport default useStudioOperation;\n","/**\n * TwickStudio Component\n *\n * The main studio component that provides a complete video editing interface.\n * Integrates all major components including canvas, toolbar, media library,\n * and properties panel into a cohesive editing environment.\n *\n * @component\n * @example\n * ```tsx\n * <LivePlayerProvider>\n * <TimelineProvider initialData={initialData} contextId=\"studio-demo\">\n * <TwickStudio />\n * </TimelineProvider>\n * </LivePlayerProvider>\n * ```\n */\n\nimport { Toolbar } from \"./toolbar\";\nimport StudioHeader from \"./header\";\nimport { useStudioManager } from \"../hooks/use-studio-manager\";\nimport ElementPanelContainer from \"./container/element-panel-container\";\nimport { useTimelineContext } from \"@twick/timeline\";\nimport { MediaProvider } from \"../context/media-context\";\nimport { PropertiesPanelContainer } from \"./container/properties-panel-container\";\nimport VideoEditor from \"@twick/video-editor\";\nimport { useMemo } from \"react\";\nimport { StudioConfig } from \"../types\";\nimport useStudioOperation from \"../hooks/use-studio-operation\";\nimport { useGenerateCaptions } from \"..\";\n\nexport function TwickStudio({ studioConfig }: { studioConfig?: StudioConfig }) {\n const {\n selectedTool,\n setSelectedTool,\n selectedElement,\n addElement,\n updateElement,\n } = useStudioManager();\n const { videoResolution, setVideoResolution } = useTimelineContext();\n const {\n onNewProject,\n onLoadProject,\n onSaveProject,\n onExportVideo,\n } = useStudioOperation(studioConfig);\n\n const {\n onGenerateCaptions,\n addCaptionsToTimeline,\n getCaptionstatus,\n pollingIntervalMs,\n } = useGenerateCaptions(studioConfig);\n\n const twickStudiConfig: StudioConfig = useMemo(\n () => ({\n canvasMode: true,\n ...(studioConfig || {}),\n videoProps: {\n ...(studioConfig?.videoProps || {}),\n width: videoResolution.width,\n height: videoResolution.height,\n },\n }),\n [videoResolution, studioConfig]\n );\n\n return (\n <MediaProvider>\n <div className=\"studio-container\">\n {/* Header */}\n <StudioHeader\n setVideoResolution={setVideoResolution}\n onNewProject={onNewProject}\n onLoadProject={onLoadProject}\n onSaveProject={onSaveProject}\n onExportVideo={onExportVideo}\n />\n {/* Main Content */}\n <div className=\"studio-content\">\n {/* Left Toolbar */}\n <Toolbar\n selectedTool={selectedTool}\n setSelectedTool={setSelectedTool}\n />\n\n {/* Left Panel (Element Library) */}\n <div className=\"studio-left-panel\">\n <ElementPanelContainer\n videoResolution={videoResolution}\n selectedTool={selectedTool}\n setSelectedTool={setSelectedTool}\n selectedElement={selectedElement}\n addElement={addElement}\n updateElement={updateElement}\n />\n </div>\n\n {/* Center - Canvas and Transport */}\n <main className=\"main-container\">\n <div className=\"canvas-wrapper\">\n <div\n className=\"canvas-container\"\n style={{\n maxWidth: twickStudiConfig.playerProps?.maxWidth ?? \"100%\",\n }}\n >\n <VideoEditor editorConfig={twickStudiConfig} />\n </div>\n </div>\n </main>\n\n {/* Right Panel (Inspector + Props Toolbar) */}\n <div className=\"studio-right-panel\">\n <PropertiesPanelContainer\n selectedElement={selectedElement}\n updateElement={updateElement}\n addCaptionsToTimeline={addCaptionsToTimeline}\n onGenerateCaptions={onGenerateCaptions}\n getCaptionstatus={getCaptionstatus}\n pollingIntervalMs={pollingIntervalMs}\n videoResolution={videoResolution}\n />\n </div>\n </div>\n </div>\n </MediaProvider>\n );\n}\n","import { ProjectJSON, useTimelineContext, VideoElement } from \"@twick/timeline\";\nimport {\n ICaptionGenerationPollingResponse,\n StudioConfig,\n CaptionEntry,\n} from \"../types\";\n\nconst useGenerateCaptions = (studioConfig?: StudioConfig) => {\n const { editor, present } = useTimelineContext();\n /**\n * Generates captions using the new polling-based service\n * Returns a function that can be called to start the generation process\n */\n const onGenerateCaptions = async (videoElement: VideoElement) => {\n // Use new polling-based service if available\n if (studioConfig?.captionGenerationService) {\n const service = studioConfig.captionGenerationService;\n const reqId = await service.generateCaptions(\n videoElement,\n present as ProjectJSON\n );\n return reqId;\n }\n alert(\"Generate captions not supported in demo mode\");\n return null;\n };\n\n const addCaptionsToTimeline = (captions: CaptionEntry[]) => {\n const updatedProjectJSON =\n studioConfig?.captionGenerationService?.updateProjectWithCaptions(\n captions\n );\n if (updatedProjectJSON) {\n editor.loadProject(updatedProjectJSON);\n }\n };\n\n const getCaptionstatus = async (reqId: string) => {\n if (studioConfig?.captionGenerationService) {\n const service = studioConfig.captionGenerationService;\n return await service.getRequestStatus(reqId);\n }\n return {\n status: \"failed\",\n error: \"Caption generation service not found\",\n } as ICaptionGenerationPollingResponse;\n };\n\n const pollingIntervalMs =\n studioConfig?.captionGenerationService?.pollingIntervalMs ?? 5000;\n\n return {\n onGenerateCaptions,\n addCaptionsToTimeline,\n getCaptionstatus,\n pollingIntervalMs,\n };\n};\n\nexport default useGenerateCaptions;\n"],"names":["__iconNode","Icon","orientation","config","Wand2","rotation","opacity","SparklesIcon","Loader2","CheckCircle2","XCircle","_a"],"mappings":"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","x_google_ignoreList":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38]}
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../../../node_modules/.pnpm/lucide-react@0.511.0_react@19.2.3/node_modules/lucide-react/dist/esm/shared/src/utils.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@19.2.3/node_modules/lucide-react/dist/esm/defaultAttributes.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@19.2.3/node_modules/lucide-react/dist/esm/Icon.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@19.2.3/node_modules/lucide-react/dist/esm/createLucideIcon.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/align-center.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/align-left.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/align-right.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/bold.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/chevron-down.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/chevron-right.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/circle-check.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/circle-x.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/circle.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/clapperboard.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/download.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/file.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/image.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/italic.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/loader-circle.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/message-square.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/music-2.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/music.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/pause.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/play.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/plus.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/rectangle-horizontal.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/rectangle-vertical.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/ruler.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/save.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/scissors.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/sparkles.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/square.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/trash-2.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/type.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/upload.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/video.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/volume-2.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/volume-x.js","../../../node_modules/.pnpm/lucide-react@0.511.0_react@19.2.3/node_modules/lucide-react/dist/esm/icons/wand-sparkles.js","../src/components/toolbar.tsx","../src/components/header.tsx","../src/hooks/use-studio-manager.tsx","../src/components/shared/media-manager.ts","../src/components/shared/url-input.tsx","../src/context/media-context.tsx","../src/hooks/use-media-panel.ts","../src/hooks/use-audio-preview.ts","../src/components/panel/audio-panel.tsx","../src/components/container/audio-panel-container.tsx","../src/components/panel/image-panel.tsx","../src/components/container/image-panel-container.tsx","../src/hooks/use-video-preview.ts","../src/components/panel/video-panel.tsx","../src/components/container/video-panel-container.tsx","../src/components/panel/text-panel.tsx","../src/hooks/use-text-panel.ts","../src/components/container/text-panel-container.tsx","../src/components/panel/rect-panel.tsx","../src/hooks/use-rect-panel.ts","../src/components/container/rect-panel-container.tsx","../src/components/panel/circle-panel.tsx","../src/hooks/use-circle-panel.ts","../src/components/container/circle-panel-container.tsx","../src/components/panel/captions-panel.tsx","../src/helpers/constant.ts","../src/hooks/use-captions-panel.ts","../src/components/container/captions-panel-container.tsx","../src/components/container/element-panel-container.tsx","../src/components/properties/property-row.tsx","../src/components/shared/accordion-item.tsx","../src/components/properties/element-props.tsx","../src/components/properties/text-effects.tsx","../src/components/properties/animation.tsx","../src/helpers/volume-db.ts","../src/components/properties/playback-props.tsx","../../media-utils/dist/index.mjs","../src/components/properties/generate-captions.tsx","../src/components/properties/text-props.tsx","../src/components/container/properties-panel-container.tsx","../src/hooks/use-studio-operation.ts","../src/components/twick-studio.tsx","../src/hooks/use-generate-captions.ts"],"sourcesContent":["/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nconst toKebabCase = (string) => string.replace(/([a-z0-9])([A-Z])/g, \"$1-$2\").toLowerCase();\nconst toCamelCase = (string) => string.replace(\n /^([A-Z])|[\\s-_]+(\\w)/g,\n (match, p1, p2) => p2 ? p2.toUpperCase() : p1.toLowerCase()\n);\nconst toPascalCase = (string) => {\n const camelCase = toCamelCase(string);\n return camelCase.charAt(0).toUpperCase() + camelCase.slice(1);\n};\nconst mergeClasses = (...classes) => classes.filter((className, index, array) => {\n return Boolean(className) && className.trim() !== \"\" && array.indexOf(className) === index;\n}).join(\" \").trim();\nconst hasA11yProp = (props) => {\n for (const prop in props) {\n if (prop.startsWith(\"aria-\") || prop === \"role\" || prop === \"title\") {\n return true;\n }\n }\n};\n\nexport { hasA11yProp, mergeClasses, toCamelCase, toKebabCase, toPascalCase };\n//# sourceMappingURL=utils.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nvar defaultAttributes = {\n xmlns: \"http://www.w3.org/2000/svg\",\n width: 24,\n height: 24,\n viewBox: \"0 0 24 24\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeWidth: 2,\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\"\n};\n\nexport { defaultAttributes as default };\n//# sourceMappingURL=defaultAttributes.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { forwardRef, createElement } from 'react';\nimport defaultAttributes from './defaultAttributes.js';\nimport { mergeClasses, hasA11yProp } from './shared/src/utils.js';\n\nconst Icon = forwardRef(\n ({\n color = \"currentColor\",\n size = 24,\n strokeWidth = 2,\n absoluteStrokeWidth,\n className = \"\",\n children,\n iconNode,\n ...rest\n }, ref) => createElement(\n \"svg\",\n {\n ref,\n ...defaultAttributes,\n width: size,\n height: size,\n stroke: color,\n strokeWidth: absoluteStrokeWidth ? Number(strokeWidth) * 24 / Number(size) : strokeWidth,\n className: mergeClasses(\"lucide\", className),\n ...!children && !hasA11yProp(rest) && { \"aria-hidden\": \"true\" },\n ...rest\n },\n [\n ...iconNode.map(([tag, attrs]) => createElement(tag, attrs)),\n ...Array.isArray(children) ? children : [children]\n ]\n )\n);\n\nexport { Icon as default };\n//# sourceMappingURL=Icon.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport { forwardRef, createElement } from 'react';\nimport { mergeClasses, toKebabCase, toPascalCase } from './shared/src/utils.js';\nimport Icon from './Icon.js';\n\nconst createLucideIcon = (iconName, iconNode) => {\n const Component = forwardRef(\n ({ className, ...props }, ref) => createElement(Icon, {\n ref,\n iconNode,\n className: mergeClasses(\n `lucide-${toKebabCase(toPascalCase(iconName))}`,\n `lucide-${iconName}`,\n className\n ),\n ...props\n })\n );\n Component.displayName = toPascalCase(iconName);\n return Component;\n};\n\nexport { createLucideIcon as default };\n//# sourceMappingURL=createLucideIcon.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M17 12H7\", key: \"16if0g\" }],\n [\"path\", { d: \"M19 18H5\", key: \"18s9l3\" }],\n [\"path\", { d: \"M21 6H3\", key: \"1jwq7v\" }]\n];\nconst AlignCenter = createLucideIcon(\"align-center\", __iconNode);\n\nexport { __iconNode, AlignCenter as default };\n//# sourceMappingURL=align-center.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M15 12H3\", key: \"6jk70r\" }],\n [\"path\", { d: \"M17 18H3\", key: \"1amg6g\" }],\n [\"path\", { d: \"M21 6H3\", key: \"1jwq7v\" }]\n];\nconst AlignLeft = createLucideIcon(\"align-left\", __iconNode);\n\nexport { __iconNode, AlignLeft as default };\n//# sourceMappingURL=align-left.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M21 12H9\", key: \"dn1m92\" }],\n [\"path\", { d: \"M21 18H7\", key: \"1ygte8\" }],\n [\"path\", { d: \"M21 6H3\", key: \"1jwq7v\" }]\n];\nconst AlignRight = createLucideIcon(\"align-right\", __iconNode);\n\nexport { __iconNode, AlignRight as default };\n//# sourceMappingURL=align-right.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n { d: \"M6 12h9a4 4 0 0 1 0 8H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h7a4 4 0 0 1 0 8\", key: \"mg9rjx\" }\n ]\n];\nconst Bold = createLucideIcon(\"bold\", __iconNode);\n\nexport { __iconNode, Bold as default };\n//# sourceMappingURL=bold.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [[\"path\", { d: \"m6 9 6 6 6-6\", key: \"qrunsl\" }]];\nconst ChevronDown = createLucideIcon(\"chevron-down\", __iconNode);\n\nexport { __iconNode, ChevronDown as default };\n//# sourceMappingURL=chevron-down.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [[\"path\", { d: \"m9 18 6-6-6-6\", key: \"mthhwq\" }]];\nconst ChevronRight = createLucideIcon(\"chevron-right\", __iconNode);\n\nexport { __iconNode, ChevronRight as default };\n//# sourceMappingURL=chevron-right.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"path\", { d: \"m9 12 2 2 4-4\", key: \"dzmm74\" }]\n];\nconst CircleCheck = createLucideIcon(\"circle-check\", __iconNode);\n\nexport { __iconNode, CircleCheck as default };\n//# sourceMappingURL=circle-check.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"path\", { d: \"m15 9-6 6\", key: \"1uzhvr\" }],\n [\"path\", { d: \"m9 9 6 6\", key: \"z0biqf\" }]\n];\nconst CircleX = createLucideIcon(\"circle-x\", __iconNode);\n\nexport { __iconNode, CircleX as default };\n//# sourceMappingURL=circle-x.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [[\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }]];\nconst Circle = createLucideIcon(\"circle\", __iconNode);\n\nexport { __iconNode, Circle as default };\n//# sourceMappingURL=circle.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n { d: \"M20.2 6 3 11l-.9-2.4c-.3-1.1.3-2.2 1.3-2.5l13.5-4c1.1-.3 2.2.3 2.5 1.3Z\", key: \"1tn4o7\" }\n ],\n [\"path\", { d: \"m6.2 5.3 3.1 3.9\", key: \"iuk76l\" }],\n [\"path\", { d: \"m12.4 3.4 3.1 4\", key: \"6hsd6n\" }],\n [\"path\", { d: \"M3 11h18v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2Z\", key: \"ltgou9\" }]\n];\nconst Clapperboard = createLucideIcon(\"clapperboard\", __iconNode);\n\nexport { __iconNode, Clapperboard as default };\n//# sourceMappingURL=clapperboard.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M12 15V3\", key: \"m9g1x1\" }],\n [\"path\", { d: \"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\", key: \"ih7n3h\" }],\n [\"path\", { d: \"m7 10 5 5 5-5\", key: \"brsn70\" }]\n];\nconst Download = createLucideIcon(\"download\", __iconNode);\n\nexport { __iconNode, Download as default };\n//# sourceMappingURL=download.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z\", key: \"1rqfz7\" }],\n [\"path\", { d: \"M14 2v4a2 2 0 0 0 2 2h4\", key: \"tnqrlb\" }]\n];\nconst File = createLucideIcon(\"file\", __iconNode);\n\nexport { __iconNode, File as default };\n//# sourceMappingURL=file.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", ry: \"2\", key: \"1m3agn\" }],\n [\"circle\", { cx: \"9\", cy: \"9\", r: \"2\", key: \"af1f0g\" }],\n [\"path\", { d: \"m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21\", key: \"1xmnt7\" }]\n];\nconst Image = createLucideIcon(\"image\", __iconNode);\n\nexport { __iconNode, Image as default };\n//# sourceMappingURL=image.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"line\", { x1: \"19\", x2: \"10\", y1: \"4\", y2: \"4\", key: \"15jd3p\" }],\n [\"line\", { x1: \"14\", x2: \"5\", y1: \"20\", y2: \"20\", key: \"bu0au3\" }],\n [\"line\", { x1: \"15\", x2: \"9\", y1: \"4\", y2: \"20\", key: \"uljnxc\" }]\n];\nconst Italic = createLucideIcon(\"italic\", __iconNode);\n\nexport { __iconNode, Italic as default };\n//# sourceMappingURL=italic.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [[\"path\", { d: \"M21 12a9 9 0 1 1-6.219-8.56\", key: \"13zald\" }]];\nconst LoaderCircle = createLucideIcon(\"loader-circle\", __iconNode);\n\nexport { __iconNode, LoaderCircle as default };\n//# sourceMappingURL=loader-circle.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\", key: \"1lielz\" }]\n];\nconst MessageSquare = createLucideIcon(\"message-square\", __iconNode);\n\nexport { __iconNode, MessageSquare as default };\n//# sourceMappingURL=message-square.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"circle\", { cx: \"8\", cy: \"18\", r: \"4\", key: \"1fc0mg\" }],\n [\"path\", { d: \"M12 18V2l7 4\", key: \"g04rme\" }]\n];\nconst Music2 = createLucideIcon(\"music-2\", __iconNode);\n\nexport { __iconNode, Music2 as default };\n//# sourceMappingURL=music-2.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M9 18V5l12-2v13\", key: \"1jmyc2\" }],\n [\"circle\", { cx: \"6\", cy: \"18\", r: \"3\", key: \"fqmcym\" }],\n [\"circle\", { cx: \"18\", cy: \"16\", r: \"3\", key: \"1hluhg\" }]\n];\nconst Music = createLucideIcon(\"music\", __iconNode);\n\nexport { __iconNode, Music as default };\n//# sourceMappingURL=music.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"rect\", { x: \"14\", y: \"4\", width: \"4\", height: \"16\", rx: \"1\", key: \"zuxfzm\" }],\n [\"rect\", { x: \"6\", y: \"4\", width: \"4\", height: \"16\", rx: \"1\", key: \"1okwgv\" }]\n];\nconst Pause = createLucideIcon(\"pause\", __iconNode);\n\nexport { __iconNode, Pause as default };\n//# sourceMappingURL=pause.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [[\"polygon\", { points: \"6 3 20 12 6 21 6 3\", key: \"1oa8hb\" }]];\nconst Play = createLucideIcon(\"play\", __iconNode);\n\nexport { __iconNode, Play as default };\n//# sourceMappingURL=play.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M5 12h14\", key: \"1ays0h\" }],\n [\"path\", { d: \"M12 5v14\", key: \"s699le\" }]\n];\nconst Plus = createLucideIcon(\"plus\", __iconNode);\n\nexport { __iconNode, Plus as default };\n//# sourceMappingURL=plus.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"rect\", { width: \"20\", height: \"12\", x: \"2\", y: \"6\", rx: \"2\", key: \"9lu3g6\" }]\n];\nconst RectangleHorizontal = createLucideIcon(\"rectangle-horizontal\", __iconNode);\n\nexport { __iconNode, RectangleHorizontal as default };\n//# sourceMappingURL=rectangle-horizontal.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"rect\", { width: \"12\", height: \"20\", x: \"6\", y: \"2\", rx: \"2\", key: \"1oxtiu\" }]\n];\nconst RectangleVertical = createLucideIcon(\"rectangle-vertical\", __iconNode);\n\nexport { __iconNode, RectangleVertical as default };\n//# sourceMappingURL=rectangle-vertical.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M21.3 15.3a2.4 2.4 0 0 1 0 3.4l-2.6 2.6a2.4 2.4 0 0 1-3.4 0L2.7 8.7a2.41 2.41 0 0 1 0-3.4l2.6-2.6a2.41 2.41 0 0 1 3.4 0Z\",\n key: \"icamh8\"\n }\n ],\n [\"path\", { d: \"m14.5 12.5 2-2\", key: \"inckbg\" }],\n [\"path\", { d: \"m11.5 9.5 2-2\", key: \"fmmyf7\" }],\n [\"path\", { d: \"m8.5 6.5 2-2\", key: \"vc6u1g\" }],\n [\"path\", { d: \"m17.5 15.5 2-2\", key: \"wo5hmg\" }]\n];\nconst Ruler = createLucideIcon(\"ruler\", __iconNode);\n\nexport { __iconNode, Ruler as default };\n//# sourceMappingURL=ruler.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M15.2 3a2 2 0 0 1 1.4.6l3.8 3.8a2 2 0 0 1 .6 1.4V19a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z\",\n key: \"1c8476\"\n }\n ],\n [\"path\", { d: \"M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7\", key: \"1ydtos\" }],\n [\"path\", { d: \"M7 3v4a1 1 0 0 0 1 1h7\", key: \"t51u73\" }]\n];\nconst Save = createLucideIcon(\"save\", __iconNode);\n\nexport { __iconNode, Save as default };\n//# sourceMappingURL=save.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"circle\", { cx: \"6\", cy: \"6\", r: \"3\", key: \"1lh9wr\" }],\n [\"path\", { d: \"M8.12 8.12 12 12\", key: \"1alkpv\" }],\n [\"path\", { d: \"M20 4 8.12 15.88\", key: \"xgtan2\" }],\n [\"circle\", { cx: \"6\", cy: \"18\", r: \"3\", key: \"fqmcym\" }],\n [\"path\", { d: \"M14.8 14.8 20 20\", key: \"ptml3r\" }]\n];\nconst Scissors = createLucideIcon(\"scissors\", __iconNode);\n\nexport { __iconNode, Scissors as default };\n//# sourceMappingURL=scissors.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z\",\n key: \"4pj2yx\"\n }\n ],\n [\"path\", { d: \"M20 3v4\", key: \"1olli1\" }],\n [\"path\", { d: \"M22 5h-4\", key: \"1gvqau\" }],\n [\"path\", { d: \"M4 17v2\", key: \"vumght\" }],\n [\"path\", { d: \"M5 18H3\", key: \"zchphs\" }]\n];\nconst Sparkles = createLucideIcon(\"sparkles\", __iconNode);\n\nexport { __iconNode, Sparkles as default };\n//# sourceMappingURL=sparkles.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", key: \"afitv7\" }]\n];\nconst Square = createLucideIcon(\"square\", __iconNode);\n\nexport { __iconNode, Square as default };\n//# sourceMappingURL=square.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M3 6h18\", key: \"d0wm0j\" }],\n [\"path\", { d: \"M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6\", key: \"4alrt4\" }],\n [\"path\", { d: \"M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2\", key: \"v07s0e\" }],\n [\"line\", { x1: \"10\", x2: \"10\", y1: \"11\", y2: \"17\", key: \"1uufr5\" }],\n [\"line\", { x1: \"14\", x2: \"14\", y1: \"11\", y2: \"17\", key: \"xtxkd\" }]\n];\nconst Trash2 = createLucideIcon(\"trash-2\", __iconNode);\n\nexport { __iconNode, Trash2 as default };\n//# sourceMappingURL=trash-2.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M12 4v16\", key: \"1654pz\" }],\n [\"path\", { d: \"M4 7V5a1 1 0 0 1 1-1h14a1 1 0 0 1 1 1v2\", key: \"e0r10z\" }],\n [\"path\", { d: \"M9 20h6\", key: \"s66wpe\" }]\n];\nconst Type = createLucideIcon(\"type\", __iconNode);\n\nexport { __iconNode, Type as default };\n//# sourceMappingURL=type.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M12 3v12\", key: \"1x0j5s\" }],\n [\"path\", { d: \"m17 8-5-5-5 5\", key: \"7q97r8\" }],\n [\"path\", { d: \"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\", key: \"ih7n3h\" }]\n];\nconst Upload = createLucideIcon(\"upload\", __iconNode);\n\nexport { __iconNode, Upload as default };\n//# sourceMappingURL=upload.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"m16 13 5.223 3.482a.5.5 0 0 0 .777-.416V7.87a.5.5 0 0 0-.752-.432L16 10.5\",\n key: \"ftymec\"\n }\n ],\n [\"rect\", { x: \"2\", y: \"6\", width: \"14\", height: \"12\", rx: \"2\", key: \"158x01\" }]\n];\nconst Video = createLucideIcon(\"video\", __iconNode);\n\nexport { __iconNode, Video as default };\n//# sourceMappingURL=video.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M11 4.702a.705.705 0 0 0-1.203-.498L6.413 7.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.705.705 0 0 0 11 19.298z\",\n key: \"uqj9uw\"\n }\n ],\n [\"path\", { d: \"M16 9a5 5 0 0 1 0 6\", key: \"1q6k2b\" }],\n [\"path\", { d: \"M19.364 18.364a9 9 0 0 0 0-12.728\", key: \"ijwkga\" }]\n];\nconst Volume2 = createLucideIcon(\"volume-2\", __iconNode);\n\nexport { __iconNode, Volume2 as default };\n//# sourceMappingURL=volume-2.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M11 4.702a.705.705 0 0 0-1.203-.498L6.413 7.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.705.705 0 0 0 11 19.298z\",\n key: \"uqj9uw\"\n }\n ],\n [\"line\", { x1: \"22\", x2: \"16\", y1: \"9\", y2: \"15\", key: \"1ewh16\" }],\n [\"line\", { x1: \"16\", x2: \"22\", y1: \"9\", y2: \"15\", key: \"5ykzw1\" }]\n];\nconst VolumeX = createLucideIcon(\"volume-x\", __iconNode);\n\nexport { __iconNode, VolumeX as default };\n//# sourceMappingURL=volume-x.js.map\n","/**\n * @license lucide-react v0.511.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"m21.64 3.64-1.28-1.28a1.21 1.21 0 0 0-1.72 0L2.36 18.64a1.21 1.21 0 0 0 0 1.72l1.28 1.28a1.2 1.2 0 0 0 1.72 0L21.64 5.36a1.2 1.2 0 0 0 0-1.72\",\n key: \"ul74o6\"\n }\n ],\n [\"path\", { d: \"m14 7 3 3\", key: \"1r5n42\" }],\n [\"path\", { d: \"M5 6v4\", key: \"ilb8ba\" }],\n [\"path\", { d: \"M19 14v4\", key: \"blhpug\" }],\n [\"path\", { d: \"M10 2v2\", key: \"7u0qdc\" }],\n [\"path\", { d: \"M7 8H3\", key: \"zfb6yr\" }],\n [\"path\", { d: \"M21 16h-4\", key: \"1cnmox\" }],\n [\"path\", { d: \"M11 3H9\", key: \"1obp7u\" }]\n];\nconst WandSparkles = createLucideIcon(\"wand-sparkles\", __iconNode);\n\nexport { __iconNode, WandSparkles as default };\n//# sourceMappingURL=wand-sparkles.js.map\n","/**\n * Toolbar Component\n * \n * A vertical toolbar that provides quick access to different editing tools\n * and media types. Displays icons with labels and optional keyboard shortcuts.\n * \n * @component\n * @param {Object} props\n * @param {string} props.selectedTool - Currently selected tool ID\n * @param {(tool: string) => void} props.setSelectedTool - Callback to update selected tool\n * \n * @example\n * ```tsx\n * <Toolbar\n * selectedTool=\"text\"\n * setSelectedTool={(tool) => console.log(`Selected ${tool}`)}\n * />\n * ```\n */\n\nimport { \n Type, \n Upload, \n Video,\n Image, \n Music,\n Circle,\n MessageSquare,\n Plus,\n Square,\n} from 'lucide-react'\nimport type { ToolCategory } from '../types'\n\nconst toolCategories: ToolCategory[] = [\n { id: 'video', name: 'Video', icon: 'Video', description: 'Add a video element' },\n { id: 'image', name: 'Image', icon: 'Image', description: 'Add an image element' },\n { id: 'audio', name: 'Audio', icon: 'Audio', description: 'Add an audio element' },\n { id: 'text', name: 'Text', icon: 'Type', description: 'Add text elements' },\n { id: 'circle', name: 'Circle', icon: 'Circle', description: 'Add a circle element'},\n { id: 'rect', name: 'Rect', icon: 'Rect', description: 'Add a rectangle element' },\n { id: 'caption', name: 'Caption', icon: 'MessageSquare', description: 'Manage captions'},\n]\n\nconst getIcon = (iconName: string) => {\n switch (iconName) {\n case 'Plus': return Plus\n case 'Type': return Type\n case 'Upload': return Upload\n case 'Square': return Square\n case 'Image': return Image\n case 'Video': return Video\n case 'Audio': return Music\n case 'Circle': return Circle\n case 'Rect': return Square\n case 'MessageSquare': return MessageSquare\n default: return Plus\n }\n}\n\nexport function Toolbar({ selectedTool, setSelectedTool }: { selectedTool: string, setSelectedTool: (tool: string) => void }) {\n\n const handleToolSelect = (toolId: string) => {\n setSelectedTool(toolId)\n }\n\n return (\n <div className=\"sidebar\">\n {/* Main Tools */}\n {toolCategories.map((tool) => {\n const Icon = getIcon(tool.icon)\n const isSelected = selectedTool === tool.id\n \n const tooltipText = `${tool.name}${tool.shortcut ? ` (${tool.shortcut})` : ''}`;\n return (\n <div\n key={tool.id}\n onClick={() => handleToolSelect(tool.id)}\n className={`toolbar-btn ${isSelected ? 'active' : ''}`}\n title={tooltipText}\n data-tooltip={tooltipText}\n >\n <Icon className=\"icon-sm\" />\n <span className=\"toolbar-label\">\n {tool.name}\n </span>\n </div>\n )\n })}\n </div>\n )\n}\n","/**\n * StudioHeader Component\n *\n * The top header bar of the studio interface. Contains the studio logo,\n * orientation controls, and action divs for saving and exporting.\n *\n * @component\n * @param {Object} props\n * @param {(resolution: Size) => void} props.setVideoResolution - Callback to update canvas resolution\n *\n * @example\n * ```tsx\n * <StudioHeader\n * setVideoResolution={(size) => console.log(`New size: ${size.width}x${size.height}`)}\n * />\n * ```\n */\n\nimport type { Size } from \"@twick/timeline\";\nimport { Save, Download, Clapperboard, File, Plus, RectangleVertical, RectangleHorizontal } from \"lucide-react\";\nimport { useEffect, useState } from \"react\";\n\ninterface StudioHeaderProps {\n setVideoResolution: (resolution: Size) => void;\n onNewProject: () => void;\n onLoadProject: () => void;\n onSaveProject: () => void;\n onExportVideo: () => void;\n}\nexport const StudioHeader = ({\n setVideoResolution,\n onNewProject,\n onLoadProject,\n onSaveProject,\n onExportVideo,\n}: StudioHeaderProps) => {\n const [orientation, setOrientation] = useState<\"horizontal\" | \"vertical\">(\n \"vertical\"\n );\n\n useEffect(() => {\n const orientation = localStorage.getItem(\"orientation\");\n if (orientation) {\n setOrientation(orientation as \"horizontal\" | \"vertical\");\n }\n }, []);\n\n const handleOrientationChange = (nextOrientation: \"horizontal\" | \"vertical\") => {\n if (nextOrientation === orientation) return;\n\n const confirmMessage =\n \"Changing orientation will create a new project with the new resolution. Do you want to continue?\";\n\n if (!window.confirm(confirmMessage)) {\n return;\n }\n\n // Create a fresh project for the new resolution\n onNewProject();\n setOrientation(nextOrientation);\n };\n\n useEffect(() => {\n if (orientation === \"horizontal\") {\n localStorage.setItem(\"orientation\", \"horizontal\");\n setVideoResolution({ width: 1280, height: 720 });\n } else {\n localStorage.setItem(\"orientation\", \"vertical\");\n setVideoResolution({ width: 720, height: 1280 });\n }\n }, [orientation]);\n\n return (\n <header className=\"header\">\n <div className=\"flex-container\">\n <Clapperboard className=\"icon-lg accent-purple\" />\n <h1 className=\"text-gradient\">\n Twick Studio\n </h1>\n <div className=\"header-separator\"></div>\n <div className=\"flex-container\" style={{ gap: \"0.5rem\" }}>\n <span className=\"text-sm opacity-80\">Orientation</span>\n <button\n className={`btn-ghost ${orientation === \"vertical\" ? \"btn-primary\" : \"\"}`}\n title=\"Portrait (720×1280)\"\n onClick={() => handleOrientationChange(\"vertical\")}\n >\n <RectangleVertical className=\"icon-sm\" />\n\n </button>\n <button\n className={`btn-ghost ${orientation === \"horizontal\" ? \"btn-primary\" : \"\"}`}\n title=\"Landscape (1280×720)\"\n onClick={() => handleOrientationChange(\"horizontal\")}\n >\n <RectangleHorizontal className=\"icon-sm\" />\n\n </button>\n </div>\n </div>\n <div className=\"flex-container\">\n <button\n className=\"btn-ghost\"\n title=\"New Project\"\n onClick={onNewProject}\n >\n <Plus className=\"icon-sm\" />\n New Project\n </button>\n <button\n className=\"btn-ghost\"\n title=\"Load Project\"\n onClick={onLoadProject}\n >\n <File className=\"icon-sm\" />\n Load Project\n </button>\n <button\n className=\"btn-ghost\"\n title=\"Save Draft\"\n onClick={onSaveProject}\n >\n <Save className=\"icon-sm\" />\n Save Draft\n </button>\n <button\n className=\"btn-primary\"\n title=\"Export\"\n onClick={onExportVideo}\n >\n <Download className=\"icon-sm\" />\n Export\n </button>\n </div>\n </header>\n );\n};\n\nexport default StudioHeader;\n","/**\n * useStudioManager Hook\n *\n * A custom hook that manages the studio's state and operations.\n * Handles tool selection, element management, and timeline interactions.\n *\n * @returns {Object} Studio manager methods and state\n * @property {string} selectedTool - Currently selected tool ID\n * @property {(tool: string) => void} setSelectedTool - Update selected tool\n * @property {TrackElement | null} selectedElement - Currently selected timeline element\n * @property {(element: TrackElement) => void} addElement - Add element to timeline\n * @property {(element: TrackElement) => void} updateElement - Update existing element\n *\n * @example\n * ```tsx\n * const {\n * selectedTool,\n * setSelectedTool,\n * selectedElement,\n * addElement,\n * updateElement\n * } = useStudioManager();\n * ```\n */\n\nimport { Track, TrackElement, useTimelineContext } from \"@twick/timeline\";\nimport { useEditorManager } from \"@twick/video-editor\";\nimport { useEffect, useRef, useState } from \"react\";\n\nexport const useStudioManager = () => {\n const [selectedProp, setSelectedProp] = useState(\"element-props\");\n\n const { selectedItem } = useTimelineContext();\n\n const { addElement, updateElement } = useEditorManager();\n\n const selectedElement =\n selectedItem instanceof TrackElement ? selectedItem : null;\n\n const [selectedTool, setSelectedTool] = useState<string>(\"none\");\n\n const isToolChanged = useRef(false);\n\n useEffect(() => {\n if (selectedItem instanceof TrackElement) {\n setSelectedTool(selectedItem.getType());\n isToolChanged.current = true;\n } else if (selectedItem instanceof Track) {\n // do-nothing\n } else {\n setSelectedTool(\"video\");\n }\n }, [selectedItem]);\n\n return {\n selectedProp,\n setSelectedProp,\n selectedTool,\n setSelectedTool,\n selectedElement,\n addElement,\n updateElement,\n };\n};\n","import { BrowserMediaManager } from \"@twick/video-editor\";\nimport type { MediaItem } from \"@twick/video-editor\";\n\nclass MediaManagerSingleton {\n private static instance: BrowserMediaManager | null = null;\n private static initializationPromise: Promise<void> | null = null;\n private static isInitialized = false;\n\n private constructor() {}\n\n public static getInstance(): BrowserMediaManager {\n if (!MediaManagerSingleton.instance) {\n MediaManagerSingleton.instance = new BrowserMediaManager();\n }\n return MediaManagerSingleton.instance;\n }\n\n public static async initializeDefaults(): Promise<void> {\n // If already initialized, return immediately\n if (MediaManagerSingleton.isInitialized) {\n return;\n }\n\n // If initialization is in progress, wait for it to complete\n if (MediaManagerSingleton.initializationPromise) {\n await MediaManagerSingleton.initializationPromise;\n return;\n }\n\n // Create and store the promise immediately to prevent concurrent initialization\n // This must be synchronous to prevent race conditions\n let resolvePromise: () => void;\n let rejectPromise: (error: any) => void;\n \n MediaManagerSingleton.initializationPromise = new Promise<void>((resolve, reject) => {\n resolvePromise = resolve;\n rejectPromise = reject;\n });\n\n // Start initialization asynchronously\n (async () => {\n try {\n await MediaManagerSingleton.doInitializeDefaults();\n MediaManagerSingleton.isInitialized = true;\n resolvePromise!();\n } catch (error) {\n MediaManagerSingleton.initializationPromise = null;\n rejectPromise!(error);\n }\n })();\n \n return MediaManagerSingleton.initializationPromise;\n }\n\n private static async doInitializeDefaults(): Promise<void> {\n const manager = MediaManagerSingleton.getInstance();\n \n // Default video URLs\n const defaultVideos = [\n {\n name: \"Mountain Road\",\n url: \"https://videos.pexels.com/video-files/31708803/13510402_1080_1920_30fps.mp4\",\n type: \"video\",\n metadata: {\n name: \"Mountain Road\",\n source: \"pexels\",\n },\n },\n {\n name: \"Vase\",\n url: \"https://videos.pexels.com/video-files/4622990/4622990-uhd_1440_2560_30fps.mp4\",\n type: \"video\",\n metadata: {\n name: \"Vase\",\n source: \"pexels\",\n },\n },\n ] as Omit<MediaItem, \"id\">[];\n\n // Default image URLs\n const defaultImages = [\n {\n name: \"Mountain Road\",\n url: \"https://images.pexels.com/photos/1955134/pexels-photo-1955134.jpeg\",\n type: \"image\",\n metadata: {\n name: \"Mountain Road\",\n source: \"pexels\",\n },\n },\n {\n name: \"Waterfall\",\n url: \"https://images.pexels.com/photos/358457/pexels-photo-358457.jpeg\",\n type: \"image\",\n metadata: {\n name: \"Waterfall\",\n source: \"pexels\",\n },\n },\n ] as Omit<MediaItem, \"id\">[];\n\n // Default audio URLs\n const defaultAudios = [\n {\n name: \"Audio 1\",\n url: \"https://cdn.pixabay.com/audio/2022/03/14/audio_782eeb590e.mp3\",\n type: \"audio\",\n metadata: {\n name: \"Audio 1\",\n source: \"pixabay\",\n },\n },\n {\n name: \"Audio 2\",\n url: \"https://cdn.pixabay.com/audio/2025/01/24/audio_24048c78b6.mp3\",\n type: \"audio\",\n metadata: {\n name: \"Audio 2\",\n source: \"pixabay\",\n },\n },\n ] as Omit<MediaItem, \"id\">[];\n\n try {\n // Check if default videos already exist in the database\n const existingVideos = await manager.search({\n type: \"video\",\n query: \"\",\n });\n\n // Check if we already have the default videos by URL\n const existingVideoUrls = new Set(existingVideos.map((v) => v.url));\n const videosToAdd = defaultVideos.filter(\n (video) => !existingVideoUrls.has(video.url)\n );\n\n // Add default videos if they don't exist (check again right before adding to prevent race conditions)\n if (videosToAdd.length > 0) {\n // Double-check to prevent duplicates in case of race conditions\n const finalCheck = await manager.search({\n type: \"video\",\n query: \"\",\n });\n const finalVideoUrls = new Set(finalCheck.map((v) => v.url));\n const finalVideosToAdd = videosToAdd.filter(\n (video) => !finalVideoUrls.has(video.url)\n );\n \n if (finalVideosToAdd.length > 0) {\n await manager.addItems(finalVideosToAdd);\n }\n }\n\n // Check if default images already exist in the database\n const existingImages = await manager.search({\n type: \"image\",\n query: \"\",\n });\n\n // Check if we already have the default images by URL\n const existingImageUrls = new Set(existingImages.map((img) => img.url));\n const imagesToAdd = defaultImages.filter(\n (image) => !existingImageUrls.has(image.url)\n );\n\n // Add default images if they don't exist (check again right before adding)\n if (imagesToAdd.length > 0) {\n // Double-check to prevent duplicates in case of race conditions\n const finalCheck = await manager.search({\n type: \"image\",\n query: \"\",\n });\n const finalImageUrls = new Set(finalCheck.map((img) => img.url));\n const finalImagesToAdd = imagesToAdd.filter(\n (image) => !finalImageUrls.has(image.url)\n );\n \n if (finalImagesToAdd.length > 0) {\n await manager.addItems(finalImagesToAdd);\n }\n }\n\n // Check if default audio files already exist in the database\n const existingAudios = await manager.search({\n type: \"audio\",\n query: \"\",\n });\n\n // Check if we already have the default audio files by URL\n const existingAudioUrls = new Set(existingAudios.map((a) => a.url));\n const audiosToAdd = defaultAudios.filter(\n (audio) => !existingAudioUrls.has(audio.url)\n );\n\n // Add default audio files if they don't exist (check again right before adding)\n if (audiosToAdd.length > 0) {\n // Double-check to prevent duplicates in case of race conditions\n const finalCheck = await manager.search({\n type: \"audio\",\n query: \"\",\n });\n const finalAudioUrls = new Set(finalCheck.map((a) => a.url));\n const finalAudiosToAdd = audiosToAdd.filter(\n (audio) => !finalAudioUrls.has(audio.url)\n );\n \n if (finalAudiosToAdd.length > 0) {\n await manager.addItems(finalAudiosToAdd);\n }\n }\n } catch (error) {\n // Error is handled in initializeDefaults, just re-throw it\n throw error;\n }\n }\n}\n\n// Export a function to get the singleton instance\nexport const getMediaManager = () => MediaManagerSingleton.getInstance();\n\n// Export a function to initialize default videos\nexport const initializeDefaultVideos = () => MediaManagerSingleton.initializeDefaults(); ","import { useState } from \"react\";\nimport { Plus } from \"lucide-react\";\n\ntype MediaType = \"video\" | \"audio\" | \"image\";\n\nconst EXTENSIONS: Record<MediaType, string[]> = {\n video: [\"mp4\", \"webm\", \"ogg\", \"mov\", \"mkv\", \"m3u8\"],\n audio: [\"mp3\", \"wav\", \"ogg\", \"m4a\", \"aac\", \"flac\"],\n image: [\"jpg\", \"jpeg\", \"png\", \"gif\", \"webp\", \"svg\"],\n};\n\nfunction isValidUrl(url: string) {\n try {\n // eslint-disable-next-line no-new\n new URL(url);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction matchesType(url: string, type: MediaType) {\n const pathname = (() => {\n try {\n return new URL(url).pathname.toLowerCase();\n } catch {\n return url.toLowerCase();\n }\n })();\n const ext = pathname.split(\".\").pop() || \"\";\n return EXTENSIONS[type].includes(ext);\n}\n\n// (name extraction removed; naming handled by caller if needed)\n\nexport default function UrlInput({\n type,\n onSubmit,\n}: {\n type: MediaType;\n onSubmit: (url: string) => void;\n}) {\n const [url, setUrl] = useState(\"\");\n const [error, setError] = useState<string>(\"\");\n\n const tryAdd = async () => {\n const trimmed = url.trim();\n if (!trimmed) return;\n\n if (!isValidUrl(trimmed)) {\n setError(\"Enter a valid URL\");\n return;\n }\n\n if (!matchesType(trimmed, type)) {\n setError(`URL must be a ${type} (${EXTENSIONS[type].join(\", \")})`);\n return;\n }\n\n setError(\"\");\n\n onSubmit(trimmed);\n setUrl(\"\");\n };\n\n const onKeyDown: React.KeyboardEventHandler<HTMLInputElement> = (e) => {\n if (e.key === \"Enter\") {\n e.preventDefault();\n void tryAdd();\n }\n };\n\n return (\n <div>\n <div className=\"flex-container\">\n <input\n type=\"url\"\n placeholder={`Paste ${type} URL...`}\n value={url}\n onChange={(e) => setUrl(e.target.value)}\n onKeyDown={onKeyDown}\n className=\"input w-full\"\n />\n <button\n className=\"btn-ghost\"\n onClick={() => void tryAdd()}\n aria-label={`Add ${type} by URL`}\n >\n <Plus size={16} />\n </button>\n </div>\n {error ? <span className=\"text-error\">{error}</span> : null}\n </div>\n );\n}\n","import { createContext, useContext, useEffect, useState, ReactNode } from \"react\";\nimport type { MediaItem } from \"@twick/video-editor\";\nimport { getMediaManager, initializeDefaultVideos } from \"../components/shared\";\n\ntype MediaType = \"video\" | \"audio\" | \"image\";\n\ninterface MediaState {\n items: MediaItem[];\n searchQuery: string;\n isLoading: boolean;\n}\n\ninterface MediaContextType {\n videoState: MediaState;\n audioState: MediaState;\n imageState: MediaState;\n setSearchQuery: (type: MediaType, query: string) => void;\n addItem: (type: MediaType, item: MediaItem) => void;\n}\n\nconst initialMediaState: MediaState = {\n items: [],\n searchQuery: \"\",\n isLoading: false,\n};\n\nconst MediaContext = createContext<MediaContextType | null>(null);\n\nexport function MediaProvider({ children }: { children: ReactNode }) {\n const [videoState, setVideoState] = useState<MediaState>(initialMediaState);\n const [audioState, setAudioState] = useState<MediaState>(initialMediaState);\n const [imageState, setImageState] = useState<MediaState>(initialMediaState);\n const mediaManager = getMediaManager();\n\n const getStateAndSetter = (type: MediaType): [MediaState, (state: MediaState) => void] => {\n switch (type) {\n case \"video\":\n return [videoState, setVideoState];\n case \"audio\":\n return [audioState, setAudioState];\n case \"image\":\n return [imageState, setImageState];\n }\n };\n\n const loadItems = async (type: MediaType, query: string) => {\n const [state, setState] = getStateAndSetter(type);\n \n setState({ ...state, isLoading: true });\n try {\n const results = await mediaManager.search({\n query,\n type,\n });\n setState({\n items: results,\n searchQuery: query,\n isLoading: false,\n });\n } catch (error) {\n console.error(`Error loading ${type} items:`, error);\n setState({\n ...state,\n isLoading: false,\n });\n }\n };\n\n // Initialize default videos and load initial data for each type\n useEffect(() => {\n const initialize = async () => {\n // Initialize default videos first\n await initializeDefaultVideos();\n // Then load all media items\n loadItems(\"video\", \"\");\n loadItems(\"audio\", \"\");\n loadItems(\"image\", \"\");\n };\n initialize();\n }, []);\n\n const setSearchQuery = (type: MediaType, query: string) => {\n const [state, setState] = getStateAndSetter(type);\n setState({ ...state, searchQuery: query });\n loadItems(type, query);\n };\n\n const addItem = (type: MediaType, newItem: MediaItem) => {\n const [state, setState] = getStateAndSetter(type);\n setState({\n ...state,\n items: [...state.items, newItem],\n });\n };\n\n return (\n <MediaContext.Provider\n value={{\n videoState,\n audioState,\n imageState,\n setSearchQuery,\n addItem,\n }}\n >\n {children}\n </MediaContext.Provider>\n );\n}\n\nexport function useMedia(type: MediaType) {\n const context = useContext(MediaContext);\n if (!context) {\n throw new Error(\"useMedia must be used within a MediaProvider\");\n }\n\n const state = context[`${type}State`];\n return {\n items: state.items,\n searchQuery: state.searchQuery,\n isLoading: state.isLoading,\n setSearchQuery: (query: string) => context.setSearchQuery(type, query),\n addItem: (item: MediaItem) => context.addItem(type, item),\n };\n}\n","import {\n TrackElement,\n VideoElement,\n AudioElement,\n ImageElement,\n Size,\n} from \"@twick/timeline\";\nimport type { MediaItem } from \"@twick/video-editor\";\nimport { getMediaManager } from \"../components/shared\";\nimport { useMedia } from \"../context/media-context\";\n\nexport interface MediaPanelState {\n items: MediaItem[];\n searchQuery: string;\n isLoading: boolean;\n acceptFileTypes: string[];\n}\n\nexport interface MediaPanelActions {\n setSearchQuery: (query: string) => void;\n handleSelection: (item: MediaItem, forceAdd?: boolean) => void;\n handleFileUpload: (fileData: { file: File; blobUrl: string }) => void;\n}\n\nexport type MediaType = \"video\" | \"audio\" | \"image\";\n\nconst mediaConfigs = {\n video: {\n acceptFileTypes: [\"video/*\"] as string[],\n createElement: (url: string, parentSize: Size) =>\n new VideoElement(url, parentSize),\n updateElement: async (element: TrackElement, url: string) => {\n if (element instanceof VideoElement) {\n element.setSrc(url);\n await element.updateVideoMeta();\n }\n },\n },\n audio: {\n acceptFileTypes: [\"audio/*\"] as string[],\n createElement: (url: string, _parentSize: Size) => new AudioElement(url),\n updateElement: async (element: TrackElement, url: string) => {\n if (element instanceof AudioElement) {\n element.setSrc(url);\n await element.updateAudioMeta();\n }\n },\n },\n image: {\n acceptFileTypes: [\"image/*\"] as string[],\n createElement: (url: string, parentSize: Size) =>\n new ImageElement(url, parentSize),\n updateElement: async (element: TrackElement, url: string) => {\n if (element instanceof ImageElement) {\n element.setSrc(url);\n await element.updateImageMeta();\n }\n },\n },\n};\n\nexport const useMediaPanel = (\n type: MediaType,\n {\n selectedElement,\n addElement,\n updateElement,\n }: {\n selectedElement: TrackElement | null;\n addElement: (element: TrackElement) => void;\n updateElement: (element: TrackElement) => void;\n },\n videoResolution: Size\n): MediaPanelState & MediaPanelActions => {\n const { items, searchQuery, setSearchQuery, addItem, isLoading } =\n useMedia(type);\n const mediaManager = getMediaManager();\n\n const handleSelection = async (item: MediaItem, forceAdd?: boolean) => {\n const config = mediaConfigs[type];\n if (forceAdd) {\n const element = config.createElement(item.url, videoResolution);\n addElement(element);\n } else {\n if (selectedElement) {\n await config.updateElement(selectedElement, item.url);\n updateElement(selectedElement);\n } else {\n const element = config.createElement(item.url, videoResolution);\n addElement(element);\n }\n }\n };\n\n const handleFileUpload = async (fileData: {\n file: File;\n blobUrl: string;\n }) => {\n const arrayBuffer = await fileData.file.arrayBuffer();\n const newItem = await mediaManager.addItem({\n name: fileData.file.name,\n url: fileData.blobUrl,\n type,\n arrayBuffer,\n metadata: {\n name: fileData.file.name,\n size: fileData.file.size,\n type: fileData.file.type,\n },\n });\n addItem(newItem);\n };\n\n const config = mediaConfigs[type];\n return {\n items,\n searchQuery,\n setSearchQuery,\n handleSelection,\n handleFileUpload,\n isLoading,\n acceptFileTypes: config.acceptFileTypes,\n };\n};\n","import { useState, useCallback, useRef, useEffect } from 'react';\nimport type { MediaItem } from '@twick/video-editor';\n\nexport interface AudioPreviewState {\n playingAudio: string | null; // ID of currently playing audio\n audioElement: HTMLAudioElement | null;\n}\n\nexport interface AudioPreviewActions {\n togglePlayPause: (item: MediaItem) => void;\n stopPlayback: () => void;\n}\n\nexport const useAudioPreview = (): AudioPreviewState & AudioPreviewActions => {\n const [playingAudio, setPlayingAudio] = useState<string | null>(null);\n const audioRef = useRef<HTMLAudioElement | null>(null);\n\n // Cleanup audio element on unmount\n useEffect(() => {\n return () => {\n if (audioRef.current) {\n audioRef.current.pause();\n audioRef.current = null;\n }\n };\n }, []);\n\n const stopPlayback = useCallback(() => {\n if (audioRef.current) {\n audioRef.current.pause();\n audioRef.current = null;\n }\n setPlayingAudio(null);\n }, []);\n\n const togglePlayPause = useCallback((item: MediaItem) => {\n // If we're already playing this audio, stop it\n if (playingAudio === item.id) {\n stopPlayback();\n return;\n }\n\n // Stop any currently playing audio\n stopPlayback();\n\n // Start playing the new audio\n const audio = new Audio(item.url);\n audio.addEventListener('ended', stopPlayback);\n audio.play();\n audioRef.current = audio;\n setPlayingAudio(item.id);\n }, [playingAudio, stopPlayback]);\n\n return {\n playingAudio,\n audioElement: audioRef.current,\n togglePlayPause,\n stopPlayback,\n };\n};\n","/**\n * AudioPanel Component\n * \n * A panel for managing audio elements in the studio. Provides functionality\n * for searching, uploading, previewing, and adding audio files to the timeline.\n * \n * @component\n * @param {Object} props\n * @param {MediaItem[]} props.items - List of audio items to display\n * @param {string} props.searchQuery - Current search query\n * @param {string | null} props.playingAudio - ID of currently playing audio, if any\n * @param {(query: string) => void} props.onSearchChange - Handle search query changes\n * @param {(item: MediaItem) => void} props.onItemSelect - Handle audio item selection\n * @param {(item: MediaItem) => void} props.onPlayPause - Toggle audio preview playback\n * @param {(data: { file: File; blobUrl: string }) => void} props.onFileUpload - Handle file uploads\n * \n * @example\n * ```tsx\n * <AudioPanel\n * items={audioItems}\n * searchQuery=\"\"\n * playingAudio={null}\n * onSearchChange={setSearchQuery}\n * onItemSelect={handleSelect}\n * onPlayPause={togglePlayback}\n * onFileUpload={handleUpload}\n * />\n * ```\n */\n\nimport { Wand2, Plus, Volume2, Play, Pause } from \"lucide-react\";\nimport { TIMELINE_DROP_MEDIA_TYPE } from \"@twick/video-editor\";\nimport UrlInput from \"../shared/url-input\";\nimport type { AudioPanelProps } from \"../../types/media-panel\";\nimport { useAudioPreview } from \"../../hooks/use-audio-preview\";\n\n\nexport const AudioPanel = ({\n items,\n onItemSelect,\n onUrlAdd,\n}: AudioPanelProps) => {\n const { playingAudio, togglePlayPause } = useAudioPreview();\n return (\n <div className=\"panel-container\">\n <div className=\"panel-title\">Audio Library</div>\n\n {/* Add by URL */}\n <div className=\"panel-section\">\n <UrlInput type=\"audio\" onSubmit={onUrlAdd} />\n </div>\n\n {/* Upload */}\n {/* <div className=\"flex panel-section\">\n <FileInput\n id=\"audio-upload\"\n acceptFileTypes={acceptFileTypes}\n onFileLoad={onFileUpload}\n buttonText=\"Import media\"\n className=\"btn-primary w-full\"\n icon={<Upload className=\"icon-sm\" />}\n />\n </div> */}\n\n {/* Audio List */}\n <div className=\"media-content\">\n <div className=\"media-list\">\n {(items || []).map((item) => (\n <div\n key={item.id}\n draggable\n onDoubleClick={() => onItemSelect(item)}\n onDragStart={(e) => {\n e.dataTransfer.setData(\n TIMELINE_DROP_MEDIA_TYPE,\n JSON.stringify({ type: \"audio\", url: item.url })\n );\n e.dataTransfer.effectAllowed = \"copy\";\n }}\n className=\"media-list-item media-item-draggable\"\n >\n {/* Audio Info */}\n <div className=\"media-list-content\">\n {/* Play/Pause button */}\n <button\n onClick={(e) => {\n e.stopPropagation();\n togglePlayPause(item);\n }}\n className=\"media-action-btn\"\n >\n {playingAudio === item.id ? (\n <Pause className=\"icon-sm\" />\n ) : (\n <Play className=\"icon-sm\" />\n )}\n </button>\n\n {/* Audio Icon */}\n <div className={`media-list-icon ${playingAudio === item.id ? 'active' : ''}`}>\n <Volume2 className=\"icon-sm\" />\n </div>\n\n {/* Audio Title */}\n <div className=\"media-list-title\">\n {item.metadata?.title || item.metadata?.name}\n </div>\n\n {/* Quick Add button */}\n <button\n onClick={(e) => {\n e.stopPropagation();\n onItemSelect(item, true);\n }}\n className=\"media-action-btn\"\n >\n <Plus className=\"icon-sm\" />\n </button>\n </div>\n </div>\n ))}\n </div>\n\n {/* Empty state */}\n {items.length === 0 && (\n <div className=\"empty-state\">\n <div className=\"empty-state-content\">\n <Wand2 className=\"empty-state-icon\" />\n <p className=\"empty-state-text\">No audio files found</p>\n </div>\n </div>\n )}\n </div>\n </div>\n );\n};","import { useMediaPanel } from \"../../hooks/use-media-panel\";\nimport { AudioPanel } from \"../panel/audio-panel\";\nimport type { PanelProps } from \"../../types\";\nimport { useMedia } from \"../../context/media-context\";\nimport { getMediaManager } from \"../shared\";\n\nexport const AudioPanelContainer = (props: PanelProps) => {\n const { addItem } = useMedia(\"audio\");\n const mediaManager = getMediaManager();\n const {\n items,\n searchQuery,\n setSearchQuery,\n handleSelection,\n handleFileUpload,\n isLoading,\n acceptFileTypes,\n } = useMediaPanel(\"audio\", {\n selectedElement: props.selectedElement ?? null,\n addElement: props.addElement!,\n updateElement: props.updateElement!,\n },\n props.videoResolution);\n\n const onUrlAdd = async (url: string) => {\n const nameFromUrl = (() => {\n try {\n const u = new URL(url);\n const parts = u.pathname.split(\"/\").filter(Boolean);\n return decodeURIComponent(parts[parts.length - 1] || url);\n } catch {\n return url;\n }\n })();\n\n const newItem = await mediaManager.addItem({\n name: nameFromUrl,\n url,\n type: \"audio\",\n metadata: { source: \"url\" },\n });\n addItem(newItem);\n };\n\n return (\n <AudioPanel\n items={items}\n searchQuery={searchQuery}\n onSearchChange={setSearchQuery}\n onItemSelect={handleSelection}\n onFileUpload={handleFileUpload}\n isLoading={isLoading}\n acceptFileTypes={acceptFileTypes}\n onUrlAdd={onUrlAdd}\n />\n );\n};\n","/**\n * ImagePanel Component\n *\n * A panel for managing image elements in the studio. Provides functionality\n * for searching, uploading, previewing, and adding image files to the timeline.\n * Features a grid layout with image thumbnails and hover actions.\n *\n * @component\n * @param {Object} props\n * @param {MediaItem[]} props.items - List of image items to display\n * @param {string} props.searchQuery - Current search query\n * @param {(query: string) => void} props.setSearchQuery - Handle search query changes\n * @param {(item: MediaItem) => void} props.handleSelection - Handle image item selection\n * @param {(data: { file: File; blobUrl: string }) => void} props.handleFileUpload - Handle file uploads\n *\n * @example\n * ```tsx\n * <ImagePanel\n * items={imageItems}\n * searchQuery=\"\"\n * setSearchQuery={setSearchQuery}\n * handleSelection={handleSelect}\n * handleFileUpload={handleUpload}\n * />\n * ```\n */\n\nimport { Wand2, Plus } from \"lucide-react\";\nimport type { MediaItem } from \"@twick/video-editor\";\nimport { TIMELINE_DROP_MEDIA_TYPE } from \"@twick/video-editor\";\nimport type { ImagePanelProps } from \"../../types/media-panel\";\nimport UrlInput from \"../shared/url-input\";\n\nexport function ImagePanel({\n items,\n onItemSelect,\n onUrlAdd,\n}: ImagePanelProps) {\n return (\n <div className=\"panel-container\">\n <div className=\"panel-title\">Image Library</div>\n\n {/* Add by URL */}\n <div className=\"panel-section\">\n <UrlInput type=\"image\" onSubmit={onUrlAdd} />\n </div>\n {/* Upload */}\n {/* <div className=\"flex panel-section\">\n <FileInput\n id=\"image-upload\"\n acceptFileTypes={acceptFileTypes}\n onFileLoad={onFileUpload}\n buttonText=\"Import media\"\n className=\"btn-primary w-full\"\n icon={<Upload className=\"icon-sm\" />}\n />\n </div> */}\n\n {/* Media Grid */}\n <div className=\"media-content\">\n <div className=\"media-grid\">\n {(items || []).map((item: MediaItem) => (\n <div\n key={item.id}\n draggable\n onDoubleClick={() => onItemSelect(item)}\n onDragStart={(e) => {\n e.dataTransfer.setData(\n TIMELINE_DROP_MEDIA_TYPE,\n JSON.stringify({ type: \"image\", url: item.url })\n );\n e.dataTransfer.effectAllowed = \"copy\";\n }}\n className=\"media-item media-item-draggable\"\n >\n <img src={item.url} alt=\"\" className=\"media-item-content\" />\n <div className=\"media-actions media-actions-corner\">\n <button\n onClick={(e) => {\n e.stopPropagation();\n onItemSelect(item, true);\n }}\n className=\"media-action-btn\"\n >\n <Plus className=\"icon-sm\" />\n </button>\n </div>\n </div>\n ))}\n </div>\n\n {/* Empty state */}\n {items.length === 0 && (\n <div className=\"empty-state\">\n <div className=\"empty-state-content\">\n <Wand2 className=\"empty-state-icon\" />\n <p className=\"empty-state-text\">No images found</p>\n </div>\n </div>\n )}\n </div>\n </div>\n );\n}\n","import type { PanelProps } from \"../../types\";\nimport { ImagePanel } from \"../panel/image-panel\";\nimport { useMediaPanel } from \"../../hooks/use-media-panel\";\nimport { useMedia } from \"../../context/media-context\";\nimport { getMediaManager } from \"../shared\";\n\nexport function ImagePanelContainer(props: PanelProps) {\n const { addItem } = useMedia(\"image\");\n const mediaManager = getMediaManager();\n const {\n items,\n searchQuery,\n setSearchQuery,\n handleSelection,\n handleFileUpload,\n isLoading,\n acceptFileTypes,\n } = useMediaPanel(\"image\", {\n selectedElement: props.selectedElement ?? null,\n addElement: props.addElement!,\n updateElement: props.updateElement!,\n },\n props.videoResolution);\n\n const onUrlAdd = async (url: string) => {\n const nameFromUrl = (() => {\n try {\n const u = new URL(url);\n const parts = u.pathname.split(\"/\").filter(Boolean);\n return decodeURIComponent(parts[parts.length - 1] || url);\n } catch {\n return url;\n }\n })();\n\n const newItem = await mediaManager.addItem({\n name: nameFromUrl,\n url,\n type: \"image\",\n metadata: { source: \"url\" },\n });\n addItem(newItem);\n };\n\n return (\n <ImagePanel\n items={items}\n searchQuery={searchQuery}\n onSearchChange={setSearchQuery}\n onItemSelect={handleSelection}\n onFileUpload={handleFileUpload}\n isLoading={isLoading}\n acceptFileTypes={acceptFileTypes}\n onUrlAdd={onUrlAdd}\n />\n );\n}\n","import { useState, useCallback, useRef, useEffect } from 'react';\nimport type { MediaItem } from '@twick/video-editor';\n\nexport interface VideoPreviewState {\n playingVideo: string | null; // ID of currently playing video\n videoElement: HTMLVideoElement | null;\n}\n\nexport interface VideoPreviewActions {\n togglePlayPause: (item: MediaItem, videoElement: HTMLVideoElement) => void;\n stopPlayback: () => void;\n}\n\nexport const useVideoPreview = (): VideoPreviewState & VideoPreviewActions => {\n const [playingVideo, setPlayingVideo] = useState<string | null>(null);\n const videoRef = useRef<HTMLVideoElement | null>(null);\n\n // Cleanup video element on unmount\n useEffect(() => {\n return () => {\n if (videoRef.current) {\n videoRef.current.pause();\n videoRef.current = null;\n }\n };\n }, []);\n\n const stopPlayback = useCallback(() => {\n if (videoRef.current) {\n videoRef.current.pause();\n videoRef.current = null;\n }\n setPlayingVideo(null);\n }, []);\n\n const togglePlayPause = useCallback((item: MediaItem, videoElement: HTMLVideoElement) => {\n // If we're already playing this video, pause it\n if (playingVideo === item.id) {\n videoElement.pause();\n stopPlayback();\n return;\n }\n\n // Stop any currently playing video\n stopPlayback();\n\n // Start playing the new video\n videoElement.currentTime = 0; // Reset to start\n videoElement.play();\n videoRef.current = videoElement;\n setPlayingVideo(item.id);\n\n // Add ended event listener\n videoElement.addEventListener('ended', stopPlayback, { once: true });\n }, [playingVideo, stopPlayback]);\n\n return {\n playingVideo,\n videoElement: videoRef.current,\n togglePlayPause,\n stopPlayback,\n };\n};","/**\n * VideoPanel Component\n * \n * A panel for managing video elements in the studio. Provides functionality\n * for searching, uploading, previewing, and adding video files to the timeline.\n * Features a grid layout with video thumbnails and hover actions.\n * \n * @component\n * @param {Object} props\n * @param {MediaItem[]} props.items - List of video items to display\n * @param {string} props.searchQuery - Current search query\n * @param {(query: string) => void} props.setSearchQuery - Handle search query changes\n * @param {(item: MediaItem) => void} props.handleSelection - Handle video item selection\n * @param {(data: { file: File; blobUrl: string }) => void} props.handleFileUpload - Handle file uploads\n * \n * @example\n * ```tsx\n * <VideoPanel\n * items={videoItems}\n * searchQuery=\"\"\n * setSearchQuery={setSearchQuery}\n * handleSelection={handleSelect}\n * handleFileUpload={handleUpload}\n * />\n * ```\n */\n\nimport { Wand2, Plus, Play, Pause } from \"lucide-react\";\nimport type { MediaItem } from \"@twick/video-editor\";\nimport { TIMELINE_DROP_MEDIA_TYPE } from \"@twick/video-editor\";\nimport type { VideoPanelProps } from \"../../types/media-panel\";\nimport { useVideoPreview } from \"../../hooks/use-video-preview\";\nimport UrlInput from \"../shared/url-input\";\n\n\nexport function VideoPanel({\n items,\n onItemSelect,\n onUrlAdd,\n}: VideoPanelProps) {\n const { playingVideo, togglePlayPause } = useVideoPreview();\n return (\n <div className=\"panel-container\">\n <div className=\"panel-title\">Video Library</div>\n\n {/* Add by URL */}\n <div className=\"flex panel-section\">\n <UrlInput type=\"video\" onSubmit={onUrlAdd} />\n </div>\n\n {/* Import Button */}\n {/* <div className=\"flex panel-section\">\n <FileInput\n id=\"video-upload\"\n acceptFileTypes={acceptFileTypes}\n onFileLoad={onFileUpload}\n buttonText=\"Import media\"\n className=\"btn-primary w-full\"\n icon={<Upload className=\"icon-sm\" />}\n />\n </div> */}\n\n {/* Media Grid */}\n <div className=\"media-content\">\n <div className=\"media-grid\">\n {(items || []).map((item: MediaItem) => (\n <div\n key={item.id}\n draggable\n onDoubleClick={() => onItemSelect(item)}\n onDragStart={(e) => {\n e.dataTransfer.setData(\n TIMELINE_DROP_MEDIA_TYPE,\n JSON.stringify({ type: \"video\", url: item.url })\n );\n e.dataTransfer.effectAllowed = \"copy\";\n }}\n className=\"media-item media-item-draggable\"\n >\n <video\n src={item.url}\n poster={item.thumbnail}\n className=\"media-item-content\"\n ref={(el) => {\n if (el) {\n el.addEventListener('ended', () => {\n el.currentTime = 0;\n }, { once: true });\n }\n }}\n />\n\n {/* Duration */}\n {/* <div className=\"media-duration\">\n 0:13\n </div> */}\n\n {/* Corner play/pause control */}\n <div className=\"media-actions media-actions-corner\">\n <button\n onClick={(e) => {\n e.stopPropagation();\n const videoEl =\n e.currentTarget.parentElement?.parentElement?.querySelector(\"video\");\n if (videoEl) {\n togglePlayPause(item, videoEl);\n }\n }}\n className=\"media-action-btn\"\n >\n {playingVideo === item.id ? (\n <Pause className=\"icon-sm\" />\n ) : (\n <Play className=\"icon-sm\" />\n )}\n </button>\n <button\n onClick={(e) => {\n e.stopPropagation();\n onItemSelect(item, true);\n }}\n className=\"media-action-btn\"\n >\n <Plus className=\"icon-sm\" />\n </button>\n </div>\n </div>\n ))}\n </div>\n\n {/* Empty state */}\n {items.length === 0 && (\n <div className=\"empty-state\">\n <div className=\"empty-state-content\">\n <Wand2 className=\"empty-state-icon\" />\n <p className=\"empty-state-text\">No videos found</p>\n </div>\n </div>\n )}\n </div>\n </div>\n );\n}","import type { PanelProps } from \"../../types\";\nimport { VideoPanel } from \"../panel/video-panel\";\nimport { useMediaPanel } from \"../../hooks/use-media-panel\";\nimport { useMedia } from \"../../context/media-context\";\nimport { getMediaManager } from \"../shared\";\n\nexport function VideoPanelContainer(props: PanelProps) {\n const { addItem } = useMedia(\"video\");\n const mediaManager = getMediaManager();\n const {\n items,\n handleSelection,\n handleFileUpload,\n isLoading,\n acceptFileTypes,\n } = useMediaPanel(\"video\", {\n selectedElement: props.selectedElement ?? null,\n addElement: props.addElement!,\n updateElement: props.updateElement!,\n },\n props.videoResolution);\n\n const onUrlAdd = async (url: string) => {\n const nameFromUrl = (() => {\n try {\n const u = new URL(url);\n const parts = u.pathname.split(\"/\").filter(Boolean);\n return decodeURIComponent(parts[parts.length - 1] || url);\n } catch {\n return url;\n }\n })();\n\n const newItem = await mediaManager.addItem({\n name: nameFromUrl,\n url,\n type: \"video\",\n metadata: { source: \"url\" },\n });\n addItem(newItem);\n };\n\n return (\n <VideoPanel\n items={items}\n onItemSelect={handleSelection}\n onFileUpload={handleFileUpload}\n isLoading={isLoading}\n acceptFileTypes={acceptFileTypes}\n onUrlAdd={onUrlAdd}\n />\n );\n}\n","/**\n * TextPanel Component\n * \n * A panel for creating and editing text elements in the studio. Provides comprehensive\n * text styling options including font selection, size, colors, stroke, and shadow effects.\n * \n * @component\n * @param {Object} props\n * @param {string} props.textContent - Text content to display\n * @param {number} props.fontSize - Font size in pixels\n * @param {string} props.selectedFont - Selected font family\n * @param {boolean} props.isBold - Whether text is bold\n * @param {boolean} props.isItalic - Whether text is italic\n * @param {string} props.textColor - Text color in hex format\n * @param {string} props.strokeColor - Stroke color in hex format\n * @param {boolean} props.applyShadow - Whether to apply shadow effect\n * @param {string} props.shadowColor - Shadow color in hex format\n * @param {number} props.strokeWidth - Width of text stroke\n * @param {boolean} props.applyBackground - Whether to apply background behind text\n * @param {string} props.backgroundColor - Background color in hex (when applyBackground is true)\n * @param {number} props.backgroundOpacity - Background opacity 0-1 (when applyBackground is true)\n * @param {string[]} props.fonts - Available font options\n * @param {(text: string) => void} props.setTextContent - Update text content\n * @param {(size: number) => void} props.setFontSize - Update font size\n * @param {(font: string) => void} props.setSelectedFont - Update selected font\n * @param {(bold: boolean) => void} props.setIsBold - Toggle bold style\n * @param {(italic: boolean) => void} props.setIsItalic - Toggle italic style\n * @param {(color: string) => void} props.setTextColor - Update text color\n * @param {(color: string) => void} props.setStrokeColor - Update stroke color\n * @param {(apply: boolean) => void} props.setApplyShadow - Toggle shadow effect\n * @param {(color: string) => void} props.setShadowColor - Update shadow color\n * @param {(width: number) => void} props.setStrokeWidth - Update stroke width\n * @param {(apply: boolean) => void} props.setApplyBackground - Toggle background\n * @param {(color: string) => void} props.setBackgroundColor - Update background color\n * @param {(opacity: number) => void} props.setBackgroundOpacity - Update background opacity\n * @param {() => void} props.handleApplyChanges - Apply text element changes\n * \n * @example\n * ```tsx\n * <TextPanel\n * textContent=\"Sample Text\"\n * fontSize={48}\n * selectedFont=\"Arial\"\n * isBold={false}\n * isItalic={false}\n * textColor=\"#000000\"\n * strokeColor=\"#ffffff\"\n * applyShadow={false}\n * shadowColor=\"#000000\"\n * strokeWidth={0}\n * fonts={[\"Arial\", \"Times New Roman\"]}\n * setTextContent={setText}\n * setFontSize={setSize}\n * // ... other handlers\n * />\n * ```\n */\n\nimport type { TextPanelState, TextPanelActions } from \"../../hooks/use-text-panel\";\n\nexport type TextPanelProps = TextPanelState & TextPanelActions;\n\nexport function TextPanel({\n textContent,\n fontSize,\n selectedFont,\n isBold,\n isItalic,\n textColor,\n strokeColor,\n applyShadow,\n shadowColor,\n strokeWidth,\n applyBackground,\n backgroundColor,\n backgroundOpacity,\n fonts,\n operation,\n setTextContent,\n setFontSize,\n setSelectedFont,\n setIsBold,\n setIsItalic,\n setTextColor,\n setStrokeColor,\n setApplyShadow,\n setShadowColor,\n setStrokeWidth,\n setApplyBackground,\n setBackgroundColor,\n setBackgroundOpacity,\n handleApplyChanges,\n}: TextPanelProps) {\n return (\n <div className=\"panel-container\">\n <div className=\"panel-title\">Text</div>\n {/* Text Content */}\n <div className=\"flex panel-section\">\n <input\n type=\"text\"\n value={textContent}\n placeholder=\"Sample\"\n onChange={(e) => setTextContent(e.target.value)}\n className=\"input-dark\"\n />\n </div>\n\n {/* Font Size */}\n <div className=\"panel-section\">\n <label className=\"label-dark\">Font Size</label>\n <div className=\"slider-container\">\n <input\n type=\"range\"\n min=\"8\"\n max=\"120\"\n value={fontSize}\n onChange={(e) => setFontSize(Number(e.target.value))}\n className=\"slider-purple\"\n />\n <span className=\"slider-value\">{fontSize}px</span>\n </div>\n </div>\n\n {/* Font */}\n <div className=\"panel-section\">\n <label className=\"label-dark\">Font</label>\n <div className=\"font-controls\">\n <select\n value={selectedFont}\n onChange={(e) => setSelectedFont(e.target.value)}\n className=\"select-dark\"\n >\n {fonts.map((font) => (\n <option key={font} value={font}>\n {font}\n </option>\n ))}\n </select>\n <button\n onClick={() => setIsBold(!isBold)}\n className={`btn-icon ${isBold ? 'btn-icon-active' : ''}`}\n >\n B\n </button>\n <button\n onClick={() => setIsItalic(!isItalic)}\n className={`btn-icon ${isItalic ? 'btn-icon-active' : ''}`}\n >\n I\n </button>\n </div>\n </div>\n\n {/* Colors */}\n <div className=\"panel-section\">\n <label className=\"label-dark\">Colors</label>\n <div className=\"color-section\">\n {/* Text Color */}\n <div className=\"color-control\">\n <label className=\"label-small\">Text Color</label>\n <div className=\"color-inputs\">\n <input\n type=\"color\"\n value={textColor}\n onChange={(e) => setTextColor(e.target.value)}\n className=\"color-picker\"\n />\n <input\n type=\"text\"\n value={textColor}\n onChange={(e) => setTextColor(e.target.value)}\n className=\"color-text\"\n />\n </div>\n </div>\n\n {/* Stroke Color */}\n <div className=\"color-control\">\n <label className=\"label-small\">Stroke Color</label>\n <div className=\"color-inputs\">\n <input\n type=\"color\"\n value={strokeColor}\n onChange={(e) => setStrokeColor(e.target.value)}\n className=\"color-picker\"\n />\n <input\n type=\"text\"\n value={strokeColor}\n onChange={(e) => setStrokeColor(e.target.value)}\n className=\"color-text\"\n />\n </div>\n </div>\n\n {/* Apply Shadow */}\n <div className=\"checkbox-control\">\n <label className=\"checkbox-label\">\n <input\n type=\"checkbox\"\n checked={applyShadow}\n onChange={(e) => setApplyShadow(e.target.checked)}\n className=\"checkbox-purple\"\n />\n Apply Shadow\n </label>\n </div>\n\n {/* Shadow Color - Only shown when shadow is enabled */}\n {applyShadow && (\n <div className=\"color-control\">\n <label className=\"label-small\">Shadow Color</label>\n <div className=\"color-inputs\">\n <input\n type=\"color\"\n value={shadowColor}\n onChange={(e) => setShadowColor(e.target.value)}\n className=\"color-picker\"\n />\n <input\n type=\"text\"\n value={shadowColor}\n onChange={(e) => setShadowColor(e.target.value)}\n className=\"color-text\"\n />\n </div>\n </div>\n )}\n </div>\n </div>\n\n {/* Stroke Width */}\n <div className=\"panel-section\">\n <label className=\"label-dark\">Stroke Width</label>\n <div className=\"slider-container\">\n <input\n type=\"range\"\n min=\"0\"\n max=\"2\"\n step={0.1}\n value={strokeWidth}\n onChange={(e) => setStrokeWidth(Number(e.target.value))}\n className=\"slider-purple\"\n />\n <span className=\"slider-value\">{strokeWidth}</span>\n </div>\n </div>\n\n {/* Background (optional) */}\n <div className=\"panel-section\">\n <label className=\"label-dark\">Background</label>\n <div className=\"color-section\">\n <div className=\"checkbox-control\">\n <label className=\"checkbox-label\">\n <input\n type=\"checkbox\"\n checked={applyBackground}\n onChange={(e) => setApplyBackground(e.target.checked)}\n className=\"checkbox-purple\"\n />\n Apply Background\n </label>\n </div>\n {applyBackground && (\n <>\n <div className=\"color-control\">\n <label className=\"label-small\">Background Color</label>\n <div className=\"color-inputs\">\n <input\n type=\"color\"\n value={backgroundColor}\n onChange={(e) => setBackgroundColor(e.target.value)}\n className=\"color-picker\"\n />\n <input\n type=\"text\"\n value={backgroundColor}\n onChange={(e) => setBackgroundColor(e.target.value)}\n className=\"color-text\"\n />\n </div>\n </div>\n <div className=\"panel-section\">\n <label className=\"label-small\">Background Opacity</label>\n <div className=\"slider-container\">\n <input\n type=\"range\"\n min=\"0\"\n max=\"1\"\n step={0.1}\n value={backgroundOpacity}\n onChange={(e) => setBackgroundOpacity(Number(e.target.value))}\n className=\"slider-purple\"\n />\n <span className=\"slider-value\">{Math.round(backgroundOpacity * 100)}%</span>\n </div>\n </div>\n </>\n )}\n </div>\n </div>\n\n {/* Operation button (only for creation, not edits) */}\n {operation !== \"Apply Changes\" && (\n <div className=\"flex panel-section\">\n <button onClick={handleApplyChanges} className=\"btn-primary w-full\">\n {operation}\n </button>\n </div>\n )}\n </div>\n );\n}","import { useEffect, useState } from \"react\";\nimport { TextElement, TrackElement, type TextAlign } from \"@twick/timeline\";\nimport { AVAILABLE_TEXT_FONTS } from \"@twick/video-editor\";\n\nexport const DEFAULT_TEXT_PROPS = {\n text: \"Sample\",\n fontSize: 48,\n fontFamily: \"Poppins\",\n fontWeight: 400,\n fontStyle: \"normal\",\n textColor: \"#ffffff\",\n strokeColor: \"#4d4d4d\",\n strokeWidth: 0,\n applyShadow: false,\n shadowColor: \"#000000\",\n textAlign: \"center\" as TextAlign,\n shadowOffset: [0, 0],\n shadowBlur: 2,\n shadowOpacity: 1.0,\n};\n\nexport interface TextPanelState {\n textContent: string;\n fontSize: number;\n selectedFont: string;\n isBold: boolean;\n isItalic: boolean;\n textColor: string;\n strokeColor: string;\n applyShadow: boolean;\n shadowColor: string;\n strokeWidth: number;\n applyBackground: boolean;\n backgroundColor: string;\n backgroundOpacity: number;\n fonts: string[];\n operation: string;\n}\n\nexport interface TextPanelActions {\n setTextContent: (text: string) => void;\n setFontSize: (size: number) => void;\n setSelectedFont: (font: string) => void;\n setIsBold: (bold: boolean) => void;\n setIsItalic: (italic: boolean) => void;\n setTextColor: (color: string) => void;\n setStrokeColor: (color: string) => void;\n setApplyShadow: (shadow: boolean) => void;\n setShadowColor: (color: string) => void;\n setStrokeWidth: (width: number) => void;\n setApplyBackground: (apply: boolean) => void;\n setBackgroundColor: (color: string) => void;\n setBackgroundOpacity: (opacity: number) => void;\n handleApplyChanges: () => void;\n}\n\nexport const useTextPanel = ({\n selectedElement,\n addElement,\n updateElement,\n}: {\n selectedElement: TrackElement | null;\n addElement: (element: TrackElement) => void;\n updateElement: (element: TrackElement) => void;\n}): TextPanelState & TextPanelActions => {\n const [textContent, setTextContent] = useState(DEFAULT_TEXT_PROPS.text);\n const [fontSize, setFontSize] = useState(DEFAULT_TEXT_PROPS.fontSize);\n const [selectedFont, setSelectedFont] = useState(DEFAULT_TEXT_PROPS.fontFamily);\n const [isBold, setIsBold] = useState(DEFAULT_TEXT_PROPS.fontWeight === 700);\n const [isItalic, setIsItalic] = useState(DEFAULT_TEXT_PROPS.fontStyle === \"italic\");\n const [textColor, setTextColor] = useState(DEFAULT_TEXT_PROPS.textColor);\n const [strokeColor, setStrokeColor] = useState(DEFAULT_TEXT_PROPS.strokeColor);\n const [applyShadow, setApplyShadow] = useState(DEFAULT_TEXT_PROPS.applyShadow);\n const [shadowColor, setShadowColor] = useState(DEFAULT_TEXT_PROPS.shadowColor);\n const [strokeWidth, setStrokeWidth] = useState(DEFAULT_TEXT_PROPS.strokeWidth);\n const [applyBackground, setApplyBackground] = useState(false);\n const [backgroundColor, setBackgroundColor] = useState(\"#FACC15\");\n const [backgroundOpacity, setBackgroundOpacity] = useState(1);\n\n const fonts = Object.values(AVAILABLE_TEXT_FONTS);\n\n const applyLiveChangesToExistingText = (overrides: Partial<TextPanelState> = {}) => {\n if (!(selectedElement instanceof TextElement)) {\n return;\n }\n\n const textElement = selectedElement;\n\n const nextState: Pick<\n TextPanelState,\n | \"textContent\"\n | \"fontSize\"\n | \"selectedFont\"\n | \"isBold\"\n | \"isItalic\"\n | \"textColor\"\n | \"strokeColor\"\n | \"strokeWidth\"\n | \"applyShadow\"\n | \"shadowColor\"\n | \"applyBackground\"\n | \"backgroundColor\"\n | \"backgroundOpacity\"\n > = {\n textContent,\n fontSize,\n selectedFont,\n isBold,\n isItalic,\n textColor,\n strokeColor,\n strokeWidth,\n applyShadow,\n shadowColor,\n applyBackground,\n backgroundColor,\n backgroundOpacity,\n ...overrides,\n };\n\n textElement.setText(nextState.textContent);\n textElement.setFontSize(nextState.fontSize);\n textElement.setFontFamily(nextState.selectedFont);\n textElement.setFontWeight(nextState.isBold ? 700 : 400);\n textElement.setFontStyle(nextState.isItalic ? \"italic\" : \"normal\");\n textElement.setFill(nextState.textColor);\n textElement.setStrokeColor(nextState.strokeColor);\n textElement.setLineWidth(nextState.strokeWidth);\n textElement.setTextAlign(DEFAULT_TEXT_PROPS.textAlign);\n\n const nextProps = { ...textElement.getProps() };\n\n if (nextState.applyShadow) {\n nextProps.shadowColor = nextState.shadowColor;\n nextProps.shadowOffset = DEFAULT_TEXT_PROPS.shadowOffset;\n nextProps.shadowBlur = DEFAULT_TEXT_PROPS.shadowBlur;\n nextProps.shadowOpacity = DEFAULT_TEXT_PROPS.shadowOpacity;\n } else {\n nextProps.shadowColor = undefined;\n nextProps.shadowOffset = undefined;\n nextProps.shadowBlur = undefined;\n nextProps.shadowOpacity = undefined;\n }\n\n if (nextState.applyBackground) {\n nextProps.backgroundColor = nextState.backgroundColor;\n nextProps.backgroundOpacity = nextState.backgroundOpacity;\n } else {\n nextProps.backgroundColor = undefined;\n nextProps.backgroundOpacity = undefined;\n }\n\n textElement.setProps(nextProps);\n updateElement(textElement);\n };\n\n const handleTextContentChange = (text: string) => {\n setTextContent(text);\n applyLiveChangesToExistingText({ textContent: text });\n };\n\n const handleFontSizeChange = (size: number) => {\n setFontSize(size);\n applyLiveChangesToExistingText({ fontSize: size });\n };\n\n const handleSelectedFontChange = (font: string) => {\n setSelectedFont(font);\n applyLiveChangesToExistingText({ selectedFont: font });\n };\n\n const handleIsBoldChange = (bold: boolean) => {\n setIsBold(bold);\n applyLiveChangesToExistingText({ isBold: bold });\n };\n\n const handleIsItalicChange = (italic: boolean) => {\n setIsItalic(italic);\n applyLiveChangesToExistingText({ isItalic: italic });\n };\n\n const handleTextColorChange = (color: string) => {\n setTextColor(color);\n applyLiveChangesToExistingText({ textColor: color });\n };\n\n const handleStrokeColorChange = (color: string) => {\n setStrokeColor(color);\n applyLiveChangesToExistingText({ strokeColor: color });\n };\n\n const handleStrokeWidthChange = (width: number) => {\n setStrokeWidth(width);\n applyLiveChangesToExistingText({ strokeWidth: width });\n };\n\n const handleApplyShadowChange = (shadow: boolean) => {\n setApplyShadow(shadow);\n applyLiveChangesToExistingText({ applyShadow: shadow });\n };\n\n const handleShadowColorChange = (color: string) => {\n setShadowColor(color);\n applyLiveChangesToExistingText({ shadowColor: color });\n };\n\n const handleApplyBackgroundChange = (apply: boolean) => {\n setApplyBackground(apply);\n applyLiveChangesToExistingText({ applyBackground: apply });\n };\n\n const handleBackgroundColorChange = (color: string) => {\n setBackgroundColor(color);\n applyLiveChangesToExistingText({ backgroundColor: color });\n };\n\n const handleBackgroundOpacityChange = (opacity: number) => {\n setBackgroundOpacity(opacity);\n applyLiveChangesToExistingText({ backgroundOpacity: opacity });\n };\n\n const handleApplyChanges = async () => {\n // For existing text elements, changes are already applied live via the handlers above.\n // The apply button is only meaningful when creating a new text element.\n if (selectedElement instanceof TextElement) {\n return;\n }\n\n const textElement = new TextElement(textContent)\n .setFontSize(fontSize)\n .setFontFamily(selectedFont)\n .setFontWeight(isBold ? 700 : 400)\n .setFontStyle(isItalic ? \"italic\" : \"normal\")\n .setFill(textColor)\n .setStrokeColor(strokeColor)\n .setLineWidth(strokeWidth)\n .setTextAlign(\"center\");\n\n const nextProps = { ...textElement.getProps() };\n if (applyShadow) {\n nextProps.shadowColor = shadowColor;\n nextProps.shadowOffset = DEFAULT_TEXT_PROPS.shadowOffset;\n nextProps.shadowBlur = DEFAULT_TEXT_PROPS.shadowBlur;\n nextProps.shadowOpacity = DEFAULT_TEXT_PROPS.shadowOpacity;\n }\n if (applyBackground) {\n nextProps.backgroundColor = backgroundColor;\n nextProps.backgroundOpacity = backgroundOpacity;\n }\n textElement.setProps(nextProps);\n await addElement(textElement);\n };\n\n useEffect(() => {\n if (selectedElement instanceof TextElement) {\n setTextContent(selectedElement.getText());\n const textProps = selectedElement.getProps();\n setSelectedFont(textProps.fontFamily ?? DEFAULT_TEXT_PROPS.fontFamily);\n setFontSize(textProps.fontSize ?? DEFAULT_TEXT_PROPS.fontSize);\n setIsBold(textProps.fontWeight === 700);\n setIsItalic(textProps.fontStyle === \"italic\");\n setTextColor(textProps.fill ?? DEFAULT_TEXT_PROPS.textColor);\n setStrokeColor(textProps.stroke ?? DEFAULT_TEXT_PROPS.strokeColor);\n setStrokeWidth(textProps.lineWidth ?? DEFAULT_TEXT_PROPS.strokeWidth);\n const hasShadow = textProps.shadowColor !== undefined;\n setApplyShadow(hasShadow);\n if (hasShadow) {\n setShadowColor(textProps.shadowColor ?? DEFAULT_TEXT_PROPS.shadowColor);\n }\n const hasBackground = textProps.backgroundColor != null && textProps.backgroundColor !== \"\";\n setApplyBackground(hasBackground);\n if (hasBackground) {\n setBackgroundColor(textProps.backgroundColor ?? \"#FACC15\");\n setBackgroundOpacity(textProps.backgroundOpacity ?? 1);\n }\n } else {\n setTextContent(DEFAULT_TEXT_PROPS.text);\n setFontSize(DEFAULT_TEXT_PROPS.fontSize);\n setSelectedFont(DEFAULT_TEXT_PROPS.fontFamily);\n setIsBold(DEFAULT_TEXT_PROPS.fontWeight === 700);\n setIsItalic(DEFAULT_TEXT_PROPS.fontStyle === \"italic\");\n setTextColor(DEFAULT_TEXT_PROPS.textColor);\n setStrokeColor(DEFAULT_TEXT_PROPS.strokeColor);\n setStrokeWidth(DEFAULT_TEXT_PROPS.strokeWidth);\n setApplyShadow(DEFAULT_TEXT_PROPS.applyShadow);\n setShadowColor(DEFAULT_TEXT_PROPS.shadowColor);\n setApplyBackground(false);\n setBackgroundColor(\"#FACC15\");\n setBackgroundOpacity(1);\n }\n }, [selectedElement]);\n\n return {\n textContent,\n fontSize,\n selectedFont,\n isBold,\n isItalic,\n textColor,\n strokeColor,\n applyShadow,\n shadowColor,\n strokeWidth,\n fonts,\n operation: selectedElement instanceof TextElement ? \"Apply Changes\": \"Add Text\",\n setTextContent: handleTextContentChange,\n setFontSize: handleFontSizeChange,\n setSelectedFont: handleSelectedFontChange,\n setIsBold: handleIsBoldChange,\n setIsItalic: handleIsItalicChange,\n setTextColor: handleTextColorChange,\n setStrokeColor: handleStrokeColorChange,\n setApplyShadow: handleApplyShadowChange,\n setShadowColor: handleShadowColorChange,\n setStrokeWidth: handleStrokeWidthChange,\n applyBackground,\n backgroundColor,\n backgroundOpacity,\n setApplyBackground: handleApplyBackgroundChange,\n setBackgroundColor: handleBackgroundColorChange,\n setBackgroundOpacity: handleBackgroundOpacityChange,\n handleApplyChanges,\n };\n};\n","import { TrackElement } from \"@twick/timeline\";\nimport { TextPanel } from \"../panel/text-panel\";\nimport { useTextPanel } from \"../../hooks/use-text-panel\";\n\ninterface TextPanelContainerProps {\n selectedElement: TrackElement | null;\n addElement: (element: TrackElement) => void;\n updateElement: (element: TrackElement) => void;\n}\n\nexport function TextPanelContainer(props: TextPanelContainerProps) {\n const textPanelProps = useTextPanel(props);\n return <TextPanel {...textPanelProps} />;\n}\n","/**\n * RectPanel Component\n * \n * A panel for creating and editing rectangle shapes in the studio. Provides controls\n * for adjusting corner radius, fill color, opacity, stroke color, and line width.\n * \n * @component\n * @param {Object} props\n * @param {number} props.cornerRadius - Corner radius in pixels\n * @param {string} props.fillColor - Fill color in hex format\n * @param {string} props.strokeColor - Stroke color in hex format\n * @param {number} props.lineWidth - Stroke width in pixels\n * @param {(radius: number) => void} props.setCornerRadius - Update corner radius\n * @param {(color: string) => void} props.setFillColor - Update fill color\n * @param {(opacity: number) => void} props.setOpacity - Update opacity\n * @param {(color: string) => void} props.setStrokeColor - Update stroke color\n * @param {(width: number) => void} props.setLineWidth - Update line width\n * @param {() => void} props.handleApplyChanges - Apply rectangle element changes\n * \n * @example\n * ```tsx\n * <RectPanel\n * cornerRadius={10}\n * fillColor=\"#ff0000\"\n * opacity={100}\n * strokeColor=\"#000000\"\n * lineWidth={2}\n * setCornerRadius={setRadius}\n * setFillColor={setFill}\n * setOpacity={setOpacity}\n * setStrokeColor={setStroke}\n * setLineWidth={setWidth}\n * handleApplyChanges={applyChanges}\n * />\n * ```\n */\n\nimport type { RectPanelState, RectPanelActions } from \"../../hooks/use-rect-panel\";\n\nexport type RectPanelProps = RectPanelState & RectPanelActions;\n\nexport function RectPanel({\n cornerRadius,\n fillColor,\n strokeColor,\n lineWidth,\n operation,\n setCornerRadius,\n setFillColor,\n setStrokeColor,\n setLineWidth,\n handleApplyChanges,\n}: RectPanelProps) {\n return (\n <div className=\"panel-container\">\n <div className=\"panel-title\">Rectangle</div>\n {/* Corner Radius */}\n <div className=\"panel-section\">\n <label className=\"label-dark\">Corner Radius</label>\n <div className=\"slider-container\">\n <input\n type=\"range\"\n min=\"0\"\n max=\"100\"\n value={cornerRadius}\n onChange={(e) => setCornerRadius(Number(e.target.value))}\n className=\"slider-purple\"\n />\n <span className=\"slider-value\">{cornerRadius}px</span>\n </div>\n </div>\n\n {/* Fill Color */}\n <div className=\"panel-section\">\n <label className=\"label-dark\">Fill Color</label>\n <div className=\"color-inputs\">\n <input\n type=\"color\"\n value={fillColor}\n onChange={(e) => setFillColor(e.target.value)}\n className=\"color-picker\"\n />\n <input\n type=\"text\"\n value={fillColor}\n onChange={(e) => setFillColor(e.target.value)}\n className=\"color-text\"\n />\n </div>\n </div>\n\n {/* Stroke Color */}\n <div className=\"panel-section\">\n <label className=\"label-dark\">Stroke Color</label>\n <div className=\"color-inputs\">\n <input\n type=\"color\"\n value={strokeColor}\n onChange={(e) => setStrokeColor(e.target.value)}\n className=\"color-picker\"\n />\n <input\n type=\"text\"\n value={strokeColor}\n onChange={(e) => setStrokeColor(e.target.value)}\n className=\"color-text\"\n />\n </div>\n </div>\n\n {/* Line Width */}\n <div className=\"panel-section\">\n <label className=\"label-dark\">Line Width</label>\n <div className=\"slider-container\">\n <input\n type=\"range\"\n min=\"0\"\n max=\"20\"\n value={lineWidth}\n onChange={(e) => setLineWidth(Number(e.target.value))}\n className=\"slider-purple\"\n />\n <span className=\"slider-value\">{lineWidth}px</span>\n </div>\n </div>\n\n {/* Operation button (only for creation, not edits) */}\n {operation !== \"Apply Changes\" && (\n <div className=\"flex panel-section\">\n <button\n onClick={handleApplyChanges}\n className=\"btn-primary w-full\"\n >\n {operation}\n </button>\n </div>\n )}\n </div>\n );\n}","import { useEffect, useState } from \"react\";\nimport { RectElement, TrackElement } from \"@twick/timeline\";\n\nexport const DEFAULT_RECT_PROPS = {\n cornerRadius: 0,\n fillColor: \"#3b82f6\",\n // UI uses 0–100%; element opacity is 0–1\n opacity: 100,\n strokeColor: \"#000000\",\n lineWidth: 0,\n};\n\nexport interface RectPanelState {\n cornerRadius: number;\n fillColor: string;\n opacity: number;\n strokeColor: string;\n lineWidth: number;\n operation: string;\n}\n\nexport interface RectPanelActions {\n setCornerRadius: (radius: number) => void;\n setFillColor: (color: string) => void;\n setOpacity: (opacity: number) => void;\n setStrokeColor: (color: string) => void;\n setLineWidth: (width: number) => void;\n handleApplyChanges: () => void;\n}\n\nexport const useRectPanel = ({\n selectedElement,\n addElement,\n updateElement,\n}: {\n selectedElement: TrackElement | null;\n addElement: (element: TrackElement) => void;\n updateElement: (element: TrackElement) => void;\n}): RectPanelState & RectPanelActions => {\n const [cornerRadius, setCornerRadius] = useState(DEFAULT_RECT_PROPS.cornerRadius);\n const [fillColor, setFillColor] = useState(DEFAULT_RECT_PROPS.fillColor);\n // Stored as percentage 0–100 for the UI slider\n const [opacity, setOpacity] = useState(DEFAULT_RECT_PROPS.opacity);\n const [strokeColor, setStrokeColor] = useState(DEFAULT_RECT_PROPS.strokeColor);\n const [lineWidth, setLineWidth] = useState(DEFAULT_RECT_PROPS.lineWidth);\n\n const applyLiveChangesToExistingRect = (overrides: Partial<RectPanelState> = {}) => {\n if (!(selectedElement instanceof RectElement)) {\n return;\n }\n\n const rectElement = selectedElement;\n const nextCornerRadius = overrides.cornerRadius ?? cornerRadius;\n const nextFillColor = overrides.fillColor ?? fillColor;\n const nextOpacityPercent = overrides.opacity ?? opacity;\n const nextStrokeColor = overrides.strokeColor ?? strokeColor;\n const nextLineWidth = overrides.lineWidth ?? lineWidth;\n\n rectElement.setCornerRadius(nextCornerRadius);\n rectElement.setFill(nextFillColor);\n // Element expects 0–1 opacity\n rectElement.setOpacity(nextOpacityPercent / 100);\n rectElement.setStrokeColor(nextStrokeColor);\n rectElement.setLineWidth(nextLineWidth);\n\n updateElement?.(rectElement);\n };\n\n const handleCornerRadiusChange = (radius: number) => {\n setCornerRadius(radius);\n applyLiveChangesToExistingRect({ cornerRadius: radius });\n };\n\n const handleFillColorChange = (color: string) => {\n setFillColor(color);\n applyLiveChangesToExistingRect({ fillColor: color });\n };\n\n const handleOpacityChange = (nextOpacity: number) => {\n setOpacity(nextOpacity);\n applyLiveChangesToExistingRect({ opacity: nextOpacity });\n };\n\n const handleStrokeColorChange = (color: string) => {\n setStrokeColor(color);\n applyLiveChangesToExistingRect({ strokeColor: color });\n };\n\n const handleLineWidthChange = (width: number) => {\n setLineWidth(width);\n applyLiveChangesToExistingRect({ lineWidth: width });\n };\n\n const handleApplyChanges = () => {\n // For existing rectangles, changes are already applied live via the handlers above.\n // The apply button is only meaningful when creating a new rectangle.\n if (selectedElement instanceof RectElement) {\n return;\n }\n\n const rectElement = new RectElement(fillColor, { width: 200, height: 200 })\n .setCornerRadius(cornerRadius)\n // Element expects 0–1 opacity; UI stores 0–100\n .setOpacity(opacity / 100)\n .setStrokeColor(strokeColor)\n .setLineWidth(lineWidth);\n\n addElement?.(rectElement);\n };\n\n useEffect(() => {\n if (selectedElement instanceof RectElement) {\n setCornerRadius(selectedElement.getCornerRadius() ?? DEFAULT_RECT_PROPS.cornerRadius);\n setFillColor(selectedElement.getFill() ?? DEFAULT_RECT_PROPS.fillColor);\n const elementOpacity = selectedElement.getOpacity();\n // Convert 0–1 element opacity into 0–100 UI percentage\n setOpacity(elementOpacity != null ? elementOpacity * 100 : DEFAULT_RECT_PROPS.opacity);\n setStrokeColor(selectedElement.getStrokeColor() ?? DEFAULT_RECT_PROPS.strokeColor);\n setLineWidth(selectedElement.getLineWidth() ?? DEFAULT_RECT_PROPS.lineWidth);\n }\n }, [selectedElement]);\n\n return {\n cornerRadius,\n fillColor,\n opacity,\n strokeColor,\n lineWidth,\n operation: selectedElement instanceof RectElement ? \"Apply Changes\": \"Add Rectangle\",\n setCornerRadius: handleCornerRadiusChange,\n setFillColor: handleFillColorChange,\n setOpacity: handleOpacityChange,\n setStrokeColor: handleStrokeColorChange,\n setLineWidth: handleLineWidthChange,\n handleApplyChanges,\n };\n};\n","import type { PanelProps } from \"../../types\";\nimport { RectPanel } from \"../panel/rect-panel\";\nimport { useRectPanel } from \"../../hooks/use-rect-panel\";\n\nexport function RectPanelContainer(props: PanelProps) {\n const rectPanelProps = useRectPanel({\n selectedElement: props.selectedElement ?? null,\n addElement: props.addElement!,\n updateElement: props.updateElement!,\n });\n return <RectPanel {...rectPanelProps} />;\n}\n","/**\n * CirclePanel Component\n *\n * A panel for creating and editing circle shapes in the studio. Provides controls\n * for adjusting radius, fill color, opacity, stroke color, and line width.\n *\n * @component\n * @param {Object} props\n * @param {number} props.radius - Circle radius in pixels\n * @param {string} props.fillColor - Fill color in hex format\n * @param {string} props.strokeColor - Stroke color in hex format\n * @param {number} props.lineWidth - Stroke width in pixels\n * @param {(radius: number) => void} props.setRadius - Update circle radius\n * @param {(color: string) => void} props.setFillColor - Update fill color\n * @param {(opacity: number) => void} props.setOpacity - Update opacity\n * @param {(color: string) => void} props.setStrokeColor - Update stroke color\n * @param {(width: number) => void} props.setLineWidth - Update line width\n * @param {() => void} props.handleApplyChanges - Apply circle element changes\n *\n * @example\n * ```tsx\n * <CirclePanel\n * radius={50}\n * fillColor=\"#ff0000\"\n * opacity={100}\n * strokeColor=\"#000000\"\n * lineWidth={2}\n * setRadius={setRadius}\n * setFillColor={setFill}\n * setOpacity={setOpacity}\n * setStrokeColor={setStroke}\n * setLineWidth={setWidth}\n * handleApplyChanges={applyChanges}\n * />\n * ```\n */\n\nimport type {\n CirclePanelState,\n CirclePanelActions,\n} from \"../../hooks/use-circle-panel\";\n\nexport type CirclePanelProps = CirclePanelState & CirclePanelActions;\n\nexport function CirclePanel({\n radius,\n fillColor,\n strokeColor,\n lineWidth,\n operation,\n setRadius,\n setFillColor,\n setStrokeColor,\n setLineWidth,\n handleApplyChanges,\n}: CirclePanelProps) {\n return (\n <div className=\"panel-container\">\n <div className=\"panel-title\">Circle</div>\n {/* Radius */}\n <div className=\"panel-section\">\n <label className=\"label-dark\">Radius</label>\n <div className=\"slider-container\">\n <input\n type=\"range\"\n min=\"10\"\n max=\"300\"\n value={radius}\n onChange={(e) => setRadius(Number(e.target.value))}\n className=\"slider-purple\"\n />\n <span className=\"slider-value\">{radius}px</span>\n </div>\n </div>\n\n {/* Fill Color */}\n <div className=\"panel-section\">\n <label className=\"label-dark\">Fill Color</label>\n <div className=\"color-inputs\">\n <input\n type=\"color\"\n value={fillColor}\n onChange={(e) => setFillColor(e.target.value)}\n className=\"color-picker\"\n />\n <input\n type=\"text\"\n value={fillColor}\n onChange={(e) => setFillColor(e.target.value)}\n className=\"color-text\"\n />\n </div>\n </div>\n\n\n {/* Stroke Color */}\n <div className=\"panel-section\">\n <label className=\"label-dark\">Stroke Color</label>\n <div className=\"color-inputs\">\n <input\n type=\"color\"\n value={strokeColor}\n onChange={(e) => setStrokeColor(e.target.value)}\n className=\"color-picker\"\n />\n <input\n type=\"text\"\n value={strokeColor}\n onChange={(e) => setStrokeColor(e.target.value)}\n className=\"color-text\"\n />\n </div>\n </div>\n\n {/* Line Width */}\n <div className=\"panel-section\">\n <label className=\"label-dark\">Line Width</label>\n <div className=\"slider-container\">\n <input\n type=\"range\"\n min=\"0\"\n max=\"20\"\n value={lineWidth}\n onChange={(e) => setLineWidth(Number(e.target.value))}\n className=\"slider-purple\"\n />\n <span className=\"slider-value\">{lineWidth}px</span>\n </div>\n </div>\n\n {/* Operation button (only for creation, not edits) */}\n {operation !== \"Apply Changes\" && (\n <div className=\"flex panel-section\">\n <button onClick={handleApplyChanges} className=\"btn-primary w-full\">\n {operation}\n </button>\n </div>\n )}\n </div>\n );\n}\n","import { useEffect, useState } from \"react\";\nimport { CircleElement, TrackElement } from \"@twick/timeline\";\n\nexport const DEFAULT_CIRCLE_PROPS = {\n radius: 50,\n fillColor: \"#3b82f6\",\n // UI uses 0–100%; element opacity is 0–1\n opacity: 100,\n strokeColor: \"#000000\",\n lineWidth: 0,\n};\n\nexport interface CirclePanelState {\n radius: number;\n fillColor: string;\n opacity: number;\n strokeColor: string;\n lineWidth: number;\n operation: string;\n}\n\nexport interface CirclePanelActions {\n setRadius: (radius: number) => void;\n setFillColor: (color: string) => void;\n setOpacity: (opacity: number) => void;\n setStrokeColor: (color: string) => void;\n setLineWidth: (width: number) => void;\n handleApplyChanges: () => void;\n}\n\nexport const useCirclePanel = ({\n selectedElement,\n addElement,\n updateElement,\n}: {\n selectedElement: TrackElement | null;\n addElement: (element: TrackElement) => void;\n updateElement: (element: TrackElement) => void;\n}): CirclePanelState & CirclePanelActions => {\n const [radius, setRadius] = useState(DEFAULT_CIRCLE_PROPS.radius);\n const [fillColor, setFillColor] = useState(DEFAULT_CIRCLE_PROPS.fillColor);\n // Stored as percentage 0–100 for the UI slider\n const [opacity, setOpacity] = useState(DEFAULT_CIRCLE_PROPS.opacity);\n const [strokeColor, setStrokeColor] = useState(DEFAULT_CIRCLE_PROPS.strokeColor);\n const [lineWidth, setLineWidth] = useState(DEFAULT_CIRCLE_PROPS.lineWidth);\n\n const applyLiveChangesToExistingCircle = (overrides: Partial<CirclePanelState> = {}) => {\n if (!(selectedElement instanceof CircleElement)) {\n return;\n }\n\n const circleElement = selectedElement;\n const nextRadius = overrides.radius ?? radius;\n const nextFillColor = overrides.fillColor ?? fillColor;\n const nextOpacityPercent = overrides.opacity ?? opacity;\n const nextStrokeColor = overrides.strokeColor ?? strokeColor;\n const nextLineWidth = overrides.lineWidth ?? lineWidth;\n\n circleElement.setRadius(nextRadius);\n circleElement.setFill(nextFillColor);\n // Element expects 0–1 opacity\n circleElement.setOpacity(nextOpacityPercent / 100);\n circleElement.setStrokeColor(nextStrokeColor);\n circleElement.setLineWidth(nextLineWidth);\n\n updateElement?.(circleElement);\n };\n\n const handleRadiusChange = (nextRadius: number) => {\n setRadius(nextRadius);\n applyLiveChangesToExistingCircle({ radius: nextRadius });\n };\n\n const handleFillColorChange = (color: string) => {\n setFillColor(color);\n applyLiveChangesToExistingCircle({ fillColor: color });\n };\n\n const handleOpacityChange = (nextOpacity: number) => {\n setOpacity(nextOpacity);\n applyLiveChangesToExistingCircle({ opacity: nextOpacity });\n };\n\n const handleStrokeColorChange = (color: string) => {\n setStrokeColor(color);\n applyLiveChangesToExistingCircle({ strokeColor: color });\n };\n\n const handleLineWidthChange = (width: number) => {\n setLineWidth(width);\n applyLiveChangesToExistingCircle({ lineWidth: width });\n };\n\n const handleApplyChanges = () => {\n // For existing circles, changes are already applied live via the handlers above.\n // The apply button is only meaningful when creating a new circle.\n if (selectedElement instanceof CircleElement) {\n return;\n }\n\n const circleElement = new CircleElement(fillColor, radius)\n // Element expects 0–1 opacity; UI stores 0–100\n .setOpacity(opacity / 100)\n .setStrokeColor(strokeColor)\n .setLineWidth(lineWidth);\n\n addElement?.(circleElement);\n };\n\n useEffect(() => {\n if (selectedElement instanceof CircleElement) {\n setRadius(selectedElement.getRadius() ?? DEFAULT_CIRCLE_PROPS.radius);\n setFillColor(selectedElement.getFill() ?? DEFAULT_CIRCLE_PROPS.fillColor);\n const elementOpacity = selectedElement.getOpacity();\n // Convert 0–1 element opacity into 0–100 UI percentage\n setOpacity(elementOpacity != null ? elementOpacity * 100 : DEFAULT_CIRCLE_PROPS.opacity);\n setStrokeColor(selectedElement.getStrokeColor() ?? DEFAULT_CIRCLE_PROPS.strokeColor);\n setLineWidth(selectedElement.getLineWidth() ?? DEFAULT_CIRCLE_PROPS.lineWidth);\n }\n }, [selectedElement]);\n\n return {\n radius,\n fillColor,\n opacity,\n strokeColor,\n lineWidth,\n operation: selectedElement instanceof CircleElement ? \"Apply Changes\": \"Add Circle\",\n setRadius: handleRadiusChange,\n setFillColor: handleFillColorChange,\n setOpacity: handleOpacityChange,\n setStrokeColor: handleStrokeColorChange,\n setLineWidth: handleLineWidthChange,\n handleApplyChanges,\n };\n};\n","import type { PanelProps } from \"../../types\";\nimport { CirclePanel } from \"../panel/circle-panel\";\nimport { useCirclePanel } from \"../../hooks/use-circle-panel\";\n\nexport function CirclePanelContainer(props: PanelProps) {\n const circlePanelProps = useCirclePanel({\n selectedElement: props.selectedElement ?? null,\n addElement: props.addElement!,\n updateElement: props.updateElement!,\n });\n return <CirclePanel {...circlePanelProps} />;\n}","/**\n * CaptionsPanel Component\n *\n * A presentational panel for managing caption entries in the studio.\n * Renders a list of caption items, each with a text input and two actions:\n * Split and Delete. A single Add button appears below the list.\n *\n * State is controlled by the parent via props; this component is stateless.\n *\n * Entry shape (CaptionEntry):\n * - `s`: start time (seconds)\n * - `e`: end time (seconds)\n * - `t`: caption text\n *\n * Props:\n * - `captions`: CaptionEntry[] — ordered list of captions\n * - `addCaption()`: add a new caption at the end\n * - `splitCaption(index)`: split the caption at `index`\n * - `deleteCaption(index)`: remove the caption at `index`\n * - `updateCaption(index, caption)`: update the caption at `index`\n *\n * @component\n * @example\n * ```tsx\n * <CaptionsPanel\n * captions={captions}\n * addCaption={addCaption}\n * splitCaption={splitCaption}\n * deleteCaption={deleteCaption}\n * updateCaption={updateCaption}\n * />\n * ```\n */\n\nimport { Trash2, Scissors } from \"lucide-react\";\n\ninterface CaptionEntry {\n s: number;\n e: number;\n t: string; \n}\n\nexport function CaptionsPanel({\n captions,\n addCaption,\n splitCaption,\n deleteCaption,\n updateCaption,\n}: {\n captions: CaptionEntry[];\n addCaption: () => void;\n splitCaption: (index: number) => void;\n deleteCaption: (index: number) => void;\n updateCaption: (index: number, caption: CaptionEntry) => void;\n}) {\n\n return (\n <div className=\"panel-container\">\n <h3 className=\"panel-title\">Captions</h3>\n\n {/* Caption Entries */}\n {captions.map((caption, i) => (\n <div\n key={i}\n className=\"panel-section gap-2\"\n >\n {/* Caption Text Input */}\n <div>\n <input\n type=\"text\"\n placeholder=\"Enter caption text\"\n value={caption.t}\n onChange={(e) => updateCaption(i, { ...caption, t: e.target.value })}\n className=\"input-dark\"\n />\n </div>\n\n {/* Action Buttons (bottom-right) */}\n <div className=\"flex-container justify-between\">\n <button\n onClick={() => splitCaption(i)}\n className=\"btn-ghost\"\n title=\"Split caption\"\n >\n <Scissors className=\"icon-sm\" />\n </button>\n <button\n onClick={() => deleteCaption(i)}\n className=\"btn-ghost\"\n title=\"Delete caption\"\n >\n <Trash2 className=\"icon-sm\" color=\"var(--color-red-500)\"/>\n </button>\n </div>\n </div>\n ))}\n\n {/* Common Add Button */}\n <div className=\"panel-section\">\n <button onClick={addCaption} className=\"btn-primary w-full\" title=\"Add caption\">\n Add\n </button>\n </div>\n </div>\n );\n}\n","import { CAPTION_STYLE } from \"@twick/timeline\";\n\nexport const CAPTION_PROPS = {\n [CAPTION_STYLE.WORD_BG_HIGHLIGHT]: {\n font: {\n size: 46,\n weight: 700,\n family: \"Bangers\",\n },\n colors: {\n text: \"#ffffff\",\n highlight: \"#ff4081\",\n bgColor: \"#444444\",\n },\n lineWidth: 0.35,\n stroke: \"#000000\",\n fontWeight: 700,\n shadowOffset: [-3, 3],\n shadowColor: \"#000000\",\n },\n [CAPTION_STYLE.WORD_BY_WORD]: {\n font: {\n size: 46,\n weight: 700,\n family: \"Bangers\",\n },\n colors: {\n text: \"#ffffff\",\n highlight: \"#ff4081\",\n bgColor: \"#444444\",\n }, \n lineWidth: 0.35,\n stroke: \"#000000\",\n shadowOffset: [-2, 2],\n shadowColor: \"#000000\",\n shadowBlur: 5,\n },\n [CAPTION_STYLE.WORD_BY_WORD_WITH_BG]: {\n font: {\n size: 46,\n weight: 700,\n family: \"Bangers\",\n },\n colors: {\n text: \"#ffffff\",\n highlight: \"#ff4081\",\n bgColor: \"#444444\",\n },\n lineWidth: 0.35,\n shadowOffset: [-2, 2],\n shadowColor: \"#000000\",\n shadowBlur: 5,\n }\n };","import { useState, useEffect, useRef } from \"react\";\nimport {\n CAPTION_STYLE,\n CaptionElement,\n Track,\n useTimelineContext,\n} from \"@twick/timeline\";\nimport { CAPTION_PROPS } from \"../helpers/constant\";\n\ninterface CaptionEntry {\n s: number;\n e: number;\n t: string;\n}\n\nexport const useCaptionsPanel = () => {\n const [captions, setCaptions] = useState<CaptionEntry[]>([]);\n const captionsTrack = useRef<Track | null>(null);\n const { editor } = useTimelineContext();\n\n const fetchCaptions = async () => {\n const editorCaptionsTrack = editor.getCaptionsTrack();\n if (editorCaptionsTrack) {\n captionsTrack.current = editorCaptionsTrack;\n setCaptions(\n editorCaptionsTrack.getElements().map((element) => ({\n s: element.getStart(),\n e: element.getEnd(),\n t: (element as CaptionElement).getText(),\n }))\n );\n }\n };\n\n useEffect(() => {\n fetchCaptions();\n }, []);\n\n const checkCaptionsTrack = () => {\n if (!captionsTrack.current) {\n captionsTrack.current = editor.addTrack(\"Caption\", \"caption\");\n const props: Record<string, any> = {\n capStyle: CAPTION_STYLE.WORD_BG_HIGHLIGHT,\n ...CAPTION_PROPS[CAPTION_STYLE.WORD_BG_HIGHLIGHT],\n x: 0,\n y: 200,\n applyToAll: true,\n };\n captionsTrack.current?.setProps(props);\n }\n };\n\n const addCaption = () => {\n const newCaption: CaptionEntry = { s: 0, e: 0, t: \"New Caption\" };\n if (captions.length > 0) {\n newCaption.s = captions[captions.length - 1].e;\n }\n newCaption.e = newCaption.s + 1;\n setCaptions([...captions, newCaption]);\n checkCaptionsTrack();\n const captionElement = new CaptionElement(\n newCaption.t,\n newCaption.s,\n newCaption.e\n );\n editor.addElementToTrack(captionsTrack.current as Track, captionElement);\n };\n\n const splitCaption = async (index: number) => {\n if (captionsTrack.current) {\n const element = captionsTrack.current.getElements()[\n index\n ] as CaptionElement;\n const splitResult = await editor.splitElement(\n element,\n element.getStart() + element.getDuration() / 2\n );\n if (splitResult.success) {\n fetchCaptions();\n }\n }\n };\n\n const deleteCaption = (index: number) => {\n setCaptions(captions.filter((_, i) => i !== index));\n if (captionsTrack.current) {\n editor.removeElement(captionsTrack.current.getElements()[index]);\n }\n };\n\n const updateCaption = (index: number, caption: CaptionEntry) => {\n setCaptions(captions.map((sub, i) => (i === index ? caption : sub)));\n if (captionsTrack.current) {\n const element = captionsTrack.current.getElements()[\n index\n ] as CaptionElement;\n element.setText(caption.t);\n editor.updateElement(element);\n }\n };\n\n return {\n captions,\n addCaption,\n splitCaption,\n deleteCaption,\n updateCaption,\n };\n};\n","import { CaptionsPanel } from \"../panel/captions-panel\";\nimport { useCaptionsPanel } from \"../../hooks/use-captions-panel\";\n\nexport function CaptionsPanelContainer() {\n const captionsPanelProps = useCaptionsPanel();\n return <CaptionsPanel {...captionsPanelProps} />;\n}","import React from \"react\";\nimport { Size, TrackElement } from \"@twick/timeline\";\nimport { AudioPanelContainer } from \"./audio-panel-container\";\nimport { ImagePanelContainer } from \"./image-panel-container\";\nimport { VideoPanelContainer } from \"./video-panel-container\";\nimport { TextPanelContainer } from \"./text-panel-container\";\nimport { RectPanelContainer } from \"./rect-panel-container\";\nimport { CirclePanelContainer } from \"./circle-panel-container\";\nimport { Wand2 } from \"lucide-react\";\nimport { CaptionsPanelContainer } from \"./captions-panel-container\";\n\n/**\n * Props interface for the ElementPanelContainer component.\n * Defines the configuration and callback functions for element management.\n */\ninterface ElementPanelContainerProps {\n selectedTool: string;\n selectedElement: TrackElement | null;\n videoResolution: Size;\n setSelectedTool: (tool: string) => void;\n addElement: (element: TrackElement) => void;\n updateElement: (element: TrackElement) => void;\n}\n\n/**\n * ElementPanelContainer component that renders the appropriate element panel\n * based on the currently selected tool. Provides a unified interface for\n * managing different types of timeline elements including media, text, shapes,\n * and captions. Shows an empty state when no tool is selected.\n *\n * @param props - Component props for element panel configuration\n * @returns JSX element containing the appropriate element panel or empty state\n * \n * @example\n * ```tsx\n * <ElementPanelContainer\n * selectedTool=\"text\"\n * selectedElement={currentElement}\n * videoResolution={{ width: 1920, height: 1080 }}\n * setSelectedTool={setTool}\n * addElement={addToTimeline}\n * updateElement={updateInTimeline}\n * />\n * ```\n */\nconst ElementPanelContainer = ({\n selectedTool,\n videoResolution,\n selectedElement,\n addElement,\n updateElement,\n}: ElementPanelContainerProps): React.ReactElement => {\n const addNewElement = async (element: TrackElement) => {\n await addElement(element);\n };\n\n // Render appropriate library based on selected tool\n const renderLibrary = () => {\n switch (selectedTool) {\n case \"image\":\n return (\n <ImagePanelContainer\n videoResolution={videoResolution}\n selectedElement={selectedElement}\n addElement={addNewElement}\n updateElement={updateElement}\n />\n );\n case \"audio\":\n return (\n <AudioPanelContainer\n videoResolution={videoResolution}\n selectedElement={selectedElement}\n addElement={addNewElement}\n updateElement={updateElement}\n />\n );\n case \"video\":\n return (\n <VideoPanelContainer\n videoResolution={videoResolution}\n selectedElement={selectedElement}\n addElement={addNewElement}\n updateElement={updateElement}\n />\n );\n case \"text\":\n return (\n <TextPanelContainer\n selectedElement={selectedElement}\n addElement={addNewElement}\n updateElement={updateElement}\n />\n );\n case \"rect\":\n return (\n <RectPanelContainer\n videoResolution={videoResolution}\n selectedElement={selectedElement}\n addElement={addNewElement}\n updateElement={updateElement}\n />\n );\n case \"circle\":\n return (\n <CirclePanelContainer\n videoResolution={videoResolution}\n selectedElement={selectedElement}\n addElement={addNewElement}\n updateElement={updateElement}\n />\n );\n case \"caption\":\n return <CaptionsPanelContainer />;\n default:\n return (\n <div className=\"panel-container\">\n <div className=\"empty-state\">\n <div className=\"empty-state-content\">\n <Wand2 className=\"empty-state-icon\" />\n <p className=\"empty-state-text\">Select an element from toolbar</p>\n </div>\n </div>\n </div>\n );\n }\n };\n\n return renderLibrary();\n};\n\nexport default ElementPanelContainer;\n","import type { ReactNode } from \"react\";\n\ninterface PropertyRowProps {\n label: string;\n children: ReactNode;\n /** Optional secondary label/value on the right (e.g. units, current value) */\n secondary?: ReactNode;\n}\n\nexport function PropertyRow({ label, children, secondary }: PropertyRowProps) {\n return (\n <div className=\"property-row\">\n <div className=\"property-row-label\">\n <span className=\"property-label\">{label}</span>\n </div>\n <div className=\"property-row-control\">\n {children}\n </div>\n {secondary && (\n <div className=\"property-row-secondary\">\n {secondary}\n </div>\n )}\n </div>\n );\n}\n\n","import { ChevronDown, ChevronRight } from \"lucide-react\";\n\ninterface AccordionItemProps {\n title: string;\n icon: React.ReactNode;\n children: React.ReactNode;\n isOpen: boolean;\n onToggle: () => void;\n}\n\nexport function AccordionItem({ title, icon, children, isOpen, onToggle }: AccordionItemProps) {\n return (\n <div className=\"accordion-item\">\n <div\n onClick={onToggle}\n className=\"accordion-header\"\n >\n <div className=\"flex-container\">\n <div className=\"accent-purple\">\n {icon}\n </div>\n <span className=\"property-title\">{title}</span>\n </div>\n {isOpen ? (\n <ChevronDown className=\"icon-sm accent-purple\" />\n ) : (\n <ChevronRight className=\"icon-sm accent-purple\" />\n )}\n </div>\n <div\n className={`accordion-content ${isOpen ? 'expanded' : ''}`}\n >\n <div className=\"accordion-panel\">\n {children}\n </div>\n </div>\n </div>\n );\n}\n","import { RectElement, CircleElement, TrackElement } from \"@twick/timeline\";\n// Dimensions in inspector: Rect and Circle only. Image/Video resize via canvas (dimensions deferred).\nimport type { PropertiesPanelProps } from \"../../types\";\nimport { PropertyRow } from \"./property-row\";\nimport { Ruler } from \"lucide-react\";\nimport { AccordionItem } from \"../shared/accordion-item\";\nimport { useState } from \"react\";\n\nexport function ElementProps({ selectedElement, updateElement }: PropertiesPanelProps) {\n const opacity = selectedElement?.getOpacity() || 1;\n const rotation = selectedElement?.getRotation() || 0;\n const position = selectedElement?.getPosition() || { x: 0, y: 0 };\n\n const handleRotationChange = (rotation: number) => {\n if (selectedElement) {\n selectedElement.setRotation(rotation);\n updateElement?.(selectedElement as TrackElement);\n }\n }\n\n const handleOpacityChange = (opacity: number) => {\n if (selectedElement) {\n selectedElement.setOpacity(opacity);\n updateElement?.(selectedElement as TrackElement);\n }\n }\n const handlePositionChange = (props: Record<string, any>) => {\n if (selectedElement) {\n selectedElement.setPosition({ x: props.x ?? 0, y: props.y ?? 0 });\n updateElement?.(selectedElement as TrackElement);\n }\n }\n\n const handleDimensionsChange = (width?: number, height?: number) => {\n if (!selectedElement) return;\n if (selectedElement instanceof RectElement) {\n const size = selectedElement.getSize();\n selectedElement.setSize({ width: width ?? size.width, height: height ?? size.height });\n updateElement?.(selectedElement as TrackElement);\n } else if (selectedElement instanceof CircleElement) {\n const dims = {\n width: selectedElement.getRadius() * 2,\n height: selectedElement.getRadius() * 2,\n };\n const newDiameter =\n width !== undefined && width !== dims.width ? width : (height ?? dims.height);\n selectedElement.setRadius(newDiameter / 2);\n updateElement?.(selectedElement as TrackElement);\n }\n }\n\n const hasShapeDimensions =\n selectedElement instanceof RectElement || selectedElement instanceof CircleElement;\n\n let dimensions: { width: number; height: number } | null = null;\n if (selectedElement instanceof RectElement) {\n dimensions = selectedElement.getSize();\n } else if (selectedElement instanceof CircleElement) {\n const r = selectedElement.getRadius();\n dimensions = { width: r * 2, height: r * 2 };\n }\n\n const [isTransformOpen, setIsTransformOpen] = useState(false);\n\n return (\n <div className=\"panel-container\">\n <div className=\"panel-title\">Properties</div>\n\n <AccordionItem\n title=\"Transform\"\n icon={<Ruler className=\"icon-sm\" />}\n isOpen={isTransformOpen}\n onToggle={() => setIsTransformOpen((open) => !open)}\n >\n <div className=\"properties-group\">\n <div className=\"property-section\">\n <PropertyRow label=\"Position X\">\n <input\n type=\"number\"\n value={position.x ?? 0}\n onChange={(e) =>\n handlePositionChange({ x: Number(e.target.value) })\n }\n className=\"input-dark\"\n />\n </PropertyRow>\n <PropertyRow label=\"Position Y\">\n <input\n type=\"number\"\n value={position.y ?? 0}\n onChange={(e) =>\n handlePositionChange({ y: Number(e.target.value) })\n }\n className=\"input-dark\"\n />\n </PropertyRow>\n </div>\n\n {/* Dimensions - for rect, circle only; image/video resize via canvas */}\n {hasShapeDimensions && dimensions && (\n <div className=\"property-section\">\n <PropertyRow label=\"Width\">\n <input\n type=\"number\"\n min={1}\n value={Math.round(dimensions.width)}\n onChange={(e) =>\n handleDimensionsChange(\n Number(e.target.value),\n dimensions!.height\n )\n }\n className=\"input-dark\"\n />\n </PropertyRow>\n <PropertyRow label=\"Height\">\n <input\n type=\"number\"\n min={1}\n value={Math.round(dimensions.height)}\n onChange={(e) =>\n handleDimensionsChange(\n dimensions!.width,\n Number(e.target.value)\n )\n }\n className=\"input-dark\"\n />\n </PropertyRow>\n </div>\n )}\n\n {/* Opacity */}\n <div className=\"property-section\">\n <PropertyRow\n label=\"Opacity\"\n secondary={\n <span>\n {Math.round((opacity ?? 1) * 100)}\n %\n </span>\n }\n >\n <input\n type=\"range\"\n min=\"0\"\n max=\"100\"\n value={(opacity ?? 1) * 100}\n onChange={(e) =>\n handleOpacityChange(Number(e.target.value) / 100)\n }\n className=\"slider-purple\"\n />\n </PropertyRow>\n </div>\n\n {/* Rotation */}\n <div className=\"property-section\">\n <PropertyRow\n label=\"Rotation\"\n secondary={\n <span>\n {Math.round(rotation ?? 0)}\n °\n </span>\n }\n >\n <input\n type=\"range\"\n min=\"0\"\n max=\"360\"\n value={rotation ?? 0}\n onChange={(e) => handleRotationChange(Number(e.target.value))}\n className=\"slider-purple\"\n />\n </PropertyRow>\n </div>\n </div>\n </AccordionItem>\n </div>\n );\n}\n","import { TEXT_EFFECTS } from \"@twick/video-editor\";\nimport { ElementTextEffect, TextElement } from \"@twick/timeline\";\nimport type { PropertiesPanelProps } from \"../../types\";\nimport { AccordionItem } from \"../shared/accordion-item\";\nimport { PropertyRow } from \"./property-row\";\nimport { SparklesIcon } from \"lucide-react\";\nimport { useState } from \"react\";\n\nexport function TextEffects({\n selectedElement,\n updateElement,\n}: PropertiesPanelProps) {\n if (!(selectedElement instanceof TextElement)) return null;\n\n const currentEffect = selectedElement.getTextEffect();\n\n const handleUpdateEffect = (props: {\n name?: string;\n delay?: number;\n duration?: number;\n bufferTime?: number;\n }) => {\n if (!selectedElement || !(selectedElement instanceof TextElement)) return;\n\n let effect = currentEffect;\n\n // If name is provided and empty, remove effect\n if (props.name === \"\") {\n selectedElement.setTextEffect(undefined);\n updateElement?.(selectedElement);\n return;\n }\n\n // Create new effect if none exists or name is changing\n if (!effect || (props.name && props.name !== effect.getName())) {\n effect = new ElementTextEffect(\n props.name || currentEffect?.getName() || TEXT_EFFECTS[0].name\n );\n // Set default values for new effect\n effect.setDelay(0);\n effect.setDuration(1);\n effect.setBufferTime(0.1);\n }\n\n // Update effect properties\n if (props.delay !== undefined) effect.setDelay(props.delay);\n if (props.duration !== undefined) effect.setDuration(props.duration);\n if (props.bufferTime !== undefined) effect.setBufferTime(props.bufferTime);\n\n // Update element with new/modified effect\n selectedElement.setTextEffect(effect);\n updateElement?.(selectedElement);\n };\n\n const [isEffectsOpen, setIsEffectsOpen] = useState(false);\n\n return (\n <div className=\"panel-container\">\n <div className=\"panel-title\">Text Effects</div>\n <AccordionItem\n title=\"Effects\"\n icon={<SparklesIcon className=\"icon-sm\" />}\n isOpen={isEffectsOpen}\n onToggle={() => setIsEffectsOpen((open) => !open)}\n >\n <div className=\"properties-group\">\n {/* Text Effect Selection */}\n <div className=\"property-section\">\n <PropertyRow label=\"Preset\">\n <select\n value={currentEffect?.getName() || \"\"}\n onChange={(e) => handleUpdateEffect({ name: e.target.value })}\n className=\"select-dark w-full\"\n >\n <option value=\"\">No Effect</option>\n {TEXT_EFFECTS.map((effect) => (\n <option key={effect.name} value={effect.name}>\n {effect.name.charAt(0).toUpperCase() + effect.name.slice(1)}\n </option>\n ))}\n </select>\n </PropertyRow>\n </div>\n\n {/* Text Effect Options */}\n {currentEffect && (\n <>\n {/* Delay */}\n <div className=\"property-section\">\n <PropertyRow label=\"Delay (s)\">\n <input\n type=\"number\"\n min=\"0\"\n max=\"5\"\n step=\"0.1\"\n value={currentEffect.getDelay() ?? 0}\n onChange={(e) =>\n handleUpdateEffect({ delay: Number(e.target.value) })\n }\n className=\"input-dark\"\n />\n </PropertyRow>\n </div>\n\n {/* Duration */}\n <div className=\"property-section\">\n <PropertyRow label=\"Duration (s)\">\n <input\n type=\"number\"\n min=\"0.1\"\n max=\"10\"\n step=\"0.1\"\n value={currentEffect.getDuration() ?? 1}\n onChange={(e) =>\n handleUpdateEffect({ duration: Number(e.target.value) })\n }\n className=\"input-dark\"\n />\n </PropertyRow>\n </div>\n\n {/* Buffer Time */}\n <div className=\"property-section\">\n <PropertyRow label=\"Buffer (s)\">\n <input\n type=\"number\"\n min=\"0.05\"\n max=\"1\"\n step=\"0.05\"\n value={currentEffect.getBufferTime() ?? 0.1}\n onChange={(e) =>\n handleUpdateEffect({\n bufferTime: Number(e.target.value),\n })\n }\n className=\"input-dark\"\n />\n </PropertyRow>\n </div>\n </>\n )}\n </div>\n </AccordionItem>\n </div>\n );\n}\n","import { ANIMATIONS } from \"@twick/video-editor\";\nimport { ElementAnimation, TrackElement } from \"@twick/timeline\";\nimport type { PropertiesPanelProps } from \"../../types\";\n\nexport function Animation({\n selectedElement,\n updateElement,\n}: PropertiesPanelProps) {\n if (!(selectedElement instanceof TrackElement)) return null;\n\n const currentAnimation = selectedElement?.getAnimation();\n\n const handleUpdateAnimation = (props: {\n name?: string;\n interval?: number;\n duration?: number;\n intensity?: number;\n animate?: \"enter\" | \"exit\" | \"both\";\n mode?: \"in\" | \"out\";\n direction?: \"up\" | \"down\" | \"left\" | \"right\" | \"center\";\n }) => {\n if (!selectedElement) return;\n\n let animation = currentAnimation;\n\n // If name is provided and empty, remove animation\n if (props.name === \"\") {\n selectedElement.setAnimation(undefined);\n updateElement?.(selectedElement);\n return;\n }\n\n // Find animation definition\n const animationDef = ANIMATIONS.find(\n (a) => a.name === (props.name || currentAnimation?.getName())\n );\n if (!animationDef) return;\n\n // Create new animation if none exists or name is changing\n if (!animation || (props.name && props.name !== animation.getName())) {\n animation = new ElementAnimation(\n props.name || currentAnimation?.getName() || ANIMATIONS[0].name\n );\n // Set default values for new animation\n animation.setInterval(animationDef.interval || 1);\n animation.setDuration(animationDef.duration || 1);\n animation.setIntensity(animationDef.intensity || 1);\n animation.setAnimate(animationDef.animate || \"enter\");\n if (animationDef.mode) animation.setMode(animationDef.mode);\n if (animationDef.direction)\n animation.setDirection(animationDef.direction);\n }\n\n // Update animation properties with validation\n if (props.interval !== undefined) {\n const [min, max] = animationDef.options?.interval || [0.1, 5];\n animation.setInterval(Math.min(Math.max(props.interval, min), max));\n }\n if (props.duration !== undefined) {\n const [min, max] = animationDef.options?.duration || [0.1, 5];\n animation.setDuration(Math.min(Math.max(props.duration, min), max));\n }\n if (props.intensity !== undefined) {\n const [min, max] = animationDef.options?.intensity || [0.1, 2];\n animation.setIntensity(Math.min(Math.max(props.intensity, min), max));\n }\n if (\n props.animate &&\n animationDef.options?.animate?.includes(props.animate)\n ) {\n animation.setAnimate(props.animate);\n }\n if (props.mode && animationDef.options?.mode?.includes(props.mode)) {\n animation.setMode(props.mode);\n }\n if (\n props.direction &&\n animationDef.options?.direction?.includes(props.direction)\n ) {\n animation.setDirection(props.direction);\n }\n\n // Update element with new/modified animation\n selectedElement.setAnimation(animation);\n updateElement?.(selectedElement);\n };\n\n return (\n <div className=\"panel-container\">\n <div className=\"panel-title\">Animations</div>\n {/* Animation Selection */}\n <div className=\"panel-section\">\n <label className=\"label-dark\">Type</label>\n <select\n value={currentAnimation?.getName() || \"\"}\n onChange={(e) => handleUpdateAnimation({ name: e.target.value })}\n className=\"select-dark w-full\"\n >\n <option value=\"\">No Animation</option>\n {ANIMATIONS.map((animation) => (\n <option key={animation.name} value={animation.name}>\n {animation.name.charAt(0).toUpperCase() + animation.name.slice(1)}\n </option>\n ))}\n </select>\n </div>\n\n {/* Animation Options */}\n {currentAnimation && (\n <>\n {/* Get current animation definition */}\n {(() => {\n const animationDef = ANIMATIONS.find(\n (a) => a.name === currentAnimation.getName()\n );\n if (!animationDef || !animationDef.options) return null;\n\n return (\n <>\n {/* Animate */}\n {animationDef.options?.animate && (\n <div className=\"panel-section\">\n <label className=\"label-dark\">When to Animate</label>\n <select\n value={currentAnimation.getAnimate()}\n onChange={(e) =>\n handleUpdateAnimation({\n animate: e.target.value as\n | \"enter\"\n | \"exit\"\n | \"both\",\n })\n }\n className=\"select-dark w-full\"\n >\n {animationDef.options?.animate.map((option) => (\n <option key={option} value={option}>\n {option.charAt(0).toUpperCase() + option.slice(1)}\n </option>\n ))}\n </select>\n </div>\n )}\n\n {/* Direction */}\n {animationDef.options?.direction && (\n <div className=\"panel-section\">\n <label className=\"label-dark\">Direction</label>\n <select\n value={currentAnimation.getDirection()}\n onChange={(e) =>\n handleUpdateAnimation({\n direction: e.target.value as\n | \"up\"\n | \"down\"\n | \"left\"\n | \"right\"\n | \"center\",\n })\n }\n className=\"select-dark w-full\"\n >\n {animationDef.options?.direction.map((option) => (\n <option key={option} value={option}>\n {option.charAt(0).toUpperCase() + option.slice(1)}\n </option>\n ))}\n </select>\n </div>\n )}\n\n {/* Mode */}\n {animationDef.options?.mode && (\n <div className=\"panel-section\">\n <label className=\"label-dark\">Mode</label>\n <select\n value={currentAnimation.getMode()}\n onChange={(e) =>\n handleUpdateAnimation({\n mode: e.target.value as \"in\" | \"out\",\n })\n }\n className=\"select-dark w-full\"\n >\n {animationDef.options?.mode.map((option) => (\n <option key={option} value={option}>\n {option.charAt(0).toUpperCase() + option.slice(1)}\n </option>\n ))}\n </select>\n </div>\n )}\n\n {/* Duration */}\n {animationDef.options?.duration && (\n <div className=\"panel-section\">\n <label className=\"label-dark\">Duration (seconds)</label>\n <div className=\"slider-container\">\n <input\n type=\"range\"\n min={animationDef.options?.duration[0]}\n max={animationDef.options?.duration[1]}\n step=\"0.1\"\n value={currentAnimation.getDuration()}\n onChange={(e) =>\n handleUpdateAnimation({\n duration: Number(e.target.value),\n })\n }\n className=\"slider-purple\"\n />\n <span className=\"slider-value\">{currentAnimation.getDuration()}</span>\n </div>\n </div>\n )}\n\n {/* Interval */}\n {animationDef.options?.interval && (\n <div className=\"panel-section\">\n <label className=\"label-dark\">Interval (seconds)</label>\n <div className=\"slider-container\">\n <input\n type=\"range\"\n min={animationDef.options?.interval[0]}\n max={animationDef.options?.interval[1]}\n step=\"0.1\"\n value={currentAnimation.getInterval()}\n onChange={(e) =>\n handleUpdateAnimation({\n interval: Number(e.target.value),\n })\n }\n className=\"slider-purple\"\n />\n <span className=\"slider-value\">{currentAnimation.getInterval()}</span>\n </div>\n </div>\n )}\n\n {/* Intensity */}\n {animationDef.options?.intensity && (\n <div className=\"panel-section\">\n <label className=\"label-dark\">Intensity</label>\n <div className=\"slider-container\">\n <input\n type=\"range\"\n min={animationDef.options?.intensity[0]}\n max={animationDef.options?.intensity[1]}\n step=\"0.1\"\n value={currentAnimation.getIntensity()}\n onChange={(e) =>\n handleUpdateAnimation({\n intensity: Number(e.target.value),\n })\n }\n className=\"slider-purple\"\n />\n <span className=\"slider-value\">{currentAnimation.getIntensity()}</span>\n </div>\n </div>\n )}\n </>\n );\n })()}\n </>\n )}\n </div>\n );\n}\n","/**\n * Volume conversion between linear (0-1) and dB scale.\n * Used for PlaybackPropsPanel to match professional audio tools (e.g. -60 dB to +6 dB).\n *\n * Formula: dB = 20 * log10(linear)\n * - 0 dB = 1.0 linear (full volume)\n * - -60 dB ≈ 0.001 linear (effectively mute)\n * - +6 dB ≈ 2.0 linear (amplification)\n */\n\nconst MIN_DB = -60;\nconst MAX_DB = 6;\n\n/**\n * Convert linear volume (0 to ~2) to dB.\n * Returns MIN_DB for linear <= 0 to avoid -Infinity.\n */\nexport function linearToDb(linear: number): number {\n if (linear <= 0) return MIN_DB;\n const db = 20 * Math.log10(linear);\n return Math.max(MIN_DB, Math.min(MAX_DB, db));\n}\n\n/**\n * Convert dB to linear volume.\n * Returns 0 for dB <= MIN_DB (mute).\n */\nexport function dbToLinear(db: number): number {\n if (db <= MIN_DB) return 0;\n const linear = Math.pow(10, db / 20);\n return Math.min(linear, Math.pow(10, MAX_DB / 20));\n}\n\nexport { MIN_DB, MAX_DB };\n","import { linearToDb, dbToLinear, MIN_DB, MAX_DB } from \"../../helpers/volume-db\";\nimport type { PropertiesPanelProps } from \"../../types\";\nimport { AccordionItem } from \"../shared/accordion-item\";\nimport { PropertyRow } from \"./property-row\";\nimport { Music2 } from \"lucide-react\";\nimport { useState } from \"react\";\n\nconst PLAYBACK_RATE_MIN = 0.25;\nconst PLAYBACK_RATE_MAX = 2;\nconst PLAYBACK_RATE_STEP = 0.25;\n\nexport function PlaybackPropsPanel({\n selectedElement,\n updateElement,\n}: PropertiesPanelProps) {\n const elementProps = selectedElement?.getProps() || {};\n const volumeLinear = elementProps.volume ?? 1;\n const volumeDb = linearToDb(volumeLinear);\n const playbackRate = elementProps.playbackRate ?? 1;\n\n const handleUpdateElement = (props: Record<string, any>) => {\n if (selectedElement) {\n updateElement?.(selectedElement?.setProps({ ...elementProps, ...props }));\n }\n };\n\n const handleVolumeDbChange = (db: number) => {\n handleUpdateElement({ volume: dbToLinear(db) });\n };\n\n const handlePlaybackRateChange = (rate: number) => {\n handleUpdateElement({ playbackRate: rate });\n };\n\n const [isPlaybackOpen, setIsPlaybackOpen] = useState(false);\n\n return (\n <div className=\"panel-container\">\n <div className=\"panel-title\">Playback</div>\n <AccordionItem\n title=\"Playback\"\n icon={<Music2 className=\"icon-sm\" />}\n isOpen={isPlaybackOpen}\n onToggle={() => setIsPlaybackOpen((open) => !open)}\n >\n <div className=\"properties-group\">\n {/* Playback rate */}\n <div className=\"property-section\">\n <PropertyRow\n label=\"Playback rate\"\n secondary={<span>{playbackRate}×</span>}\n >\n <input\n type=\"range\"\n min={PLAYBACK_RATE_MIN}\n max={PLAYBACK_RATE_MAX}\n step={PLAYBACK_RATE_STEP}\n value={playbackRate}\n onChange={(e) =>\n handlePlaybackRateChange(Number(e.target.value))\n }\n className=\"slider-purple\"\n />\n </PropertyRow>\n </div>\n\n {/* Volume (dB) */}\n <div className=\"property-section\">\n <PropertyRow\n label=\"Volume\"\n secondary={\n <span>\n {volumeDb <= MIN_DB ? \"−∞\" : `${Math.round(volumeDb)} dB`}\n </span>\n }\n >\n <input\n type=\"range\"\n min={MIN_DB}\n max={MAX_DB}\n step={1}\n value={volumeDb}\n onChange={(e) =>\n handleVolumeDbChange(Number(e.target.value))\n }\n className=\"slider-purple\"\n />\n </PropertyRow>\n </div>\n </div>\n </AccordionItem>\n </div>\n );\n}\n","const imageDimensionsCache = {};\nconst videoMetaCache = {};\nconst audioDurationCache = {};\n\nconst getAudioDuration = (audioSrc) => {\n if (audioDurationCache[audioSrc]) {\n return Promise.resolve(audioDurationCache[audioSrc]);\n }\n return new Promise((resolve, reject) => {\n const audio = document.createElement(\"audio\");\n audio.preload = \"metadata\";\n const isSafeUrl = /^(https?:|blob:|data:audio\\/)/i.test(audioSrc);\n if (!isSafeUrl) {\n throw new Error(\"Unsafe audio source URL\");\n }\n audio.src = audioSrc;\n audio.onloadedmetadata = () => {\n const duration = audio.duration;\n audioDurationCache[audioSrc] = duration;\n resolve(duration);\n };\n audio.onerror = () => {\n reject(new Error(\"Failed to load audio metadata\"));\n };\n });\n};\n\nconst concurrencyLimit = 5;\nlet activeCount = 0;\nconst queue = [];\nfunction runNext() {\n if (queue.length === 0 || activeCount >= concurrencyLimit) return;\n const next = queue.shift();\n if (next) {\n activeCount++;\n next();\n }\n}\nfunction limit(fn) {\n return new Promise((resolve, reject) => {\n const task = () => {\n fn().then(resolve).catch(reject).finally(() => {\n activeCount--;\n runNext();\n });\n };\n if (activeCount < concurrencyLimit) {\n activeCount++;\n task();\n } else {\n queue.push(task);\n }\n });\n}\n\nconst loadImageDimensions = (url) => {\n return new Promise((resolve, reject) => {\n if (typeof document === \"undefined\") {\n reject(new Error(\"getImageDimensions() is only available in the browser.\"));\n return;\n }\n const img = new Image();\n img.onload = () => {\n resolve({ width: img.naturalWidth, height: img.naturalHeight });\n };\n img.onerror = reject;\n img.src = url;\n });\n};\nconst getImageDimensions = (url) => {\n if (imageDimensionsCache[url]) {\n return Promise.resolve(imageDimensionsCache[url]);\n }\n return limit(() => loadImageDimensions(url)).then((dimensions) => {\n imageDimensionsCache[url] = dimensions;\n return dimensions;\n });\n};\n\nconst getVideoMeta = (videoSrc) => {\n if (videoMetaCache[videoSrc]) {\n return Promise.resolve(videoMetaCache[videoSrc]);\n }\n return new Promise((resolve, reject) => {\n const isSafeUrl = /^(https?:|blob:|data:video\\/)/i.test(videoSrc);\n if (!isSafeUrl) {\n reject(new Error(\"Unsafe video source URL\"));\n return;\n }\n const tryLoadVideo = (useCors) => {\n const video = document.createElement(\"video\");\n video.preload = \"metadata\";\n video.crossOrigin = useCors ? \"anonymous\" : null;\n video.src = videoSrc;\n video.onloadedmetadata = () => {\n const meta = {\n width: video.videoWidth,\n height: video.videoHeight,\n duration: video.duration\n };\n videoMetaCache[videoSrc] = meta;\n resolve(meta);\n };\n video.onerror = () => {\n if (useCors) {\n video.src = \"\";\n tryLoadVideo(false);\n } else {\n reject(new Error(\"Failed to load video metadata. This may be due to CORS restrictions or an invalid video URL.\"));\n }\n };\n };\n tryLoadVideo(true);\n });\n};\n\nconst getThumbnail = async (videoUrl, seekTime = 0.1, playbackRate = 1) => {\n return new Promise((resolve, reject) => {\n const tryLoadThumbnail = (useCors) => {\n const video = document.createElement(\"video\");\n video.crossOrigin = useCors ? \"anonymous\" : null;\n video.muted = true;\n video.playsInline = true;\n video.autoplay = false;\n video.preload = \"auto\";\n video.playbackRate = playbackRate;\n video.style.position = \"absolute\";\n video.style.left = \"-9999px\";\n video.style.top = \"-9999px\";\n video.style.width = \"1px\";\n video.style.height = \"1px\";\n video.style.opacity = \"0\";\n video.style.pointerEvents = \"none\";\n video.style.zIndex = \"-1\";\n let timeoutId;\n const cleanup = () => {\n if (video.parentNode) video.remove();\n if (timeoutId) clearTimeout(timeoutId);\n };\n const handleError = () => {\n cleanup();\n if (useCors) {\n tryLoadThumbnail(false);\n } else {\n reject(new Error(`Failed to load video: ${video.error?.message || \"Unknown error. This may be due to CORS restrictions or an invalid video URL.\"}`));\n }\n };\n const handleSeeked = () => {\n try {\n video.pause();\n const canvas = document.createElement(\"canvas\");\n const width = video.videoWidth || 640;\n const height = video.videoHeight || 360;\n canvas.width = width;\n canvas.height = height;\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) {\n cleanup();\n reject(new Error(\"Failed to get canvas context\"));\n return;\n }\n ctx.drawImage(video, 0, 0, width, height);\n try {\n const dataUrl = canvas.toDataURL(\"image/jpeg\", 0.8);\n cleanup();\n resolve(dataUrl);\n } catch {\n canvas.toBlob((blob) => {\n if (!blob) {\n cleanup();\n reject(new Error(\"Failed to create Blob\"));\n return;\n }\n const blobUrl = URL.createObjectURL(blob);\n cleanup();\n resolve(blobUrl);\n }, \"image/jpeg\", 0.8);\n }\n } catch (err) {\n cleanup();\n reject(new Error(`Error creating thumbnail: ${err}`));\n }\n };\n video.addEventListener(\"error\", handleError, { once: true });\n video.addEventListener(\"seeked\", handleSeeked, { once: true });\n video.addEventListener(\"loadedmetadata\", () => {\n const playPromise = video.play();\n if (playPromise !== void 0) {\n playPromise.then(() => {\n video.currentTime = seekTime || 0.1;\n }).catch(() => {\n video.currentTime = seekTime || 0.1;\n });\n } else {\n video.currentTime = seekTime || 0.1;\n }\n }, { once: true });\n timeoutId = window.setTimeout(() => {\n cleanup();\n reject(new Error(\"Video loading timed out\"));\n }, 15e3);\n video.src = videoUrl;\n document.body.appendChild(video);\n };\n tryLoadThumbnail(true);\n });\n};\n\nclass LRUCache {\n constructor(maxSize = 100) {\n if (maxSize <= 0) {\n throw new Error(\"maxSize must be greater than 0\");\n }\n this.maxSize = maxSize;\n this.cache = /* @__PURE__ */ new Map();\n }\n /**\n * Get a value from the cache.\n * Moves the item to the end (most recently used).\n */\n get(key) {\n const value = this.cache.get(key);\n if (value === void 0) {\n return void 0;\n }\n this.cache.delete(key);\n this.cache.set(key, value);\n return value;\n }\n /**\n * Set a value in the cache.\n * If cache is full, removes the least recently used item.\n */\n set(key, value) {\n if (this.cache.has(key)) {\n this.cache.delete(key);\n } else if (this.cache.size >= this.maxSize) {\n const firstKey = this.cache.keys().next().value;\n if (firstKey !== void 0) {\n this.cache.delete(firstKey);\n }\n }\n this.cache.set(key, value);\n }\n /**\n * Check if a key exists in the cache.\n */\n has(key) {\n return this.cache.has(key);\n }\n /**\n * Delete a key from the cache.\n */\n delete(key) {\n return this.cache.delete(key);\n }\n /**\n * Clear all entries from the cache.\n */\n clear() {\n this.cache.clear();\n }\n /**\n * Get the current size of the cache.\n */\n get size() {\n return this.cache.size;\n }\n}\n\nclass VideoFrameExtractor {\n constructor(options = {}) {\n this.frameCache = new LRUCache(\n options.maxCacheSize ?? 50\n );\n this.videoElements = /* @__PURE__ */ new Map();\n this.maxVideoElements = options.maxVideoElements ?? 5;\n this.loadTimeout = options.loadTimeout ?? 15e3;\n this.jpegQuality = options.jpegQuality ?? 0.8;\n this.playbackRate = options.playbackRate ?? 1;\n }\n /**\n * Get a frame thumbnail from a video at a specific time.\n * Uses caching and reuses video elements for optimal performance.\n * Uses 0.1s instead of 0 when seekTime is 0, since frames at t=0 are often blank.\n *\n * @param videoUrl - The URL of the video\n * @param seekTime - The time in seconds to extract the frame (0 is treated as 0.1)\n * @returns Promise resolving to a thumbnail image URL (data URL or blob URL)\n */\n async getFrame(videoUrl, seekTime = 0.1) {\n const effectiveSeekTime = seekTime === 0 ? 0.1 : seekTime;\n const cacheKey = this.getCacheKey(videoUrl, effectiveSeekTime);\n const cached = this.frameCache.get(cacheKey);\n if (cached) {\n return cached;\n }\n const videoState = await this.getVideoElement(videoUrl);\n const thumbnail = await this.extractFrame(videoState.video, effectiveSeekTime);\n this.frameCache.set(cacheKey, thumbnail);\n return thumbnail;\n }\n /**\n * Get or create a video element for the given URL.\n * Reuses existing elements and manages cleanup.\n */\n async getVideoElement(videoUrl) {\n let videoState = this.videoElements.get(videoUrl);\n if (videoState && videoState.isReady) {\n videoState.lastUsed = Date.now();\n return videoState;\n }\n if (videoState && videoState.isLoading && videoState.loadPromise) {\n await videoState.loadPromise;\n if (videoState.isReady) {\n videoState.lastUsed = Date.now();\n return videoState;\n }\n }\n if (this.videoElements.size >= this.maxVideoElements) {\n this.cleanupOldVideoElements();\n }\n videoState = await this.createVideoElement(videoUrl);\n this.videoElements.set(videoUrl, videoState);\n videoState.lastUsed = Date.now();\n return videoState;\n }\n /**\n * Create and initialize a new video element.\n */\n async createVideoElement(videoUrl) {\n const video = document.createElement(\"video\");\n video.crossOrigin = \"anonymous\";\n video.muted = true;\n video.playsInline = true;\n video.autoplay = false;\n video.preload = \"auto\";\n video.playbackRate = this.playbackRate;\n video.style.position = \"absolute\";\n video.style.left = \"-9999px\";\n video.style.top = \"-9999px\";\n video.style.width = \"1px\";\n video.style.height = \"1px\";\n video.style.opacity = \"0\";\n video.style.pointerEvents = \"none\";\n video.style.zIndex = \"-1\";\n const state = {\n video,\n isReady: false,\n isLoading: true,\n loadPromise: null,\n lastUsed: Date.now()\n };\n state.loadPromise = new Promise((resolve, reject) => {\n let timeoutId;\n const cleanup = () => {\n if (timeoutId) clearTimeout(timeoutId);\n };\n const handleError = () => {\n cleanup();\n state.isLoading = false;\n reject(new Error(`Failed to load video: ${video.error?.message || \"Unknown error\"}`));\n };\n const handleLoadedMetadata = () => {\n cleanup();\n state.isReady = true;\n state.isLoading = false;\n resolve();\n };\n video.addEventListener(\"error\", handleError, { once: true });\n video.addEventListener(\"loadedmetadata\", handleLoadedMetadata, { once: true });\n timeoutId = window.setTimeout(() => {\n cleanup();\n state.isLoading = false;\n reject(new Error(\"Video loading timed out\"));\n }, this.loadTimeout);\n video.src = videoUrl;\n document.body.appendChild(video);\n });\n try {\n await state.loadPromise;\n } catch (error) {\n if (video.parentNode) {\n video.remove();\n }\n throw error;\n }\n return state;\n }\n /**\n * Extract a frame from a video at the specified time.\n */\n async extractFrame(video, seekTime) {\n return new Promise((resolve, reject) => {\n video.pause();\n const timeThreshold = 0.1;\n if (Math.abs(video.currentTime - seekTime) < timeThreshold) {\n try {\n const canvas = document.createElement(\"canvas\");\n const width = video.videoWidth || 640;\n const height = video.videoHeight || 360;\n canvas.width = width;\n canvas.height = height;\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) {\n reject(new Error(\"Failed to get canvas context\"));\n return;\n }\n ctx.drawImage(video, 0, 0, width, height);\n try {\n const dataUrl = canvas.toDataURL(\"image/jpeg\", this.jpegQuality);\n resolve(dataUrl);\n } catch {\n canvas.toBlob(\n (blob) => {\n if (!blob) {\n reject(new Error(\"Failed to create Blob\"));\n return;\n }\n const blobUrl = URL.createObjectURL(blob);\n resolve(blobUrl);\n },\n \"image/jpeg\",\n this.jpegQuality\n );\n }\n return;\n } catch (err) {\n reject(new Error(`Error creating thumbnail: ${err}`));\n return;\n }\n }\n const handleSeeked = () => {\n try {\n const canvas = document.createElement(\"canvas\");\n const width = video.videoWidth || 640;\n const height = video.videoHeight || 360;\n canvas.width = width;\n canvas.height = height;\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) {\n reject(new Error(\"Failed to get canvas context\"));\n return;\n }\n ctx.drawImage(video, 0, 0, width, height);\n try {\n const dataUrl = canvas.toDataURL(\"image/jpeg\", this.jpegQuality);\n resolve(dataUrl);\n } catch {\n canvas.toBlob(\n (blob) => {\n if (!blob) {\n reject(new Error(\"Failed to create Blob\"));\n return;\n }\n const blobUrl = URL.createObjectURL(blob);\n resolve(blobUrl);\n },\n \"image/jpeg\",\n this.jpegQuality\n );\n }\n } catch (err) {\n reject(new Error(`Error creating thumbnail: ${err}`));\n }\n };\n video.addEventListener(\"seeked\", handleSeeked, { once: true });\n const playPromise = video.play();\n if (playPromise !== void 0) {\n playPromise.then(() => {\n video.currentTime = seekTime;\n }).catch(() => {\n video.currentTime = seekTime;\n });\n } else {\n video.currentTime = seekTime;\n }\n });\n }\n /**\n * Generate cache key for a video URL and seek time.\n */\n getCacheKey(videoUrl, seekTime) {\n const roundedTime = Math.round(seekTime * 100) / 100;\n return `${videoUrl}:${roundedTime}`;\n }\n /**\n * Cleanup least recently used video elements.\n */\n cleanupOldVideoElements() {\n if (this.videoElements.size < this.maxVideoElements) {\n return;\n }\n const entries = Array.from(this.videoElements.entries());\n entries.sort((a, b) => a[1].lastUsed - b[1].lastUsed);\n const toRemove = entries.slice(0, entries.length - this.maxVideoElements + 1);\n for (const [url, state] of toRemove) {\n if (state.video.parentNode) {\n state.video.remove();\n }\n this.videoElements.delete(url);\n }\n }\n /**\n * Clear the frame cache.\n */\n clearCache() {\n this.frameCache.clear();\n }\n /**\n * Remove a specific video element and clear its cached frames.\n */\n removeVideo(videoUrl) {\n const state = this.videoElements.get(videoUrl);\n if (state) {\n if (state.video.parentNode) {\n state.video.remove();\n }\n this.videoElements.delete(videoUrl);\n }\n this.frameCache.clear();\n }\n /**\n * Dispose of all video elements and clear caches.\n * Removes all video elements from the DOM and clears both the frame cache\n * and video element cache. Call this when the extractor is no longer needed\n * to prevent memory leaks.\n */\n dispose() {\n for (const state of this.videoElements.values()) {\n if (state.video.parentNode) {\n state.video.remove();\n }\n }\n this.videoElements.clear();\n this.frameCache.clear();\n }\n}\nlet defaultExtractor = null;\nfunction getDefaultVideoFrameExtractor(options) {\n if (!defaultExtractor) {\n defaultExtractor = new VideoFrameExtractor(options);\n }\n return defaultExtractor;\n}\nasync function getThumbnailCached(videoUrl, seekTime = 0.1, playbackRate) {\n const extractor = getDefaultVideoFrameExtractor(\n playbackRate !== void 0 ? { playbackRate } : void 0\n );\n return extractor.getFrame(videoUrl, seekTime);\n}\n\nconst extractAudio = async ({\n src,\n playbackRate = 1,\n start = 0,\n end\n}) => {\n if (!src) throw new Error(\"src is required\");\n if (playbackRate <= 0) throw new Error(\"playbackRate must be > 0\");\n const isSafeUrl = /^(https?:|blob:|data:)/i.test(src);\n if (!isSafeUrl) throw new Error(\"Unsafe media source URL\");\n const audioBuffer = await fetchAndDecodeAudio(src);\n if (audioBuffer.duration === 0 || audioBuffer.length === 0) {\n throw new Error(\"No audio track found in the media source\");\n }\n if (isAudioSilent(audioBuffer)) {\n throw new Error(\"Audio track is silent (no audio content detected)\");\n }\n const clampedStart = Math.max(0, start || 0);\n const fullDuration = audioBuffer.duration;\n const clampedEnd = Math.min(\n typeof end === \"number\" ? end : fullDuration,\n fullDuration\n );\n if (clampedEnd <= clampedStart)\n throw new Error(\"Invalid range: end must be greater than start\");\n const renderedBuffer = await renderAudioSegment(\n audioBuffer,\n clampedStart,\n clampedEnd,\n playbackRate\n );\n const mp3Blob = await audioBufferToMp3(renderedBuffer);\n return URL.createObjectURL(mp3Blob);\n};\nconst hasAudio = async (src) => {\n if (!src) return false;\n const isSafeUrl = /^(https?:|blob:|data:)/i.test(src);\n if (!isSafeUrl) return false;\n try {\n const audioBuffer = await fetchAndDecodeAudio(src);\n if (audioBuffer.duration === 0 || audioBuffer.length === 0) {\n return false;\n }\n if (isAudioSilent(audioBuffer)) {\n return false;\n }\n return true;\n } catch (error) {\n return false;\n }\n};\nconst stitchAudio = async (segments, totalDuration) => {\n if (!segments || segments.length === 0) {\n throw new Error(\"At least one audio segment is required\");\n }\n const duration = totalDuration || Math.max(...segments.map((s) => s.e));\n const renderedBuffer = await createAudioTimeline(segments, duration);\n const mp3Blob = await audioBufferToMp3(renderedBuffer);\n return URL.createObjectURL(mp3Blob);\n};\nconst fetchAndDecodeAudio = async (src) => {\n const response = await fetch(src);\n if (!response.ok) throw new Error(`Failed to fetch source: ${response.status}`);\n const arrayBuffer = await response.arrayBuffer();\n return decodeAudioData(arrayBuffer);\n};\nconst decodeAudioData = async (arrayBuffer) => {\n const AudioContextCtor = window.AudioContext || window.webkitAudioContext;\n if (!AudioContextCtor) throw new Error(\"Web Audio API not supported\");\n const audioContext = new AudioContextCtor();\n try {\n return await new Promise((resolve, reject) => {\n audioContext.decodeAudioData(\n arrayBuffer.slice(0),\n (buf) => resolve(buf),\n (err) => reject(err || new Error(\"Failed to decode audio: no audio track found or unsupported format\"))\n );\n });\n } finally {\n audioContext.close();\n }\n};\nconst isAudioSilent = (buffer, threshold = 1e-3) => {\n for (let channel = 0; channel < buffer.numberOfChannels; channel++) {\n const channelData = buffer.getChannelData(channel);\n for (let i = 0; i < channelData.length; i += 100) {\n if (Math.abs(channelData[i]) > threshold) {\n return false;\n }\n }\n }\n return true;\n};\nconst renderAudioSegment = async (audioBuffer, start, end, playbackRate) => {\n const OfflineAudioContextCtor = window.OfflineAudioContext || window.webkitOfflineAudioContext;\n if (!OfflineAudioContextCtor) throw new Error(\"OfflineAudioContext not supported\");\n const sampleRate = audioBuffer.sampleRate;\n const numChannels = audioBuffer.numberOfChannels;\n const sourceDuration = end - start;\n const renderedFrames = Math.max(\n 1,\n Math.ceil(sourceDuration / playbackRate * sampleRate)\n );\n const offline = new OfflineAudioContextCtor(numChannels, renderedFrames, sampleRate);\n const sourceNode = offline.createBufferSource();\n sourceNode.buffer = audioBuffer;\n sourceNode.playbackRate.value = playbackRate;\n sourceNode.connect(offline.destination);\n sourceNode.start(0, start, sourceDuration);\n return await offline.startRendering();\n};\nconst createAudioTimeline = async (segments, duration) => {\n const OfflineAudioContextCtor = window.OfflineAudioContext || window.webkitOfflineAudioContext;\n if (!OfflineAudioContextCtor) throw new Error(\"OfflineAudioContext not supported\");\n const sampleRate = 44100;\n const totalFrames = Math.ceil(duration * sampleRate);\n const offline = new OfflineAudioContextCtor(2, totalFrames, sampleRate);\n for (const segment of segments) {\n if (segment.s >= segment.e) continue;\n const volume = segment.volume ?? 1;\n if (volume <= 0) continue;\n try {\n const audioBuffer = await fetchAndDecodeAudio(segment.src);\n const segmentDuration = segment.e - segment.s;\n const sourceDuration = Math.min(segmentDuration, audioBuffer.duration);\n const source = offline.createBufferSource();\n source.buffer = audioBuffer;\n if (volume !== 1) {\n const gainNode = offline.createGain();\n gainNode.gain.value = volume;\n source.connect(gainNode);\n gainNode.connect(offline.destination);\n } else {\n source.connect(offline.destination);\n }\n source.start(segment.s, 0, sourceDuration);\n } catch {\n }\n }\n return await offline.startRendering();\n};\nconst audioBufferToMp3 = async (buffer) => {\n try {\n const wavArrayBuffer = audioBufferToWavArrayBuffer(buffer);\n const pcmBuffer = await decodeAudioData(wavArrayBuffer);\n return await encodePcmToMp3(pcmBuffer);\n } catch (error) {\n return audioBufferToWavBlob(buffer);\n }\n};\nconst audioBufferToWavArrayBuffer = (buffer) => {\n const numChannels = buffer.numberOfChannels;\n const sampleRate = buffer.sampleRate;\n const numFrames = buffer.length;\n const interleaved = interleave(buffer, numChannels, numFrames);\n const bytesPerSample = 2;\n const blockAlign = numChannels * bytesPerSample;\n const byteRate = sampleRate * blockAlign;\n const dataSize = interleaved.length * bytesPerSample;\n const bufferSize = 44 + dataSize;\n const arrayBuffer = new ArrayBuffer(bufferSize);\n const view = new DataView(arrayBuffer);\n writeString(view, 0, \"RIFF\");\n view.setUint32(4, 36 + dataSize, true);\n writeString(view, 8, \"WAVE\");\n writeString(view, 12, \"fmt \");\n view.setUint32(16, 16, true);\n view.setUint16(20, 1, true);\n view.setUint16(22, numChannels, true);\n view.setUint32(24, sampleRate, true);\n view.setUint32(28, byteRate, true);\n view.setUint16(32, blockAlign, true);\n view.setUint16(34, 16, true);\n writeString(view, 36, \"data\");\n view.setUint32(40, dataSize, true);\n floatTo16BitPCM(view, 44, interleaved);\n return arrayBuffer;\n};\nconst encodePcmToMp3 = async (buffer) => {\n const lamejs = await import('./index-CXhwwSX-.mjs').then(n => n.i);\n const channels = buffer.numberOfChannels >= 2 ? 2 : 1;\n const targetSampleRate = 22050;\n const downsampledBuffer = downsampleAudioBuffer(buffer, targetSampleRate);\n const kbps = 48;\n const mp3encoder = new lamejs.default.Mp3Encoder(channels, targetSampleRate, kbps);\n const samplesPerFrame = 1152;\n const leftFloat = downsampledBuffer.getChannelData(0);\n const left = floatTo16(leftFloat);\n let right;\n if (channels === 2) {\n const rightFloat = downsampledBuffer.getChannelData(1);\n right = floatTo16(rightFloat);\n }\n const mp3Chunks = [];\n for (let i = 0; i < left.length; i += samplesPerFrame) {\n const leftChunk = left.subarray(i, Math.min(i + samplesPerFrame, left.length));\n let mp3buf;\n if (channels === 2 && right) {\n const rightChunk = right.subarray(i, Math.min(i + samplesPerFrame, right.length));\n mp3buf = mp3encoder.encodeBuffer(leftChunk, rightChunk);\n } else {\n mp3buf = mp3encoder.encodeBuffer(leftChunk);\n }\n if (mp3buf.length > 0) mp3Chunks.push(mp3buf);\n }\n const end = mp3encoder.flush();\n if (end.length > 0) mp3Chunks.push(end);\n return new Blob(mp3Chunks, { type: \"audio/mpeg\" });\n};\nconst audioBufferToWavBlob = (buffer) => {\n const arrayBuffer = audioBufferToWavArrayBuffer(buffer);\n return new Blob([arrayBuffer], { type: \"audio/wav\" });\n};\nconst downsampleAudioBuffer = (buffer, targetSampleRate) => {\n if (buffer.sampleRate === targetSampleRate) {\n return buffer;\n }\n const ratio = buffer.sampleRate / targetSampleRate;\n const newLength = Math.round(buffer.length / ratio);\n const newBuffer = new AudioContext().createBuffer(\n buffer.numberOfChannels,\n newLength,\n targetSampleRate\n );\n for (let channel = 0; channel < buffer.numberOfChannels; channel++) {\n const oldData = buffer.getChannelData(channel);\n const newData = newBuffer.getChannelData(channel);\n for (let i = 0; i < newLength; i++) {\n const oldIndex = Math.floor(i * ratio);\n newData[i] = oldData[oldIndex];\n }\n }\n return newBuffer;\n};\nconst interleave = (buffer, numChannels, numFrames) => {\n if (numChannels === 1) {\n return buffer.getChannelData(0).slice(0, numFrames);\n }\n const result = new Float32Array(numFrames * numChannels);\n const channelData = [];\n for (let ch = 0; ch < numChannels; ch++) {\n channelData[ch] = buffer.getChannelData(ch);\n }\n let writeIndex = 0;\n for (let i = 0; i < numFrames; i++) {\n for (let ch = 0; ch < numChannels; ch++) {\n result[writeIndex++] = channelData[ch][i];\n }\n }\n return result;\n};\nconst floatTo16BitPCM = (view, offset, input) => {\n let pos = offset;\n for (let i = 0; i < input.length; i++, pos += 2) {\n let s = Math.max(-1, Math.min(1, input[i]));\n view.setInt16(pos, s < 0 ? s * 32768 : s * 32767, true);\n }\n};\nconst floatTo16 = (input) => {\n const output = new Int16Array(input.length);\n for (let i = 0; i < input.length; i++) {\n const s = Math.max(-1, Math.min(1, input[i]));\n output[i] = s < 0 ? s * 32768 : s * 32767;\n }\n return output;\n};\nconst writeString = (view, offset, str) => {\n for (let i = 0; i < str.length; i++) {\n view.setUint8(offset + i, str.charCodeAt(i));\n }\n};\n\nconst getScaledDimensions = (width, height, maxWidth, maxHeight) => {\n if (width <= maxWidth && height <= maxHeight) {\n return {\n width: width % 2 === 0 ? width : width - 1,\n height: height % 2 === 0 ? height : height - 1\n };\n }\n const widthRatio = maxWidth / width;\n const heightRatio = maxHeight / height;\n const scale = Math.min(widthRatio, heightRatio);\n let scaledWidth = Math.round(width * scale);\n let scaledHeight = Math.round(height * scale);\n if (scaledWidth % 2 !== 0) {\n scaledWidth -= 1;\n }\n if (scaledHeight % 2 !== 0) {\n scaledHeight -= 1;\n }\n return {\n width: Math.min(scaledWidth, maxWidth),\n height: Math.min(scaledHeight, maxHeight)\n };\n};\nconst getObjectFitSize = (objectFit, elementSize, containerSize) => {\n const elementAspectRatio = elementSize.width / elementSize.height;\n const containerAspectRatio = containerSize.width / containerSize.height;\n switch (objectFit) {\n case \"contain\":\n if (elementAspectRatio > containerAspectRatio) {\n return {\n width: containerSize.width,\n height: containerSize.width / elementAspectRatio\n };\n } else {\n return {\n width: containerSize.height * elementAspectRatio,\n height: containerSize.height\n };\n }\n case \"cover\":\n if (elementAspectRatio > containerAspectRatio) {\n return {\n width: containerSize.height * elementAspectRatio,\n height: containerSize.height\n };\n } else {\n return {\n width: containerSize.width,\n height: containerSize.width / elementAspectRatio\n };\n }\n case \"fill\":\n return {\n width: containerSize.width,\n height: containerSize.height\n };\n default:\n return {\n width: elementSize.width,\n height: elementSize.height\n };\n }\n};\n\nconst blobUrlToFile = async (blobUrl, fileName) => {\n const response = await fetch(blobUrl);\n const blob = await response.blob();\n return new File([blob], fileName, { type: blob.type });\n};\nconst loadFile = (accept) => {\n return new Promise((resolve, reject) => {\n try {\n const input = document.createElement(\"input\");\n input.type = \"file\";\n input.accept = accept;\n input.style.display = \"none\";\n document.body.appendChild(input);\n const cleanup = () => {\n input.value = \"\";\n document.body.removeChild(input);\n };\n input.onchange = () => {\n const file = input.files && input.files[0];\n cleanup();\n if (!file) {\n reject(new Error(\"No file selected\"));\n return;\n }\n resolve(file);\n };\n input.click();\n } catch (error) {\n reject(error);\n }\n });\n};\nconst saveAsFile = (content, type, name) => {\n const blob = typeof content === \"string\" ? new Blob([content], { type }) : content;\n const url = URL.createObjectURL(blob);\n const a = document.createElement(\"a\");\n a.href = url;\n a.download = name;\n a.click();\n URL.revokeObjectURL(url);\n};\nconst downloadFile = async (url, filename) => {\n try {\n const response = await fetch(url);\n const blob = await response.blob();\n const downloadUrl = window.URL.createObjectURL(blob);\n const link = document.createElement(\"a\");\n link.href = downloadUrl;\n link.download = filename;\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n window.URL.revokeObjectURL(downloadUrl);\n } catch (error) {\n throw error;\n }\n};\n\nconst detectMediaTypeFromUrl = async (url) => {\n try {\n const response = await fetch(url, { method: \"HEAD\" });\n const contentType = response.headers.get(\"Content-Type\");\n if (!contentType) return null;\n if (contentType.startsWith(\"image/\")) return \"image\";\n if (contentType.startsWith(\"video/\")) return \"video\";\n if (contentType.startsWith(\"audio/\")) return \"audio\";\n return null;\n } catch {\n return null;\n }\n};\n\nexport { VideoFrameExtractor, blobUrlToFile, detectMediaTypeFromUrl, downloadFile, extractAudio, getAudioDuration, getDefaultVideoFrameExtractor, getImageDimensions, getObjectFitSize, getScaledDimensions, getThumbnail, getThumbnailCached, getVideoMeta, hasAudio, limit, loadFile, saveAsFile, stitchAudio };\n//# sourceMappingURL=index.mjs.map\n","import { TrackElement, VideoElement } from \"@twick/timeline\";\nimport { useEffect, useState, useRef } from \"react\";\nimport { hasAudio } from \"@twick/media-utils\";\nimport { Loader2, VolumeX, Volume2, CheckCircle2, XCircle } from \"lucide-react\";\nimport { ICaptionGenerationPollingResponse } from \"../../types\";\n\nexport function GenerateCaptionsPanel({\n selectedElement,\n addCaptionsToTimeline,\n onGenerateCaptions,\n getCaptionstatus,\n pollingIntervalMs = 5000,\n}: {\n selectedElement: TrackElement;\n addCaptionsToTimeline: (captions: { s: number; e: number; t: string }[]) => void;\n onGenerateCaptions: (videoElement: VideoElement) => Promise<string | null>;\n getCaptionstatus: (reqId: string) => Promise<ICaptionGenerationPollingResponse>;\n pollingIntervalMs?: number;\n}) {\n const [containsAudio, setContainsAudio] = useState<boolean | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n const [isGenerating, setIsGenerating] = useState(false);\n const [pollingStatus, setPollingStatus] = useState<\"idle\" | \"polling\" | \"success\" | \"error\">(\"idle\");\n const [errorMessage, setErrorMessage] = useState<string | null>(null);\n const pollingIntervalRef = useRef<NodeJS.Timeout | null>(null);\n const currentReqIdRef = useRef<string | null>(null);\n\n // Cleanup polling on unmount\n useEffect(() => {\n return () => {\n if (pollingIntervalRef.current) {\n clearInterval(pollingIntervalRef.current);\n }\n };\n }, []);\n\n const stopPolling = () => {\n if (pollingIntervalRef.current) {\n clearInterval(pollingIntervalRef.current);\n pollingIntervalRef.current = null;\n }\n };\n\n const startPolling = async (reqId: string) => {\n if (!getCaptionstatus) {\n return;\n }\n setPollingStatus(\"polling\");\n setIsGenerating(true);\n setErrorMessage(null);\n\n const poll = async () => {\n try {\n const response = await getCaptionstatus(reqId);\n\n \n if (response.status === \"completed\") {\n stopPolling();\n setPollingStatus(\"success\");\n setIsGenerating(false);\n \n // Add captions to timeline\n addCaptionsToTimeline(response.captions || []);\n \n // Reset status after 3 seconds\n setTimeout(() => {\n setPollingStatus(\"idle\");\n }, 3000);\n } else if (response.status === \"pending\") {\n // Continue polling - interval will call this again\n } else if (response.status === \"failed\") {\n stopPolling();\n setPollingStatus(\"error\");\n setIsGenerating(false);\n setErrorMessage(response.error || \"Failed to generate captions\");\n console.error(\"Error generating captions:\", response.error);\n }\n } catch (error) {\n stopPolling();\n setPollingStatus(\"error\");\n setIsGenerating(false);\n setErrorMessage(error instanceof Error ? error.message : \"Failed to get caption status\");\n console.error(\"Error polling for captions:\", error);\n }\n };\n\n // Poll immediately, then at configured interval (default 5 seconds)\n await poll();\n pollingIntervalRef.current = setInterval(poll, pollingIntervalMs);\n };\n\n const handleGenerateCaptions = async () => {\n if (!(selectedElement instanceof VideoElement)) {\n return;\n }\n\n setIsGenerating(true);\n setPollingStatus(\"polling\");\n const videoElement = selectedElement as VideoElement;\n \n\n try {\n const reqId = await onGenerateCaptions(videoElement);\n if (!reqId) {\n setPollingStatus(\"error\");\n setIsGenerating(false);\n setErrorMessage(\"Failed to start caption generation\");\n console.error(\"Error generating captions: Failed to start caption generation\");\n return;\n }\n currentReqIdRef.current = reqId;\n await startPolling(reqId);\n } catch (error) {\n setPollingStatus(\"error\");\n setIsGenerating(false);\n setErrorMessage(error instanceof Error ? error.message : \"Failed to start caption generation\");\n console.error(\"Error generating captions:\", error);\n }\n };\n\n const checkAudio = async () => {\n setIsLoading(true);\n if (selectedElement instanceof VideoElement) {\n const videoElement = selectedElement as VideoElement;\n const videoUrl = videoElement.getSrc();\n if (videoUrl) {\n try {\n const hasAudioTrack = await hasAudio(videoUrl);\n setContainsAudio(hasAudioTrack);\n } catch (error) {\n console.error(\"Error checking audio:\", error);\n setContainsAudio(false);\n }\n } else {\n setContainsAudio(false);\n }\n } else {\n setContainsAudio(false);\n }\n setIsLoading(false);\n };\n\n useEffect(() => {\n checkAudio();\n // Reset polling state when element changes\n stopPolling();\n setPollingStatus(\"idle\");\n setIsGenerating(false);\n setErrorMessage(null);\n }, [selectedElement]);\n\n return (\n <div className=\"panel-container\">\n <div className=\"panel-title\">Generate Captions Panel</div>\n \n {/* Loading State */}\n {isLoading && (\n <div className=\"panel-section\">\n <div className=\"empty-state\">\n <div className=\"empty-state-content\">\n <Loader2 className=\"empty-state-icon animate-spin\" />\n <p className=\"empty-state-text\">Checking for audio...</p>\n </div>\n </div>\n </div>\n )}\n\n {/* No Audio State */}\n {!isLoading && containsAudio === false && (\n <div className=\"panel-section\">\n <div className=\"empty-state\">\n <div className=\"empty-state-content\">\n <VolumeX className=\"empty-state-icon\" />\n <p className=\"empty-state-text\">No audio track found in this video</p>\n </div>\n </div>\n </div>\n )}\n\n {/* Audio Present State */}\n {!isLoading && containsAudio === true && pollingStatus === \"idle\" && !isGenerating && (\n <div className=\"panel-section\">\n <div className=\"empty-state\">\n <div className=\"empty-state-content\">\n <Volume2 className=\"empty-state-icon\" />\n <p className=\"empty-state-text\">Audio detected! You can now generate captions</p>\n </div>\n </div>\n </div>\n )}\n\n {/* Polling/Generating State */}\n {!isLoading && isGenerating && pollingStatus === \"polling\" && (\n <div className=\"panel-section\">\n <div className=\"empty-state\">\n <div className=\"empty-state-content\">\n <Loader2 className=\"empty-state-icon animate-spin\" />\n <p className=\"empty-state-text\">Generating captions... Please wait</p>\n </div>\n </div>\n </div>\n )}\n\n {/* Success State */}\n {!isLoading && pollingStatus === \"success\" && (\n <div className=\"panel-section\">\n <div className=\"empty-state\">\n <div className=\"empty-state-content\">\n <CheckCircle2 className=\"empty-state-icon\" color=\"var(--color-green-500)\" />\n <p className=\"empty-state-text\">Captions generated successfully!</p>\n </div>\n </div>\n </div>\n )}\n\n {/* Error State */}\n {!isLoading && pollingStatus === \"error\" && (\n <div className=\"panel-section\">\n <div className=\"empty-state\">\n <div className=\"empty-state-content\">\n <XCircle className=\"empty-state-icon\" color=\"var(--color-red-500)\" />\n <p className=\"empty-state-text\">{errorMessage || \"Failed to generate captions\"}</p>\n </div>\n </div>\n </div>\n )}\n\n {/* Generate Button */}\n {!isLoading && (\n <div className=\"flex panel-section\">\n <button\n onClick={handleGenerateCaptions}\n disabled={!containsAudio || isGenerating}\n className=\"btn-primary w-full\"\n >\n {isGenerating ? \"Generating...\" : \"Generate Captions\"}\n </button>\n </div>\n )}\n </div>\n );\n}\n","import { TextElement } from \"@twick/timeline\";\nimport type { PropertiesPanelProps } from \"../../types\";\nimport { AccordionItem } from \"../shared/accordion-item\";\nimport { PropertyRow } from \"./property-row\";\nimport { Type, AlignLeft, AlignCenter, AlignRight, Bold, Italic } from \"lucide-react\";\nimport { useState } from \"react\";\n\nexport function TextPropsPanel({\n selectedElement,\n updateElement,\n}: PropertiesPanelProps) {\n if (!(selectedElement instanceof TextElement)) return null;\n\n const textProps = selectedElement.getProps() || {};\n\n const [isTypographyOpen, setIsTypographyOpen] = useState(false);\n\n const currentAlign = textProps.textAlign ?? \"center\";\n const currentWeight = textProps.fontWeight ?? 400;\n const isBold = currentWeight >= 600;\n const isItalic = textProps.fontStyle === \"italic\";\n\n const handleUpdate = (patch: Partial<typeof textProps>) => {\n if (!selectedElement) return;\n const next = { ...textProps, ...patch };\n selectedElement.setProps(next);\n updateElement?.(selectedElement);\n };\n\n const toggleBold = () => {\n handleUpdate({ fontWeight: isBold ? 400 : 700 });\n };\n\n const toggleItalic = () => {\n handleUpdate({ fontStyle: isItalic ? \"normal\" : \"italic\" });\n };\n\n const setAlign = (align: \"left\" | \"center\" | \"right\") => {\n handleUpdate({ textAlign: align });\n };\n\n return (\n <div className=\"panel-container\">\n <div className=\"panel-title\">Typography</div>\n <AccordionItem\n title=\"Typography\"\n icon={<Type className=\"icon-sm\" />}\n isOpen={isTypographyOpen}\n onToggle={() => setIsTypographyOpen((open) => !open)}\n >\n <div className=\"properties-group\">\n {/* Font size */}\n <div className=\"property-section\">\n <PropertyRow\n label=\"Font size\"\n secondary={<span>{textProps.fontSize ?? 48}px</span>}\n >\n <input\n type=\"range\"\n min={8}\n max={160}\n value={textProps.fontSize ?? 48}\n onChange={(e) =>\n handleUpdate({ fontSize: Number(e.target.value) })\n }\n className=\"slider-purple\"\n />\n </PropertyRow>\n </div>\n\n {/* Style: bold / italic */}\n <div className=\"property-section\">\n <PropertyRow label=\"Style\">\n <button\n type=\"button\"\n className={`form-btn ${isBold ? \"active\" : \"\"}`}\n onClick={toggleBold}\n title=\"Bold\"\n >\n <Bold className=\"icon-sm\" />\n </button>\n <button\n type=\"button\"\n className={`form-btn ${isItalic ? \"active\" : \"\"}`}\n onClick={toggleItalic}\n title=\"Italic\"\n >\n <Italic className=\"icon-sm\" />\n </button>\n </PropertyRow>\n </div>\n\n {/* Alignment */}\n <div className=\"property-section\">\n <PropertyRow label=\"Align\">\n <button\n type=\"button\"\n className={`form-btn ${currentAlign === \"left\" ? \"active\" : \"\"}`}\n onClick={() => setAlign(\"left\")}\n title=\"Align left\"\n >\n <AlignLeft className=\"icon-sm\" />\n </button>\n <button\n type=\"button\"\n className={`form-btn ${\n currentAlign === \"center\" ? \"active\" : \"\"\n }`}\n onClick={() => setAlign(\"center\")}\n title=\"Align center\"\n >\n <AlignCenter className=\"icon-sm\" />\n </button>\n <button\n type=\"button\"\n className={`form-btn ${\n currentAlign === \"right\" ? \"active\" : \"\"\n }`}\n onClick={() => setAlign(\"right\")}\n title=\"Align right\"\n >\n <AlignRight className=\"icon-sm\" />\n </button>\n </PropertyRow>\n </div>\n\n </div>\n </AccordionItem>\n </div>\n );\n}\n\n","import { ElementProps } from \"../properties/element-props\";\nimport { TextEffects } from \"../properties/text-effects\";\nimport { Animation } from \"../properties/animation\";\nimport { VideoElement, TextElement, AudioElement, type TrackElement, Size } from \"@twick/timeline\";\nimport { PlaybackPropsPanel } from \"../properties/playback-props\";\nimport { GenerateCaptionsPanel } from \"../properties/generate-captions.tsx\";\nimport { TextPropsPanel } from \"../properties/text-props\";\nimport { ICaptionGenerationPollingResponse, CaptionEntry } from \"../../types\";\n\ninterface PropertiesPanelContainerProps {\n selectedElement: TrackElement | null;\n updateElement: (element: TrackElement) => void;\n addCaptionsToTimeline: (captions: CaptionEntry[]) => void;\n onGenerateCaptions: (videoElement: VideoElement) => Promise<string | null>;\n getCaptionstatus: (reqId: string) => Promise<ICaptionGenerationPollingResponse>;\n pollingIntervalMs: number;\n videoResolution: Size;\n}\n\nexport function PropertiesPanelContainer({\n selectedElement,\n updateElement,\n addCaptionsToTimeline,\n onGenerateCaptions,\n getCaptionstatus,\n pollingIntervalMs,\n videoResolution,\n}: PropertiesPanelContainerProps) {\n\n const title = selectedElement instanceof TextElement ? selectedElement.getText() : selectedElement?.getName() || selectedElement?.getType() || \"Element\";\n\n return (\n <aside className=\"properties-panel\" aria-label=\"Element properties inspector\">\n <div className=\"properties-header\">\n {!selectedElement && (\n <h3 className=\"properties-title\">Composition</h3>\n )}\n {selectedElement && selectedElement.getType() === \"caption\" && (\n <h3 className=\"properties-title\">Edit from the captions panel</h3>\n )}\n {selectedElement && selectedElement.getType() !== \"caption\" && (\n <h3 className=\"properties-title\">\n {title}\n </h3>\n )}\n </div>\n\n <div className=\"prop-content\">\n {/* Composition inspector when nothing selected */}\n {!selectedElement && (\n <div className=\"panel-container\">\n <div className=\"panel-title\">Canvas & Render</div>\n <div className=\"properties-group\">\n <div className=\"property-section\">\n <span className=\"property-label\">Size</span>\n <span className=\"properties-size-readonly\">\n {videoResolution.width} × {videoResolution.height}\n </span>\n </div>\n </div>\n </div>\n )}\n\n {/* Element inspector when something is selected */}\n {selectedElement && selectedElement.getType() === \"caption\"\n ? null\n : selectedElement && (\n <>\n {(() => {\n const isText = selectedElement instanceof TextElement;\n const isVideo = selectedElement instanceof VideoElement;\n const isAudio = selectedElement instanceof AudioElement;\n\n return (\n <>\n {/* Typography (Text only) */}\n {isText && (\n <TextPropsPanel\n selectedElement={selectedElement}\n updateElement={updateElement}\n />\n )}\n\n {/* Transform – visual elements only (not audio) */}\n {!isAudio && (\n <ElementProps\n selectedElement={selectedElement}\n updateElement={updateElement}\n />\n )}\n\n {/* Playback + Volume – video and audio */}\n {(isVideo || isAudio) && (\n <PlaybackPropsPanel\n selectedElement={selectedElement}\n updateElement={updateElement}\n />\n )}\n\n {/* Text Effects – text only */}\n {isText && (\n <TextEffects\n selectedElement={selectedElement}\n updateElement={updateElement}\n />\n )}\n\n {/* Animations – visual elements only (not audio) */}\n {!isAudio && (\n <Animation\n selectedElement={selectedElement}\n updateElement={updateElement}\n />\n )}\n\n {/* Generate Captions – video only */}\n {isVideo && (\n <GenerateCaptionsPanel\n selectedElement={selectedElement}\n addCaptionsToTimeline={addCaptionsToTimeline}\n onGenerateCaptions={onGenerateCaptions}\n getCaptionstatus={getCaptionstatus}\n pollingIntervalMs={pollingIntervalMs}\n />\n )}\n </>\n );\n })()}\n </>\n )}\n </div>\n </aside>\n );\n}\n","import { PLAYER_STATE, ProjectJSON, useTimelineContext, VideoElement } from \"@twick/timeline\";\nimport { ICaptionGenerationPollingResponse, StudioConfig, CaptionEntry } from \"../types\";\nimport { loadFile, saveAsFile } from \"@twick/media-utils\";\nimport { useState } from \"react\";\nimport { useLivePlayerContext } from \"@twick/live-player\";\n\nconst useStudioOperation = (studioConfig?: StudioConfig) => {\n const { editor, present, videoResolution } = useTimelineContext();\n const { setSeekTime, setPlayerState } = useLivePlayerContext();\n const [projectName, setProjectName] = useState(\"\");\n\n const onNewProject = () => {\n setPlayerState(PLAYER_STATE.PAUSED);\n editor.loadProject({\n tracks: [],\n version: 0,\n });\n setSeekTime(0);\n }\n\n const onLoadProject = async () => {\n let project: ProjectJSON;\n setPlayerState(PLAYER_STATE.PAUSED);\n if (studioConfig?.loadProject) {\n project = await studioConfig.loadProject();\n } else {\n const file = await loadFile(\"application/json\");\n const text = await file.text();\n setProjectName(file.name);\n project = JSON.parse(text);\n }\n editor.loadProject(project);\n setSeekTime(0.01);\n };\n\n const onSaveProject = async () => {\n let fileName;\n if (projectName) {\n fileName = projectName;\n } else {\n fileName = prompt(\"Enter the name of the project\") || \"untitled-project\";\n fileName = fileName + \".json\";\n setProjectName(fileName);\n }\n if (studioConfig?.saveProject && present) {\n await studioConfig.saveProject(present, fileName);\n } else {\n const file = await saveAsFile(\n JSON.stringify(present),\n \"application/json\",\n fileName\n );\n if (file) {\n console.log(\"File saved\", file);\n }\n }\n };\n\n const onExportVideo = async () => {\n if (studioConfig?.exportVideo && present) {\n await studioConfig.exportVideo(present, {\n outFile: \"output.mp4\",\n fps: 30,\n resolution: {\n width: videoResolution.width,\n height: videoResolution.height,\n },\n });\n } else {\n alert(\"Export video not supported in demo mode\");\n }\n };\n\n\n\n /**\n * Generates captions using the new polling-based service\n * Returns a function that can be called to start the generation process\n */\n const onGenerateCaptions = async (videoElement: VideoElement) => {\n // Use new polling-based service if available\n if (studioConfig?.captionGenerationService) {\n const service = studioConfig.captionGenerationService;\n const reqId = await service.generateCaptions(videoElement, present as ProjectJSON);\n return reqId;\n }\n alert(\"Generate captions not supported in demo mode\");\n return null;\n };\n\n const addCaptionsToTimeline = (captions: CaptionEntry[]) => {\n const updatedProjectJSON = studioConfig?.captionGenerationService?.updateProjectWithCaptions(captions);\n if (updatedProjectJSON) {\n editor.loadProject(updatedProjectJSON);\n }\n }\n\n const getCaptionstatus = async (reqId: string) => {\n if (studioConfig?.captionGenerationService) {\n const service = studioConfig.captionGenerationService;\n return await service.getRequestStatus(reqId);\n }\n return {\n status: \"failed\",\n error: \"Caption generation service not found\",\n } as ICaptionGenerationPollingResponse;\n }\n\n return { \n onLoadProject, \n onSaveProject, \n onExportVideo, \n onNewProject,\n onGenerateCaptions,\n addCaptionsToTimeline,\n getCaptionstatus,\n };\n};\n\nexport default useStudioOperation;\n","/**\n * TwickStudio Component\n *\n * The main studio component that provides a complete video editing interface.\n * Integrates all major components including canvas, toolbar, media library,\n * and properties panel into a cohesive editing environment.\n *\n * @component\n * @example\n * ```tsx\n * <LivePlayerProvider>\n * <TimelineProvider initialData={initialData} contextId=\"studio-demo\">\n * <TwickStudio />\n * </TimelineProvider>\n * </LivePlayerProvider>\n * ```\n */\n\nimport { Toolbar } from \"./toolbar\";\nimport StudioHeader from \"./header\";\nimport { useStudioManager } from \"../hooks/use-studio-manager\";\nimport ElementPanelContainer from \"./container/element-panel-container\";\nimport { useTimelineContext } from \"@twick/timeline\";\nimport { MediaProvider } from \"../context/media-context\";\nimport { PropertiesPanelContainer } from \"./container/properties-panel-container\";\nimport VideoEditor from \"@twick/video-editor\";\nimport { useMemo } from \"react\";\nimport { StudioConfig } from \"../types\";\nimport useStudioOperation from \"../hooks/use-studio-operation\";\nimport { useGenerateCaptions } from \"..\";\n\nexport function TwickStudio({ studioConfig }: { studioConfig?: StudioConfig }) {\n const {\n selectedTool,\n setSelectedTool,\n selectedElement,\n addElement,\n updateElement,\n } = useStudioManager();\n const { videoResolution, setVideoResolution } = useTimelineContext();\n const {\n onNewProject,\n onLoadProject,\n onSaveProject,\n onExportVideo,\n } = useStudioOperation(studioConfig);\n\n const {\n onGenerateCaptions,\n addCaptionsToTimeline,\n getCaptionstatus,\n pollingIntervalMs,\n } = useGenerateCaptions(studioConfig);\n\n const twickStudiConfig: StudioConfig = useMemo(\n () => ({\n canvasMode: true,\n ...(studioConfig || {}),\n videoProps: {\n ...(studioConfig?.videoProps || {}),\n width: videoResolution.width,\n height: videoResolution.height,\n },\n }),\n [videoResolution, studioConfig]\n );\n\n return (\n <MediaProvider>\n <div className=\"studio-container\">\n {/* Header */}\n <StudioHeader\n setVideoResolution={setVideoResolution}\n onNewProject={onNewProject}\n onLoadProject={onLoadProject}\n onSaveProject={onSaveProject}\n onExportVideo={onExportVideo}\n />\n {/* Main Content */}\n <div className=\"studio-content\">\n {/* Left Toolbar */}\n <Toolbar\n selectedTool={selectedTool}\n setSelectedTool={setSelectedTool}\n />\n\n {/* Left Panel (Element Library) */}\n <div className=\"studio-left-panel\">\n <ElementPanelContainer\n videoResolution={videoResolution}\n selectedTool={selectedTool}\n setSelectedTool={setSelectedTool}\n selectedElement={selectedElement}\n addElement={addElement}\n updateElement={updateElement}\n />\n </div>\n\n {/* Center - Canvas and Transport */}\n <main className=\"main-container\">\n <div className=\"canvas-wrapper\">\n <div\n className=\"canvas-container\"\n style={{\n maxWidth: twickStudiConfig.playerProps?.maxWidth ?? \"100%\",\n }}\n >\n <VideoEditor editorConfig={twickStudiConfig} />\n </div>\n </div>\n </main>\n\n {/* Right Panel (Inspector + Props Toolbar) */}\n <div className=\"studio-right-panel\">\n <PropertiesPanelContainer\n selectedElement={selectedElement}\n updateElement={updateElement}\n addCaptionsToTimeline={addCaptionsToTimeline}\n onGenerateCaptions={onGenerateCaptions}\n getCaptionstatus={getCaptionstatus}\n pollingIntervalMs={pollingIntervalMs}\n videoResolution={videoResolution}\n />\n </div>\n </div>\n </div>\n </MediaProvider>\n );\n}\n","import { ProjectJSON, useTimelineContext, VideoElement } from \"@twick/timeline\";\nimport {\n ICaptionGenerationPollingResponse,\n StudioConfig,\n CaptionEntry,\n} from \"../types\";\n\nconst useGenerateCaptions = (studioConfig?: StudioConfig) => {\n const { editor, present } = useTimelineContext();\n /**\n * Generates captions using the new polling-based service\n * Returns a function that can be called to start the generation process\n */\n const onGenerateCaptions = async (videoElement: VideoElement) => {\n // Use new polling-based service if available\n if (studioConfig?.captionGenerationService) {\n const service = studioConfig.captionGenerationService;\n const reqId = await service.generateCaptions(\n videoElement,\n present as ProjectJSON\n );\n return reqId;\n }\n alert(\"Generate captions not supported in demo mode\");\n return null;\n };\n\n const addCaptionsToTimeline = (captions: CaptionEntry[]) => {\n const updatedProjectJSON =\n studioConfig?.captionGenerationService?.updateProjectWithCaptions(\n captions\n );\n if (updatedProjectJSON) {\n editor.loadProject(updatedProjectJSON);\n }\n };\n\n const getCaptionstatus = async (reqId: string) => {\n if (studioConfig?.captionGenerationService) {\n const service = studioConfig.captionGenerationService;\n return await service.getRequestStatus(reqId);\n }\n return {\n status: \"failed\",\n error: \"Caption generation service not found\",\n } as ICaptionGenerationPollingResponse;\n };\n\n const pollingIntervalMs =\n studioConfig?.captionGenerationService?.pollingIntervalMs ?? 5000;\n\n return {\n onGenerateCaptions,\n addCaptionsToTimeline,\n getCaptionstatus,\n pollingIntervalMs,\n };\n};\n\nexport default useGenerateCaptions;\n"],"names":["__iconNode","Icon","orientation","config","Wand2","rotation","opacity","SparklesIcon","Loader2","CheckCircle2","XCircle","_a"],"mappings":"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","x_google_ignoreList":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38]}
|