melies-video-editor 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,10 @@
1
+ import './index.less';
2
+ export type MeliesVideoEditorProps = {
3
+ /**
4
+ * URLs (often blob: URLs) to show in the footage bin.
5
+ * When omitted or empty, the footage bin will be empty.
6
+ */
7
+ footageUrls?: string[];
8
+ };
9
+ declare const MeliesVideoEditor: ({ footageUrls }: MeliesVideoEditorProps) => import("react/jsx-runtime").JSX.Element;
10
+ export default MeliesVideoEditor;
@@ -0,0 +1,29 @@
1
+ import type { TimelineEngine } from '@xzdarcy/react-timeline-editor';
2
+ declare class AudioControl {
3
+ private howlBySrc;
4
+ private activeByActionId;
5
+ private getHowl;
6
+ /**
7
+ * Ensure the underlying WebAudio context is resumed.
8
+ *
9
+ * Some browsers (notably iOS Safari) block audio playback until a user gesture
10
+ * resumes the AudioContext. Timeline engine callbacks may occur outside the
11
+ * original gesture call stack, so we explicitly unlock in the toolbar handler.
12
+ */
13
+ unlock(): void;
14
+ warm(src: string): void;
15
+ private seekForEngineTime;
16
+ start(data: {
17
+ actionId: string;
18
+ engine: TimelineEngine;
19
+ src: string;
20
+ startTime: number;
21
+ time: number;
22
+ offset?: number;
23
+ }): void;
24
+ stop(data: {
25
+ actionId: string;
26
+ }): void;
27
+ }
28
+ declare const _default: AudioControl;
29
+ export default _default;
@@ -0,0 +1,14 @@
1
+ import type { FC } from 'react';
2
+ import type { CustomTimelineAction, CusTomTimelineRow } from './mock';
3
+ export declare const CustomRender0: FC<{
4
+ action: CustomTimelineAction;
5
+ row: CusTomTimelineRow;
6
+ }>;
7
+ export declare const CustomRender1: FC<{
8
+ action: CustomTimelineAction;
9
+ row: CusTomTimelineRow;
10
+ }>;
11
+ export declare const CustomRender2: FC<{
12
+ action: CustomTimelineAction;
13
+ row: CusTomTimelineRow;
14
+ }>;
@@ -0,0 +1,12 @@
1
+ export type FootageItem = {
2
+ id: string;
3
+ kind: 'video' | 'audio';
4
+ name: string;
5
+ src: string;
6
+ /** Optional lower-res/proxy source for smooth preview playback. */
7
+ previewSrc?: string;
8
+ defaultDuration?: number;
9
+ };
10
+ export declare const FOOTAGE_BIN: FootageItem[];
11
+ export declare const VIDEO_ITEMS: FootageItem[];
12
+ export declare const AUDIO_ITEMS: FootageItem[];
@@ -0,0 +1 @@
1
+ import 'antd/dist/antd.css';
@@ -0,0 +1,3 @@
1
+ export { default as MeliesVideoEditor } from '../App';
2
+ export type { MeliesVideoEditorProps } from '../App';
3
+ export type { TimelineAction, TimelineEffect, TimelineRow, TimelineState, } from '@xzdarcy/react-timeline-editor';
@@ -0,0 +1,28 @@
1
+ import { type AnimationItem } from 'lottie-web';
2
+ declare class LottieControl {
3
+ cacheMap: Record<string, AnimationItem>;
4
+ private _goToAndStop;
5
+ enter(data: {
6
+ id: string;
7
+ src: string;
8
+ startTime: number;
9
+ endTime: number;
10
+ time: number;
11
+ }): void;
12
+ update(data: {
13
+ id: string;
14
+ src: string;
15
+ startTime: number;
16
+ endTime: number;
17
+ time: number;
18
+ }): void;
19
+ leave(data: {
20
+ id: string;
21
+ startTime: number;
22
+ endTime: number;
23
+ time: number;
24
+ }): void;
25
+ destroy(): void;
26
+ }
27
+ declare const _default: LottieControl;
28
+ export default _default;
@@ -0,0 +1,20 @@
1
+ type MediaKind = 'video' | 'audio' | 'other';
2
+ declare const guessKind: (src: string) => MediaKind;
3
+ declare class MediaCache {
4
+ private blobUrlBySrc;
5
+ private pendingBySrc;
6
+ /**
7
+ * Preloads a URL into memory and returns a blob: URL.
8
+ * Useful to avoid runtime buffering/stalls when seeking frequently.
9
+ */
10
+ preloadToBlobUrl(src: string): Promise<string>;
11
+ /** Returns a blob URL if available, otherwise the original `src`. */
12
+ resolve(src: string): string;
13
+ /** Starts preload in background (non-blocking). */
14
+ warm(src: string): void;
15
+ /** Convenience: preload all unique action.data.src from editor data. */
16
+ warmFromEditorData(editorData: unknown): void;
17
+ }
18
+ declare const mediaCache: MediaCache;
19
+ export default mediaCache;
20
+ export { guessKind };
@@ -0,0 +1,23 @@
1
+ import type { TimelineAction, TimelineEffect, TimelineRow } from '@xzdarcy/react-timeline-editor';
2
+ export declare const scaleWidth = 160;
3
+ export declare const scale = 5;
4
+ export declare const startLeft = 20;
5
+ export interface CustomTimelineAction extends TimelineAction {
6
+ data: {
7
+ src: string;
8
+ previewSrc?: string;
9
+ name: string;
10
+ /** Shared id for clips that should move/trim together (e.g. video + its embedded audio). */
11
+ linkId?: string;
12
+ /**
13
+ * In-point offset into the underlying media (seconds).
14
+ * Used for split clips so the right segment continues from the correct time.
15
+ */
16
+ offset?: number;
17
+ };
18
+ }
19
+ export interface CusTomTimelineRow extends TimelineRow {
20
+ actions: CustomTimelineAction[];
21
+ }
22
+ export declare const mockEffect: Record<string, TimelineEffect>;
23
+ export declare const mockData: CusTomTimelineRow[];
@@ -0,0 +1,15 @@
1
+ import type { TimelineState } from '@xzdarcy/react-timeline-editor';
2
+ export declare const Rates: number[];
3
+ declare const TimelinePlayer: ({ timelineState, autoScrollWhenPlay, editorData, selectedActionId, onDeleteSelectedClip, onSplitSelectedClip, canUndo, canRedo, onUndo, onRedo, }: {
4
+ timelineState: React.MutableRefObject<TimelineState | null>;
5
+ autoScrollWhenPlay: React.MutableRefObject<boolean>;
6
+ editorData: any[];
7
+ selectedActionId: string | null;
8
+ onDeleteSelectedClip: () => void;
9
+ onSplitSelectedClip: () => void;
10
+ canUndo: boolean;
11
+ canRedo: boolean;
12
+ onUndo: () => void;
13
+ onRedo: () => void;
14
+ }) => import("react/jsx-runtime").JSX.Element;
15
+ export default TimelinePlayer;
@@ -0,0 +1 @@
1
+ export declare function useCoarsePointer(): boolean;
@@ -0,0 +1,30 @@
1
+ import type { TimelineEngine } from '@xzdarcy/react-timeline-editor';
2
+ declare class VideoControl {
3
+ private videoEl;
4
+ private currentSrc;
5
+ private lastSeekAtMs;
6
+ private lastRate;
7
+ private boundEngine;
8
+ private boundActionStart;
9
+ private vfcHandle;
10
+ private rafHandle;
11
+ attach(el: HTMLVideoElement | null): void;
12
+ setActive(active: boolean): void;
13
+ bindEngine(engine: TimelineEngine, actionStart: number): void;
14
+ unbindEngine(): void;
15
+ private tickFromVideo;
16
+ setSource(src: string): void;
17
+ warm(src: string): void;
18
+ setRate(rate: number): void;
19
+ /**
20
+ * Sync the video to a desired timeline time.
21
+ * To avoid buffering/stutters, we only seek when drift is large or when paused/scrubbing.
22
+ */
23
+ seek(time: number, opts?: {
24
+ force?: boolean;
25
+ }): void;
26
+ play(): Promise<void>;
27
+ pause(): void;
28
+ }
29
+ declare const _default: VideoControl;
30
+ export default _default;
package/package.json ADDED
@@ -0,0 +1,74 @@
1
+ {
2
+ "name": "melies-video-editor",
3
+ "version": "0.1.0",
4
+ "description": "A React video timeline editor GUI built on @xzdarcy/react-timeline-editor.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "keywords": [
8
+ "timeline",
9
+ "video",
10
+ "editor",
11
+ "react",
12
+ "base44"
13
+ ],
14
+ "main": "./dist/index.cjs",
15
+ "module": "./dist/index.js",
16
+ "types": "./dist/types/lib/index.d.ts",
17
+ "exports": {
18
+ ".": {
19
+ "types": "./dist/types/lib/index.d.ts",
20
+ "import": "./dist/index.js",
21
+ "require": "./dist/index.cjs"
22
+ },
23
+ "./style.css": "./dist/style.css"
24
+ },
25
+ "files": [
26
+ "dist",
27
+ "README.md",
28
+ "LICENSE"
29
+ ],
30
+ "sideEffects": [
31
+ "**/*.css"
32
+ ],
33
+ "scripts": {
34
+ "dev": "vite --host",
35
+ "dev:server": "node server/index.mjs",
36
+ "build": "tsc -b && vite build && tsc -p tsconfig.types.json",
37
+ "lint": "eslint .",
38
+ "preview": "vite preview"
39
+ },
40
+ "dependencies": {
41
+ "@ant-design/icons": "4.7.0",
42
+ "@dnd-kit/core": "^6.3.1",
43
+ "@xzdarcy/react-timeline-editor": "0.1.8",
44
+ "antd": "4.21.6",
45
+ "howler": "2.2.3",
46
+ "lodash": "4.17.21",
47
+ "lottie-web": "5.10.0"
48
+ },
49
+ "peerDependencies": {
50
+ "react": "^18.0.0",
51
+ "react-dom": "^18.0.0"
52
+ },
53
+ "devDependencies": {
54
+ "@eslint/js": "^9.39.1",
55
+ "@types/node": "^24.10.1",
56
+ "@types/howler": "^2.2.12",
57
+ "@types/react": "^18.3.18",
58
+ "@types/react-dom": "^18.3.5",
59
+ "@vitejs/plugin-react": "^5.1.1",
60
+ "eslint": "^9.39.1",
61
+ "eslint-plugin-react-hooks": "^7.0.1",
62
+ "eslint-plugin-react-refresh": "^0.4.24",
63
+ "express": "^4.21.2",
64
+ "globals": "^16.5.0",
65
+ "less": "^4.5.1",
66
+ "multer": "^2.0.2",
67
+ "react": "^18.2.0",
68
+ "react-dom": "^18.2.0",
69
+ "typescript": "~5.9.3",
70
+ "typescript-eslint": "^8.46.4",
71
+ "vite": "^7.2.4"
72
+ },
73
+ "packageManager": "pnpm@8.7.1+sha1.cb9fb56ca170a718619cd9bc669d99ddadc1afb5"
74
+ }