@pixerate/editor-svelte 0.66.0 → 0.67.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.
@@ -7,7 +7,8 @@
7
7
  normalizeVideoGrade,
8
8
  VIDEO_GRADE_CONTROLS,
9
9
  VIDEO_GRADE_PRESET_NAMES,
10
- videoGradePreset,
10
+ videoGradeLook,
11
+ videoLutEdits,
11
12
  VIDEO_BLEND_MODE_LABELS,
12
13
  VIDEO_BLEND_MODES,
13
14
  VIDEO_FADE_CURVE_LABELS,
@@ -27,6 +28,7 @@
27
28
  type VideoEditorController,
28
29
  type VideoFadeCurve,
29
30
  type VideoGradeControl,
31
+ type VideoGradeLut,
30
32
  type VideoGradePreset,
31
33
  type VideoKeyframeRow,
32
34
  type VideoTransitionType,
@@ -119,9 +121,46 @@
119
121
  set('grade', normalizeVideoGrade({ ...clip.grade, [c.key]: n }), `Change ${c.label.toLowerCase()}`);
120
122
  }
121
123
  function gradePreset(name: string) {
122
- const grade = clip && name ? videoGradePreset(name as VideoGradePreset) : undefined;
124
+ const grade = clip && name ? videoGradeLook(clip.grade, name as VideoGradePreset) : undefined;
123
125
  if (clip && grade) apply({ op: 'update_clip', clip: clip.id, set: { grade } }, `Apply ${name} look`);
124
126
  }
127
+ /** Gives the clip a LUT (keeping its other grade settings), or takes it off with `null`. */
128
+ function setLut(setting: VideoGradeLut | null, label: string) {
129
+ if (!clip) return;
130
+ localError = null;
131
+ const r = controller.apply(videoLutEdits(editor.project, [clip.id], setting), label);
132
+ if (!r.ok) localError = { text: r.error, revision: editor.revision };
133
+ }
134
+ /** A `.cube` path or URL, checked by loading it; empty removes the LUT. */
135
+ async function chooseLut(src: string) {
136
+ if (!clip) return;
137
+ const strength = clip.grade?.lut?.strength;
138
+ if (!src) return clip.grade?.lut && setLut(null, 'Remove LUT');
139
+ try {
140
+ const table = await controller.luts.load(src);
141
+ setLut({ src, ...(strength !== undefined ? { strength } : {}), ...(table.title ? { name: table.title } : {}) }, 'Apply LUT');
142
+ } catch (e) {
143
+ localError = { text: e instanceof Error ? e.message : String(e), revision: editor.revision };
144
+ }
145
+ }
146
+ /** A `.cube` file read in place: its name becomes the `src`, so keep the file beside the export. */
147
+ async function loadLutFile(file: File | undefined) {
148
+ if (!file || !clip) return;
149
+ const strength = clip.grade?.lut?.strength;
150
+ try {
151
+ const table = controller.luts.set(file.name, await file.text());
152
+ setLut({ src: file.name, ...(strength !== undefined ? { strength } : {}), ...(table.title ? { name: table.title } : {}) }, 'Apply LUT');
153
+ } catch (e) {
154
+ localError = { text: `${file.name}: ${e instanceof Error ? e.message : String(e)}`, revision: editor.revision };
155
+ }
156
+ }
157
+ function lutStrength(raw: string) {
158
+ const lut = clip?.grade?.lut;
159
+ const n = Number(raw);
160
+ if (!lut || !raw.trim() || !Number.isFinite(n)) return;
161
+ // A strength of 0 changes nothing, so it takes the LUT off.
162
+ setLut(n > 0 ? { ...lut, strength: Math.min(1, n) } : null, n > 0 ? 'Change LUT strength' : 'Remove LUT');
163
+ }
125
164
  function transitionAudioCurve(curve: string) {
126
165
  if (!clip?.transition) return;
127
166
  const { audioCurve: _, ...rest } = clip.transition;
@@ -186,6 +225,21 @@
186
225
  <span class="text-muted-foreground">{c.label}</span>
187
226
  <input class={input} type="number" min={c.min} max={c.max} step={c.step} placeholder="0" aria-label={c.label} {disabled} value={clip.grade?.[c.key] ?? ''} onchange={(e) => gradeValue(c, e.currentTarget.value)} data-field="grade.{c.key}" />
188
227
  {/each}
228
+ <span class="text-muted-foreground">LUT</span>
229
+ <div class="flex min-w-0 gap-1" data-field="grade.lut">
230
+ <input class={input} placeholder="look.cube" aria-label="LUT file" {disabled} value={clip.grade?.lut?.src ?? ''} onchange={(e) => chooseLut(e.currentTarget.value.trim())} />
231
+ <label class="{btn} cursor-pointer whitespace-nowrap" title="Load a .cube file">
232
+ Load
233
+ <input type="file" accept=".cube" class="sr-only" {disabled} aria-label="Load a .cube LUT" onchange={(e) => loadLutFile(e.currentTarget.files?.[0])} />
234
+ </label>
235
+ {#if clip.grade?.lut}
236
+ <button type="button" class={btn} {disabled} aria-label="Remove LUT" onclick={() => setLut(null, 'Remove LUT')}>✕</button>
237
+ {/if}
238
+ </div>
239
+ {#if clip.grade?.lut}
240
+ <span class="text-muted-foreground">LUT strength</span>
241
+ <input class={input} type="number" min="0" max="1" step="0.05" aria-label="LUT strength" {disabled} value={clip.grade.lut.strength ?? 1} onchange={(e) => lutStrength(e.currentTarget.value)} data-field="grade.lut.strength" />
242
+ {/if}
189
243
  {/if}
190
244
  {#if at?.track.kind === 'video'}
191
245
  {#each [{ key: 'animateIn', label: 'Animate in', change: 'Change entrance' }, { key: 'animateOut', label: 'Animate out', change: 'Change exit' }] as const as row (row.key)}
@@ -1 +1 @@
1
- {"version":3,"file":"ClipInspector.svelte.d.ts","sourceRoot":"","sources":["../../src/video-editor/ClipInspector.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,EAyBH,KAAK,qBAAqB,EAO3B,MAAM,+BAA+B,CAAC;AAIvC,UAAU,KAAK;IACb,UAAU,EAAE,qBAAqB,CAAC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AA2PH,QAAA,MAAM,aAAa,2CAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"ClipInspector.svelte.d.ts","sourceRoot":"","sources":["../../src/video-editor/ClipInspector.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,EA0BH,KAAK,qBAAqB,EAQ3B,MAAM,+BAA+B,CAAC;AAIvC,UAAU,KAAK;IACb,UAAU,EAAE,qBAAqB,CAAC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AA+SH,QAAA,MAAM,aAAa,2CAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pixerate/editor-svelte",
3
- "version": "0.66.0",
3
+ "version": "0.67.0",
4
4
  "description": "Svelte bindings and prompt/rich-text components for @pixerate/editor",
5
5
  "author": "Pixerate",
6
6
  "license": "MIT",
@@ -131,7 +131,7 @@
131
131
  "@tiptap/extension-bubble-menu": "^2.11.5",
132
132
  "@tiptap/extension-placeholder": "^2.11.5",
133
133
  "@tiptap/starter-kit": "^2.11.5",
134
- "@pixerate/editor": "0.87.0"
134
+ "@pixerate/editor": "0.88.0"
135
135
  },
136
136
  "peerDependencies": {
137
137
  "@dagrejs/dagre": "^1.1.4",