@twick/timeline 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +175 -0
- package/dist/context/timeline-context.d.ts +33 -0
- package/dist/context/undo-redo-context.d.ts +21 -0
- package/dist/core/addOns/animation.d.ts +24 -0
- package/dist/core/addOns/frame-effect.d.ts +14 -0
- package/dist/core/addOns/text-effect.d.ts +19 -0
- package/dist/core/editor/timeline.editor.d.ts +94 -0
- package/dist/core/elements/audio.element.d.ts +20 -0
- package/dist/core/elements/base.element.d.ts +35 -0
- package/dist/core/elements/caption.element.d.ts +10 -0
- package/dist/core/elements/circle.element.d.ts +13 -0
- package/dist/core/elements/icon.element.d.ts +9 -0
- package/dist/core/elements/image.element.d.ts +32 -0
- package/dist/core/elements/rect.element.d.ts +11 -0
- package/dist/core/elements/text.element.d.ts +26 -0
- package/dist/core/elements/video.element.d.ts +41 -0
- package/dist/core/track/track.d.ts +77 -0
- package/dist/core/track/track.friend.d.ts +34 -0
- package/dist/core/visitor/element-adder.d.ts +29 -0
- package/dist/core/visitor/element-cloner.d.ts +22 -0
- package/dist/core/visitor/element-deserializer.d.ts +23 -0
- package/dist/core/visitor/element-remover.d.ts +28 -0
- package/dist/core/visitor/element-serializer.d.ts +23 -0
- package/dist/core/visitor/element-splitter.d.ts +28 -0
- package/dist/core/visitor/element-updater.d.ts +28 -0
- package/dist/core/visitor/element-validator.d.ts +34 -0
- package/dist/core/visitor/element-visitor.d.ts +19 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.js +2630 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +2628 -0
- package/dist/index.mjs.map +1 -0
- package/dist/services/data.service.d.ts +25 -0
- package/dist/types/index.d.ts +169 -0
- package/dist/utils/constants.d.ts +55 -0
- package/dist/utils/register-editor.d.ts +8 -0
- package/dist/utils/timeline.utils.d.ts +11 -0
- package/package.json +40 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/utils/constants.ts","../src/utils/timeline.utils.ts","../../media-utils/dist/index.mjs","../src/core/elements/base.element.ts","../src/core/elements/video.element.ts","../src/core/elements/audio.element.ts","../src/core/elements/image.element.ts","../src/core/elements/text.element.ts","../src/core/elements/caption.element.ts","../src/core/elements/icon.element.ts","../src/core/elements/circle.element.ts","../src/core/elements/rect.element.ts","../src/core/addOns/animation.ts","../src/core/addOns/frame-effect.ts","../src/core/addOns/text-effect.ts","../src/core/visitor/element-deserializer.ts","../src/core/visitor/element-serializer.ts","../src/core/visitor/element-validator.ts","../src/core/track/track.friend.ts","../src/core/track/track.ts","../src/services/data.service.ts","../src/core/visitor/element-adder.ts","../src/core/visitor/element-remover.ts","../src/core/visitor/element-updater.ts","../src/core/visitor/element-cloner.ts","../src/core/visitor/element-splitter.ts","../src/core/editor/timeline.editor.ts","../src/context/undo-redo-context.tsx","../src/utils/register-editor.ts","../src/context/timeline-context.tsx","../src/index.ts"],"sourcesContent":["export const PLAYER_STATE = {\r\n REFRESH: \"Refresh\",\r\n PLAYING: \"Playing\",\r\n PAUSED: \"Paused\",\r\n};\r\n\r\nexport const CAPTION_STYLE = {\r\n WORD_BG_HIGHLIGHT: \"highlight_bg\",\r\n WORD_BY_WORD: \"word_by_word\",\r\n WORD_BY_WORD_WITH_BG: \"word_by_word_with_bg\",\r\n};\r\n\r\nexport const CAPTION_STYLE_OPTIONS = {\r\n [CAPTION_STYLE.WORD_BG_HIGHLIGHT]: {\r\n label: \"Highlight Background\",\r\n value: CAPTION_STYLE.WORD_BG_HIGHLIGHT,\r\n },\r\n [CAPTION_STYLE.WORD_BY_WORD]: {\r\n label: \"Word by Word\",\r\n value: CAPTION_STYLE.WORD_BY_WORD,\r\n },\r\n [CAPTION_STYLE.WORD_BY_WORD_WITH_BG]: {\r\n label: \"Word with Background\",\r\n value: CAPTION_STYLE.WORD_BY_WORD_WITH_BG,\r\n },\r\n};\r\n\r\nexport const CAPTION_FONT = {\r\n size: 40,\r\n};\r\n\r\nexport const CAPTION_COLOR = {\r\n text: \"#ffffff\",\r\n highlight: \"#ff4081\",\r\n bgColor: \"#8C52FF\",\r\n};\r\n\r\nexport const WORDS_PER_PHRASE = 4;\r\n\r\nexport const TIMELINE_ACTION = {\r\n NONE: \"none\",\r\n SET_PLAYER_STATE: \"setPlayerState\",\r\n UPDATE_PLAYER_DATA: \"updatePlayerData\",\r\n ON_PLAYER_UPDATED: \"onPlayerUpdated\",\r\n};\r\n\r\nexport const TIMELINE_ELEMENT_TYPE = {\r\n VIDEO: \"video\",\r\n CAPTION: \"caption\",\r\n IMAGE: \"image\",\r\n AUDIO: \"audio\",\r\n TEXT: \"text\",\r\n RECT: \"rect\",\r\n CIRCLE: \"circle\",\r\n ICON: \"icon\",\r\n};\r\n\r\nexport const PROCESS_STATE = {\r\n IDLE: \"Idle\",\r\n PROCESSING: \"Processing\",\r\n COMPLETED: \"Completed\",\r\n FAILED: \"Failed\",\r\n}; ","import { TrackElement } from \"../core/elements/base.element\";\r\nimport { Track } from \"../core/track/track\";\r\nimport { TrackJSON } from \"../types\";\r\n\r\nexport const getDecimalNumber = (num: number, precision = 3) => {\r\n return Number(num.toFixed(precision));\r\n};\r\n\r\nexport const getTotalDuration = (tracks: TrackJSON[]) => {\r\n return (tracks || []).reduce(\r\n (maxDuration, timeline) =>\r\n Math.max(\r\n maxDuration,\r\n (timeline?.elements || []).reduce(\r\n (timelineDuration, element) => Math.max(timelineDuration, element.e),\r\n 0\r\n )\r\n ),\r\n 0\r\n );\r\n};\r\n\r\nexport const generateShortUuid = (): string => {\r\n return \"xxxxxxxxxxxx\".replace(/[xy]/g, (c) => {\r\n const r = (Math.random() * 16) | 0,\r\n v = c === \"x\" ? r : (r & 0x3) | 0x8;\r\n return v.toString(16);\r\n });\r\n};\r\n\r\nexport const getCurrentElements = (\r\n currentTime: number,\r\n tracks: Track[]\r\n): Array<Readonly<TrackElement>> => {\r\n const currentElements: Array<Readonly<TrackElement>> = [];\r\n if (tracks?.length) {\r\n for (let i = 0; i < tracks.length; i++) {\r\n if (tracks[i]) {\r\n const elements = tracks[i].getElements();\r\n for (let j = 0; j < elements.length; j++) {\r\n const element = elements[j];\r\n if ((element.getStart() <= currentTime) && element.getEnd() >= currentTime) {\r\n currentElements.push(element);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n return currentElements;\r\n}; \r\n\r\n\r\nexport const canSplitElement = (element: TrackElement, currentTime: number) => {\r\n return element.getStart() <= currentTime && element.getEnd() >= currentTime;\r\n}\r\n\r\nexport const isElementId = (id: string) => id.startsWith(\"e-\");\r\nexport const isTrackId = (id: string) => id.startsWith(\"t-\");","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 video = document.createElement(\"video\");\n video.preload = \"metadata\";\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 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 = () => reject(new Error(\"Failed to load video metadata\"));\n });\n};\n\nconst getThumbnail = async (videoUrl, seekTime = 0.1, playbackRate = 1) => {\n return new Promise((resolve, reject) => {\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 = 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 reject(new Error(`Failed to load video: ${video.error?.message || \"Unknown error\"}`));\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;\n }).catch(() => {\n video.currentTime = seekTime;\n });\n } else {\n video.currentTime = seekTime;\n }\n }, { once: true });\n timeoutId = window.setTimeout(() => {\n cleanup();\n reject(new Error(\"Video loading timed out\"));\n }, 5e3);\n video.src = videoUrl;\n document.body.appendChild(video);\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 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 console.error(\"Error downloading file:\", 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 (error) {\n console.error(\"Fetch failed:\", error);\n return null;\n }\n};\n\nexport { blobUrlToFile, detectMediaTypeFromUrl, downloadFile, getAudioDuration, getImageDimensions, getObjectFitSize, getScaledDimensions, getThumbnail, getVideoMeta, limit, saveAsFile };\n//# sourceMappingURL=index.mjs.map\n","import { generateShortUuid } from \"../../utils/timeline.utils\";\r\nimport type { ElementVisitor } from \"../visitor/element-visitor\";\r\nimport { ElementAnimation } from \"../addOns/animation\";\r\nimport { Position } from \"../../types\";\r\n\r\nexport abstract class TrackElement {\r\n protected id: string;\r\n protected type: string;\r\n protected s!: number;\r\n protected e!: number;\r\n protected trackId!: string;\r\n protected name!: string;\r\n protected animation?: ElementAnimation;\r\n protected props: Record<string, any>;\r\n\r\n constructor(type: string, id?: string) {\r\n this.id = id ?? `e-${generateShortUuid()}`;\r\n this.type = type;\r\n this.props = {\r\n x: 0,\r\n y: 0\r\n };\r\n }\r\n\r\n abstract accept<T>(visitor: ElementVisitor<T>): T;\r\n\r\n getId(): string {\r\n return this.id;\r\n }\r\n\r\n getType(): string {\r\n return this.type;\r\n }\r\n\r\n getStart(): number {\r\n return this.s;\r\n }\r\n\r\n getEnd(): number {\r\n return this.e;\r\n }\r\n\r\n getDuration(): number {\r\n return this.e - this.s;\r\n }\r\n\r\n getTrackId(): string {\r\n return this.trackId;\r\n }\r\n\r\n getProps(): Record<string, any> {\r\n return this.props;\r\n }\r\n\r\n getName(): string {\r\n return this.name;\r\n }\r\n\r\n getAnimation(): ElementAnimation | undefined {\r\n return this.animation;\r\n }\r\n\r\n getPosition(): Position {\r\n return {\r\n x: this.props?.x ?? 0,\r\n y: this.props?.y ?? 0\r\n };\r\n }\r\n\r\n setId(id: string) {\r\n this.id = id;\r\n return this;\r\n }\r\n\r\n setType(type: string) {\r\n this.type = type;\r\n return this;\r\n }\r\n\r\n setStart(s: number) {\r\n this.s = Math.max(0, s);\r\n return this;\r\n }\r\n\r\n setEnd(e: number) {\r\n this.e = Math.max(this.s ?? 0, e);\r\n return this;\r\n }\r\n\r\n setTrackId(trackId: string) {\r\n this.trackId = trackId;\r\n return this;\r\n }\r\n\r\n setName(name: string) {\r\n this.name = name;\r\n return this;\r\n }\r\n\r\n setAnimation(animation?: ElementAnimation) {\r\n this.animation = animation;\r\n return this;\r\n }\r\n\r\n setPosition(position: Position) {\r\n this.props.x = position.x;\r\n this.props.y = position.y;\r\n return this;\r\n }\r\n\r\n setProps(props: Record<string, any>) {\r\n this.props = structuredClone(props);\r\n return this;\r\n }\r\n}\r\n","import { getObjectFitSize, getVideoMeta } from \"@twick/media-utils\";\r\nimport { Frame, ObjectFit, Position, Size, VideoProps } from \"../../types\";\r\nimport { TrackElement } from \"./base.element\";\r\nimport type { ElementVisitor } from \"../visitor/element-visitor\";\r\nimport { TIMELINE_ELEMENT_TYPE } from \"../../utils/constants\";\r\nimport { ElementFrameEffect } from \"../addOns/frame-effect\";\r\n\r\nexport class VideoElement extends TrackElement {\r\n protected baseSize!: Size;\r\n protected mediaDuration!: number;\r\n protected parentSize: Size;\r\n protected backgroundColor!: string;\r\n protected objectFit: ObjectFit;\r\n protected frameEffects?: ElementFrameEffect[];\r\n protected frame!: Frame;\r\n protected declare props: VideoProps;\r\n\r\n constructor(src: string, parentSize: Size) {\r\n super(TIMELINE_ELEMENT_TYPE.VIDEO);\r\n this.objectFit = \"cover\";\r\n this.frameEffects = [];\r\n this.parentSize = parentSize;\r\n this.props = {\r\n src,\r\n play: true,\r\n playbackRate: 1,\r\n time: 0,\r\n mediaFilter: \"none\",\r\n volume: 1,\r\n };\r\n }\r\n\r\n getParentSize() {\r\n return this.parentSize;\r\n }\r\n\r\n getFrame() {\r\n return this.frame;\r\n }\r\n\r\n getFrameEffects() {\r\n return this.frameEffects;\r\n }\r\n\r\n getBackgroundColor() {\r\n return this.backgroundColor;\r\n }\r\n\r\n getObjectFit() {\r\n return this.objectFit;\r\n }\r\n\r\n getMediaDuration() {\r\n return this.mediaDuration;\r\n }\r\n\r\n getStartAt(): number {\r\n return this.props.time || 0;\r\n }\r\n\r\n override getPosition(): Position {\r\n return {\r\n x: this.frame.x ?? 0,\r\n y: this.frame.y ?? 0\r\n };\r\n }\r\n\r\n async updateVideoMeta(updateFrame: boolean = true) {\r\n const meta = await getVideoMeta(this.props.src);\r\n\r\n if (updateFrame) {\r\n const baseSize = getObjectFitSize(\r\n \"contain\",\r\n { width: meta.width, height: meta.height },\r\n this.parentSize\r\n );\r\n this.frame = {\r\n ...this.frame,\r\n size: [baseSize.width, baseSize.height],\r\n };\r\n }\r\n this.mediaDuration = meta.duration;\r\n }\r\n\r\n override setPosition(position: Position) {\r\n this.frame.x = position.x;\r\n this.frame.y = position.y;\r\n return this;\r\n }\r\n\r\n async setSrc(src: string) {\r\n this.props.src = src;\r\n await this.updateVideoMeta();\r\n return this;\r\n }\r\n\r\n setMediaDuration(mediaDuration: number) {\r\n this.mediaDuration = mediaDuration;\r\n return this;\r\n }\r\n\r\n setParentSize(parentSize: Size) {\r\n this.parentSize = structuredClone(parentSize);\r\n return this;\r\n }\r\n\r\n setObjectFit(objectFit: ObjectFit) {\r\n this.objectFit = objectFit;\r\n return this;\r\n }\r\n\r\n setFrame(frame: Frame) {\r\n this.frame = structuredClone(frame);\r\n return this;\r\n }\r\n\r\n setPlay(play: boolean) {\r\n this.props.play = play;\r\n return this;\r\n }\r\n\r\n setPlaybackRate(playbackRate: number) {\r\n this.props.playbackRate = playbackRate;\r\n return this;\r\n }\r\n\r\n setStartAt(time: number) {\r\n this.props.time = Math.max(0, time);\r\n return this;\r\n }\r\n\r\n setMediaFilter(mediaFilter: string) {\r\n this.props.mediaFilter = mediaFilter;\r\n return this;\r\n }\r\n\r\n setVolume(volume: number) {\r\n this.props.volume = volume;\r\n return this;\r\n }\r\n\r\n setBackgroundColor(backgroundColor: string) {\r\n this.backgroundColor = backgroundColor;\r\n return this;\r\n }\r\n\r\n override setProps(props: Omit<any, \"src\">) {\r\n this.props = {\r\n play: this.props.play,\r\n ...structuredClone(props),\r\n src: this.props.src,\r\n };\r\n return this;\r\n }\r\n\r\n setFrameEffects(frameEffects?: ElementFrameEffect[]) {\r\n this.frameEffects = frameEffects;\r\n return this;\r\n }\r\n\r\n addFrameEffect(frameEffect: ElementFrameEffect) {\r\n this.frameEffects?.push(frameEffect);\r\n return this;\r\n }\r\n\r\n accept<T>(visitor: ElementVisitor<T>): T {\r\n return visitor.visitVideoElement(this);\r\n }\r\n}\r\n","import { getAudioDuration } from \"@twick/media-utils\";\r\nimport { TrackElement } from \"./base.element\";\r\nimport type { ElementVisitor } from \"../visitor/element-visitor\";\r\nimport { AudioProps } from \"../../types\";\r\nimport { TIMELINE_ELEMENT_TYPE } from \"../../utils/constants\";\r\n\r\nexport class AudioElement extends TrackElement {\r\n protected mediaDuration!: number;\r\n protected declare props: AudioProps;\r\n\r\n constructor(src: string) {\r\n super(TIMELINE_ELEMENT_TYPE.AUDIO);\r\n this.props = {\r\n src,\r\n time: 0,\r\n play: true,\r\n playbackRate: 1,\r\n volume: 1,\r\n loop: false,\r\n };\r\n }\r\n\r\n getMediaDuration() {\r\n return this.mediaDuration;\r\n }\r\n\r\n getStartAt(): number {\r\n return this.props.time || 0;\r\n }\r\n\r\n async updateAudioMeta() {\r\n this.mediaDuration = await getAudioDuration(this.props.src);\r\n }\r\n\r\n async setSrc(src: string) {\r\n this.props.src = src;\r\n await this.updateAudioMeta();\r\n return this;\r\n }\r\n\r\n setMediaDuration(mediaDuration: number) {\r\n this.mediaDuration = mediaDuration;\r\n return this;\r\n }\r\n\r\n setVolume(volume: number) {\r\n this.props.volume = volume;\r\n return this;\r\n }\r\n\r\n setLoop(loop: boolean) {\r\n this.props.loop = loop;\r\n return this;\r\n }\r\n\r\n setStartAt(time: number) {\r\n this.props.time = Math.max(0, time);\r\n return this;\r\n }\r\n\r\n setPlaybackRate(playbackRate: number) {\r\n this.props.playbackRate = playbackRate;\r\n return this;\r\n }\r\n\r\n override setProps(props: Omit<any, \"src\">) {\r\n this.props = {\r\n play: this.props.play,\r\n ...structuredClone(props),\r\n src: this.props.src,\r\n };\r\n return this;\r\n }\r\n\r\n accept<T>(visitor: ElementVisitor<T>): T {\r\n return visitor.visitAudioElement(this);\r\n }\r\n}\r\n","import { getObjectFitSize, getImageDimensions } from \"@twick/media-utils\";\r\nimport { Frame, ImageProps, ObjectFit, Position, Size } from \"../../types\";\r\nimport { TrackElement } from \"./base.element\";\r\nimport type { ElementVisitor } from \"../visitor/element-visitor\";\r\nimport { TIMELINE_ELEMENT_TYPE } from \"../../utils/constants\";\r\nimport { ElementFrameEffect } from \"../addOns/frame-effect\";\r\n\r\nexport class ImageElement extends TrackElement {\r\n protected backgroundColor!: string;\r\n protected parentSize: Size;\r\n protected objectFit: ObjectFit;\r\n frameEffects?: ElementFrameEffect[];\r\n frame!: Frame;\r\n protected declare props: ImageProps;\r\n\r\n constructor(src: string, parentSize: Size) {\r\n super(TIMELINE_ELEMENT_TYPE.IMAGE);\r\n this.parentSize = parentSize;\r\n this.objectFit = \"cover\";\r\n this.frameEffects = [];\r\n this.props = {\r\n src,\r\n mediaFilter: \"none\",\r\n };\r\n this.frame = {\r\n x: 0,\r\n y: 0\r\n }\r\n }\r\n\r\n getParentSize() {\r\n return this.parentSize;\r\n }\r\n\r\n getFrame() {\r\n return this.frame;\r\n }\r\n\r\n getFrameEffects() {\r\n return this.frameEffects;\r\n } \r\n\r\n getBackgroundColor() {\r\n return this.backgroundColor;\r\n }\r\n\r\n getObjectFit() {\r\n return this.objectFit;\r\n }\r\n\r\n override getPosition(): Position {\r\n return {\r\n x: this.frame.x ?? 0,\r\n y: this.frame.y ?? 0\r\n };\r\n }\r\n\r\n async updateImageMeta(updateFrame: boolean = true) {\r\n const meta = await getImageDimensions(this.props.src);\r\n if (updateFrame) {\r\n const baseSize = getObjectFitSize(\r\n \"contain\",\r\n { width: meta.width, height: meta.height },\r\n this.parentSize\r\n );\r\n this.frame = {\r\n size: [baseSize.width, baseSize.height],\r\n ...this.frame,\r\n }\r\n }\r\n }\r\n\r\n override setPosition(position: Position) {\r\n this.frame.x = position.x;\r\n this.frame.y = position.y;\r\n return this;\r\n }\r\n\r\n async setSrc(src: string) {\r\n this.props.src = src;\r\n await this.updateImageMeta();\r\n return this;\r\n }\r\n\r\n setObjectFit(objectFit: ObjectFit) {\r\n this.objectFit = objectFit;\r\n return this;\r\n }\r\n\r\n setFrame(frame: Frame) {\r\n this.frame = structuredClone(frame);\r\n return this;\r\n }\r\n\r\n\r\n setParentSize(parentSize: Size) {\r\n this.parentSize = structuredClone(parentSize);\r\n return this;\r\n }\r\n\r\n setMediaFilter(mediaFilter: string) {\r\n this.props.mediaFilter = mediaFilter;\r\n return this;\r\n }\r\n\r\n setBackgroundColor(backgroundColor: string) {\r\n this.backgroundColor = backgroundColor;\r\n return this;\r\n }\r\n\r\n override setProps(props: Omit<any, \"src\">) {\r\n this.props = {...structuredClone(props), src: this.props.src};\r\n return this;\r\n }\r\n\r\n setFrameEffects(frameEffects? : ElementFrameEffect[]) {\r\n this.frameEffects = frameEffects;\r\n return this;\r\n }\r\n\r\n addFrameEffect(frameEffect: ElementFrameEffect) {\r\n this.frameEffects?.push(frameEffect);\r\n return this;\r\n }\r\n\r\n accept<T>(visitor: ElementVisitor<T>): T {\r\n return visitor.visitImageElement(this);\r\n }\r\n\r\n}\r\n","import { TextAlign, TextProps } from \"../../types\";\r\nimport { TrackElement } from \"./base.element\";\r\nimport type { ElementVisitor } from \"../visitor/element-visitor\";\r\nimport { TIMELINE_ELEMENT_TYPE } from \"../../utils/constants\";\r\nimport { ElementTextEffect } from \"../addOns/text-effect\";\r\n\r\nexport class TextElement extends TrackElement {\r\n protected textEffect?: ElementTextEffect;\r\n protected declare props: TextProps;\r\n\r\n constructor(text: string) {\r\n super(TIMELINE_ELEMENT_TYPE.TEXT);\r\n this.props = {\r\n text,\r\n fill: \"#888888\" //default-grey\r\n };\r\n }\r\n\r\n getTextEffect() {\r\n return this.textEffect;\r\n }\r\n\r\n getText(): string {\r\n return this.props.text;\r\n }\r\n\r\n getStrokeColor() {\r\n return this.props.stroke;\r\n }\r\n\r\n getLineWidth() {\r\n return this.props.lineWidth;\r\n }\r\n\r\n setText(text: string) {\r\n this.props.text = text;\r\n return this;\r\n }\r\n\r\n setFill(fill: string) {\r\n this.props.fill = fill;\r\n return this;\r\n }\r\n\r\n setRotation(rotation: number) {\r\n this.props.rotation = rotation;\r\n return this;\r\n }\r\n\r\n setFontSize(fontSize: number) {\r\n this.props.fontSize = fontSize;\r\n return this;\r\n }\r\n\r\n setFontFamily(fontFamily: string) {\r\n this.props.fontFamily = fontFamily;\r\n return this;\r\n }\r\n\r\n setFontWeight(fontWeight: number) {\r\n this.props.fontWeight = fontWeight;\r\n return this;\r\n }\r\n\r\n setFontStyle(fontStyle: \"normal\" | \"italic\") {\r\n this.props.fontStyle = fontStyle;\r\n return this;\r\n }\r\n\r\n setTextEffect(textEffect?: ElementTextEffect) {\r\n this.textEffect = textEffect;\r\n return this;\r\n }\r\n\r\n setTextAlign(textAlign: TextAlign) {\r\n this.props.textAlign = textAlign;\r\n return this;\r\n }\r\n\r\n setStrokeColor(stroke: string) {\r\n this.props.stroke = stroke;\r\n return this;\r\n }\r\n\r\n setLineWidth(lineWidth: number) {\r\n this.props.lineWidth = lineWidth;\r\n return this;\r\n }\r\n\r\n accept<T>(visitor: ElementVisitor<T>): T {\r\n return visitor.visitTextElement(this);\r\n }\r\n}\r\n","import { TrackElement } from \"./base.element\";\r\nimport type { ElementVisitor } from \"../visitor/element-visitor\";\r\nimport { TIMELINE_ELEMENT_TYPE } from \"../../utils/constants\";\r\n\r\nexport class CaptionElement extends TrackElement {\r\n protected t: string;\r\n\r\n constructor(t: string, start: number, end: number) {\r\n super(TIMELINE_ELEMENT_TYPE.CAPTION);\r\n this.t = t;\r\n this.s = start;\r\n this.e = end;\r\n }\r\n\r\n getText(): string {\r\n return this.t;\r\n }\r\n\r\n setText(t: string) {\r\n this.t = t;\r\n return this;\r\n }\r\n\r\n accept<T>(visitor: ElementVisitor<T>): T {\r\n return visitor.visitCaptionElement(this);\r\n }\r\n\r\n}\r\n","import { TrackElement } from \"./base.element\";\r\nimport type { ElementVisitor } from \"../visitor/element-visitor\";\r\nimport { IconProps, Size } from \"../../types\";\r\nimport { TIMELINE_ELEMENT_TYPE } from \"../../utils/constants\";\r\n\r\nexport class IconElement extends TrackElement {\r\n protected declare props: IconProps;\r\n constructor(src: string, size: Size) {\r\n super(TIMELINE_ELEMENT_TYPE.ICON);\r\n this.props = {\r\n src,\r\n size,\r\n };\r\n }\r\n\r\n accept<T>(visitor: ElementVisitor<T>): T {\r\n return visitor.visitIconElement(this);\r\n }\r\n}\r\n","import { TrackElement } from \"./base.element\";\r\nimport type { ElementVisitor } from \"../visitor/element-visitor\";\r\nimport { CircleProps } from \"../../types\";\r\nimport { TIMELINE_ELEMENT_TYPE } from \"../../utils/constants\";\r\n\r\nexport class CircleElement extends TrackElement {\r\n protected declare props: CircleProps;\r\n constructor(fill: string, radius: number) {\r\n super(TIMELINE_ELEMENT_TYPE.CIRCLE);\r\n this.props = {\r\n radius,\r\n fill,\r\n };\r\n }\r\n\r\n getFill(): string {\r\n return this.props.fill;\r\n }\r\n\r\n getRadius(): number {\r\n return this.props.radius;\r\n }\r\n\r\n setFill(fill: string) {\r\n this.props.fill = fill;\r\n return this;\r\n }\r\n\r\n setRadius(radius: number) {\r\n this.props.radius = radius;\r\n return this;\r\n }\r\n \r\n\r\n accept<T>(visitor: ElementVisitor<T>): T {\r\n return visitor.visitCircleElement(this);\r\n }\r\n}\r\n","import { RectProps, Size } from \"../../types\";\r\nimport { TrackElement } from \"./base.element\";\r\nimport { ElementVisitor } from \"../visitor/element-visitor\";\r\nimport { TIMELINE_ELEMENT_TYPE } from \"../../utils/constants\";\r\n\r\nexport class RectElement extends TrackElement{\r\n protected declare props: RectProps;\r\n\r\n constructor(fill:string, size: Size) {\r\n super(TIMELINE_ELEMENT_TYPE.RECT); \r\n this.props = {\r\n width: size.width,\r\n height: size.height,\r\n fill,\r\n };\r\n }\r\n\r\n setFill(fill: string) { \r\n this.props.fill = fill;\r\n return this;\r\n }\r\n\r\n setSize(size: Size) {\r\n this.props.width = size.width;\r\n this.props.height = size.height;\r\n return this;\r\n }\r\n\r\n accept<T>(visitor: ElementVisitor<T>): T {\r\n return visitor.visitRectElement(this);\r\n }\r\n}","import { Animation } from \"../../types\";\r\n\r\nexport class ElementAnimation {\r\n private name: string;\r\n private interval?: number;\r\n private intensity?: number;\r\n private animate?: \"enter\" | \"exit\" | \"both\";\r\n private mode?: \"in\" | \"out\";\r\n private direction?: \"up\" | \"down\" | \"left\" | \"right\" | \"center\";\r\n\r\n constructor(name: string) {\r\n this.name = name;\r\n }\r\n\r\n getName() {\r\n return this.name;\r\n }\r\n\r\n getInterval() {\r\n return this.interval;\r\n } \r\n\r\n getIntensity() {\r\n return this.intensity;\r\n }\r\n\r\n getAnimate() {\r\n return this.animate;\r\n }\r\n\r\n getMode() {\r\n return this.mode;\r\n }\r\n\r\n getDirection() {\r\n return this.direction;\r\n }\r\n\r\n setInterval(interval?: number) {\r\n this.interval = interval;\r\n }\r\n\r\n setIntensity(intensity?: number) {\r\n this.intensity = intensity;\r\n }\r\n\r\n setAnimate(animate?: \"enter\" | \"exit\" | \"both\") {\r\n this.animate = animate;\r\n }\r\n\r\n setMode(mode?: \"in\" | \"out\") {\r\n this.mode = mode;\r\n }\r\n\r\n setDirection(direction?: \"up\" | \"down\" | \"left\" | \"right\" | \"center\") {\r\n this.direction = direction;\r\n }\r\n\r\n toJSON(): Animation {\r\n return {\r\n name: this.name,\r\n interval: this.interval,\r\n intensity: this.intensity,\r\n animate: this.animate,\r\n mode: this.mode,\r\n direction: this.direction,\r\n };\r\n }\r\n\r\n static fromJSON(json: Animation) {\r\n const animation = new ElementAnimation(json.name);\r\n animation.setInterval(json.interval);\r\n animation.setIntensity(json.intensity);\r\n animation.setAnimate(json.animate);\r\n animation.setMode(json.mode);\r\n animation.setDirection(json.direction);\r\n return animation;\r\n };\r\n}\r\n\r\n\r\n","import { FrameEffect, FrameEffectProps } from \"../../types\";\r\n\r\nexport class ElementFrameEffect {\r\n private s: number;\r\n private e: number;\r\n private props!: FrameEffectProps;\r\n constructor(start: number, end: number) {\r\n this.s = start;\r\n this.e = end;\r\n }\r\n\r\n setProps(props: FrameEffectProps) {\r\n this.props = props;\r\n }\r\n\r\n getProps() {\r\n return this.props;\r\n }\r\n\r\n getStart() {\r\n return this.s;\r\n }\r\n\r\n getEnd() {\r\n return this.e;\r\n }\r\n\r\n toJSON(): FrameEffect {\r\n return {\r\n s: this.s,\r\n e: this.e,\r\n props: this.props,\r\n };\r\n }\r\n \r\n static fromJSON(json: FrameEffect) {\r\n const effect = new ElementFrameEffect(json.s, json.e);\r\n effect.setProps(json.props);\r\n return effect;\r\n }\r\n}\r\n","import { TextEffect } from \"../../types\";\r\n\r\nexport class ElementTextEffect {\r\n private name: string;\r\n private duration?: number;\r\n private delay?: number;\r\n private bufferTime?: number;\r\n\r\n constructor(name: string) {\r\n this.name = name;\r\n }\r\n\r\n getName() {\r\n return this.name;\r\n }\r\n\r\n getDuration() {\r\n return this.duration;\r\n } \r\n\r\n getDelay() {\r\n return this.delay;\r\n }\r\n\r\n getBufferTime() {\r\n return this.bufferTime;\r\n }\r\n\r\n setName(name: string) {\r\n this.name = name;\r\n }\r\n\r\n setDuration(duration?: number) {\r\n this.duration = duration;\r\n }\r\n\r\n setDelay(delay?: number) {\r\n this.delay = delay;\r\n }\r\n\r\n setBufferTime(bufferTime?: number) {\r\n this.bufferTime = bufferTime;\r\n }\r\n\r\n toJSON(): TextEffect {\r\n return {\r\n name: this.name,\r\n delay: this.delay,\r\n duration: this.duration,\r\n bufferTime: this.bufferTime,\r\n };\r\n }\r\n\r\n static fromJSON(json: TextEffect) {\r\n const effect = new ElementTextEffect(json.name);\r\n effect.setDelay(json.delay);\r\n effect.setDuration(json.duration);\r\n effect.setBufferTime(json.bufferTime);\r\n return effect;\r\n };\r\n}\r\n\r\n\r\n","import { ElementJSON } from \"../../types\";\r\nimport { VideoElement } from \"../elements/video.element\";\r\nimport { AudioElement } from \"../elements/audio.element\";\r\nimport { ImageElement } from \"../elements/image.element\";\r\nimport { TextElement } from \"../elements/text.element\";\r\nimport { CaptionElement } from \"../elements/caption.element\";\r\nimport { IconElement } from \"../elements/icon.element\";\r\nimport { CircleElement } from \"../elements/circle.element\";\r\nimport { RectElement } from \"../elements/rect.element\";\r\nimport { TrackElement } from \"../elements/base.element\";\r\nimport { ElementAnimation } from \"../addOns/animation\";\r\nimport { ElementFrameEffect } from \"../addOns/frame-effect\";\r\nimport { ElementTextEffect } from \"../addOns/text-effect\";\r\n\r\nexport class ElementDeserializer {\r\n private static deserializeBaseElement(element: TrackElement, json: ElementJSON): void {\r\n if (json.id) element.setId(json.id);\r\n if (json.trackId) element.setTrackId(json.trackId);\r\n if (json.s !== undefined) element.setStart(json.s);\r\n if (json.e !== undefined) element.setEnd(json.e);\r\n if (json.props) element.setProps(json.props);\r\n if (json.animation) element.setAnimation(ElementAnimation.fromJSON(json.animation));\r\n }\r\n\r\n static deserializeVideoElement(json: ElementJSON): VideoElement {\r\n const parentSize = json.frame && json.frame.size \r\n ? { width: json.frame.size[0], height: json.frame.size[1] } \r\n : { width: 0, height: 0 };\r\n \r\n const videoElement = new VideoElement(json.props?.src || \"\", parentSize);\r\n ElementDeserializer.deserializeBaseElement(videoElement, json);\r\n \r\n if (json.mediaDuration !== undefined) videoElement.setMediaDuration(json.mediaDuration);\r\n if (json.objectFit) videoElement.setObjectFit(json.objectFit);\r\n if (json.frame) videoElement.setFrame(json.frame);\r\n if (json.frameEffects) videoElement.setFrameEffects(json.frameEffects.map((frameEffect) => ElementFrameEffect.fromJSON(frameEffect)));\r\n if (json.backgroundColor) videoElement.setBackgroundColor(json.backgroundColor);\r\n \r\n return videoElement;\r\n }\r\n\r\n static deserializeAudioElement(json: ElementJSON): AudioElement {\r\n const audioElement = new AudioElement(json.props?.src || \"\");\r\n ElementDeserializer.deserializeBaseElement(audioElement, json);\r\n \r\n if (json.mediaDuration !== undefined) audioElement.setMediaDuration(json.mediaDuration);\r\n \r\n return audioElement;\r\n }\r\n\r\n static deserializeImageElement(json: ElementJSON): ImageElement {\r\n const parentSize = json.frame && json.frame.size \r\n ? { width: json.frame.size[0], height: json.frame.size[1] } \r\n : { width: 0, height: 0 };\r\n \r\n const imageElement = new ImageElement(json.props?.src || \"\", parentSize);\r\n ElementDeserializer.deserializeBaseElement(imageElement, json);\r\n \r\n if (json.objectFit) imageElement.setObjectFit(json.objectFit);\r\n if (json.frame) imageElement.setFrame(json.frame);\r\n if (json.frameEffects) imageElement.setFrameEffects(json.frameEffects.map((frameEffect) => ElementFrameEffect.fromJSON(frameEffect)));\r\n if (json.backgroundColor) imageElement.setBackgroundColor(json.backgroundColor);\r\n \r\n return imageElement;\r\n }\r\n\r\n static deserializeTextElement(json: ElementJSON): TextElement {\r\n const textElement = new TextElement(json.props?.text || \"\");\r\n ElementDeserializer.deserializeBaseElement(textElement, json);\r\n \r\n if (json.textEffect) textElement.setTextEffect(ElementTextEffect.fromJSON(json.textEffect));\r\n \r\n return textElement;\r\n }\r\n\r\n static deserializeCaptionElement(json: ElementJSON): CaptionElement {\r\n const captionElement = new CaptionElement(\r\n json.t || \"\",\r\n json.s || 0,\r\n json.e || 0\r\n );\r\n ElementDeserializer.deserializeBaseElement(captionElement, json);\r\n \r\n return captionElement;\r\n }\r\n\r\n static deserializeIconElement(json: ElementJSON): IconElement {\r\n const size = json.props?.size \r\n ? { width: json.props.size[0], height: json.props.size[1] }\r\n : { width: 0, height: 0 };\r\n \r\n const iconElement = new IconElement(\r\n json.props?.src || \"\",\r\n size\r\n );\r\n ElementDeserializer.deserializeBaseElement(iconElement, json);\r\n \r\n return iconElement;\r\n }\r\n\r\n static deserializeCircleElement(json: ElementJSON): CircleElement {\r\n const circleElement = new CircleElement(\r\n json.props?.fill || \"\",\r\n json.props?.radius || 0\r\n );\r\n ElementDeserializer.deserializeBaseElement(circleElement, json);\r\n \r\n return circleElement;\r\n }\r\n\r\n static deserializeRectElement(json: ElementJSON): RectElement {\r\n const rectElement = new RectElement(\r\n json.props?.fill || \"\",\r\n { \r\n width: json.props?.width || 0, \r\n height: json.props?.height || 0 \r\n }\r\n );\r\n ElementDeserializer.deserializeBaseElement(rectElement, json);\r\n \r\n return rectElement;\r\n }\r\n\r\n static fromJSON(json: ElementJSON): TrackElement | null{\r\n try {\r\n switch (json.type) {\r\n case \"video\":\r\n return ElementDeserializer.deserializeVideoElement(json);\r\n case \"audio\":\r\n return ElementDeserializer.deserializeAudioElement(json);\r\n case \"image\":\r\n return ElementDeserializer.deserializeImageElement(json);\r\n case \"text\":\r\n return ElementDeserializer.deserializeTextElement(json);\r\n case \"caption\":\r\n return ElementDeserializer.deserializeCaptionElement(json);\r\n case \"icon\":\r\n return ElementDeserializer.deserializeIconElement(json);\r\n case \"circle\":\r\n return ElementDeserializer.deserializeCircleElement(json);\r\n case \"rect\":\r\n return ElementDeserializer.deserializeRectElement(json);\r\n default:\r\n throw new Error(`Unknown element type: ${json.type}`);\r\n }\r\n } catch(error) {\r\n console.error(\"Error deserializing element:\", error);\r\n return null;\r\n }\r\n }\r\n}\r\n","import { ElementJSON } from \"../../types\";\r\nimport { ElementVisitor } from \"./element-visitor\";\r\nimport { VideoElement } from \"../elements/video.element\";\r\nimport { AudioElement } from \"../elements/audio.element\";\r\nimport { ImageElement } from \"../elements/image.element\";\r\nimport { TextElement } from \"../elements/text.element\";\r\nimport { CaptionElement } from \"../elements/caption.element\";\r\nimport { RectElement } from \"../elements/rect.element\";\r\nimport { CircleElement } from \"../elements/circle.element\";\r\nimport { IconElement } from \"../elements/icon.element\";\r\nimport { TrackElement } from \"../elements/base.element\";\r\n\r\nexport class ElementSerializer implements ElementVisitor<ElementJSON> {\r\n serializeElement(element: TrackElement): ElementJSON {\r\n return {\r\n id: element.getId(),\r\n trackId: element.getTrackId(),\r\n type: element.getType(),\r\n name: element.getName(),\r\n s: element.getStart(),\r\n e: element.getEnd(),\r\n props: structuredClone(element.getProps()),\r\n animation: element.getAnimation()?.toJSON(),\r\n };\r\n }\r\n visitVideoElement(element: VideoElement): ElementJSON {\r\n return {\r\n ...this.serializeElement(element),\r\n frame: structuredClone(element.getFrame()),\r\n frameEffects: element.getFrameEffects()?.map((frameEffect) => frameEffect.toJSON()),\r\n backgroundColor: element.getBackgroundColor(),\r\n objectFit: element.getObjectFit(),\r\n mediaDuration: element.getMediaDuration(),\r\n };\r\n }\r\n\r\n visitAudioElement(element: AudioElement): ElementJSON {\r\n return {\r\n ...this.serializeElement(element),\r\n mediaDuration: element.getMediaDuration(),\r\n };\r\n }\r\n\r\n visitImageElement(element: ImageElement): ElementJSON {\r\n return {\r\n ...this.serializeElement(element),\r\n frame: structuredClone(element.getFrame()),\r\n frameEffects: element.getFrameEffects()?.map((frameEffect) => frameEffect.toJSON()),\r\n backgroundColor: element.getBackgroundColor(),\r\n objectFit: element.getObjectFit(),\r\n };\r\n }\r\n\r\n visitTextElement(element: TextElement): ElementJSON {\r\n return {\r\n ...this.serializeElement(element),\r\n textEffect: element.getTextEffect()?.toJSON(),\r\n };\r\n }\r\n\r\n visitCaptionElement(element: CaptionElement): ElementJSON {\r\n return {\r\n ...this.serializeElement(element),\r\n t: structuredClone(element.getText()),\r\n };\r\n }\r\n\r\n visitIconElement(element: IconElement): ElementJSON {\r\n return {\r\n ...this.serializeElement(element),\r\n };\r\n }\r\n\r\n visitCircleElement(element: CircleElement): ElementJSON {\r\n return {\r\n ...this.serializeElement(element),\r\n };\r\n }\r\n\r\n visitRectElement(element: RectElement): ElementJSON {\r\n return {\r\n ...this.serializeElement(element),\r\n };\r\n }\r\n}\r\n","import { ElementVisitor } from \"./element-visitor\";\r\nimport { VideoElement } from \"../elements/video.element\";\r\nimport { AudioElement } from \"../elements/audio.element\";\r\nimport { ImageElement } from \"../elements/image.element\";\r\nimport { TextElement } from \"../elements/text.element\";\r\nimport { CaptionElement } from \"../elements/caption.element\";\r\nimport { IconElement } from \"../elements/icon.element\";\r\nimport { CircleElement } from \"../elements/circle.element\";\r\nimport { RectElement } from \"../elements/rect.element\";\r\n\r\nexport class ValidationError extends Error {\r\n constructor(\r\n message: string,\r\n public errors: string[],\r\n public warnings: string[] = []\r\n ) {\r\n super(message);\r\n this.name = 'ValidationError';\r\n }\r\n}\r\n\r\nexport class ElementValidator implements ElementVisitor<boolean> {\r\n private validateBasicProperties(element: any): { errors: string[]; warnings: string[] } {\r\n const errors: string[] = [];\r\n const warnings: string[] = [];\r\n\r\n // Check required basic properties\r\n if (!element.getId()) {\r\n errors.push(\"Element must have an ID\");\r\n }\r\n\r\n if (!element.getType()) {\r\n errors.push(\"Element must have a type\");\r\n }\r\n\r\n if (element.getStart() === undefined || element.getStart() === null) {\r\n errors.push(\"Element must have a start time (s)\");\r\n }\r\n\r\n if (element.getEnd() === undefined || element.getEnd() === null) {\r\n errors.push(\"Element must have an end time (e)\");\r\n }\r\n\r\n if (element.getStart() !== undefined && element.getEnd() !== undefined) {\r\n if (element.getStart() < 0) {\r\n errors.push(\"Start time cannot be negative\");\r\n }\r\n \r\n if (element.getEnd() <= element.getStart()) {\r\n errors.push(\"End time must be greater than start time\");\r\n }\r\n }\r\n\r\n if (!element.getName()) {\r\n warnings.push(\"Element should have a name for better identification\");\r\n }\r\n\r\n if (!element.getTrackId()) {\r\n warnings.push(\"Element should have a track Id\");\r\n }\r\n\r\n return { errors, warnings };\r\n }\r\n\r\n private validateTextElement(element: TextElement): { errors: string[]; warnings: string[] } {\r\n const basicValidation = this.validateBasicProperties(element);\r\n const errors = [...basicValidation.errors];\r\n const warnings = [...basicValidation.warnings];\r\n\r\n // Check text-specific properties\r\n const props = element.getProps();\r\n if (!props?.text) {\r\n errors.push(\"Text element must have text content\");\r\n }\r\n\r\n if (props?.fontSize !== undefined && props.fontSize <= 0) {\r\n errors.push(\"Font size must be greater than 0\");\r\n }\r\n\r\n if (props?.fontWeight !== undefined && props.fontWeight < 0) {\r\n errors.push(\"Font weight cannot be negative\");\r\n }\r\n\r\n return { errors, warnings };\r\n }\r\n\r\n private validateVideoElement(element: VideoElement): { errors: string[]; warnings: string[] } {\r\n const basicValidation = this.validateBasicProperties(element);\r\n const errors = [...basicValidation.errors];\r\n const warnings = [...basicValidation.warnings];\r\n\r\n // Check video-specific properties\r\n const props = element.getProps();\r\n if (!props?.src) {\r\n errors.push(\"Video element must have a source URL\");\r\n }\r\n\r\n if (props?.volume !== undefined && (props.volume < 0 || props.volume > 1)) {\r\n errors.push(\"Volume must be between 0 and 1\");\r\n }\r\n\r\n if (props?.playbackRate !== undefined && props.playbackRate <= 0) {\r\n errors.push(\"Playback rate must be greater than 0\");\r\n }\r\n\r\n // Note: frame property is protected, so we can't validate it directly\r\n // This would need to be validated through a public method if needed\r\n\r\n return { errors, warnings };\r\n }\r\n\r\n private validateAudioElement(element: AudioElement): { errors: string[]; warnings: string[] } {\r\n const basicValidation = this.validateBasicProperties(element);\r\n const errors = [...basicValidation.errors];\r\n const warnings = [...basicValidation.warnings];\r\n\r\n // Check audio-specific properties\r\n const props = element.getProps();\r\n if (!props?.src) {\r\n errors.push(\"Audio element must have a source URL\");\r\n }\r\n\r\n if (props?.volume !== undefined && (props.volume < 0 || props.volume > 1)) {\r\n errors.push(\"Volume must be between 0 and 1\");\r\n }\r\n\r\n if (props?.playbackRate !== undefined && props.playbackRate <= 0) {\r\n errors.push(\"Playback rate must be greater than 0\");\r\n }\r\n\r\n return { errors, warnings };\r\n }\r\n\r\n private validateImageElement(element: ImageElement): { errors: string[]; warnings: string[] } {\r\n const basicValidation = this.validateBasicProperties(element);\r\n const errors = [...basicValidation.errors];\r\n const warnings = [...basicValidation.warnings];\r\n\r\n // Check image-specific properties\r\n const props = element.getProps();\r\n if (!props?.src) {\r\n errors.push(\"Image element must have a source URL\");\r\n }\r\n\r\n // Note: frame property is protected, so we can't validate it directly\r\n // This would need to be validated through a public method if needed\r\n\r\n return { errors, warnings };\r\n }\r\n\r\n private validateCaptionElement(element: CaptionElement): { errors: string[]; warnings: string[] } {\r\n const basicValidation = this.validateBasicProperties(element);\r\n const errors = [...basicValidation.errors];\r\n const warnings = [...basicValidation.warnings];\r\n\r\n // Check caption-specific properties\r\n const props = element.getProps();\r\n if (!props?.text) {\r\n errors.push(\"Caption element must have text content\");\r\n }\r\n\r\n return { errors, warnings };\r\n }\r\n\r\n private validateIconElement(element: IconElement): { errors: string[]; warnings: string[] } {\r\n const basicValidation = this.validateBasicProperties(element);\r\n const errors = [...basicValidation.errors];\r\n const warnings = [...basicValidation.warnings];\r\n\r\n // Check icon-specific properties\r\n const props = element.getProps();\r\n if (!props?.icon) {\r\n errors.push(\"Icon element must have an icon name\");\r\n }\r\n\r\n // Note: frame property is protected, so we can't validate it directly\r\n // This would need to be validated through a public method if needed\r\n\r\n return { errors, warnings };\r\n }\r\n\r\n private validateCircleElement(element: CircleElement): { errors: string[]; warnings: string[] } {\r\n const basicValidation = this.validateBasicProperties(element);\r\n const errors = [...basicValidation.errors];\r\n const warnings = [...basicValidation.warnings];\r\n\r\n // Check circle-specific properties\r\n const props = element.getProps();\r\n if (props?.radius !== undefined && props.radius <= 0) {\r\n errors.push(\"Circle radius must be greater than 0\");\r\n }\r\n\r\n // Note: frame property is protected, so we can't validate it directly\r\n // This would need to be validated through a public method if needed\r\n\r\n return { errors, warnings };\r\n }\r\n\r\n private validateRectElement(element: RectElement): { errors: string[]; warnings: string[] } {\r\n const basicValidation = this.validateBasicProperties(element);\r\n const errors = [...basicValidation.errors];\r\n const warnings = [...basicValidation.warnings];\r\n\r\n // Check rectangle-specific properties\r\n const props = element.getProps();\r\n if (props?.width !== undefined && props.width <= 0) {\r\n errors.push(\"Rectangle width must be greater than 0\");\r\n }\r\n\r\n if (props?.height !== undefined && props.height <= 0) {\r\n errors.push(\"Rectangle height must be greater than 0\");\r\n }\r\n\r\n // Note: frame property is protected, so we can't validate it directly\r\n // This would need to be validated through a public method if needed\r\n\r\n return { errors, warnings };\r\n }\r\n\r\n visitVideoElement(element: VideoElement): boolean {\r\n const validation = this.validateVideoElement(element);\r\n \r\n if (validation.errors.length > 0) {\r\n throw new ValidationError(\r\n `Video element validation failed: ${validation.errors.join(', ')}`,\r\n validation.errors,\r\n validation.warnings\r\n );\r\n }\r\n \r\n return true;\r\n }\r\n\r\n visitAudioElement(element: AudioElement): boolean {\r\n const validation = this.validateAudioElement(element);\r\n \r\n if (validation.errors.length > 0) {\r\n throw new ValidationError(\r\n `Audio element validation failed: ${validation.errors.join(', ')}`,\r\n validation.errors,\r\n validation.warnings\r\n );\r\n }\r\n \r\n return true;\r\n }\r\n\r\n visitImageElement(element: ImageElement): boolean {\r\n const validation = this.validateImageElement(element);\r\n \r\n if (validation.errors.length > 0) {\r\n throw new ValidationError(\r\n `Image element validation failed: ${validation.errors.join(', ')}`,\r\n validation.errors,\r\n validation.warnings\r\n );\r\n }\r\n \r\n return true;\r\n }\r\n\r\n visitTextElement(element: TextElement): boolean {\r\n const validation = this.validateTextElement(element);\r\n \r\n if (validation.errors.length > 0) {\r\n throw new ValidationError(\r\n `Text element validation failed: ${validation.errors.join(', ')}`,\r\n validation.errors,\r\n validation.warnings\r\n );\r\n }\r\n \r\n return true;\r\n }\r\n\r\n visitCaptionElement(element: CaptionElement): boolean {\r\n const validation = this.validateCaptionElement(element);\r\n \r\n if (validation.errors.length > 0) {\r\n throw new ValidationError(\r\n `Caption element validation failed: ${validation.errors.join(', ')}`,\r\n validation.errors,\r\n validation.warnings\r\n );\r\n }\r\n \r\n return true;\r\n }\r\n\r\n visitIconElement(element: IconElement): boolean {\r\n const validation = this.validateIconElement(element);\r\n \r\n if (validation.errors.length > 0) {\r\n throw new ValidationError(\r\n `Icon element validation failed: ${validation.errors.join(', ')}`,\r\n validation.errors,\r\n validation.warnings\r\n );\r\n }\r\n \r\n return true;\r\n }\r\n\r\n visitCircleElement(element: CircleElement): boolean {\r\n const validation = this.validateCircleElement(element);\r\n \r\n if (validation.errors.length > 0) {\r\n throw new ValidationError(\r\n `Circle element validation failed: ${validation.errors.join(', ')}`,\r\n validation.errors,\r\n validation.warnings\r\n );\r\n }\r\n \r\n return true;\r\n }\r\n\r\n visitRectElement(element: RectElement): boolean {\r\n const validation = this.validateRectElement(element);\r\n \r\n if (validation.errors.length > 0) {\r\n throw new ValidationError(\r\n `Rectangle element validation failed: ${validation.errors.join(', ')}`,\r\n validation.errors,\r\n validation.warnings\r\n );\r\n }\r\n \r\n return true;\r\n }\r\n} ","import { TrackElement } from \"../elements/base.element\";\r\nimport { Track } from \"./track\";\r\n\r\n/**\r\n * Friend class that provides explicit access to Track's protected methods\r\n * This implements the Friend Class Pattern for better encapsulation control\r\n */\r\nexport class TrackFriend {\r\n constructor(private track: Track) {}\r\n \r\n /**\r\n * Add an element to the track with validation\r\n * @param element The element to add\r\n * @param skipValidation If true, skips validation (use with caution)\r\n * @returns true if element was added successfully, throws ValidationError if validation fails\r\n */\r\n addElement(\r\n element: TrackElement,\r\n skipValidation: boolean = false\r\n ): boolean {\r\n // Use the public friend method that delegates to protected method\r\n return this.track.addElementViaFriend(element, skipValidation);\r\n }\r\n \r\n /**\r\n * Remove an element from the track\r\n * @param element The element to remove\r\n */\r\n removeElement(element: TrackElement): void {\r\n // Use the public friend method that delegates to protected method\r\n this.track.removeElementViaFriend(element);\r\n }\r\n \r\n /**\r\n * Update an element in the track with validation\r\n * @param element The element to update\r\n * @returns true if element was updated successfully, throws ValidationError if validation fails\r\n */\r\n updateElement(element: TrackElement): boolean {\r\n // Use the public friend method that delegates to protected method\r\n return this.track.updateElementViaFriend(element);\r\n }\r\n \r\n /**\r\n * Get the track instance (for advanced operations)\r\n * @returns The track instance\r\n */\r\n getTrack(): Track {\r\n return this.track;\r\n }\r\n }","import { ElementJSON, TrackJSON } from \"../../types\";\r\nimport { generateShortUuid } from \"../../utils/timeline.utils\";\r\nimport { TrackElement } from \"../elements/base.element\";\r\nimport { ElementDeserializer } from \"../visitor/element-deserializer\";\r\nimport { ElementSerializer } from \"../visitor/element-serializer\";\r\nimport {\r\n ElementValidator,\r\n ValidationError,\r\n} from \"../visitor/element-validator\";\r\nimport { TrackFriend } from \"./track.friend\";\r\n\r\nexport class Track {\r\n private id: string;\r\n private name: string;\r\n private type: string;\r\n private elements: TrackElement[];\r\n private validator: ElementValidator;\r\n\r\n constructor(name: string, id?: string) {\r\n this.name = name;\r\n this.id = id ?? `t-${generateShortUuid}`;\r\n this.type = \"element\";\r\n this.elements = [];\r\n this.validator = new ElementValidator();\r\n }\r\n\r\n /**\r\n * Create a friend instance for explicit access to protected methods\r\n * This implements the Friend Class Pattern\r\n * @returns TrackFriend instance\r\n */\r\n createFriend(): TrackFriend {\r\n return new TrackFriend(this);\r\n }\r\n\r\n /**\r\n * Friend method to add element (called by TrackFriend)\r\n * @param element The element to add\r\n * @param skipValidation If true, skips validation\r\n * @returns true if element was added successfully\r\n */\r\n addElementViaFriend(\r\n element: TrackElement,\r\n skipValidation: boolean = false\r\n ): boolean {\r\n return this.addElement(element, skipValidation);\r\n }\r\n\r\n /**\r\n * Friend method to remove element (called by TrackFriend)\r\n * @param element The element to remove\r\n */\r\n removeElementViaFriend(element: TrackElement): void {\r\n this.removeElement(element);\r\n }\r\n\r\n /**\r\n * Friend method to update element (called by TrackFriend)\r\n * @param element The element to update\r\n * @returns true if element was updated successfully\r\n */\r\n updateElementViaFriend(element: TrackElement): boolean {\r\n return this.updateElement(element);\r\n }\r\n\r\n getId(): string {\r\n return this.id;\r\n }\r\n\r\n getName(): string {\r\n return this.name;\r\n }\r\n\r\n getType(): string {\r\n return this.type;\r\n }\r\n\r\n getElements(): ReadonlyArray<TrackElement> {\r\n return [...this.elements];\r\n }\r\n\r\n /**\r\n * Validates an element\r\n * @param element The element to validate\r\n * @returns true if valid, throws ValidationError if invalid\r\n */\r\n validateElement(element: TrackElement): boolean {\r\n return element.accept(this.validator);\r\n }\r\n\r\n getTrackDuration(): number {\r\n return this.elements?.length\r\n ? this.elements[this.elements.length - 1].getEnd()\r\n : 0;\r\n }\r\n\r\n /**\r\n * Adds an element to the track with validation\r\n * @param element The element to add\r\n * @param skipValidation If true, skips validation (use with caution)\r\n * @returns true if element was added successfully, throws ValidationError if validation fails\r\n */\r\n protected addElement(\r\n element: TrackElement,\r\n skipValidation: boolean = false\r\n ): boolean {\r\n element.setTrackId(this.id);\r\n if (skipValidation) {\r\n this.elements.push(element);\r\n return true;\r\n }\r\n\r\n try {\r\n const isValid = this.validateElement(element);\r\n if (isValid) {\r\n this.elements.push(element);\r\n return true;\r\n }\r\n } catch (error) {\r\n if (error instanceof ValidationError) {\r\n throw error;\r\n }\r\n throw error;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n protected removeElement(element: TrackElement): void {\r\n const index = this.elements.findIndex((e) => e.getId() === element.getId());\r\n if (index !== -1) {\r\n this.elements.splice(index, 1);\r\n }\r\n }\r\n\r\n /**\r\n * Updates an element in the track with validation\r\n * @param element The element to update\r\n * @returns true if element was updated successfully, throws ValidationError if validation fails\r\n */\r\n protected updateElement(element: TrackElement): boolean {\r\n try {\r\n const isValid = this.validateElement(element);\r\n if (isValid) {\r\n const index = this.elements.findIndex(\r\n (e) => e.getId() === element.getId()\r\n );\r\n if (index !== -1) {\r\n this.elements[index] = element;\r\n return true;\r\n }\r\n }\r\n } catch (error) {\r\n if (error instanceof ValidationError) {\r\n throw error;\r\n }\r\n throw error;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n getElementById(id: string): Readonly<TrackElement> | undefined {\r\n const element = this.elements.find((e) => e.getId() === id);\r\n if (!element) return undefined;\r\n return element;\r\n }\r\n\r\n /**\r\n * Validates all elements in the track and returns combined result and per-element status\r\n * @returns Object with overall isValid and array of per-element validation results\r\n */\r\n validateAllElements(): {\r\n isValid: boolean;\r\n results: Array<{\r\n element: TrackElement;\r\n isValid: boolean;\r\n errors?: string[];\r\n warnings?: string[];\r\n }>;\r\n } {\r\n let validResult = true;\r\n const results = this.elements.map((element) => {\r\n try {\r\n const isValid = this.validateElement(element);\r\n if (!isValid) {\r\n validResult = false;\r\n }\r\n return { element, isValid };\r\n } catch (error) {\r\n if (error instanceof ValidationError) {\r\n validResult = false;\r\n return {\r\n element,\r\n isValid: false,\r\n errors: error.errors,\r\n warnings: error.warnings,\r\n };\r\n }\r\n return {\r\n element,\r\n isValid: false,\r\n errors: [error instanceof Error ? error.message : \"Unknown error\"],\r\n };\r\n }\r\n });\r\n return { isValid: validResult, results };\r\n }\r\n\r\n serialize(): TrackJSON {\r\n const serializer = new ElementSerializer();\r\n return {\r\n id: this.id,\r\n name: this.name,\r\n type: this.type,\r\n elements: this.elements.map(\r\n (element) => element.accept(serializer) as ElementJSON\r\n ),\r\n };\r\n }\r\n\r\n static fromJSON(json: any): Track {\r\n const track = new Track(json.name, json.id);\r\n track.type = json.type;\r\n track.elements = (json.elements || []).map(ElementDeserializer.fromJSON);\r\n return track;\r\n }\r\n}\r\n","import { TrackElement } from \"../core/elements/base.element\";\r\nimport { Track } from \"../core/track/track\";\r\n\r\ntype TimelineStore = {\r\n tracks: Track[];\r\n version: number;\r\n elementMap: Record<string, TrackElement>;\r\n trackMap: Record<string, any>;\r\n captionProps: Record<string, any>;\r\n}\r\n\r\nexport type TimelineTrackData = {\r\n tracks: Track[];\r\n version: number;\r\n}\r\n\r\nexport class TimelineContextStore {\r\n private static instance: TimelineContextStore;\r\n private storeMap: Map<string, TimelineStore>;\r\n\r\n private constructor() {\r\n this.storeMap = new Map();\r\n }\r\n\r\n public static getInstance(): TimelineContextStore {\r\n if (!TimelineContextStore.instance) {\r\n TimelineContextStore.instance = new TimelineContextStore();\r\n }\r\n return TimelineContextStore.instance;\r\n }\r\n\r\n public initializeContext(contextId: string): void {\r\n if (!this.storeMap.has(contextId)) {\r\n this.storeMap.set(contextId, {\r\n tracks: [],\r\n version: 0,\r\n elementMap: {},\r\n trackMap: {},\r\n captionProps: {},\r\n });\r\n }\r\n }\r\n\r\n public getTimelineData(contextId: string): TimelineTrackData | null {\r\n const timelineStore = this.storeMap.get(contextId);\r\n return timelineStore ? {\r\n tracks: timelineStore.tracks,\r\n version: timelineStore.version,\r\n } : null;\r\n }\r\n\r\n public setTimelineData(contextId: string, timelineData: TimelineTrackData): TimelineTrackData {\r\n this.ensureContext(contextId);\r\n this.storeMap.get(contextId)!.tracks = timelineData.tracks;\r\n this.storeMap.get(contextId)!.version = timelineData.version;\r\n return timelineData;\r\n }\r\n\r\n public getElementMap(contextId: string): Record<string, TrackElement> {\r\n this.ensureContext(contextId);\r\n return this.storeMap.get(contextId)!.elementMap;\r\n }\r\n\r\n public setElementMap(contextId: string, elementMap: Record<string, TrackElement>): void {\r\n this.ensureContext(contextId);\r\n this.storeMap.get(contextId)!.elementMap = elementMap;\r\n }\r\n\r\n public getTrackMap(contextId: string): Record<string, any> {\r\n this.ensureContext(contextId);\r\n return this.storeMap.get(contextId)!.trackMap;\r\n }\r\n\r\n public setTrackMap(contextId: string, trackMap: Record<string, any>): void {\r\n this.ensureContext(contextId);\r\n this.storeMap.get(contextId)!.trackMap = trackMap;\r\n }\r\n\r\n public getCaptionProps(contextId: string): Record<string, any> {\r\n this.ensureContext(contextId);\r\n return this.storeMap.get(contextId)!.captionProps;\r\n }\r\n\r\n public setCaptionProps(contextId: string, captionProps: Record<string, any>): void {\r\n this.ensureContext(contextId);\r\n this.storeMap.get(contextId)!.captionProps = captionProps;\r\n }\r\n\r\n public clearContext(contextId: string): void {\r\n this.storeMap.delete(contextId);\r\n }\r\n\r\n private ensureContext(contextId: string): void {\r\n if (!this.storeMap.has(contextId)) {\r\n this.initializeContext(contextId);\r\n }\r\n }\r\n}\r\n\r\nexport const timelineContextStore = TimelineContextStore.getInstance();","import { ElementVisitor } from \"./element-visitor\";\r\nimport { VideoElement } from \"../elements/video.element\";\r\nimport { AudioElement } from \"../elements/audio.element\";\r\nimport { ImageElement } from \"../elements/image.element\";\r\nimport { TextElement } from \"../elements/text.element\";\r\nimport { CaptionElement } from \"../elements/caption.element\";\r\nimport { IconElement } from \"../elements/icon.element\";\r\nimport { CircleElement } from \"../elements/circle.element\";\r\nimport { RectElement } from \"../elements/rect.element\";\r\nimport { Track } from \"../track/track\";\r\nimport { TrackFriend } from \"../track/track.friend\";\r\n\r\n/**\r\n * ElementAdder visitor for adding elements to tracks\r\n * Uses the visitor pattern to handle different element types\r\n * Implements the Friend Class Pattern for explicit access control\r\n */\r\nexport class ElementAdder implements ElementVisitor<Promise<boolean>> {\r\n private track: Track;\r\n private trackFriend: TrackFriend;\r\n\r\n constructor(track: Track) {\r\n this.track = track;\r\n this.trackFriend = track.createFriend();\r\n }\r\n\r\n async visitVideoElement(element: VideoElement): Promise<boolean> {\r\n await element.updateVideoMeta();\r\n const elements = this.track.getElements();\r\n const lastEndtime = elements?.length\r\n ? elements[elements.length - 1].getEnd()\r\n : 0;\r\n if (isNaN(element.getStart())) {\r\n element.setStart(lastEndtime);\r\n }\r\n if (isNaN(element.getEnd())) {\r\n element.setEnd(element.getStart() + element.getMediaDuration());\r\n }\r\n\r\n return this.trackFriend.addElement(element);\r\n }\r\n\r\n async visitAudioElement(element: AudioElement): Promise<boolean> {\r\n await element.updateAudioMeta();\r\n const elements = this.track.getElements();\r\n const lastEndtime = elements?.length\r\n ? elements[elements.length - 1].getEnd()\r\n : 0;\r\n if (isNaN(element.getStart())) {\r\n element.setStart(lastEndtime);\r\n }\r\n if (isNaN(element.getEnd())) {\r\n element.setEnd(element.getStart() + element.getMediaDuration());\r\n }\r\n \r\n return this.trackFriend.addElement(element);\r\n }\r\n\r\n async visitImageElement(element: ImageElement): Promise<boolean> {\r\n await element.updateImageMeta();\r\n const elements = this.track.getElements();\r\n const lastEndtime = elements?.length\r\n ? elements[elements.length - 1].getEnd()\r\n : 0;\r\n if (isNaN(element.getStart())) {\r\n element.setStart(lastEndtime);\r\n }\r\n if (isNaN(element.getEnd())) {\r\n element.setEnd(element.getStart() + 1);\r\n }\r\n \r\n return this.trackFriend.addElement(element);\r\n }\r\n\r\n async visitTextElement(element: TextElement): Promise<boolean> {\r\n const elements = this.track.getElements();\r\n const lastEndtime = elements?.length\r\n ? elements[elements.length - 1].getEnd()\r\n : 0;\r\n if (isNaN(element.getStart())) {\r\n element.setStart(lastEndtime);\r\n }\r\n if (isNaN(element.getEnd())) {\r\n element.setEnd(element.getStart() + 1);\r\n }\r\n \r\n return this.trackFriend.addElement(element);\r\n }\r\n\r\n async visitCaptionElement(element: CaptionElement): Promise<boolean> {\r\n const elements = this.track.getElements();\r\n const lastEndtime = elements?.length\r\n ? elements[elements.length - 1].getEnd()\r\n : 0;\r\n if (isNaN(element.getStart())) {\r\n element.setStart(lastEndtime);\r\n }\r\n if (isNaN(element.getEnd())) {\r\n element.setEnd(element.getStart() + 1);\r\n }\r\n \r\n return this.trackFriend.addElement(element);\r\n }\r\n\r\n async visitIconElement(element: IconElement): Promise<boolean> {\r\n const elements = this.track.getElements();\r\n const lastEndtime = elements?.length\r\n ? elements[elements.length - 1].getEnd()\r\n : 0;\r\n if (isNaN(element.getStart())) {\r\n element.setStart(lastEndtime);\r\n }\r\n if (isNaN(element.getEnd())) {\r\n element.setEnd(element.getStart() + 1);\r\n }\r\n \r\n return this.trackFriend.addElement(element);\r\n }\r\n\r\n async visitCircleElement(element: CircleElement): Promise<boolean> {\r\n const elements = this.track.getElements();\r\n const lastEndtime = elements?.length\r\n ? elements[elements.length - 1].getEnd()\r\n : 0;\r\n if (isNaN(element.getStart())) {\r\n element.setStart(lastEndtime);\r\n }\r\n if (isNaN(element.getEnd())) {\r\n element.setEnd(element.getStart() + 1);\r\n }\r\n \r\n return this.trackFriend.addElement(element);\r\n }\r\n\r\n async visitRectElement(element: RectElement): Promise<boolean> {\r\n const elements = this.track.getElements();\r\n const lastEndtime = elements?.length\r\n ? elements[elements.length - 1].getEnd()\r\n : 0;\r\n if (isNaN(element.getStart())) {\r\n element.setStart(lastEndtime);\r\n }\r\n if (isNaN(element.getEnd())) {\r\n element.setEnd(element.getStart() + 1);\r\n }\r\n \r\n return this.trackFriend.addElement(element);\r\n }\r\n}\r\n","import { ElementVisitor } from \"./element-visitor\";\r\nimport { VideoElement } from \"../elements/video.element\";\r\nimport { AudioElement } from \"../elements/audio.element\";\r\nimport { ImageElement } from \"../elements/image.element\";\r\nimport { TextElement } from \"../elements/text.element\";\r\nimport { CaptionElement } from \"../elements/caption.element\";\r\nimport { IconElement } from \"../elements/icon.element\";\r\nimport { CircleElement } from \"../elements/circle.element\";\r\nimport { RectElement } from \"../elements/rect.element\";\r\nimport { Track } from \"../track/track\";\r\nimport { TrackFriend } from \"../track/track.friend\";\r\n\r\n/**\r\n * ElementRemover visitor for removing elements from tracks\r\n * Uses the visitor pattern to handle different element types\r\n * Implements the Friend Class Pattern for explicit access control\r\n */\r\nexport class ElementRemover implements ElementVisitor<boolean> {\r\n private trackFriend: TrackFriend;\r\n\r\n constructor(track: Track) {\r\n this.trackFriend = track.createFriend();\r\n }\r\n\r\n visitVideoElement(element: VideoElement): boolean {\r\n this.trackFriend.removeElement(element);\r\n return true;\r\n }\r\n\r\n visitAudioElement(element: AudioElement): boolean {\r\n this.trackFriend.removeElement(element);\r\n return true;\r\n }\r\n\r\n visitImageElement(element: ImageElement): boolean {\r\n this.trackFriend.removeElement(element);\r\n return true;\r\n }\r\n\r\n visitTextElement(element: TextElement): boolean {\r\n this.trackFriend.removeElement(element);\r\n return true;\r\n }\r\n\r\n visitCaptionElement(element: CaptionElement): boolean {\r\n this.trackFriend.removeElement(element);\r\n return true;\r\n }\r\n\r\n visitIconElement(element: IconElement): boolean {\r\n this.trackFriend.removeElement(element);\r\n return true;\r\n }\r\n\r\n visitCircleElement(element: CircleElement): boolean {\r\n this.trackFriend.removeElement(element);\r\n return true;\r\n }\r\n\r\n visitRectElement(element: RectElement): boolean {\r\n this.trackFriend.removeElement(element);\r\n return true;\r\n }\r\n} ","import { ElementVisitor } from \"./element-visitor\";\r\nimport { VideoElement } from \"../elements/video.element\";\r\nimport { AudioElement } from \"../elements/audio.element\";\r\nimport { ImageElement } from \"../elements/image.element\";\r\nimport { TextElement } from \"../elements/text.element\";\r\nimport { CaptionElement } from \"../elements/caption.element\";\r\nimport { IconElement } from \"../elements/icon.element\";\r\nimport { CircleElement } from \"../elements/circle.element\";\r\nimport { RectElement } from \"../elements/rect.element\";\r\nimport { Track } from \"../track/track\";\r\nimport { TrackFriend } from \"../track/track.friend\";\r\n\r\n/**\r\n * ElementUpdater visitor for updating elements in tracks\r\n * Uses the visitor pattern to handle different element types\r\n * Implements the Friend Class Pattern for explicit access control\r\n */\r\nexport class ElementUpdater implements ElementVisitor<boolean> {\r\n private trackFriend: TrackFriend;\r\n\r\n constructor(track: Track) {\r\n this.trackFriend = track.createFriend();\r\n }\r\n\r\n visitVideoElement(element: VideoElement): boolean {\r\n return this.trackFriend.updateElement(element);\r\n }\r\n\r\n visitAudioElement(element: AudioElement): boolean {\r\n return this.trackFriend.updateElement(element);\r\n }\r\n\r\n visitImageElement(element: ImageElement): boolean {\r\n return this.trackFriend.updateElement(element);\r\n }\r\n\r\n visitTextElement(element: TextElement): boolean {\r\n return this.trackFriend.updateElement(element);\r\n }\r\n\r\n visitCaptionElement(element: CaptionElement): boolean {\r\n return this.trackFriend.updateElement(element);\r\n }\r\n\r\n visitIconElement(element: IconElement): boolean {\r\n return this.trackFriend.updateElement(element);\r\n }\r\n\r\n visitCircleElement(element: CircleElement): boolean {\r\n return this.trackFriend.updateElement(element);\r\n }\r\n\r\n visitRectElement(element: RectElement): boolean {\r\n return this.trackFriend.updateElement(element);\r\n }\r\n} ","import { ElementVisitor } from \"./element-visitor\";\r\nimport { VideoElement } from \"../elements/video.element\";\r\nimport { AudioElement } from \"../elements/audio.element\";\r\nimport { ImageElement } from \"../elements/image.element\";\r\nimport { TextElement } from \"../elements/text.element\";\r\nimport { CaptionElement } from \"../elements/caption.element\";\r\nimport { RectElement } from \"../elements/rect.element\";\r\nimport { CircleElement } from \"../elements/circle.element\";\r\nimport { IconElement } from \"../elements/icon.element\";\r\nimport { TrackElement } from \"../elements/base.element\";\r\n\r\nexport class ElementCloner implements ElementVisitor<TrackElement> {\r\n cloneElementProperties(srcElement: TrackElement, destElement: TrackElement) {\r\n return destElement\r\n .setName(srcElement.getName())\r\n .setType(srcElement.getType())\r\n .setStart(srcElement.getStart())\r\n .setEnd(srcElement.getEnd())\r\n .setProps(srcElement.getProps())\r\n .setAnimation(srcElement.getAnimation());\r\n }\r\n\r\n visitVideoElement(element: VideoElement): TrackElement {\r\n const props = element.getProps();\r\n const clonedElement = new VideoElement(props!.src, element.getParentSize());\r\n this.cloneElementProperties(element, clonedElement);\r\n clonedElement\r\n .setParentSize(element.getParentSize())\r\n .setMediaDuration(element.getMediaDuration())\r\n .setFrame(element.getFrame())\r\n .setFrameEffects(element.getFrameEffects() ?? [])\r\n .setBackgroundColor(element.getBackgroundColor())\r\n .setObjectFit(element.getObjectFit())\r\n return clonedElement;\r\n }\r\n\r\n visitAudioElement(element: AudioElement): TrackElement {\r\n const clonedElement = new AudioElement(element.getProps()!.src);\r\n this.cloneElementProperties(element, clonedElement);\r\n clonedElement.setMediaDuration(element.getMediaDuration());\r\n return clonedElement;\r\n }\r\n\r\n visitImageElement(element: ImageElement): TrackElement {\r\n const clonedElement = new ImageElement(\r\n element.getProps()!.src,\r\n element.getParentSize()\r\n );\r\n this.cloneElementProperties(element, clonedElement);\r\n clonedElement\r\n .setParentSize(element.getParentSize())\r\n .setFrame(element.getFrame())\r\n .setFrameEffects(element.getFrameEffects())\r\n .setBackgroundColor(element.getBackgroundColor())\r\n .setObjectFit(element.getObjectFit())\r\n\r\n return clonedElement;\r\n }\r\n\r\n visitTextElement(element: TextElement): TrackElement {\r\n const clonedElement = new TextElement(element.getProps()!.text);\r\n this.cloneElementProperties(element, clonedElement);\r\n clonedElement.setTextEffect(element.getTextEffect());\r\n return clonedElement;\r\n }\r\n\r\n visitCaptionElement(element: CaptionElement): TrackElement {\r\n const clonedElement = new CaptionElement(\r\n element.getProps()!.text,\r\n element.getStart(),\r\n element.getEnd()\r\n );\r\n this.cloneElementProperties(element, clonedElement);\r\n return clonedElement;\r\n }\r\n\r\n visitRectElement(element: RectElement): TrackElement {\r\n const clonedElement = new RectElement(\r\n element.getProps()!.fill,\r\n element.getProps()!.size\r\n );\r\n this.cloneElementProperties(element, clonedElement);\r\n return clonedElement;\r\n }\r\n\r\n visitCircleElement(element: CircleElement): TrackElement {\r\n const clonedElement = new CircleElement(\r\n element.getProps()!.fill,\r\n element.getProps()!.radius\r\n );\r\n this.cloneElementProperties(element, clonedElement);\r\n return clonedElement;\r\n }\r\n\r\n visitIconElement(element: IconElement): TrackElement {\r\n const clonedElement = new IconElement(\r\n element.getProps()!.src,\r\n element.getProps()!.size\r\n );\r\n this.cloneElementProperties(element, clonedElement);\r\n return clonedElement;\r\n }\r\n}\r\n","import { ElementVisitor } from \"./element-visitor\";\r\nimport { VideoElement } from \"../elements/video.element\";\r\nimport { AudioElement } from \"../elements/audio.element\";\r\nimport { ImageElement } from \"../elements/image.element\";\r\nimport { TextElement } from \"../elements/text.element\";\r\nimport { CaptionElement } from \"../elements/caption.element\";\r\nimport { RectElement } from \"../elements/rect.element\";\r\nimport { CircleElement } from \"../elements/circle.element\";\r\nimport { IconElement } from \"../elements/icon.element\";\r\nimport { ElementCloner } from \"./element-cloner\";\r\nimport { canSplitElement } from \"../../utils/timeline.utils\";\r\n\r\nexport interface SplitResult {\r\n firstElement: any;\r\n secondElement: any;\r\n success: boolean;\r\n}\r\n\r\nexport class ElementSplitter implements ElementVisitor<SplitResult> {\r\n private splitTime: number;\r\n private elementCloner: ElementCloner;\r\n constructor(splitTime: number) {\r\n this.splitTime = splitTime;\r\n this.elementCloner = new ElementCloner();\r\n }\r\n\r\n visitVideoElement(element: VideoElement): SplitResult {\r\n if (!canSplitElement(element, this.splitTime)) {\r\n return { firstElement: null, secondElement: null, success: false };\r\n }\r\n\r\n const firstElement = this.elementCloner.visitVideoElement(\r\n element\r\n ) as VideoElement;\r\n const secondElement = this.elementCloner.visitVideoElement(\r\n element\r\n ) as VideoElement;\r\n\r\n const props = element.getProps();\r\n const secondStartAt =\r\n (props!.time ?? 0) +\r\n (this.splitTime - element.getStart()) * (props!.playbackRate ?? 1);\r\n firstElement.setEnd(this.splitTime);\r\n secondElement.setStart(this.splitTime).setStartAt(secondStartAt);\r\n\r\n return { firstElement, secondElement, success: true };\r\n }\r\n\r\n visitAudioElement(element: AudioElement): SplitResult {\r\n if (!canSplitElement(element, this.splitTime)) {\r\n return { firstElement: null, secondElement: null, success: false };\r\n }\r\n const firstElement = this.elementCloner.visitAudioElement(\r\n element\r\n ) as AudioElement;\r\n const secondElement = this.elementCloner.visitAudioElement(\r\n element\r\n ) as AudioElement;\r\n\r\n const props = element.getProps();\r\n const secondStartAt =\r\n (props!.time ?? 0) +\r\n (this.splitTime - element.getStart()) * (props!.playbackRate ?? 1);\r\n firstElement.setEnd(this.splitTime);\r\n secondElement.setStart(this.splitTime).setStartAt(secondStartAt);\r\n\r\n return { firstElement, secondElement, success: true };\r\n }\r\n\r\n visitImageElement(element: ImageElement): SplitResult {\r\n if (!canSplitElement(element, this.splitTime)) {\r\n return { firstElement: null, secondElement: null, success: false };\r\n }\r\n const firstElement = this.elementCloner.visitImageElement(\r\n element\r\n ) as ImageElement;\r\n const secondElement = this.elementCloner.visitImageElement(\r\n element\r\n ) as ImageElement;\r\n firstElement.setEnd(this.splitTime);\r\n secondElement.setStart(this.splitTime);\r\n return { firstElement, secondElement, success: true };\r\n }\r\n\r\n visitTextElement(element: TextElement): SplitResult {\r\n if (!canSplitElement(element, this.splitTime)) {\r\n return { firstElement: null, secondElement: null, success: false };\r\n }\r\n const originalText = element.getText() || \"\";\r\n const originalTextArray = originalText.split(\" \");\r\n const percentage =\r\n (this.splitTime - element.getStart()) / element.getDuration();\r\n const firstElement = this.elementCloner.visitTextElement(\r\n element\r\n ) as TextElement;\r\n firstElement.setText(\r\n originalTextArray\r\n .slice(0, Math.floor(originalTextArray.length * percentage))\r\n .join(\" \")\r\n );\r\n firstElement.setEnd(this.splitTime);\r\n const secondElement = this.elementCloner.visitTextElement(\r\n element\r\n ) as TextElement;\r\n secondElement.setText(\r\n originalTextArray\r\n .slice(\r\n Math.floor(originalTextArray.length * percentage),\r\n originalTextArray.length\r\n )\r\n .join(\" \")\r\n );\r\n secondElement.setStart(this.splitTime);\r\n return { firstElement, secondElement, success: true };\r\n }\r\n\r\n visitCaptionElement(element: CaptionElement): SplitResult {\r\n if (!canSplitElement(element, this.splitTime)) {\r\n return { firstElement: null, secondElement: null, success: false };\r\n }\r\n const originalText = element.getText() || \"\";\r\n const originalTextArray = originalText.split(\" \");\r\n const percentage =\r\n (this.splitTime - element.getStart()) / element.getDuration();\r\n const firstElement = this.elementCloner.visitCaptionElement(\r\n element\r\n ) as CaptionElement;\r\n firstElement.setText(\r\n originalTextArray\r\n .slice(0, Math.floor(originalTextArray.length * percentage))\r\n .join(\" \")\r\n );\r\n firstElement.setEnd(this.splitTime);\r\n const secondElement = this.elementCloner.visitCaptionElement(\r\n element\r\n ) as CaptionElement;\r\n secondElement.setText(\r\n originalTextArray\r\n .slice(\r\n Math.floor(originalTextArray.length * percentage),\r\n originalTextArray.length\r\n )\r\n .join(\" \")\r\n );\r\n secondElement.setStart(this.splitTime);\r\n return { firstElement, secondElement, success: true };\r\n }\r\n\r\n visitRectElement(element: RectElement): SplitResult {\r\n if (!canSplitElement(element, this.splitTime)) {\r\n return { firstElement: null, secondElement: null, success: false };\r\n }\r\n const firstElement = this.elementCloner.visitRectElement(\r\n element\r\n ) as RectElement;\r\n const secondElement = this.elementCloner.visitRectElement(\r\n element\r\n ) as RectElement;\r\n firstElement.setEnd(this.splitTime);\r\n secondElement.setStart(this.splitTime);\r\n return { firstElement, secondElement, success: true };\r\n }\r\n\r\n visitCircleElement(element: CircleElement): SplitResult {\r\n if (!canSplitElement(element, this.splitTime)) {\r\n return { firstElement: null, secondElement: null, success: false };\r\n }\r\n const firstElement = this.elementCloner.visitCircleElement(element);\r\n const secondElement = this.elementCloner.visitCircleElement(element);\r\n firstElement.setEnd(this.splitTime);\r\n secondElement.setStart(this.splitTime);\r\n return { firstElement, secondElement, success: true };\r\n }\r\n\r\n visitIconElement(element: IconElement): SplitResult {\r\n if (!canSplitElement(element, this.splitTime)) {\r\n return { firstElement: null, secondElement: null, success: false };\r\n }\r\n const firstElement = this.elementCloner.visitIconElement(element);\r\n const secondElement = this.elementCloner.visitIconElement(element);\r\n firstElement.setEnd(this.splitTime);\r\n secondElement.setStart(this.splitTime);\r\n return { firstElement, secondElement, success: true };\r\n }\r\n}\r\n","import {\r\n generateShortUuid,\r\n getTotalDuration,\r\n} from \"../../utils/timeline.utils\";\r\nimport { Track } from \"../track/track\";\r\nimport {\r\n timelineContextStore,\r\n TimelineTrackData,\r\n} from \"../../services/data.service\";\r\nimport { PLAYER_STATE, TIMELINE_ACTION } from \"../../utils/constants\";\r\nimport { ElementAdder } from \"../visitor/element-adder\";\r\nimport { ElementRemover } from \"../visitor/element-remover\";\r\nimport { ElementUpdater } from \"../visitor/element-updater\";\r\nimport { ElementSplitter, SplitResult } from \"../visitor/element-splitter\";\r\nimport { ElementCloner } from \"../visitor/element-cloner\";\r\nimport { TrackElement } from \"../elements/base.element\";\r\nimport { ProjectJSON, TrackJSON } from \"../../types\";\r\n\r\n/**\r\n * Type for timeline operation context\r\n */\r\nexport interface TimelineOperationContext {\r\n contextId: string;\r\n setTotalDuration: (duration: number) => void;\r\n setPresent: (data: ProjectJSON) => void;\r\n handleUndo: () => ProjectJSON | null;\r\n handleRedo: () => ProjectJSON | null;\r\n handleResetHistory: () => void;\r\n updateChangeLog: () => void;\r\n setTimelineAction?: (action: string, payload?: unknown) => void;\r\n}\r\n\r\n/**\r\n * TimelineEditor\r\n *\r\n * This class provides an interface to execute all timeline operations\r\n * using a direct, class-based approach with track-based management.\r\n * It also handles undo/redo operations internally.\r\n */\r\nexport class TimelineEditor {\r\n private context: TimelineOperationContext;\r\n\r\n constructor(context: TimelineOperationContext) {\r\n this.context = context;\r\n // Ensure context is initialized in timelineContextStore\r\n timelineContextStore.initializeContext(this.context.contextId);\r\n }\r\n\r\n getContext(): TimelineOperationContext {\r\n return this.context;\r\n }\r\n\r\n pauseVideo(): void {\r\n if (this.context?.setTimelineAction) {\r\n this.context.setTimelineAction(\r\n TIMELINE_ACTION.SET_PLAYER_STATE,\r\n PLAYER_STATE.PAUSED\r\n );\r\n }\r\n }\r\n\r\n getTimelineData(): TimelineTrackData | null {\r\n const contextId = this.context.contextId;\r\n return timelineContextStore.getTimelineData(contextId);\r\n }\r\n\r\n getLatestVersion(): number {\r\n const contextId = this.context.contextId;\r\n const timelineData = timelineContextStore.getTimelineData(contextId);\r\n return timelineData?.version || 0;\r\n }\r\n\r\n protected setTimelineData(\r\n tracks: Track[],\r\n version?: number\r\n ): TimelineTrackData {\r\n const prevTimelineData = this.getTimelineData();\r\n const updatedVersion = version ?? (prevTimelineData?.version || 0) + 1;\r\n const updatedTimelineData = {\r\n tracks,\r\n version: updatedVersion,\r\n };\r\n timelineContextStore.setTimelineData(\r\n this.context.contextId,\r\n updatedTimelineData\r\n );\r\n this.updateHistory(updatedTimelineData);\r\n this.context.updateChangeLog();\r\n return updatedTimelineData as TimelineTrackData;\r\n }\r\n\r\n addTrack(name: string): Track {\r\n const prevTimelineData = this.getTimelineData();\r\n const id = `t-${generateShortUuid()}`;\r\n const track = new Track(name, id);\r\n const updatedTimelines = [...(prevTimelineData?.tracks || []), track];\r\n this.setTimelineData(updatedTimelines);\r\n return track;\r\n }\r\n\r\n getTrackById(id: string): Track | null {\r\n const prevTimelineData = this.getTimelineData();\r\n const track = prevTimelineData?.tracks.find((t) => t.getId() === id);\r\n return track as Track | null;\r\n }\r\n\r\n getTrackByName(name: string): Track | null {\r\n const prevTimelineData = this.getTimelineData();\r\n const track = prevTimelineData?.tracks.find((t) => t.getName() === name);\r\n return track as Track | null;\r\n }\r\n\r\n removeTrackById(id: string): void {\r\n const tracks = this.getTimelineData()?.tracks || [];\r\n const updatedTracks = tracks.filter((t) => t.getId() !== id);\r\n this.setTimelineData(updatedTracks);\r\n }\r\n\r\n removeTrack(track: Track): void {\r\n const tracks = this.getTimelineData()?.tracks || [];\r\n const updatedTracks = tracks.filter((t) => t.getId() !== track.getId());\r\n this.setTimelineData(updatedTracks);\r\n }\r\n\r\n /**\r\n * Refresh the timeline data\r\n */\r\n refresh(): void {\r\n const currentData = this.getTimelineData();\r\n if (currentData) {\r\n this.setTimelineData(currentData.tracks);\r\n }\r\n }\r\n\r\n /**\r\n * Add an element to a specific track using the visitor pattern\r\n * @param track The track to add the element to\r\n * @param element The element to add\r\n * @returns Promise<boolean> true if element was added successfully\r\n */\r\n async addElementToTrack(\r\n track: Track,\r\n element: TrackElement\r\n ): Promise<boolean> {\r\n if (!track) {\r\n return false;\r\n }\r\n try {\r\n // Use the visitor pattern to handle different element types\r\n const elementAdder = new ElementAdder(track);\r\n const result = await element.accept(elementAdder);\r\n \r\n if (result) {\r\n // Update the timeline data to reflect the change\r\n const currentData = this.getTimelineData();\r\n if (currentData) {\r\n this.setTimelineData(currentData.tracks);\r\n }\r\n }\r\n return result;\r\n } catch (error) {\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Remove an element from a specific track using the visitor pattern\r\n * @param element The element to remove\r\n * @returns boolean true if element was removed successfully\r\n */\r\n removeElement(element: TrackElement): boolean {\r\n const track = this.getTrackById(element.getTrackId());\r\n if (!track) {\r\n return false;\r\n }\r\n\r\n try {\r\n // Use the visitor pattern to handle different element types\r\n const elementRemover = new ElementRemover(track);\r\n const result = element.accept(elementRemover);\r\n \r\n if (result) {\r\n // Update the timeline data to reflect the change\r\n const currentData = this.getTimelineData();\r\n if (currentData) {\r\n this.setTimelineData(currentData.tracks);\r\n }\r\n }\r\n\r\n return result;\r\n } catch (error) {\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Update an element in a specific track using the visitor pattern\r\n * @param element The updated element\r\n * @returns boolean true if element was updated successfully\r\n */\r\n updateElement(element: TrackElement): boolean {\r\n const track = this.getTrackById(element.getTrackId());\r\n if (!track) {\r\n return false;\r\n }\r\n\r\n try {\r\n // Use the visitor pattern to handle different element types\r\n const elementUpdater = new ElementUpdater(track);\r\n const result = element.accept(elementUpdater);\r\n \r\n if (result) {\r\n // Update the timeline data to reflect the change\r\n const currentData = this.getTimelineData();\r\n if (currentData) {\r\n this.setTimelineData(currentData.tracks);\r\n }\r\n }\r\n\r\n return result;\r\n } catch (error) {\r\n return false;\r\n }\r\n }\r\n\r\n /**\r\n * Split an element at a specific time point using the visitor pattern\r\n * @param element The element to split\r\n * @param splitTime The time point to split at\r\n * @returns SplitResult with first element, second element, and success status\r\n */\r\n async splitElement(element: TrackElement, splitTime: number): Promise<SplitResult> {\r\n const track = this.getTrackById(element.getTrackId());\r\n if (!track) {\r\n return { firstElement: element, secondElement: null, success: false };\r\n }\r\n\r\n try {\r\n // Use the visitor pattern to handle different element types\r\n const elementSplitter = new ElementSplitter(splitTime);\r\n const result = element.accept(elementSplitter);\r\n \r\n if (result.success) {\r\n const elementRemover = new ElementRemover(track);\r\n // Remove the original element from the track\r\n element.accept(elementRemover);\r\n\r\n // Add the first split element to the track\r\n const elementAdder = new ElementAdder(track);\r\n result.firstElement.accept(elementAdder);\r\n result.secondElement.accept(elementAdder);\r\n \r\n // Update the timeline data to reflect the change\r\n const currentData = this.getTimelineData();\r\n if (currentData) {\r\n this.setTimelineData(currentData.tracks);\r\n }\r\n }\r\n return result;\r\n } catch (error) {\r\n return { firstElement: element, secondElement: null, success: false };\r\n }\r\n }\r\n\r\n /**\r\n * Clone an element using the visitor pattern\r\n * @param element The element to clone\r\n * @returns TrackElement | null - the cloned element or null if cloning failed\r\n */\r\n cloneElement(element: TrackElement): TrackElement | null {\r\n try {\r\n const elementCloner = new ElementCloner();\r\n return element.accept(elementCloner);\r\n } catch (error) {\r\n return null;\r\n }\r\n }\r\n\r\n reorderTracks(tracks: Track[]): void {\r\n this.setTimelineData(tracks);\r\n }\r\n\r\n updateHistory(timelineTrackData: TimelineTrackData): void {\r\n const tracks = timelineTrackData.tracks.map((t) => t.serialize());\r\n this.context.setTotalDuration(getTotalDuration(tracks));\r\n const version = timelineTrackData.version;\r\n this.context.setPresent({\r\n tracks,\r\n version,\r\n });\r\n }\r\n\r\n /**\r\n * Trigger undo operation and update timeline data\r\n */\r\n undo(): void {\r\n const result = this.context.handleUndo();\r\n if (result && result.tracks) {\r\n // Update the timeline data in the editor's store\r\n const tracks = result.tracks.map((t: TrackJSON) => Track.fromJSON(t));\r\n timelineContextStore.setTimelineData(this.context.contextId, {\r\n tracks,\r\n version: result.version,\r\n });\r\n\r\n // Update total duration\r\n this.context.setTotalDuration(getTotalDuration(result.tracks));\r\n this.context.updateChangeLog();\r\n\r\n // Trigger timeline action to notify components\r\n if (this.context?.setTimelineAction) {\r\n this.context.setTimelineAction(TIMELINE_ACTION.UPDATE_PLAYER_DATA, {\r\n tracks: result.tracks,\r\n version: result.version,\r\n });\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Trigger redo operation and update timeline data\r\n */\r\n redo(): void {\r\n const result = this.context.handleRedo();\r\n if (result && result.tracks) {\r\n // Update the timeline data in the editor's store\r\n const tracks = result.tracks.map((t: TrackJSON) => Track.fromJSON(t));\r\n timelineContextStore.setTimelineData(this.context.contextId, {\r\n tracks,\r\n version: result.version,\r\n });\r\n\r\n // Update total duration\r\n this.context.setTotalDuration(getTotalDuration(result.tracks));\r\n this.context.updateChangeLog();\r\n\r\n // Trigger timeline action to notify components\r\n if (this.context?.setTimelineAction) {\r\n this.context.setTimelineAction(TIMELINE_ACTION.UPDATE_PLAYER_DATA, {\r\n tracks: result.tracks,\r\n version: result.version,\r\n });\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Reset history and clear timeline data\r\n */\r\n resetHistory(): void {\r\n this.context.handleResetHistory();\r\n\r\n // Clear the timeline data in the editor's store\r\n timelineContextStore.setTimelineData(this.context.contextId, {\r\n tracks: [],\r\n version: 0,\r\n });\r\n\r\n // Reset total duration and version\r\n this.context.setTotalDuration(0);\r\n this.context.updateChangeLog();\r\n\r\n // Trigger timeline action to notify components\r\n if (this.context?.setTimelineAction) {\r\n this.context.setTimelineAction(TIMELINE_ACTION.UPDATE_PLAYER_DATA, {\r\n tracks: [],\r\n version: 0,\r\n });\r\n }\r\n }\r\n\r\n loadProject({\r\n tracks,\r\n version,\r\n }: {\r\n tracks: TrackJSON[];\r\n version: number;\r\n }): void {\r\n this.pauseVideo();\r\n this.context.handleResetHistory();\r\n // Convert Timeline[] to Track[] and set\r\n const timelineTracks = tracks.map((t) => Track.fromJSON(t));\r\n this.setTimelineData(timelineTracks, version);\r\n if (this.context?.setTimelineAction) {\r\n this.context.setTimelineAction(TIMELINE_ACTION.UPDATE_PLAYER_DATA, {\r\n tracks: tracks,\r\n version: version,\r\n forceUpdate: true,\r\n });\r\n }\r\n }\r\n}\r\n","import { createContext, useContext, useState } from \"react\";\r\nimport { ProjectJSON } from \"../types\";\r\n\r\nconst MAX_HISTORY = 20;\r\n\r\n// Helper function for deep cloning\r\nconst deepClone = <T,>(obj: T): T => {\r\n return JSON.parse(JSON.stringify(obj));\r\n};\r\n\r\ninterface UndoRedoState {\r\n past: ProjectJSON[];\r\n present: ProjectJSON | null;\r\n future: ProjectJSON[];\r\n}\r\n\r\ninterface UndoRedoContextType {\r\n // State\r\n canUndo: boolean;\r\n canRedo: boolean;\r\n present: ProjectJSON | null;\r\n // Actions\r\n setPresent: (data: ProjectJSON) => void;\r\n undo: () => ProjectJSON | null;\r\n redo: () => ProjectJSON | null;\r\n resetHistory: () => void;\r\n getLastPersistedState: () => ProjectJSON | null;\r\n // Configuration\r\n disablePersistence: () => void;\r\n}\r\n\r\nconst UndoRedoContext = createContext<UndoRedoContextType | undefined>(\r\n undefined\r\n);\r\n\r\n// Local storage utilities\r\nconst STORAGE_KEY_PREFIX = \"twick_undo_redo_\";\r\n\r\nconst saveToStorage = (key: string, state: UndoRedoState): void => {\r\n try {\r\n localStorage.setItem(key, JSON.stringify(state));\r\n } catch (error) {\r\n console.warn(\"Failed to save undo-redo state to localStorage:\", error);\r\n }\r\n};\r\n\r\nconst loadFromStorage = (key: string): UndoRedoState | null => {\r\n try {\r\n const stored = localStorage.getItem(key);\r\n if (!stored) return null;\r\n return JSON.parse(stored);\r\n } catch (error) {\r\n console.warn(\"Failed to load undo-redo state from localStorage:\", error);\r\n return null;\r\n }\r\n};\r\n\r\nexport interface UndoRedoProviderProps {\r\n children: React.ReactNode;\r\n persistenceKey?: string;\r\n maxHistorySize?: number;\r\n}\r\n\r\nexport const UndoRedoProvider: React.FC<UndoRedoProviderProps> = ({\r\n children,\r\n persistenceKey,\r\n maxHistorySize = MAX_HISTORY,\r\n}) => {\r\n const [state, setState] = useState<UndoRedoState>(() => {\r\n // Load from storage if persistence is enabled\r\n if (persistenceKey) {\r\n const stored = loadFromStorage(STORAGE_KEY_PREFIX + persistenceKey);\r\n if (stored) {\r\n return {\r\n past: stored.past,\r\n present: stored.present,\r\n future: stored.future,\r\n };\r\n }\r\n }\r\n\r\n return {\r\n past: [],\r\n present: null,\r\n future: [],\r\n };\r\n });\r\n\r\n // Save to storage whenever state changes (if persistence enabled)\r\n const saveState = (newState: UndoRedoState) => {\r\n if (persistenceKey) {\r\n saveToStorage(STORAGE_KEY_PREFIX + persistenceKey, newState);\r\n }\r\n };\r\n\r\n // When user makes a new change\r\n const setPresent = (data: ProjectJSON) => {\r\n setState((prevState) => {\r\n let newPast = [...prevState.past];\r\n if (prevState.present) {\r\n newPast.push(deepClone(prevState.present));\r\n }\r\n\r\n const newState: UndoRedoState = {\r\n past: newPast,\r\n present: deepClone(data),\r\n future: [], // Clear future because it's a new change\r\n };\r\n\r\n // Limit history size\r\n if (newState.past.length > maxHistorySize) {\r\n newState.past.shift(); // Remove oldest\r\n }\r\n\r\n saveState(newState);\r\n return newState;\r\n });\r\n };\r\n\r\n const undo = (): ProjectJSON | null => {\r\n let undoResult: ProjectJSON | null = null;\r\n\r\n setState((prevState) => {\r\n if (prevState.past.length === 0) return prevState;\r\n\r\n const previous = prevState.past[prevState.past.length - 1];\r\n const newState: UndoRedoState = {\r\n past: prevState.past.slice(0, -1), // Remove last item\r\n present: previous,\r\n future: prevState.present\r\n ? [deepClone(prevState.present), ...prevState.future]\r\n : prevState.future,\r\n };\r\n\r\n undoResult = previous;\r\n saveState(newState);\r\n return newState;\r\n });\r\n\r\n return undoResult;\r\n };\r\n\r\n const redo = (): ProjectJSON | null => {\r\n let redoResult: ProjectJSON | null = null;\r\n\r\n setState((prevState) => {\r\n if (prevState.future.length === 0) return prevState;\r\n\r\n const next = prevState.future[0];\r\n const newState: UndoRedoState = {\r\n past: prevState.present\r\n ? [...prevState.past, deepClone(prevState.present)]\r\n : prevState.past,\r\n present: next,\r\n future: prevState.future.slice(1), // Remove first item\r\n };\r\n\r\n // Limit history size\r\n if (newState.past.length > maxHistorySize) {\r\n newState.past.shift();\r\n }\r\n\r\n redoResult = next;\r\n saveState(newState);\r\n return newState;\r\n });\r\n\r\n return redoResult;\r\n };\r\n\r\n const getLastPersistedState = () => {\r\n if (persistenceKey) {\r\n const stored = loadFromStorage(STORAGE_KEY_PREFIX + persistenceKey);\r\n return stored?.present || null;\r\n }\r\n return null;\r\n };\r\n\r\n // Reset all history\r\n const resetHistory = () => {\r\n const newState: UndoRedoState = {\r\n past: [],\r\n present: null,\r\n future: [],\r\n };\r\n\r\n setState(newState);\r\n\r\n // Clear from storage too\r\n if (persistenceKey) {\r\n localStorage.removeItem(STORAGE_KEY_PREFIX + persistenceKey);\r\n }\r\n };\r\n\r\n const disablePersistence = () => {\r\n if (persistenceKey) {\r\n localStorage.removeItem(STORAGE_KEY_PREFIX + persistenceKey);\r\n }\r\n };\r\n\r\n const contextValue: UndoRedoContextType = {\r\n canUndo: state.past.length > 0,\r\n canRedo: state.future.length > 0,\r\n present: state.present,\r\n setPresent,\r\n undo,\r\n redo,\r\n resetHistory,\r\n getLastPersistedState,\r\n disablePersistence,\r\n };\r\n\r\n return (\r\n <UndoRedoContext.Provider value={contextValue}>\r\n {children}\r\n </UndoRedoContext.Provider>\r\n );\r\n};\r\n\r\nexport const useUndoRedo = (): UndoRedoContextType => {\r\n const context = useContext(UndoRedoContext);\r\n if (context === undefined) {\r\n throw new Error(\"useUndoRedo must be used within an UndoRedoProvider\");\r\n }\r\n return context;\r\n};\r\n","import { TimelineEditor } from \"../core/editor/timeline.editor\";\r\n\r\n// Global registry to store editor instances by contextId\r\nexport const editorRegistry = new Map<string, TimelineEditor>();\r\n\r\n// Expose the registry to the global window object for console access\r\ndeclare global {\r\n interface Window {\r\n twickTimelineEditors: Map<string, TimelineEditor>;\r\n }\r\n}\r\n\r\n// Initialize the global registry on window\r\nif (typeof window !== 'undefined') {\r\n window.twickTimelineEditors = editorRegistry;\r\n}","import {\r\n createContext,\r\n useContext,\r\n useState,\r\n useEffect,\r\n useMemo,\r\n useRef,\r\n} from \"react\";\r\nimport { TIMELINE_ACTION } from \"../utils/constants\";\r\nimport { UndoRedoProvider, useUndoRedo } from \"./undo-redo-context\";\r\nimport { Track } from \"../core/track/track\";\r\nimport { TrackElement } from \"../core/elements/base.element\";\r\nimport { ProjectJSON, TrackJSON } from \"../types\";\r\nimport { TimelineEditor } from \"../core/editor/timeline.editor\";\r\nimport { editorRegistry } from \"../utils/register-editor\";\r\n\r\nexport type TimelineContextType = {\r\n contextId: string;\r\n editor: TimelineEditor;\r\n selectedItem: Track | TrackElement | null;\r\n changeLog: number;\r\n timelineAction: {\r\n type: string;\r\n payload: any;\r\n };\r\n totalDuration: number;\r\n present: ProjectJSON | null;\r\n canUndo: boolean;\r\n canRedo: boolean;\r\n setSelectedItem: (item: Track | TrackElement | null) => void;\r\n setTimelineAction: (type: string, payload: any) => void;\r\n};\r\n\r\nconst TimelineContext = createContext<TimelineContextType | undefined>(\r\n undefined\r\n);\r\n\r\nexport interface TimelineProviderProps {\r\n children: React.ReactNode;\r\n contextId: string;\r\n initialData?: {\r\n tracks: TrackJSON[];\r\n version: number;\r\n };\r\n undoRedoPersistenceKey?: string;\r\n maxHistorySize?: number;\r\n}\r\n\r\n// Inner component that uses the UndoRedo context\r\nconst TimelineProviderInner = ({\r\n contextId,\r\n children,\r\n initialData,\r\n}: TimelineProviderProps) => {\r\n const [timelineAction, setTimelineActionState] = useState<{\r\n type: string;\r\n payload: any;\r\n }>({\r\n type: TIMELINE_ACTION.NONE,\r\n payload: null,\r\n });\r\n\r\n const [selectedItem, setSelectedItem] = useState<Track | TrackElement | null>(\r\n null\r\n );\r\n\r\n const [totalDuration, setTotalDuration] = useState(0);\r\n\r\n const [changeLog, setChangeLog] = useState(0);\r\n\r\n const undoRedoContext = useUndoRedo();\r\n\r\n const dataInitialized = useRef(false);\r\n\r\n const updateChangeLog = () => {\r\n setChangeLog((prev) => prev + 1);\r\n };\r\n\r\n // Create a single editor instance that's shared across all components\r\n const editor = useMemo(() => {\r\n if (editorRegistry.has(contextId)) {\r\n editorRegistry.delete(contextId);\r\n }\r\n const newEditor = new TimelineEditor({\r\n contextId,\r\n setTotalDuration,\r\n setPresent: undoRedoContext.setPresent,\r\n handleUndo: undoRedoContext.undo,\r\n handleRedo: undoRedoContext.redo,\r\n handleResetHistory: undoRedoContext.resetHistory,\r\n updateChangeLog: updateChangeLog,\r\n setTimelineAction: (action: string, payload?: unknown) => {\r\n setTimelineActionState({ type: action, payload });\r\n },\r\n });\r\n\r\n // Register the editor instance in the global registry\r\n editorRegistry.set(contextId, newEditor);\r\n\r\n return newEditor;\r\n }, [contextId]);\r\n\r\n const setTimelineAction = (type: string, payload: any) => {\r\n setTimelineActionState({ type, payload });\r\n };\r\n\r\n const initialize = (data: ProjectJSON) => {\r\n const lastPersistedState = undoRedoContext.getLastPersistedState();\r\n if (lastPersistedState) {\r\n editor.loadProject(lastPersistedState);\r\n return;\r\n } else {\r\n editor.loadProject(data);\r\n }\r\n };\r\n\r\n // Initialize timeline data if provided\r\n useEffect(() => {\r\n if (initialData && !dataInitialized.current) {\r\n initialize(initialData);\r\n dataInitialized.current = true;\r\n }\r\n }, [initialData]);\r\n\r\n const contextValue: TimelineContextType = {\r\n contextId,\r\n selectedItem,\r\n timelineAction,\r\n totalDuration,\r\n changeLog,\r\n present: undoRedoContext.present,\r\n canUndo: undoRedoContext.canUndo,\r\n canRedo: undoRedoContext.canRedo,\r\n setSelectedItem,\r\n setTimelineAction,\r\n editor, // Include the editor instance\r\n };\r\n\r\n return (\r\n <TimelineContext.Provider value={contextValue}>\r\n {children}\r\n </TimelineContext.Provider>\r\n );\r\n};\r\n\r\nexport const TimelineProvider = ({\r\n contextId,\r\n children,\r\n initialData,\r\n undoRedoPersistenceKey,\r\n maxHistorySize,\r\n}: TimelineProviderProps) => {\r\n // If undo/redo is enabled, wrap with UndoRedoProvider\r\n return (\r\n <UndoRedoProvider\r\n persistenceKey={undoRedoPersistenceKey}\r\n maxHistorySize={maxHistorySize}\r\n >\r\n <TimelineProviderInner\r\n initialData={initialData}\r\n contextId={contextId}\r\n undoRedoPersistenceKey={undoRedoPersistenceKey}\r\n maxHistorySize={maxHistorySize}\r\n >\r\n {children}\r\n </TimelineProviderInner>\r\n </UndoRedoProvider>\r\n );\r\n};\r\n\r\nexport const useTimelineContext = () => {\r\n const context = useContext(TimelineContext);\r\n if (context === undefined) {\r\n throw new Error(\r\n \"useTimelineContext must be used within a TimelineProvider\"\r\n );\r\n }\r\n return context;\r\n};\r\n","import { TIMELINE_ELEMENT_TYPE } from \"./utils/constants\";\r\nimport { TimelineEditor } from \"./core/editor/timeline.editor\";\r\nimport {\r\n TimelineProvider,\r\n TimelineProviderProps,\r\n} from \"./context/timeline-context\";\r\nimport { Track } from \"./core/track/track\";\r\nimport { ElementDeserializer } from \"./core/visitor/element-deserializer\";\r\nimport { ElementSerializer } from \"./core/visitor/element-serializer\";\r\nimport { ElementValidator } from \"./core/visitor/element-validator\";\r\nimport { ElementAdder } from \"./core/visitor/element-adder\";\r\nimport { ElementRemover } from \"./core/visitor/element-remover\";\r\nimport { ElementUpdater } from \"./core/visitor/element-updater\";\r\nimport { ElementSplitter } from \"./core/visitor/element-splitter\";\r\nimport { ElementCloner } from \"./core/visitor/element-cloner\";\r\nimport { CaptionElement } from \"./core/elements/caption.element\";\r\nimport { RectElement } from \"./core/elements/rect.element\";\r\nimport { TextElement } from \"./core/elements/text.element\";\r\nimport { ImageElement } from \"./core/elements/image.element\";\r\nimport { AudioElement } from \"./core/elements/audio.element\";\r\nimport { CircleElement } from \"./core/elements/circle.element\";\r\nimport { IconElement } from \"./core/elements/icon.element\";\r\nimport { VideoElement } from \"./core/elements/video.element\";\r\nimport {\r\n generateShortUuid,\r\n getTotalDuration,\r\n getCurrentElements,\r\n isTrackId,\r\n isElementId,\r\n} from \"./utils/timeline.utils\";\r\nimport { TrackElement } from \"./core/elements/base.element\";\r\nimport { ElementAnimation } from \"./core/addOns/animation\";\r\nimport { ElementFrameEffect } from \"./core/addOns/frame-effect\";\r\nimport { ElementTextEffect } from \"./core/addOns/text-effect\";\r\n\r\nexport {\r\n TrackElement,\r\n Track,\r\n CaptionElement,\r\n RectElement,\r\n TextElement,\r\n ImageElement,\r\n IconElement,\r\n AudioElement,\r\n CircleElement,\r\n VideoElement,\r\n ElementAnimation,\r\n ElementFrameEffect,\r\n ElementTextEffect\r\n};\r\n\r\nexport {\r\n TimelineProvider,\r\n TimelineEditor,\r\n};\r\n\r\nexport type { TimelineProviderProps };\r\nexport { TIMELINE_ELEMENT_TYPE };\r\n\r\nexport * from \"./types\";\r\nexport * from \"./utils/constants\";\r\nexport * from \"./utils/timeline.utils\";\r\nexport * from \"./context/timeline-context\";\r\n// Export core components\r\nexport * from \"./core/track/track\";\r\nexport * from \"./core/elements/base.element\";\r\nexport * from \"./core/visitor/element-visitor\";\r\nexport * from \"./core/visitor/element-serializer\";\r\nexport * from \"./core/visitor/element-deserializer\";\r\nexport * from \"./core/visitor/element-validator\";\r\nexport * from \"./core/visitor/element-adder\";\r\nexport * from \"./core/visitor/element-remover\";\r\nexport * from \"./core/visitor/element-updater\";\r\nexport * from \"./core/visitor/element-splitter\";\r\nexport * from \"./core/visitor/element-cloner\";\r\n\r\n// Expose classes globally on window object for browser access\r\nif (typeof window !== \"undefined\") {\r\n // Also expose the main exports\r\n (window as any).Twick = {\r\n Track: Track,\r\n TrackElement,\r\n ElementDeserializer,\r\n ElementSerializer,\r\n ElementValidator,\r\n ElementAdder,\r\n ElementRemover,\r\n ElementUpdater,\r\n ElementSplitter,\r\n ElementCloner,\r\n TimelineEditor,\r\n TimelineProvider,\r\n TIMELINE_ELEMENT_TYPE,\r\n // Element types\r\n CaptionElement,\r\n RectElement,\r\n TextElement,\r\n ImageElement,\r\n AudioElement,\r\n CircleElement,\r\n IconElement,\r\n VideoElement,\r\n ElementAnimation,\r\n ElementFrameEffect,\r\n ElementTextEffect,\r\n // Utility functions\r\n generateShortUuid,\r\n getTotalDuration,\r\n getCurrentElements,\r\n isTrackId,\r\n isElementId,\r\n };\r\n}\r\n"],"names":["createContext","useState","useContext","useRef","useMemo","useEffect","jsx"],"mappings":"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"}
|