cursedbelt 5.112.0 → 5.113.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/react/activity-bar/ActivityBar.d.ts.map +1 -1
- package/dist/react/activity-bar/ActivityBar.js +8 -2
- package/dist/react/activity-bar/ActivityBar.js.map +1 -1
- package/dist/react/activity-bar/activityBar.css +4 -0
- package/dist/react/media/CutTimeline.d.ts +31 -0
- package/dist/react/media/CutTimeline.d.ts.map +1 -0
- package/dist/react/media/CutTimeline.js +197 -0
- package/dist/react/media/CutTimeline.js.map +1 -0
- package/dist/react/media/VideoCutEditor.d.ts +32 -6
- package/dist/react/media/VideoCutEditor.d.ts.map +1 -1
- package/dist/react/media/VideoCutEditor.js +97 -63
- package/dist/react/media/VideoCutEditor.js.map +1 -1
- package/dist/react/media/cutTimelineMath.d.ts +80 -0
- package/dist/react/media/cutTimelineMath.d.ts.map +1 -0
- package/dist/react/media/cutTimelineMath.js +116 -0
- package/dist/react/media/cutTimelineMath.js.map +1 -0
- package/dist/react/media/useFrameRate.d.ts +34 -0
- package/dist/react/media/useFrameRate.d.ts.map +1 -0
- package/dist/react/media/useFrameRate.js +66 -0
- package/dist/react/media/useFrameRate.js.map +1 -0
- package/dist/react/media/videoCutEditor.css +249 -63
- package/dist/react/media-gallery/MediaGallery.d.ts +10 -1
- package/dist/react/media-gallery/MediaGallery.d.ts.map +1 -1
- package/dist/react/media-gallery/MediaGallery.js +29 -7
- package/dist/react/media-gallery/MediaGallery.js.map +1 -1
- package/dist/react/media-gallery/galleryDeepLink.d.ts +14 -0
- package/dist/react/media-gallery/galleryDeepLink.d.ts.map +1 -1
- package/dist/react/media-gallery/galleryDeepLink.js +44 -5
- package/dist/react/media-gallery/galleryDeepLink.js.map +1 -1
- package/dist/react/media-gallery/index.d.ts +1 -1
- package/dist/react/media-gallery/index.d.ts.map +1 -1
- package/dist/react/media-gallery/index.js +1 -1
- package/dist/react/media-gallery/index.js.map +1 -1
- package/dist/react/media-gallery/types.d.ts +5 -0
- package/dist/react/media-gallery/types.d.ts.map +1 -1
- package/dist/testing/designAudit.d.ts +8 -1
- package/dist/testing/designAudit.d.ts.map +1 -1
- package/dist/testing/designAudit.js +21 -0
- package/dist/testing/designAudit.js.map +1 -1
- package/package.json +5 -3
- package/scripts/demoServer.ts +1 -1
- package/scripts/guardrails-baseline.json +1 -1
- package/src/demoFixture.spec.ts +17 -5
- package/src/demoRun.spec.ts +10 -1
- package/src/react/activity-bar/ActivityBar.spec.tsx +15 -0
- package/src/react/activity-bar/ActivityBar.tsx +8 -2
- package/src/react/activity-bar/activityBar.css +4 -0
- package/src/react/media/CutTimeline.tsx +379 -0
- package/src/react/media/VideoCutEditor.spec.tsx +1 -1
- package/src/react/media/VideoCutEditor.tsx +277 -214
- package/src/react/media/cutTimelineMath.spec.ts +90 -0
- package/src/react/media/cutTimelineMath.ts +140 -0
- package/src/react/media/useFrameRate.ts +96 -0
- package/src/react/media/videoCutEditor.css +249 -63
- package/src/react/media-gallery/MediaGallery.tsx +38 -7
- package/src/react/media-gallery/galleryDeepLink.spec.tsx +87 -2
- package/src/react/media-gallery/galleryDeepLink.ts +58 -5
- package/src/react/media-gallery/index.ts +1 -0
- package/src/react/media-gallery/types.ts +5 -0
- package/src/testing/designAudit.ts +22 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ActivityBar.d.ts","sourceRoot":"","sources":["../../../src/react/activity-bar/ActivityBar.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+EG;AACH,OAAO,EAEL,KAAK,GAAG,EAIR,KAAK,SAAS,EAKf,MAAM,OAAO,CAAC;AAGf,OAAO,mBAAmB,CAAC;AAG3B;;;;;;;GAOG;AACH,MAAM,WAAW,eAAe;IAC9B,wEAAwE;IACxE,EAAE,EAAE,MAAM,CAAC;IACX;;;;;;;;OAQG;IACH,KAAK,EAAE,MAAM,CAAC;IACd,2FAA2F;IAC3F,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,wFAAwF;IACxF,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,iFAAiF;IACjF,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAChD;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;;;;OAOG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,uFAAuF;IACvF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,kEAAkE;IAClE,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,iDAAiD;IACjD,GAAG,EAAE,SAAS,eAAe,EAAE,CAAC;IAChC,uFAAuF;IACvF,MAAM,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IACpC,kDAAkD;IAClD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,qFAAqF;IACrF,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;CAC5C;AAID,6FAA6F;AAC7F,eAAO,MAAM,cAAc,MAAM,CAAC;AAElC,oEAAoE;AACpE,eAAO,MAAM,eAAe,MAAM,CAAC;AACnC,qFAAqF;AACrF,eAAO,MAAM,eAAe,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"ActivityBar.d.ts","sourceRoot":"","sources":["../../../src/react/activity-bar/ActivityBar.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+EG;AACH,OAAO,EAEL,KAAK,GAAG,EAIR,KAAK,SAAS,EAKf,MAAM,OAAO,CAAC;AAGf,OAAO,mBAAmB,CAAC;AAG3B;;;;;;;GAOG;AACH,MAAM,WAAW,eAAe;IAC9B,wEAAwE;IACxE,EAAE,EAAE,MAAM,CAAC;IACX;;;;;;;;OAQG;IACH,KAAK,EAAE,MAAM,CAAC;IACd,2FAA2F;IAC3F,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,wFAAwF;IACxF,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,iFAAiF;IACjF,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAChD;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;;;;OAOG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,uFAAuF;IACvF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,kEAAkE;IAClE,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,iDAAiD;IACjD,GAAG,EAAE,SAAS,eAAe,EAAE,CAAC;IAChC,uFAAuF;IACvF,MAAM,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IACpC,kDAAkD;IAClD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,qFAAqF;IACrF,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;CAC5C;AAID,6FAA6F;AAC7F,eAAO,MAAM,cAAc,MAAM,CAAC;AAElC,oEAAoE;AACpE,eAAO,MAAM,eAAe,MAAM,CAAC;AACnC,qFAAqF;AACrF,eAAO,MAAM,eAAe,MAAM,CAAC;AA+NnC,wBAAgB,WAAW,CAAC,EAC1B,GAAG,EACH,MAAW,EACX,SAAgC,EAChC,SAAS,EACT,UAAiB,EACjB,MAAc,EACd,cAAc,EACd,GAAG,IAAI,EACR,EAAE,gBAAgB,GAAG,GAAG,CAAC,OAAO,CAoDhC"}
|
|
@@ -83,7 +83,7 @@ import { useCallback, useEffect, useRef, useState, } from 'react';
|
|
|
83
83
|
import { Tooltip } from '../components/Tooltip.js';
|
|
84
84
|
import { useMediaQuery } from '../hooks/useMediaQuery.js';
|
|
85
85
|
import './activityBar.css';
|
|
86
|
-
import { cn
|
|
86
|
+
import { cn } from '../lib/cn.js';
|
|
87
87
|
const noop = () => { };
|
|
88
88
|
/** The narrowest screen the lock works on — below it the rail stays an overlay (a phone). */
|
|
89
89
|
export const LOCK_MIN_WIDTH = 768;
|
|
@@ -100,7 +100,13 @@ function ActivityButton({ item, onChosen, className, }) {
|
|
|
100
100
|
// module's self-contained plain CSS. cursedbelt's `Button` runs on the Tailwind token
|
|
101
101
|
// layer, which fights `.cbab-btn`'s fixed 48px column geometry on cascade order rather
|
|
102
102
|
// than composing with it — the same split `GalleryActionButton` records.
|
|
103
|
-
|
|
103
|
+
//
|
|
104
|
+
// 🔴 No RAW_BUTTON either: `.cbab-btn` states every reset it needs. desk scopes the belt's
|
|
105
|
+
// utilities as `.cs-root .p-0` — two classes, unlayered — so RAW_BUTTON's `p-0`,
|
|
106
|
+
// `bg-transparent` and `text-inherit` beat this one-class stylesheet there: the 10px inset
|
|
107
|
+
// went, every glyph sat 10px left of the rail's middle, and the muted color and hover fill
|
|
108
|
+
// went with it (forge task 4355). `font-[inherit]` is the one utility it keeps.
|
|
109
|
+
type: 'button', className: cn('font-[inherit]', 'cbab-btn', className), "data-active": item.active || undefined, onClick: disabled
|
|
104
110
|
? undefined
|
|
105
111
|
: (event) => {
|
|
106
112
|
item.onSelect?.(event.currentTarget);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ActivityBar.js","sourceRoot":"","sources":["../../../src/react/activity-bar/ActivityBar.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+EG;AACH,OAAO,EAOL,WAAW,EACX,SAAS,EACT,MAAM,EACN,QAAQ,GACT,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,mBAAmB,CAAC;AAC3B,OAAO,EAAE,EAAE,EAAE,
|
|
1
|
+
{"version":3,"file":"ActivityBar.js","sourceRoot":"","sources":["../../../src/react/activity-bar/ActivityBar.tsx"],"names":[],"mappings":"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"}
|
|
@@ -111,6 +111,10 @@
|
|
|
111
111
|
inline-size: 40px;
|
|
112
112
|
block-size: 40px;
|
|
113
113
|
padding-block: 0;
|
|
114
|
+
/* The button resets are stated here, not borrowed from RAW_BUTTON's utilities, which outrank
|
|
115
|
+
this rule in a host that scopes them (see the component, forge task 4355). */
|
|
116
|
+
margin: 0;
|
|
117
|
+
font: inherit;
|
|
114
118
|
border: 0;
|
|
115
119
|
white-space: nowrap;
|
|
116
120
|
border-radius: var(--radius-sm, 0.375rem);
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type PlanSegment, type VideoCut } from 'cursedbelt-core/media/video-cuts';
|
|
3
|
+
/**
|
|
4
|
+
* The Trim page's timeline: a ruler, the clip's pieces, and a playhead, at any zoom from the
|
|
5
|
+
* whole clip down to one frame per 12 px (forge task 4311).
|
|
6
|
+
*
|
|
7
|
+
* The gestures are a map's and an NLE's, so nothing here has to be learned:
|
|
8
|
+
* · ⌘/Ctrl + wheel, or a trackpad pinch (which Chromium and Safari deliver as a ctrl-wheel),
|
|
9
|
+
* zooms around the POINTER; two fingers on a touch screen pinch the same way.
|
|
10
|
+
* · a plain wheel, or a drag anywhere on the track, pans.
|
|
11
|
+
* · a click on the ruler moves the playhead there, onto the frame under the pointer.
|
|
12
|
+
* · a click on a piece is the ✗ it always was — a drag that started on one never toggles it.
|
|
13
|
+
* The slider, ± and Fit do the same with no gesture at all (CNV-1: the wheel alone never zooms;
|
|
14
|
+
* CNV-3: a fit control on every canvas).
|
|
15
|
+
*
|
|
16
|
+
* 🔴 Drawn VIRTUALLY: only what is on screen is in the DOM, each piece clipped to the view. At
|
|
17
|
+
* 12 px a frame a two-hour 60 fps film is ten million pixels wide, which no browser will lay out
|
|
18
|
+
* as one element — so the track is always exactly the view, and the view is two numbers.
|
|
19
|
+
*/
|
|
20
|
+
export interface CutTimelineProps {
|
|
21
|
+
duration: number;
|
|
22
|
+
fps: number;
|
|
23
|
+
playhead: number;
|
|
24
|
+
segments: readonly PlanSegment[];
|
|
25
|
+
onSeek: (seconds: number) => void;
|
|
26
|
+
onToggle: (segment: VideoCut) => void;
|
|
27
|
+
/** The transport, drawn at the start of the timeline's one-line toolbar (FRM-14). */
|
|
28
|
+
transport?: React.ReactNode;
|
|
29
|
+
}
|
|
30
|
+
export declare function CutTimeline({ duration, fps, playhead, segments, onSeek, onToggle, transport, ...passThrough }: CutTimelineProps): React.JSX.Element;
|
|
31
|
+
//# sourceMappingURL=CutTimeline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CutTimeline.d.ts","sourceRoot":"","sources":["../../../src/react/media/CutTimeline.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAe,KAAK,WAAW,EAAE,KAAK,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAmBhG;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,SAAS,WAAW,EAAE,CAAC;IACjC,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,QAAQ,EAAE,CAAC,OAAO,EAAE,QAAQ,KAAK,IAAI,CAAC;IACtC,qFAAqF;IACrF,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC7B;AAeD,wBAAgB,WAAW,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,WAAW,EAAE,EAAE,gBAAgB,qBA4T/H"}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { Maximize2, X, ZoomIn, ZoomOut } from 'lucide-react';
|
|
4
|
+
import { cutTimecode } from 'cursedbelt-core/media/video-cuts';
|
|
5
|
+
import { IconButton } from '../components/IconButton.js';
|
|
6
|
+
import { Button } from '../components/Button.js';
|
|
7
|
+
import { Slider } from '../components/Slider.js';
|
|
8
|
+
import { Tooltip } from '../components/Tooltip.js';
|
|
9
|
+
import { cn, RAW_BUTTON } from '../lib/cn.js';
|
|
10
|
+
import { clampViewStart, frameAt, frameStart, rulerLabel, rulerStep, sliderToZoom, snapToFrame, zoomAround, zoomBounds, zoomToSlider, } from './cutTimelineMath.js';
|
|
11
|
+
/** A drag shorter than this is a click — the slop every pointer library uses. */
|
|
12
|
+
const DRAG_SLOP_PX = 4;
|
|
13
|
+
/** The width drawn at before the track is measured. */
|
|
14
|
+
const NOMINAL_WIDTH_PX = 1000;
|
|
15
|
+
/** Frame ticks are drawn once frames are at least this far apart. */
|
|
16
|
+
const FRAME_TICK_MIN_PX = 6;
|
|
17
|
+
export function CutTimeline({ duration, fps, playhead, segments, onSeek, onToggle, transport, ...passThrough }) {
|
|
18
|
+
const trackRef = React.useRef(null);
|
|
19
|
+
const [measured, setWidth] = React.useState(0);
|
|
20
|
+
// Until the track has been measured (and in a DOM with no layout at all), draw at a nominal
|
|
21
|
+
// width rather than at zero — zero would put every piece off screen, and the first real
|
|
22
|
+
// measurement lands in a layout effect, before anything paints.
|
|
23
|
+
const width = measured > 0 ? measured : NOMINAL_WIDTH_PX;
|
|
24
|
+
const [view, setView] = React.useState({ start: 0, pps: null });
|
|
25
|
+
React.useLayoutEffect(() => {
|
|
26
|
+
const track = trackRef.current;
|
|
27
|
+
if (!track)
|
|
28
|
+
return;
|
|
29
|
+
const measure = () => setWidth(track.clientWidth);
|
|
30
|
+
measure();
|
|
31
|
+
const observer = new ResizeObserver(measure);
|
|
32
|
+
observer.observe(track);
|
|
33
|
+
return () => observer.disconnect();
|
|
34
|
+
}, []);
|
|
35
|
+
const bounds = zoomBounds(width, duration, fps);
|
|
36
|
+
const pps = Math.min(bounds.max, Math.max(bounds.fit, view.pps ?? bounds.fit));
|
|
37
|
+
const start = clampViewStart(view.start, pps, width, duration);
|
|
38
|
+
const span = pps > 0 ? width / pps : 0;
|
|
39
|
+
const canZoom = bounds.max > bounds.fit && bounds.fit > 0;
|
|
40
|
+
// The handlers below are bound once (the wheel has to be non-passive, so it is a native
|
|
41
|
+
// listener) and read the current numbers from here.
|
|
42
|
+
const now = React.useRef({ pps, start, width, duration, bounds });
|
|
43
|
+
now.current = { pps, start, width, duration, bounds };
|
|
44
|
+
const zoomTo = React.useCallback((next, anchorX) => {
|
|
45
|
+
const n = now.current;
|
|
46
|
+
setView(zoomAround({ start: n.start, pps: n.pps }, next, anchorX, n.width, n.duration, n.bounds));
|
|
47
|
+
}, []);
|
|
48
|
+
/** Zoom by a factor around the playhead when it is on screen, else around the middle. */
|
|
49
|
+
const zoomBy = (factor) => {
|
|
50
|
+
const x = playhead >= start && playhead <= start + span ? (playhead - start) * pps : width / 2;
|
|
51
|
+
zoomTo(pps * factor, x);
|
|
52
|
+
};
|
|
53
|
+
React.useEffect(() => {
|
|
54
|
+
const track = trackRef.current;
|
|
55
|
+
if (!track)
|
|
56
|
+
return;
|
|
57
|
+
const onWheel = (event) => {
|
|
58
|
+
event.preventDefault();
|
|
59
|
+
const n = now.current;
|
|
60
|
+
const lines = event.deltaMode === 1 ? 16 : event.deltaMode === 2 ? n.width : 1;
|
|
61
|
+
if (event.ctrlKey || event.metaKey) {
|
|
62
|
+
const x = event.clientX - track.getBoundingClientRect().left;
|
|
63
|
+
zoomTo(n.pps * Math.exp(-event.deltaY * lines * 0.01), x);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
// A vertical wheel pans too: most mice have no other, and the page has nothing to scroll here.
|
|
67
|
+
const dx = Math.abs(event.deltaX) > Math.abs(event.deltaY) ? event.deltaX : event.deltaY;
|
|
68
|
+
setView({ pps: n.pps, start: clampViewStart(n.start + (dx * lines) / n.pps, n.pps, n.width, n.duration) });
|
|
69
|
+
};
|
|
70
|
+
track.addEventListener('wheel', onWheel, { passive: false });
|
|
71
|
+
return () => track.removeEventListener('wheel', onWheel);
|
|
72
|
+
}, [zoomTo]);
|
|
73
|
+
// Keep the playhead in view while it moves (playing, stepping, a seek from the cuts list) —
|
|
74
|
+
// a page-turn, as Resolve does, rather than a scroll that never lets the eye settle.
|
|
75
|
+
React.useEffect(() => {
|
|
76
|
+
const n = now.current;
|
|
77
|
+
if (n.width <= 0 || n.pps <= n.bounds.fit + 1e-9)
|
|
78
|
+
return;
|
|
79
|
+
const viewSpan = n.width / n.pps;
|
|
80
|
+
if (playhead < n.start || playhead > n.start + viewSpan) {
|
|
81
|
+
setView({ pps: n.pps, start: clampViewStart(playhead - viewSpan * 0.1, n.pps, n.width, n.duration) });
|
|
82
|
+
}
|
|
83
|
+
}, [playhead]);
|
|
84
|
+
/*
|
|
85
|
+
* Pointers. One pointer that moves past the slop pans; two pinch. One that does not move is a
|
|
86
|
+
* click: on the ruler it seeks, on a piece the piece's own button does its job.
|
|
87
|
+
*/
|
|
88
|
+
const gesture = React.useRef({ pointers: new Map(), fromX: 0, fromStart: 0, dragged: false, pinch: null });
|
|
89
|
+
const onPointerDown = (event) => {
|
|
90
|
+
if (event.pointerType === 'mouse' && event.button !== 0)
|
|
91
|
+
return;
|
|
92
|
+
const g = gesture.current;
|
|
93
|
+
g.pointers.set(event.pointerId, event.clientX);
|
|
94
|
+
if (g.pointers.size === 1) {
|
|
95
|
+
g.fromX = event.clientX;
|
|
96
|
+
g.fromStart = start;
|
|
97
|
+
g.dragged = false;
|
|
98
|
+
g.pinch = null;
|
|
99
|
+
}
|
|
100
|
+
else if (g.pointers.size === 2) {
|
|
101
|
+
const [a, b] = [...g.pointers.values()];
|
|
102
|
+
g.pinch = { distance: Math.max(1, Math.abs(a - b)), pps };
|
|
103
|
+
g.dragged = true;
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
const onPointerMove = (event) => {
|
|
107
|
+
const g = gesture.current;
|
|
108
|
+
if (!g.pointers.has(event.pointerId))
|
|
109
|
+
return;
|
|
110
|
+
g.pointers.set(event.pointerId, event.clientX);
|
|
111
|
+
const left = event.currentTarget.getBoundingClientRect().left;
|
|
112
|
+
if (g.pinch && g.pointers.size >= 2) {
|
|
113
|
+
const [a, b] = [...g.pointers.values()];
|
|
114
|
+
zoomTo(g.pinch.pps * (Math.max(1, Math.abs(a - b)) / g.pinch.distance), (a + b) / 2 - left);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
const dx = event.clientX - g.fromX;
|
|
118
|
+
if (!g.dragged && Math.abs(dx) < DRAG_SLOP_PX)
|
|
119
|
+
return;
|
|
120
|
+
if (!g.dragged) {
|
|
121
|
+
g.dragged = true;
|
|
122
|
+
// Captured only once it is a drag: capturing on press would retarget the click of a
|
|
123
|
+
// piece's button to the track, and the ✗ would stop working.
|
|
124
|
+
event.currentTarget.setPointerCapture(event.pointerId);
|
|
125
|
+
}
|
|
126
|
+
const n = now.current;
|
|
127
|
+
setView({ pps: n.pps, start: clampViewStart(g.fromStart - dx / n.pps, n.pps, n.width, n.duration) });
|
|
128
|
+
};
|
|
129
|
+
const onPointerUp = (event) => {
|
|
130
|
+
const g = gesture.current;
|
|
131
|
+
if (!g.pointers.delete(event.pointerId))
|
|
132
|
+
return;
|
|
133
|
+
if (g.pointers.size > 0)
|
|
134
|
+
return;
|
|
135
|
+
g.pinch = null;
|
|
136
|
+
if (g.dragged || event.target.closest('.cbvc-seg'))
|
|
137
|
+
return;
|
|
138
|
+
const n = now.current;
|
|
139
|
+
const x = event.clientX - event.currentTarget.getBoundingClientRect().left;
|
|
140
|
+
onSeek(Math.min(n.duration, snapToFrame(n.start + x / n.pps, fps)));
|
|
141
|
+
};
|
|
142
|
+
// A drag that ended over a piece must not also toggle it.
|
|
143
|
+
const onClickCapture = (event) => {
|
|
144
|
+
if (gesture.current.dragged) {
|
|
145
|
+
event.preventDefault();
|
|
146
|
+
event.stopPropagation();
|
|
147
|
+
gesture.current.dragged = false;
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
const x = (seconds) => (seconds - start) * pps;
|
|
151
|
+
const end = start + span;
|
|
152
|
+
// The ruler: a labeled tick per step, and a tick per FRAME once frames are far enough apart.
|
|
153
|
+
const step = rulerStep(pps, fps);
|
|
154
|
+
const labels = [];
|
|
155
|
+
if (pps > 0 && duration > 0) {
|
|
156
|
+
// Counted in frames when the step is, so 0.1 s × 3 lands on frame 3 and not on 0.30000000000000004.
|
|
157
|
+
const stepFrames = Math.round(step.label * fps);
|
|
158
|
+
for (let k = Math.floor(start / step.label); k * step.label <= end + 1e-9; k += 1) {
|
|
159
|
+
const t = step.frames ? frameStart(k * stepFrames, fps) : k * step.label;
|
|
160
|
+
if (t >= start - 1e-9 && t <= duration + 1e-9)
|
|
161
|
+
labels.push(t);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
const frameTicks = [];
|
|
165
|
+
if (pps / fps >= FRAME_TICK_MIN_PX) {
|
|
166
|
+
for (let k = frameAt(start, fps); frameStart(k, fps) <= Math.min(end, duration) + 1e-9; k += 1)
|
|
167
|
+
frameTicks.push(k);
|
|
168
|
+
}
|
|
169
|
+
return (_jsxs("div", { ...passThrough, className: 'cbvc-timeline', children: [_jsxs("div", { className: 'cbvc-tools', children: [transport, _jsxs("div", { className: 'cbvc-zoom', children: [_jsx(IconButton, { size: 'sm', label: 'Zoom out', tooltip: 'Zoom out (\u2318 or Ctrl + wheel, or pinch)', disabled: !canZoom || pps <= bounds.fit + 1e-9, onClick: () => zoomBy(0.5), children: _jsx(ZoomOut, { "aria-hidden": 'true' }) }), _jsx(Slider, { className: 'cbvc-zoom-slider', "aria-label": 'Zoom', "aria-valuetext": `${(pps / fps).toFixed(pps / fps < 1 ? 2 : 1)} px per frame`, min: 0, max: 1000, step: 1, disabled: !canZoom, value: Math.round(zoomToSlider(pps, bounds) * 1000), onChange: (value) => {
|
|
170
|
+
const next = sliderToZoom(value / 1000, bounds);
|
|
171
|
+
const x0 = playhead >= start && playhead <= end ? (playhead - start) * pps : width / 2;
|
|
172
|
+
zoomTo(next, x0);
|
|
173
|
+
} }), _jsx(IconButton, { size: 'sm', label: 'Zoom in', tooltip: 'Zoom in \u2014 down to single frames', disabled: !canZoom || pps >= bounds.max - 1e-9, onClick: () => zoomBy(2), children: _jsx(ZoomIn, { "aria-hidden": 'true' }) }), _jsxs(Button, { size: 'sm', variant: 'ghost', tooltip: 'Fit the whole clip in the timeline', disabled: view.pps === null || pps <= bounds.fit + 1e-9, onClick: () => setView({ start: 0, pps: null }), children: [_jsx(Maximize2, { "aria-hidden": 'true', size: 14 }), " Fit"] })] })] }), _jsxs("div", { ref: trackRef, className: 'cbvc-track', "data-px-per-second": pps, "data-view-start": start, onPointerDown: onPointerDown, onPointerMove: onPointerMove, onPointerUp: onPointerUp, onPointerCancel: onPointerUp, onClickCapture: onClickCapture, children: [_jsxs("div", { className: 'cbvc-ruler', "aria-hidden": 'true', children: [frameTicks.map((k) => (_jsx("span", { className: 'cbvc-frame-tick', "data-frame": k, style: { left: `${x(frameStart(k, fps))}px` } }, `f${k}`))), labels.map((t) => (_jsx("span", { className: 'cbvc-tick', style: { left: `${x(t)}px` }, children: _jsx("span", { className: 'cbvc-tick-label', children: rulerLabel(t, fps, step.frames, duration) }) }, `l${t}`)))] }), _jsx("ul", { className: 'cbvc-strip', "aria-label": segments.length <= 1
|
|
174
|
+
? 'The whole clip, uncut'
|
|
175
|
+
: `${segments.length} sections; ${segments.filter((segment) => segment.removed).length} marked for removal`, children: segments
|
|
176
|
+
.filter((segment) => segment.end > start && segment.start < end)
|
|
177
|
+
.map((segment) => {
|
|
178
|
+
// Clipped to the view (a pixel past each edge, so no border shows at the cut-off).
|
|
179
|
+
const left = Math.max(-1, x(segment.start));
|
|
180
|
+
const right = Math.min(width + 1, x(segment.end));
|
|
181
|
+
const words = segment.removed
|
|
182
|
+
? `Keep ${cutTimecode(segment.start)} to ${cutTimecode(segment.end)} after all`
|
|
183
|
+
: `Remove ${cutTimecode(segment.start)} to ${cutTimecode(segment.end)}`;
|
|
184
|
+
return (_jsx("li", { className: 'cbvc-seg-item', style: { left: `${left}px`, width: `${Math.max(0, right - left)}px` }, children: _jsx(Tooltip, { content: words, children: _jsxs("button", {
|
|
185
|
+
// guardrails-ignore no-raw-action-button: a segment of the timeline, sized to
|
|
186
|
+
// its own duration — a `Button` carries padding and a min-width, which is
|
|
187
|
+
// exactly wrong for a control whose WIDTH is the information.
|
|
188
|
+
type: 'button', className: cn(RAW_BUTTON, `cbvc-seg${segment.removed ? ' is-removed' : ''}`), "aria-pressed": segment.removed, "aria-label": words, "data-start": segment.start, "data-end": segment.end, onClick: () => onToggle(segment), children: [_jsx(X, { className: 'cbvc-seg-x', "aria-hidden": 'true', size: 12 }), _jsx("span", { className: 'cbvc-seg-label', children: segment.removed ? 'Removed' : cutTimecode(segment.end - segment.start) })] }) }) }, segment.key));
|
|
189
|
+
}) }), playhead >= start - 1e-9 && playhead <= end + 1e-9 ? (_jsx("span", { className: 'cbvc-strip-head', style: { left: `${x(playhead)}px` } })) : null] }), pps > bounds.fit + 1e-9 ? (_jsxs("div", { className: 'cbvc-overview', "aria-hidden": 'true', onClick: (event) => {
|
|
190
|
+
const rect = event.currentTarget.getBoundingClientRect();
|
|
191
|
+
const t = ((event.clientX - rect.left) / rect.width) * duration;
|
|
192
|
+
setView({ pps, start: clampViewStart(t - span / 2, pps, width, duration) });
|
|
193
|
+
}, children: [segments
|
|
194
|
+
.filter((segment) => segment.removed)
|
|
195
|
+
.map((segment) => (_jsx("span", { className: 'cbvc-overview-cut', style: { left: `${(segment.start / duration) * 100}%`, width: `${((segment.end - segment.start) / duration) * 100}%` } }, segment.key))), _jsx("span", { className: 'cbvc-overview-window', style: { left: `${(start / duration) * 100}%`, width: `${Math.max(0.5, (span / duration) * 100)}%` } }), _jsx("span", { className: 'cbvc-overview-head', style: { left: `${(playhead / duration) * 100}%` } })] })) : null] }));
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=CutTimeline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CutTimeline.js","sourceRoot":"","sources":["../../../src/react/media/CutTimeline.tsx"],"names":[],"mappings":"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"}
|
|
@@ -12,7 +12,7 @@ import { type VideoCut } from 'cursedbelt-core/media/video-cuts';
|
|
|
12
12
|
* it uses ... It can then remove the parts of the video I don't want, save a new copy and I
|
|
13
13
|
* can view it when it's done."*
|
|
14
14
|
*
|
|
15
|
-
* So this
|
|
15
|
+
* So this page never touches a byte. It produces a `VideoCut[]`, hands it to `onSubmit`,
|
|
16
16
|
* and closes. Everything about what makes a list valid is `videoCuts.ts`, shared with the
|
|
17
17
|
* server that executes it, so the dialog and the encoder cannot disagree about what was
|
|
18
18
|
* asked for.
|
|
@@ -51,7 +51,28 @@ import { type VideoCut } from 'cursedbelt-core/media/video-cuts';
|
|
|
51
51
|
* ONE `InfoHint` — the fleet's standard ⓘ, which costs a 16px glyph at rest and opens on
|
|
52
52
|
* hover, focus or tap. That is the answer to *"tooltips or an info icon or something we
|
|
53
53
|
* standardize can make it clear without taking up space when out of use"*: the explanation
|
|
54
|
-
* exists, in one predictable place, and pays no permanent rent
|
|
54
|
+
* exists, in one predictable place, and pays no permanent rent on the page.
|
|
55
|
+
*
|
|
56
|
+
* ── A PAGE, with a zoomable timeline, down to the frame (owner, 2026-11-03) ───────────
|
|
57
|
+
* *"a full Trim page with a zoomable timeline, down to frame-by-frame selection."* It was a
|
|
58
|
+
* `size='lg'` modal with one fixed strip, so on a two-hour film a pixel was several seconds
|
|
59
|
+
* and the frame he wanted could not be marked at all. Now it is the shape of an NLE's trim
|
|
60
|
+
* view (YouTube Studio's editor, Resolve's cut page): the picture on top, the transport and a
|
|
61
|
+
* full-width timeline under it, the actions bottom-right.
|
|
62
|
+
* · It COVERS the viewport and has an address of its own when the app gives it one
|
|
63
|
+
* (`MediaGallery`'s `trimming`, `useGalleryDeepLink({ trim: true })`), so Back closes it
|
|
64
|
+
* and a reload keeps it. Underneath it is still the belt's dialog primitive — that is what
|
|
65
|
+
* traps focus, takes Escape and makes the gallery's own keys stand down (`openDialogs`).
|
|
66
|
+
* · The timeline zooms from the whole clip to one frame per 12 px (`CutTimeline`).
|
|
67
|
+
* · `,` and `.` step one frame, every split lands on a frame boundary, and the readout is
|
|
68
|
+
* `hh:mm:ss:ff`. The rate is the catalog's probe, else measured from the clip
|
|
69
|
+
* (`useFrameRate`), and an assumed rate is labeled as one.
|
|
70
|
+
*
|
|
71
|
+
* 🔴 Frame-accurate is a promise only because binary-server KEEPS it: its trim decodes and
|
|
72
|
+
* re-encodes every kept span (`trim=start:end` + `concat` into libx264 — `cutArgs`,
|
|
73
|
+
* `apps/binary-server/src/media/processing/ffmpegJobs.ts`), so a cut lands on the frame it
|
|
74
|
+
* names, not on the keyframe before it. The note under the timeline says so; a stream-copy
|
|
75
|
+
* trim would make that sentence false, and it must change with it.
|
|
55
76
|
*/
|
|
56
77
|
export interface VideoCutEditorProps {
|
|
57
78
|
/**
|
|
@@ -78,21 +99,26 @@ export interface VideoCutEditorProps {
|
|
|
78
99
|
/**
|
|
79
100
|
* The clip's length, when the app already knows it. The element's own metadata still wins
|
|
80
101
|
* once it loads: a duration the catalog rounded to the second would put every mark a
|
|
81
|
-
* fraction out, and the marks are the entire output of this
|
|
102
|
+
* fraction out, and the marks are the entire output of this page.
|
|
82
103
|
*/
|
|
83
104
|
durationSeconds?: number | null;
|
|
105
|
+
/**
|
|
106
|
+
* Frames per second from the catalog's probe, when it has one. Without it the page measures
|
|
107
|
+
* the clip itself (`useFrameRate`) and, until it can, says the rate it draws with is assumed.
|
|
108
|
+
*/
|
|
109
|
+
frameRate?: number | null;
|
|
84
110
|
open?: boolean;
|
|
85
111
|
onClose: () => void;
|
|
86
112
|
/**
|
|
87
|
-
* Send the marks. Resolving CLOSES the
|
|
113
|
+
* Send the marks. Resolving CLOSES the page; rejecting leaves it open with the marks
|
|
88
114
|
* intact, because the alternative is losing several minutes of careful scrubbing to one
|
|
89
115
|
* failed request.
|
|
90
116
|
*/
|
|
91
117
|
onSubmit: (cuts: VideoCut[]) => void | Promise<void>;
|
|
92
118
|
/** Wording for the confirm button — apps queue this differently. */
|
|
93
119
|
submitLabel?: string;
|
|
94
|
-
/** Shown under the
|
|
120
|
+
/** Shown under the timeline: what happens after Send, in the app's own words. */
|
|
95
121
|
note?: React.ReactNode;
|
|
96
122
|
}
|
|
97
|
-
export declare function VideoCutEditor({ src, hlsUrl, posterUrl, resolving, name, durationSeconds, open, onClose, onSubmit, submitLabel, note, ...passThrough }: VideoCutEditorProps): React.JSX.Element;
|
|
123
|
+
export declare function VideoCutEditor({ src, hlsUrl, posterUrl, resolving, name, durationSeconds, frameRate, open, onClose, onSubmit, submitLabel, note, ...passThrough }: VideoCutEditorProps): React.JSX.Element;
|
|
98
124
|
//# sourceMappingURL=VideoCutEditor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VideoCutEditor.d.ts","sourceRoot":"","sources":["../../../src/react/media/VideoCutEditor.tsx"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAC9B,OAAO,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"VideoCutEditor.d.ts","sourceRoot":"","sources":["../../../src/react/media/VideoCutEditor.tsx"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAC9B,OAAO,KAAK,MAAM,OAAO,CAAC;AAU1B,OAAO,EAYL,KAAK,QAAQ,EACd,MAAM,kCAAkC,CAAC;AAO1C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwEG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;;;;;;OAQG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ,4FAA4F;IAC5F,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,kFAAkF;IAClF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB;;;;OAIG;IACH,QAAQ,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,oEAAoE;IACpE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iFAAiF;IACjF,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CACxB;AAED,wBAAgB,cAAc,CAAC,EAC7B,GAAG,EACH,MAAM,EACN,SAAS,EACT,SAAiB,EACjB,IAAI,EACJ,eAAe,EACf,SAAS,EACT,IAAW,EACX,OAAO,EACP,QAAQ,EACR,WAAmC,EACnC,IAAI,EACJ,GAAG,WAAW,EACf,EAAE,mBAAmB,qBAmXrB"}
|