@pixerate/editor-react 0.59.0 → 0.61.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/dist/index.js CHANGED
@@ -31,7 +31,7 @@ import {
31
31
  SelectionOptionsBar,
32
32
  useImageEditor,
33
33
  useImageHistogram
34
- } from "./chunk-SYTV33TW.js";
34
+ } from "./chunk-OSOGA2OJ.js";
35
35
  import {
36
36
  CommandPalette,
37
37
  useCommandPalette,
@@ -205,6 +205,18 @@ function VideoTransport({ controller, editable = true, className = "" }) {
205
205
  " / ",
206
206
  (0, import_video_editor4.formatVideoTimecode)(duration, project.fps)
207
207
  ] }),
208
+ (0, import_video_editor4.videoProjectHasProxies)(project) && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
209
+ "select",
210
+ {
211
+ className: "rounded border border-border bg-transparent px-1 py-0.5 text-xs",
212
+ value: String(state.previewScale),
213
+ onChange: (e) => controller.setPreviewScale((0, import_video_editor4.parseVideoPreviewScale)(e.target.value)),
214
+ "aria-label": "Preview size",
215
+ title: "Play proxies in the preview (the export always uses the originals)",
216
+ "data-preview-scale": "",
217
+ children: import_video_editor4.VIDEO_PREVIEW_SCALE_OPTIONS.map((o) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: o.value, children: o.label }, o.value))
218
+ }
219
+ ),
208
220
  editable && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
209
221
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "mx-1 h-4 w-px bg-border" }),
210
222
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: btn, onClick: () => controller.splitAtPlayhead(), disabled: !canEdit, title: "Split at the playhead (S)", "data-split": "", children: "Split" }),
@@ -253,6 +265,27 @@ function ClipWaveform({ controller, clip, asset, width, height }) {
253
265
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { className: "pointer-events-none absolute inset-0", width, height, "aria-hidden": "true", "data-waveform": clip.id, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d, fill: "currentColor", fillOpacity: 0.45 }) });
254
266
  }
255
267
  var isField = (el) => el instanceof HTMLElement && /^(INPUT|TEXTAREA|SELECT)$/.test(el.tagName);
268
+ function useCachedRanges(controller, project, px) {
269
+ const [ranges, setRanges] = (0, import_react4.useState)([]);
270
+ (0, import_react4.useEffect)(() => {
271
+ const cache = controller.frameCache;
272
+ if (!cache) return setRanges([]);
273
+ let timer = null;
274
+ const read = () => {
275
+ timer = null;
276
+ setRanges(cache.cachedRanges(project, { step: 2e3 / px }));
277
+ };
278
+ read();
279
+ const off = cache.subscribe(() => {
280
+ timer ??= setTimeout(read, 250);
281
+ });
282
+ return () => {
283
+ off();
284
+ if (timer) clearTimeout(timer);
285
+ };
286
+ }, [controller, project, px]);
287
+ return ranges;
288
+ }
256
289
  function VideoTimeline({ controller, pxPerSecond, onPxPerSecondChange, editable = true, waveforms = "audio", className = "" }) {
257
290
  const state = useVideoEditorState(controller);
258
291
  const { project, duration, time, selection, readOnly, error } = state;
@@ -268,6 +301,7 @@ function VideoTimeline({ controller, pxPerSecond, onPxPerSecondChange, editable
268
301
  const span = Math.max(duration + 5e3, 1e4);
269
302
  const width = msToPx(span);
270
303
  const ticks = (0, import_video_editor5.videoRulerTicks)(span, px, project.fps);
304
+ const cached = useCachedRanges(controller, project, px);
271
305
  const seekAt = (clientX) => {
272
306
  const box = ruler.current.getBoundingClientRect();
273
307
  controller.seek(Math.max(0, (clientX - box.left) * 1e3 / px));
@@ -429,6 +463,7 @@ function VideoTimeline({ controller, pxPerSecond, onPxPerSecondChange, editable
429
463
  },
430
464
  children: [
431
465
  ticks.map((t) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: `absolute bottom-0 w-px ${t.major ? "h-2.5 bg-muted-foreground/70" : "h-1 bg-muted-foreground/40"}`, style: { left: t.x }, "data-tick": t.time, children: t.label && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "absolute -top-3.5 left-1 whitespace-nowrap tabular-nums", children: t.label }) }, t.time)),
466
+ cached.map((r) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "pointer-events-none absolute bottom-0 h-[3px] bg-emerald-500/70", style: { left: msToPx(r.start), width: Math.max(1, msToPx(r.end - r.start)) }, title: "Frames cached: plays and scrubs without waiting", "data-cached-range": "" }, r.start)),
432
467
  (project.markers ?? []).map((m) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
433
468
  "div",
434
469
  {
@@ -933,6 +968,7 @@ function MediaBin({ controller, editable = true, fileToUrl, probe = import_video
933
968
  project.assets.length ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("ul", { className: "flex flex-col gap-1", "aria-label": "Media assets", children: project.assets.map((asset) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("li", { className: "flex items-center gap-2 text-xs", "data-asset": asset.id, children: [
934
969
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "rounded bg-muted px-1 text-[10px] uppercase text-muted-foreground", "data-asset-kind": "", children: asset.kind }),
935
970
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "min-w-0 flex-1 truncate", title: asset.src, children: asset.name ?? asset.id }),
971
+ asset.proxies?.length ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "rounded bg-muted px-1 text-[10px] text-muted-foreground", title: `Proxies: ${asset.proxies.map((p) => `${p.scale * 100}%`).join(", ")} (the preview can play these; exports use the original)`, "data-asset-proxies": "", children: "proxy" }) : null,
936
972
  asset.duration !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "tabular-nums text-muted-foreground", children: (0, import_video_editor7.formatVideoSeconds)(asset.duration) }),
937
973
  editable && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: btn3, disabled: !canEdit, onClick: () => addToTimeline(asset), "data-add-to-timeline": "", children: "Add to timeline" })
938
974
  ] }, asset.id)) }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("p", { className: "text-xs text-muted-foreground", children: [