@elah/editor 0.3.2 → 0.4.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 CHANGED
@@ -16,7 +16,9 @@ Ships `EditorProvider`, `Preview` (WebGL2 canvas + interactive transform overlay
16
16
  npm install @elah/editor
17
17
  ```
18
18
 
19
- Peer dependencies: `react`, `react-dom` >= 18.
19
+ Peer dependencies: `react`, `react-dom` >= 18, `lucide-react` >= 0.400.0 (used by the
20
+ bundled `@elah/timeline` UI for clip icons — install it alongside `react`/`react-dom`
21
+ even though nothing in your own code imports it).
20
22
 
21
23
  **Bundle size:** ~10 KiB gzipped for the editor layer (51 KiB raw); ~63 KiB gzipped for the full SDK graph (`core` + `timeline` + `editor`, 330 KiB raw). `mediabunny` is injected, never bundled — see [BUNDLE_STRATEGY.md](../../BUNDLE_STRATEGY.md).
22
24
 
@@ -142,16 +144,27 @@ Runs in a web worker. Reuses `resolveTimeline` + the GPU renderer's placement ma
142
144
  ## Package layers
143
145
 
144
146
  ```
145
- @elah/core — engine, playback, resolver, stores, media, export (framework-agnostic)
146
- @elah/timeline — React timeline UI components and hooks
147
- @elah/editor — EditorProvider, Preview, AssetPanel + re-exports everything above
147
+ @elah/core — engine, playback, resolver, vanilla stores, media, export (framework-agnostic)
148
+ @elah/react — React bindings: EditorContext, store hooks, audio hooks
149
+ @elah/timeline — React timeline UI components and hooks (consumes @elah/core + @elah/react)
150
+ @elah/editor — EditorProvider, Preview, AssetPanel + re-exports @elah/core, @elah/react, @elah/timeline
148
151
  @elah/cli — headless split/trim/build/export/serve on top of @elah/core
149
152
  ```
150
153
 
151
154
  Use `@elah/editor` for the full in-browser experience. Use `@elah/core` directly
152
- for headless or custom rendering pipelines. Use `@elah/cli` for automation,
155
+ for headless or custom rendering pipelines, or pair it with `@elah/react` if you
156
+ want the hooks without the timeline UI. Use `@elah/cli` for automation,
153
157
  AI-generation pipelines, and server-side rendering.
154
158
 
159
+ **One active project per page.** `@elah/core`'s stores (`tracksStore`,
160
+ `playbackStore`, `selectionStore`, `transitionsStore`, `mediaLibraryStore`) are
161
+ module-level singletons, and `<EditorProvider>` wires the `TimelineEngine` /
162
+ `PlaybackEngine` it creates into those same shared stores. Mounting a second
163
+ `<EditorProvider>` on the same page (two independent projects at once) will have
164
+ both instances overwrite each other's state — there is currently no per-instance
165
+ scoping. If you need multiple concurrent editors, isolate each in its own
166
+ tab/window/iframe.
167
+
155
168
  ---
156
169
 
157
170
  ## Links
@@ -1,7 +1,8 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useCallback, useEffect, useRef, useState, } from 'react';
3
3
  import { createPortal } from 'react-dom';
4
- import { importFiles, importUrl, MEDIA_DRAG_MIME, mediaDragKindMime, useMediaLibrary, useMediaLibraryStore, } from '@elah/core';
4
+ import { importFiles, importUrl, MEDIA_DRAG_MIME, mediaDragKindMime, } from '@elah/core';
5
+ import { useMediaLibrary, useMediaLibraryStore } from '@elah/react';
5
6
  import { cn } from '@elah/timeline';
6
7
  import { isActivationKey, useAssetActivation, } from '../activation';
7
8
  const KIND_ICONS = {
@@ -1,6 +1,7 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { useEffect, useMemo } from 'react';
3
- import { TimelineEngine, PlaybackEngine, useTracksStore, usePlaybackStore, useTransitionsStore, EditorContext, installTraceGlobal, trace, } from '@elah/core';
3
+ import { TimelineEngine, PlaybackEngine, installTraceGlobal, trace, } from '@elah/core';
4
+ import { useTracksStore, usePlaybackStore, useTransitionsStore, EditorContext, } from '@elah/react';
4
5
  export function EditorProvider({ fps, stage, defaultTrackHeight, maxHistorySize, initialTracks, children, }) {
5
6
  const engine = useMemo(() => new TimelineEngine({
6
7
  fps,
@@ -1,6 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useCallback, useLayoutEffect, useMemo, useRef, useState, } from 'react';
3
- import { useTimelineEngine, useSelectionStore, usePlaybackStore, useMediaLibraryStore, resolveDrawRect, transformFromContainRect, computeContainViewport, } from '@elah/core';
3
+ import { resolveDrawRect, transformFromContainRect, computeContainViewport, } from '@elah/core';
4
+ import { useTimelineEngine, useSelectionStore, usePlaybackStore, useMediaLibraryStore, } from '@elah/react';
4
5
  import { useResolvedScene } from '../useResolvedScene';
5
6
  const MIN_BOX_PX = 28;
6
7
  const BOX_PAD = 0;
@@ -2,8 +2,8 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { forwardRef, useEffect, useImperativeHandle, useRef, } from 'react';
3
3
  import { GpuRenderer } from '@elah/core';
4
4
  import { resolveTimeline } from '@elah/core';
5
- import { useTimelineEngine, usePlaybackEngine } from '@elah/core';
6
- import { AudioPlaybackController, useMediaLibraryStore, preloadProjectImages, warmImageSrc } from '@elah/core';
5
+ import { useTimelineEngine, usePlaybackEngine, useMediaLibraryStore } from '@elah/react';
6
+ import { AudioPlaybackController, preloadProjectImages, warmImageSrc } from '@elah/core';
7
7
  import { cn } from '@elah/timeline';
8
8
  import { TextOverlay } from './TextOverlay';
9
9
  import { ShapeOverlay } from './ShapeOverlay';
@@ -1,6 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useCallback, useLayoutEffect, useMemo, useRef, useState, } from 'react';
3
- import { useTimelineEngine, useSelectionStore, usePlaybackStore, computeContainViewport, } from '@elah/core';
3
+ import { computeContainViewport } from '@elah/core';
4
+ import { useTimelineEngine, useSelectionStore, usePlaybackStore, } from '@elah/react';
4
5
  import { useResolvedScene } from '../useResolvedScene';
5
6
  const DEFAULT_SCALE = 0.5;
6
7
  const DEFAULT_CENTER = 0.5;
@@ -1,6 +1,7 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { useLayoutEffect, useMemo, useRef, useState } from 'react';
3
- import { computeContainViewport, useTracksStore } from '@elah/core';
3
+ import { computeContainViewport } from '@elah/core';
4
+ import { useTracksStore } from '@elah/react';
4
5
  export function StageBorder() {
5
6
  const rootRef = useRef(null);
6
7
  const [size, setSize] = useState({ width: 0, height: 0 });
@@ -1,6 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState, } from 'react';
3
- import { computeTextLayout, computeContainViewport, useTimelineEngine, useSelectionStore, usePlaybackStore, SIDE_MARGIN, } from '@elah/core';
3
+ import { computeTextLayout, computeContainViewport, SIDE_MARGIN, } from '@elah/core';
4
+ import { useTimelineEngine, useSelectionStore, usePlaybackStore, } from '@elah/react';
4
5
  import { useResolvedScene } from '../useResolvedScene';
5
6
  const MIN_FONT_SIZE = 6;
6
7
  const MAX_FONT_SIZE = 4000;
@@ -1,7 +1,8 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useCallback, useEffect, useRef, useState, } from 'react';
3
3
  import { createPortal } from 'react-dom';
4
- import { importFiles, importUrl, MEDIA_DRAG_MIME, mediaDragKindMime, useMediaLibrary, useMediaLibraryStore, } from '@elah/core';
4
+ import { importFiles, importUrl, MEDIA_DRAG_MIME, mediaDragKindMime, } from '@elah/core';
5
+ import { useMediaLibrary, useMediaLibraryStore } from '@elah/react';
5
6
  import { ELEMENT_DRAG_MIME, cn } from '@elah/timeline';
6
7
  import { isActivationKey, useAssetActivation, } from '../activation';
7
8
  const KIND_ICONS = { video: '▶', audio: '♪', image: '◻' };
@@ -1,4 +1,4 @@
1
- import { type MediaAsset } from '@elah/core';
1
+ import type { MediaAsset } from '@elah/core';
2
2
  import { type ElementKind, type ShapeVariant } from '@elah/timeline';
3
3
  export interface ActivationToast {
4
4
  message: string;
@@ -1,5 +1,5 @@
1
1
  import { useCallback, useContext } from 'react';
2
- import { EditorContext } from '@elah/core';
2
+ import { EditorContext } from '@elah/react';
3
3
  import { insertElement, insertMediaAsset, } from '@elah/timeline';
4
4
  export function isActivationKey(key) {
5
5
  return key === 'Enter' || key === ' ';
@@ -1,5 +1,6 @@
1
1
  import { useMemo, useRef } from 'react';
2
- import { useTimelineEngine, useTracksStore, usePlaybackStore, resolveTimeline, } from '@elah/core';
2
+ import { resolveTimeline } from '@elah/core';
3
+ import { useTimelineEngine, useTracksStore, usePlaybackStore, } from '@elah/react';
3
4
  export function useResolvedScene(frameOverride) {
4
5
  const engine = useTimelineEngine();
5
6
  const playbackFrame = usePlaybackStore((s) => (s.isPlaying ? null : s.currentFrame));
package/dist/index.d.ts CHANGED
@@ -18,11 +18,12 @@ export { AudioPlaybackController } from '@elah/core';
18
18
  export type { AudioPlaybackControllerOptions } from '@elah/core';
19
19
  export { defaultAudioResolver } from '@elah/core';
20
20
  export type { AudioResolver } from '@elah/core';
21
- export { useMediaLibrary, useMediaLibraryStore, MEDIA_DRAG_MIME, mediaDragKindMime, importFiles, importUrl } from '@elah/core';
21
+ export { MEDIA_DRAG_MIME, mediaDragKindMime, importFiles, importUrl } from '@elah/core';
22
+ export { useMediaLibrary, useMediaLibraryStore } from '@elah/react';
22
23
  export type { MediaAsset, MediaKind, DragMediaPayload, ImportFilesOptions, ImportFilesResult, SkippedImport } from '@elah/core';
23
- export { useTracksStore } from '@elah/core';
24
- export { usePlaybackStore } from '@elah/core';
25
- export { useSelectionStore } from '@elah/core';
24
+ export { useTracksStore } from '@elah/react';
25
+ export { usePlaybackStore } from '@elah/react';
26
+ export { useSelectionStore } from '@elah/react';
26
27
  export { createVideoClip } from '@elah/core';
27
28
  export { createAudioClip } from '@elah/core';
28
29
  export { createTextClip } from '@elah/core';
@@ -48,7 +49,9 @@ export { ELEMENT_DRAG_MIME } from '@elah/timeline';
48
49
  export type { DragElementPayload, ElementKind, ShapeVariant, InsertAssetOptions, InsertAssetResult, InsertAssetFailureReason, InsertedKind, } from '@elah/timeline';
49
50
  export { EditorProvider } from './editor/EditorProvider';
50
51
  export type { EditorProviderProps } from './editor/EditorProvider';
51
- export { useEditor, useTimelineEngine, usePlaybackEngine } from '@elah/core';
52
+ export { useEditor, useTimelineEngine, usePlaybackEngine } from '@elah/react';
53
+ export { useAudioMixer, useMasterVolume, useTrackLevels } from '@elah/react';
54
+ export type { AudioMixerApi, MasterVolumeApi, TrackLevel } from '@elah/react';
52
55
  export { useResolvedScene } from './editor/useResolvedScene';
53
56
  export { AssetPanel } from './editor/AssetPanel';
54
57
  export type { AssetPanelProps } from './editor/AssetPanel';
package/dist/index.js CHANGED
@@ -7,10 +7,11 @@ export { createDefaultDemuxerFactory, createMediabunnyBackend, isMediabunnyCompa
7
7
  export { createVideoFrameProvider, MockVideoFrameProvider, SyntheticVideoFrameProvider } from '@elah/core';
8
8
  export { AudioPlaybackController } from '@elah/core';
9
9
  export { defaultAudioResolver } from '@elah/core';
10
- export { useMediaLibrary, useMediaLibraryStore, MEDIA_DRAG_MIME, mediaDragKindMime, importFiles, importUrl } from '@elah/core';
11
- export { useTracksStore } from '@elah/core';
12
- export { usePlaybackStore } from '@elah/core';
13
- export { useSelectionStore } from '@elah/core';
10
+ export { MEDIA_DRAG_MIME, mediaDragKindMime, importFiles, importUrl } from '@elah/core';
11
+ export { useMediaLibrary, useMediaLibraryStore } from '@elah/react';
12
+ export { useTracksStore } from '@elah/react';
13
+ export { usePlaybackStore } from '@elah/react';
14
+ export { useSelectionStore } from '@elah/react';
14
15
  export { createVideoClip } from '@elah/core';
15
16
  export { createAudioClip } from '@elah/core';
16
17
  export { createTextClip } from '@elah/core';
@@ -30,7 +31,8 @@ export { useTimelineDrop } from '@elah/timeline';
30
31
  export { insertMediaAsset, insertElement } from '@elah/timeline';
31
32
  export { ELEMENT_DRAG_MIME } from '@elah/timeline';
32
33
  export { EditorProvider } from './editor/EditorProvider';
33
- export { useEditor, useTimelineEngine, usePlaybackEngine } from '@elah/core';
34
+ export { useEditor, useTimelineEngine, usePlaybackEngine } from '@elah/react';
35
+ export { useAudioMixer, useMasterVolume, useTrackLevels } from '@elah/react';
34
36
  export { useResolvedScene } from './editor/useResolvedScene';
35
37
  export { AssetPanel } from './editor/AssetPanel';
36
38
  export { ElementsPanel } from './editor/ElementsPanel';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elah/editor",
3
- "version": "0.3.2",
3
+ "version": "0.4.0",
4
4
  "description": "Full React video editor SDK — timeline UI, WebGL2 preview, media library, drag and drop, and MP4 export",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -55,11 +55,13 @@
55
55
  "license": "Apache-2.0",
56
56
  "peerDependencies": {
57
57
  "react": ">=18.0.0",
58
- "react-dom": ">=18.0.0"
58
+ "react-dom": ">=18.0.0",
59
+ "lucide-react": ">=0.400.0"
59
60
  },
60
61
  "dependencies": {
61
- "@elah/core": "^0.3.0",
62
- "@elah/timeline": "^0.3.0",
62
+ "@elah/core": "^0.4.0",
63
+ "@elah/react": "^0.4.0",
64
+ "@elah/timeline": "^0.4.0",
63
65
  "immer": "^10.1.1",
64
66
  "zustand": "^5.0.3"
65
67
  },
@@ -67,6 +69,7 @@
67
69
  "@types/react": "^18.3.18",
68
70
  "@types/react-dom": "^18.3.5",
69
71
  "autoprefixer": "^10.4.21",
72
+ "lucide-react": "^0.511.0",
70
73
  "postcss": "^8.5.3",
71
74
  "tailwindcss": "^3.4.17",
72
75
  "typescript": "^5.7.3",