cursedbelt 3.0.2 → 4.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.
- package/dist/react/components/ListToolbar.d.ts +94 -0
- package/dist/react/components/ListToolbar.d.ts.map +1 -0
- package/dist/react/components/ListToolbar.js +66 -0
- package/dist/react/components/ListToolbar.js.map +1 -0
- package/dist/react/file-tree/FileTree.d.ts +282 -3
- package/dist/react/file-tree/FileTree.d.ts.map +1 -1
- package/dist/react/file-tree/FileTree.js +799 -131
- package/dist/react/file-tree/FileTree.js.map +1 -1
- package/dist/react/file-tree/fileTree.css +151 -0
- package/dist/react/file-tree/fileTreeSelection.d.ts +187 -0
- package/dist/react/file-tree/fileTreeSelection.d.ts.map +1 -0
- package/dist/react/file-tree/fileTreeSelection.js +264 -0
- package/dist/react/file-tree/fileTreeSelection.js.map +1 -0
- package/dist/react/file-tree/index.d.ts +1 -0
- package/dist/react/file-tree/index.d.ts.map +1 -1
- package/dist/react/file-tree/index.js +8 -0
- package/dist/react/file-tree/index.js.map +1 -1
- package/dist/react/index.d.ts +1 -0
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +1 -0
- package/dist/react/index.js.map +1 -1
- package/dist/react/lib/form.d.ts +3 -0
- package/dist/react/lib/form.d.ts.map +1 -1
- package/dist/react/lib/form.js +43 -5
- package/dist/react/lib/form.js.map +1 -1
- package/dist/react/media/DenseGalleryShell.d.ts +19 -3
- package/dist/react/media/DenseGalleryShell.d.ts.map +1 -1
- package/dist/react/media/DenseGalleryShell.js +55 -15
- package/dist/react/media/DenseGalleryShell.js.map +1 -1
- package/dist/react/media/FocusViewer.d.ts.map +1 -1
- package/dist/react/media/FocusViewer.js +14 -14
- package/dist/react/media/FocusViewer.js.map +1 -1
- package/dist/react/media/FrameGrabber.d.ts +23 -0
- package/dist/react/media/FrameGrabber.d.ts.map +1 -1
- package/dist/react/media/FrameGrabber.js +67 -1
- package/dist/react/media/FrameGrabber.js.map +1 -1
- package/dist/react/media/MediaResize.d.ts +51 -19
- package/dist/react/media/MediaResize.d.ts.map +1 -1
- package/dist/react/media/MediaResize.js +20 -13
- package/dist/react/media/MediaResize.js.map +1 -1
- package/dist/react/media/VideoChapterEditor.d.ts +67 -0
- package/dist/react/media/VideoChapterEditor.d.ts.map +1 -0
- package/dist/react/media/VideoChapterEditor.js +148 -0
- package/dist/react/media/VideoChapterEditor.js.map +1 -0
- package/dist/react/media/VideoPlayer.d.ts +46 -4
- package/dist/react/media/VideoPlayer.d.ts.map +1 -1
- package/dist/react/media/VideoPlayer.js +124 -11
- package/dist/react/media/VideoPlayer.js.map +1 -1
- package/dist/react/media/VideoTurner.d.ts +15 -2
- package/dist/react/media/VideoTurner.d.ts.map +1 -1
- package/dist/react/media/VideoTurner.js +29 -2
- package/dist/react/media/VideoTurner.js.map +1 -1
- package/dist/react/media/denseGallery.css +104 -46
- package/dist/react/media/hlsSource.d.ts +57 -0
- package/dist/react/media/hlsSource.d.ts.map +1 -1
- package/dist/react/media/hlsSource.js +177 -1
- package/dist/react/media/hlsSource.js.map +1 -1
- package/dist/react/media/index.d.ts +2 -0
- package/dist/react/media/index.d.ts.map +1 -1
- package/dist/react/media/index.js +6 -0
- package/dist/react/media/index.js.map +1 -1
- package/dist/react/media/mediaResize.css +127 -54
- package/dist/react/media/pictureEditor.css +52 -6
- package/dist/react/media/videoChapterEditor.css +203 -0
- package/dist/react/media/videoChapters.d.ts +117 -0
- package/dist/react/media/videoChapters.d.ts.map +1 -0
- package/dist/react/media/videoChapters.js +95 -0
- package/dist/react/media/videoChapters.js.map +1 -0
- package/dist/react/media-gallery/GalleryTable.d.ts +52 -1
- package/dist/react/media-gallery/GalleryTable.d.ts.map +1 -1
- package/dist/react/media-gallery/GalleryTable.js +40 -9
- package/dist/react/media-gallery/GalleryTable.js.map +1 -1
- package/dist/react/media-gallery/MediaGallery.d.ts +107 -4
- package/dist/react/media-gallery/MediaGallery.d.ts.map +1 -1
- package/dist/react/media-gallery/MediaGallery.js +484 -104
- package/dist/react/media-gallery/MediaGallery.js.map +1 -1
- package/dist/react/media-gallery/MediaMetaEditor.d.ts +48 -0
- package/dist/react/media-gallery/MediaMetaEditor.d.ts.map +1 -0
- package/dist/react/media-gallery/MediaMetaEditor.js +66 -0
- package/dist/react/media-gallery/MediaMetaEditor.js.map +1 -0
- package/dist/react/media-gallery/index.d.ts +2 -0
- package/dist/react/media-gallery/index.d.ts.map +1 -1
- package/dist/react/media-gallery/index.js +5 -0
- package/dist/react/media-gallery/index.js.map +1 -1
- package/dist/react/media-gallery/mediaGallery.css +180 -4
- package/dist/react/media-gallery/mediaMeta.d.ts +62 -0
- package/dist/react/media-gallery/mediaMeta.d.ts.map +1 -0
- package/dist/react/media-gallery/mediaMeta.js +56 -0
- package/dist/react/media-gallery/mediaMeta.js.map +1 -0
- package/dist/react/media-gallery/playbackPreferences.d.ts +77 -0
- package/dist/react/media-gallery/playbackPreferences.d.ts.map +1 -1
- package/dist/react/media-gallery/playbackPreferences.js +42 -0
- package/dist/react/media-gallery/playbackPreferences.js.map +1 -1
- package/dist/react/media-gallery/types.d.ts +34 -0
- package/dist/react/media-gallery/types.d.ts.map +1 -1
- package/dist/scripts/guardrailsEnforce.d.ts +29 -0
- package/dist/scripts/guardrailsEnforce.d.ts.map +1 -0
- package/dist/styles-areas/activity-bar.css +30 -0
- package/dist/styles-areas/analytics.css +672 -0
- package/dist/styles-areas/auth.css +154 -0
- package/dist/styles-areas/calendar.css +416 -0
- package/dist/styles-areas/chart-table.css +41 -0
- package/dist/styles-areas/charts.css +89 -0
- package/dist/styles-areas/chat.css +364 -0
- package/dist/styles-areas/clipboard.css +26 -0
- package/dist/styles-areas/code-editor.css +130 -0
- package/dist/styles-areas/companion-link.css +70 -0
- package/dist/styles-areas/core.css +2503 -0
- package/dist/styles-areas/dashboard-grid.css +84 -0
- package/dist/styles-areas/data-table.css +657 -0
- package/dist/styles-areas/deep-link.css +26 -0
- package/dist/styles-areas/diff-viewer.css +30 -0
- package/dist/styles-areas/disk-usage.css +262 -0
- package/dist/styles-areas/emoji.css +154 -0
- package/dist/styles-areas/fields.css +582 -0
- package/dist/styles-areas/file-tree.css +33 -0
- package/dist/styles-areas/filter-rail.css +235 -0
- package/dist/styles-areas/folder-tree.css +219 -0
- package/dist/styles-areas/keep-awake.css +26 -0
- package/dist/styles-areas/layout-engine.css +239 -0
- package/dist/styles-areas/markdown.css +87 -0
- package/dist/styles-areas/master-detail.css +239 -0
- package/dist/styles-areas/master-lock.css +26 -0
- package/dist/styles-areas/media-gallery.css +351 -0
- package/dist/styles-areas/media.css +658 -0
- package/dist/styles-areas/nav.css +488 -0
- package/dist/styles-areas/notifications.css +245 -0
- package/dist/styles-areas/overlays.css +133 -0
- package/dist/styles-areas/palette.css +140 -0
- package/dist/styles-areas/pdf-viewer.css +47 -0
- package/dist/styles-areas/problem-detail.css +97 -0
- package/dist/styles-areas/rich-text.css +167 -0
- package/dist/styles-areas/sharing.css +153 -0
- package/dist/styles-areas/spreadsheet.css +37 -0
- package/dist/styles-areas/stats.css +281 -0
- package/dist/styles-areas/test-report.css +133 -0
- package/dist/styles-areas/virtual.css +30 -0
- package/dist/styles-areas/wizard.css +381 -0
- package/dist/styles-areas/workbench.css +543 -0
- package/dist/styles-areas/workbook-viewer.css +44 -0
- package/dist/styles-static.css +34 -23
- package/dist/styles.css +34 -23
- package/package.json +130 -32
- package/scripts/checkDistExports.ts +67 -0
- package/scripts/cssRules.ts +125 -0
- package/scripts/fixtureAppCss.ts +344 -0
- package/scripts/generateAreaStyles.ts +253 -0
- package/scripts/guardrailsEnforce.spec.ts +62 -0
- package/scripts/guardrailsEnforce.ts +67 -3
- package/scripts/paths.ts +106 -0
- package/scripts/styleAreas.ts +585 -0
- package/scripts/verify.ts +5 -0
- package/src/barrelsReachNoOptionalPeer.spec.ts +117 -9
- package/src/docsMatchTheSplit.spec.ts +98 -0
- package/src/fixtureAppCss.spec.ts +177 -0
- package/src/namedSubpathsResolve.spec.ts +35 -0
- package/src/publishShape.spec.ts +67 -0
- package/src/react/components/ListToolbar.spec.tsx +172 -0
- package/src/react/components/ListToolbar.tsx +151 -0
- package/src/react/file-tree/FileTree.spec.tsx +1009 -0
- package/src/react/file-tree/FileTree.tsx +1459 -309
- package/src/react/file-tree/fileTree.css +151 -0
- package/src/react/file-tree/fileTreeSelection.spec.ts +327 -0
- package/src/react/file-tree/fileTreeSelection.ts +321 -0
- package/src/react/file-tree/index.ts +21 -0
- package/src/react/index.ts +1 -0
- package/src/react/lib/form.ts +51 -8
- package/src/react/markdown/MarkdownDoc.spec.tsx +1 -1
- package/src/react/media/DenseGalleryShell.tsx +108 -36
- package/src/react/media/FocusViewer.tsx +15 -8
- package/src/react/media/FrameGrabber.spec.tsx +175 -0
- package/src/react/media/FrameGrabber.tsx +67 -0
- package/src/react/media/MediaResize.spec.tsx +84 -14
- package/src/react/media/MediaResize.tsx +51 -19
- package/src/react/media/VideoChapterEditor.tsx +428 -0
- package/src/react/media/VideoPlayer.spec.tsx +111 -1
- package/src/react/media/VideoPlayer.tsx +158 -11
- package/src/react/media/VideoTurner.spec.tsx +67 -0
- package/src/react/media/VideoTurner.tsx +70 -15
- package/src/react/media/denseGallery.css +104 -46
- package/src/react/media/hlsSource.recovery.spec.ts +213 -0
- package/src/react/media/hlsSource.spec.ts +8 -0
- package/src/react/media/hlsSource.ts +189 -1
- package/src/react/media/index.ts +14 -0
- package/src/react/media/mediaResize.css +127 -54
- package/src/react/media/pictureEditor.css +52 -6
- package/src/react/media/videoChapterEditor.css +203 -0
- package/src/react/media/videoChapters.spec.ts +176 -0
- package/src/react/media/videoChapters.ts +181 -0
- package/src/react/media-gallery/GalleryTable.tsx +93 -3
- package/src/react/media-gallery/MediaGallery.spec.tsx +1156 -10
- package/src/react/media-gallery/MediaGallery.tsx +813 -95
- package/src/react/media-gallery/MediaMetaEditor.tsx +237 -0
- package/src/react/media-gallery/galleryTable.spec.ts +41 -1
- package/src/react/media-gallery/index.ts +7 -0
- package/src/react/media-gallery/mediaGallery.css +180 -4
- package/src/react/media-gallery/mediaMeta.spec.ts +95 -0
- package/src/react/media-gallery/mediaMeta.ts +101 -0
- package/src/react/media-gallery/playbackPreferences.spec.ts +172 -0
- package/src/react/media-gallery/playbackPreferences.ts +100 -0
- package/src/react/media-gallery/types.ts +34 -0
- package/src/shippedFilesAreTracked.spec.ts +69 -0
- package/src/styles-areas/activity-bar.css +30 -0
- package/src/styles-areas/analytics.css +672 -0
- package/src/styles-areas/auth.css +154 -0
- package/src/styles-areas/calendar.css +416 -0
- package/src/styles-areas/chart-table.css +41 -0
- package/src/styles-areas/charts.css +89 -0
- package/src/styles-areas/chat.css +364 -0
- package/src/styles-areas/clipboard.css +26 -0
- package/src/styles-areas/code-editor.css +130 -0
- package/src/styles-areas/companion-link.css +70 -0
- package/src/styles-areas/core.css +2503 -0
- package/src/styles-areas/dashboard-grid.css +84 -0
- package/src/styles-areas/data-table.css +657 -0
- package/src/styles-areas/deep-link.css +26 -0
- package/src/styles-areas/diff-viewer.css +30 -0
- package/src/styles-areas/disk-usage.css +262 -0
- package/src/styles-areas/emoji.css +154 -0
- package/src/styles-areas/fields.css +582 -0
- package/src/styles-areas/file-tree.css +33 -0
- package/src/styles-areas/filter-rail.css +235 -0
- package/src/styles-areas/folder-tree.css +219 -0
- package/src/styles-areas/keep-awake.css +26 -0
- package/src/styles-areas/layout-engine.css +239 -0
- package/src/styles-areas/markdown.css +87 -0
- package/src/styles-areas/master-detail.css +239 -0
- package/src/styles-areas/master-lock.css +26 -0
- package/src/styles-areas/media-gallery.css +351 -0
- package/src/styles-areas/media.css +658 -0
- package/src/styles-areas/nav.css +488 -0
- package/src/styles-areas/notifications.css +245 -0
- package/src/styles-areas/overlays.css +133 -0
- package/src/styles-areas/palette.css +140 -0
- package/src/styles-areas/pdf-viewer.css +47 -0
- package/src/styles-areas/problem-detail.css +97 -0
- package/src/styles-areas/rich-text.css +167 -0
- package/src/styles-areas/sharing.css +153 -0
- package/src/styles-areas/spreadsheet.css +37 -0
- package/src/styles-areas/stats.css +281 -0
- package/src/styles-areas/test-report.css +133 -0
- package/src/styles-areas/virtual.css +30 -0
- package/src/styles-areas/wizard.css +381 -0
- package/src/styles-areas/workbench.css +543 -0
- package/src/styles-areas/workbook-viewer.css +44 -0
- package/src/styles-static.css +34 -23
- package/src/styles.css +34 -23
- package/src/stylesAreas.spec.ts +247 -0
- package/src/stylesUtilitiesMatches.spec.ts +6 -77
- package/src/testFilesRunInParallel.spec.ts +79 -0
- package/src/typecheckCachesAreSeparate.spec.ts +128 -0
- package/src/verifyGraph.spec.ts +6 -0
package/src/react/media/index.ts
CHANGED
|
@@ -222,6 +222,20 @@ export { VideoTrimmer } from './VideoTrimmer';
|
|
|
222
222
|
// that a server executes, which is the only shape that works on a phone master. See
|
|
223
223
|
// `videoCuts.ts` for the owner's reasoning.
|
|
224
224
|
export { VideoCutEditor, type VideoCutEditorProps } from './VideoCutEditor';
|
|
225
|
+
// Naming points in time and KEEPING them — the other half of the same gesture, and a separate
|
|
226
|
+
// model on purpose: a cut list is a request that costs a re-encode, a chapter list is metadata
|
|
227
|
+
// that applies on save. `videoChapters.ts`'s header says why the model is in this package
|
|
228
|
+
// rather than in `cursedbelt-core` beside `videoCuts.ts`.
|
|
229
|
+
export { VideoChapterEditor, type VideoChapterEditorProps } from './VideoChapterEditor';
|
|
230
|
+
export {
|
|
231
|
+
type ChapteredVideo,
|
|
232
|
+
type ChapterSpan,
|
|
233
|
+
chapterProblem,
|
|
234
|
+
chapterSpans,
|
|
235
|
+
MIN_CHAPTER_SECONDS,
|
|
236
|
+
normalizeChapters,
|
|
237
|
+
type VideoChapter,
|
|
238
|
+
} from './videoChapters';
|
|
225
239
|
// Re-exported from `core/media`, where the model lives so a SERVER can import it without
|
|
226
240
|
// dragging React in — see the header of `videoCuts.ts`.
|
|
227
241
|
export {
|
|
@@ -9,44 +9,103 @@
|
|
|
9
9
|
* and the owner reported the feature as absent while prod was serving it. So both grips are
|
|
10
10
|
* legible without hover, and both brighten further on hover/focus rather than appearing on
|
|
11
11
|
* it. Do not "quieten" either back to a hover-only affordance.
|
|
12
|
+
*
|
|
13
|
+
* ── 🔴 2026-09-16: the grips live OUTSIDE the picture ──────────────────────────────────
|
|
14
|
+
* Owner, `ideas/collections-09-14.md`: *"Fix the drag to resize area to no longer overlap
|
|
15
|
+
* part of the horizontal play timeline area that shows what part of the video is playing. It
|
|
16
|
+
* should only be draggable when my mouse pointer is at the bottom right corner of the video
|
|
17
|
+
* player, just like mac windows for other apps work."*
|
|
18
|
+
*
|
|
19
|
+
* The corner grip used to be a 64×64 overlay `position: absolute; right: 0; bottom: 0` INSIDE
|
|
20
|
+
* the clipped frame, riding at `z-index: 12` over Vidstack's control layer, and the gallery
|
|
21
|
+
* reserved a matching `padding-inline-end` gutter in the player's last two control groups so
|
|
22
|
+
* the buttons would not lay out underneath it.
|
|
23
|
+
*
|
|
24
|
+
* 🔴 MEASURED before anything was changed, with that geometry restored in a real browser
|
|
25
|
+
* (`e2e/resize-grip-rail.spec.ts` has the numbers): the gutter DID keep the corner's rectangle
|
|
26
|
+
* off `.vds-time-slider`'s. It is not the thing that was broken, and widening it would have
|
|
27
|
+
* fixed nothing. Three things were, and none of them is reachable from a gutter:
|
|
28
|
+
*
|
|
29
|
+
* 1. `.cbmr-bar` — a full-width strip under the frame whose `padding: 11px 0` with
|
|
30
|
+
* `margin-block: -11px` put 11px of drag surface back inside the picture, spanning the
|
|
31
|
+
* whole scrub bar. Horizontal padding is BESIDE the slider; the bar is UNDER it.
|
|
32
|
+
* 2. A gutter can only shorten a control bar this package styles. A `nativeVideoStage`
|
|
33
|
+
* gallery puts a plain `<video controls>` in that frame and its UA bar is full-width and
|
|
34
|
+
* untouchable, so a grip in the corner lands on the native timeline with no recourse.
|
|
35
|
+
* 3. It was paid for in the thing the owner was complaining about: 64px of scrub bar,
|
|
36
|
+
* surrendered so the grip could sit beside it.
|
|
37
|
+
*
|
|
38
|
+
* So the grips moved off the picture entirely, into `.cbmr-rail` — a strip of chrome BELOW the
|
|
39
|
+
* frame, which is where a Mac window's resize corner is: the window's outside edge, not a
|
|
40
|
+
* patch of its content. Nothing of either grip is inside the frame at any size, and that is
|
|
41
|
+
* the only shape in which "does not overlap the timeline" is a property of the layout rather
|
|
42
|
+
* than a tuning against whatever the current player happens to draw. The gutter rule in
|
|
43
|
+
* `denseGallery.css` went with it, so the time slider is full width again — which is the rest
|
|
44
|
+
* of the same sentence.
|
|
12
45
|
*/
|
|
13
46
|
|
|
14
47
|
/*
|
|
15
|
-
* 🔴 ONE number
|
|
48
|
+
* 🔴 ONE number: the grip's reach AND the height of the rail that holds it.
|
|
16
49
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* Declared on `:root` because the
|
|
22
|
-
* custom property set on the grip itself does not reach back up the tree.
|
|
50
|
+
* 64px is the owner's 2026-08-25 *"make the corner expansion grabbable area bigger … for some
|
|
51
|
+
* reason it's hard to grab"* and it may not go down — see `.cbmr-corner`. The rail is exactly
|
|
52
|
+
* that tall because the rail exists to hold the grip; two literals would desync on the first
|
|
53
|
+
* tweak and the symptom is a grip clipped by its own strip, which only shows up by hand.
|
|
54
|
+
* Declared on `:root` because the coarse-pointer block at the bottom raises it for both.
|
|
23
55
|
*/
|
|
24
56
|
:root {
|
|
25
57
|
--cbmr-corner-size: 64px;
|
|
26
58
|
}
|
|
27
59
|
|
|
60
|
+
/* ── The rail: the chrome the grips live in ──────────────────────────────────────────── */
|
|
61
|
+
|
|
62
|
+
/*
|
|
63
|
+
* 🔴 A sibling of the frame, never a child of it. Every consumer renders it directly after
|
|
64
|
+
* the picture's box (`DenseGalleryShell`, `FocusViewer`), and `MediaResize.spec.tsx` fails if
|
|
65
|
+
* a player stops doing so — a grip that drifts back inside the frame is exactly the
|
|
66
|
+
* 2026-09-14 report, and it is invisible to everything except a rendered rectangle.
|
|
67
|
+
*
|
|
68
|
+
* It is the positioning context for the corner, which is what keeps the grip's 64px box
|
|
69
|
+
* bounded by this strip instead of hanging up over the picture.
|
|
70
|
+
*/
|
|
71
|
+
.cbmr-rail {
|
|
72
|
+
position: relative;
|
|
73
|
+
display: flex;
|
|
74
|
+
align-items: center;
|
|
75
|
+
justify-content: center;
|
|
76
|
+
inline-size: 100%;
|
|
77
|
+
block-size: var(--cbmr-corner-size, 64px);
|
|
78
|
+
/* Both consumers stack it in a flex COLUMN (`.cbgd-watch-player`, `.inspector`), where a
|
|
79
|
+
default `flex-shrink: 1` would let a short container squeeze the strip and clip the grip
|
|
80
|
+
out of its own bottom-right corner. The picture is what gives way, never the handle. */
|
|
81
|
+
flex: none;
|
|
82
|
+
}
|
|
83
|
+
|
|
28
84
|
/* ── The corner ─────────────────────────────────────────────────────────────────────── */
|
|
29
85
|
|
|
30
86
|
.cbmr-corner {
|
|
31
87
|
position: absolute;
|
|
32
|
-
|
|
33
|
-
|
|
88
|
+
inset-inline-end: 0;
|
|
89
|
+
inset-block-end: 0;
|
|
34
90
|
/*
|
|
35
91
|
* 🔴 ABOVE the video player's control layer, which is `z-index: 10` (Vidstack's
|
|
36
|
-
* `[data-view-type='video'] .vds-controls`)
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
92
|
+
* `[data-view-type='video'] .vds-controls`) — `[data-media-player]` sets `contain:
|
|
93
|
+
* style`, which opens no stacking context, so nothing isolates the player's chrome
|
|
94
|
+
* from the frame around it. At the old `3` the grip was painted over and, worse,
|
|
95
|
+
* click-blocked by the bottom `.vds-controls-group` (`width: 100%`, `pointer-events:
|
|
96
|
+
* auto`) whenever the bar was visible — which is on hover, which is precisely when a
|
|
97
|
+
* person reaches for it. That is the owner's 2026-08-25 *"for some reason it's hard to
|
|
98
|
+
* grab"*, and it is why this number may not go back down.
|
|
99
|
+
*
|
|
100
|
+
* Since 2026-09-16 the grip is in `.cbmr-rail`, outside the frame, so it no longer has
|
|
101
|
+
* to win that fight — but a player whose control layer grows a `bottom: -Npx` overhang
|
|
102
|
+
* would re-open it, and 12 costs nothing. Keep it.
|
|
44
103
|
*
|
|
45
104
|
* `12` and not more: it must stay UNDER Vidstack's menus (50) and its fullscreen
|
|
46
105
|
* surface, so opening the settings cog still covers the grip rather than the grip
|
|
47
106
|
* punching a hole through an open menu.
|
|
48
107
|
*
|
|
49
|
-
* LOCAL stacking only. This lifts the grip inside its own positioned
|
|
108
|
+
* LOCAL stacking only. This lifts the grip inside its own positioned rail and must
|
|
50
109
|
* never reach the app-wide bands — a `--z-` band here would raise the grip over the
|
|
51
110
|
* sticky header and every overlay above it.
|
|
52
111
|
* guardrails-ignore no-raw-zindex: local stacking inside a positioned media frame. */
|
|
@@ -54,35 +113,37 @@
|
|
|
54
113
|
display: flex;
|
|
55
114
|
align-items: flex-end;
|
|
56
115
|
justify-content: flex-end;
|
|
57
|
-
/* The target
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
the glyph is the mark. */
|
|
116
|
+
/* The target. Well over DESIGN.md §5's 44px floor, deliberately: the owner asked for a
|
|
117
|
+
bigger grab area in the same breath as reporting he could not hit it. The padding is
|
|
118
|
+
the reach, the glyph is the mark. It fills the rail exactly — see `--cbmr-corner-size`. */
|
|
61
119
|
inline-size: var(--cbmr-corner-size, 64px);
|
|
62
120
|
block-size: var(--cbmr-corner-size, 64px);
|
|
63
|
-
padding: 0
|
|
121
|
+
padding: 0 6px 6px 0;
|
|
64
122
|
box-sizing: border-box;
|
|
65
123
|
cursor: nwse-resize;
|
|
66
124
|
touch-action: none;
|
|
67
125
|
border: 0;
|
|
68
126
|
background: none;
|
|
69
|
-
/* A soft scrim rather than a filled chip: the grip must be legible over a white sky and
|
|
70
|
-
over black letterboxing, and a corner-anchored gradient does that without drawing a
|
|
71
|
-
box on top of the picture. */
|
|
72
|
-
border-end-end-radius: inherit;
|
|
73
127
|
}
|
|
74
128
|
|
|
129
|
+
/*
|
|
130
|
+
* The hover plate.
|
|
131
|
+
*
|
|
132
|
+
* 🔴 A TOKEN, where this used to be a hardcoded black radial scrim. The scrim was right while
|
|
133
|
+
* the grip rode on arbitrary media — a photograph has no theme, so app colours tinted it. In
|
|
134
|
+
* the rail the grip rides on app chrome like every other control, so it takes the app's
|
|
135
|
+
* colours and the two `guardrails-ignore no-hardcoded-colors` suppressions this rule used to
|
|
136
|
+
* need are gone with it.
|
|
137
|
+
*/
|
|
75
138
|
.cbmr-corner::before {
|
|
76
139
|
content: '';
|
|
77
140
|
position: absolute;
|
|
78
|
-
inset:
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
/* guardrails-ignore no-hardcoded-colors: one line, because the excuse covers the LINE. */
|
|
85
|
-
background: radial-gradient(circle at 100% 100%, rgb(0 0 0 / 0.55) 0%, rgb(0 0 0 / 0.34) 52%, rgb(0 0 0 / 0) 80%);
|
|
141
|
+
inset-inline-end: 2px;
|
|
142
|
+
inset-block-end: 2px;
|
|
143
|
+
inline-size: 30px;
|
|
144
|
+
block-size: 30px;
|
|
145
|
+
border-radius: var(--radius-md, 0.5rem);
|
|
146
|
+
background: transparent;
|
|
86
147
|
pointer-events: none;
|
|
87
148
|
transition: background 120ms ease;
|
|
88
149
|
}
|
|
@@ -93,10 +154,9 @@
|
|
|
93
154
|
block-size: 16px;
|
|
94
155
|
overflow: visible;
|
|
95
156
|
fill: none;
|
|
96
|
-
/*
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
stroke: rgb(255 255 255 / 0.92);
|
|
157
|
+
/* Legible at rest — see the file header. `--muted-foreground`, never `--border`, which is
|
|
158
|
+
the colour of a hairline nobody is meant to look at. */
|
|
159
|
+
stroke: var(--muted-foreground, currentColor);
|
|
100
160
|
stroke-width: 1.6;
|
|
101
161
|
stroke-linecap: round;
|
|
102
162
|
transition: stroke 120ms ease, transform 120ms ease;
|
|
@@ -104,15 +164,13 @@
|
|
|
104
164
|
|
|
105
165
|
.cbmr-corner:hover .cbmr-corner-glyph,
|
|
106
166
|
.cbmr-corner:focus-visible .cbmr-corner-glyph {
|
|
107
|
-
|
|
108
|
-
stroke: rgb(255 255 255 / 1);
|
|
167
|
+
stroke: var(--foreground, var(--muted-foreground));
|
|
109
168
|
transform: scale(1.15);
|
|
110
169
|
}
|
|
111
170
|
|
|
112
171
|
.cbmr-corner:hover::before,
|
|
113
172
|
.cbmr-corner:focus-visible::before {
|
|
114
|
-
|
|
115
|
-
background: radial-gradient(circle at 100% 100%, rgb(0 0 0 / 0.7) 0%, rgb(0 0 0 / 0.45) 45%, rgb(0 0 0 / 0) 75%);
|
|
173
|
+
background: var(--border);
|
|
116
174
|
}
|
|
117
175
|
|
|
118
176
|
.cbmr-corner:focus-visible {
|
|
@@ -122,18 +180,27 @@
|
|
|
122
180
|
|
|
123
181
|
/* ── The bottom edge ────────────────────────────────────────────────────────────────── */
|
|
124
182
|
|
|
183
|
+
/*
|
|
184
|
+
* 🔴 COARSE POINTERS ONLY, and that is a decision, not a tidy-up — see `MediaResize.tsx`'s
|
|
185
|
+
* header for the whole of it. *"It should only be draggable when my mouse pointer is at the
|
|
186
|
+
* bottom right corner"* is a verdict on this bar as much as on the corner's old position; the
|
|
187
|
+
* one reason it was ever kept beside the corner is about a THUMB, so it survives exactly where
|
|
188
|
+
* a thumb is.
|
|
189
|
+
*/
|
|
125
190
|
.cbmr-bar {
|
|
191
|
+
display: none;
|
|
126
192
|
inline-size: 100%;
|
|
127
193
|
block-size: 22px;
|
|
128
|
-
display: flex;
|
|
129
194
|
align-items: center;
|
|
130
195
|
justify-content: center;
|
|
131
196
|
cursor: ns-resize;
|
|
132
197
|
touch-action: none;
|
|
133
|
-
/* The generous half of the 44px target, without 44px of visible gutter.
|
|
198
|
+
/* The generous half of the 44px target, without 44px of visible gutter. 🔴 No negative
|
|
199
|
+
margin pulling it back out of the rail: that is how invisible padding came to hang over
|
|
200
|
+
the picture's bottom edge and over the transport below it, which is the overlap the
|
|
201
|
+
2026-09-14 report is about. The rail is tall enough to hold the reach. */
|
|
134
202
|
padding: 11px 0;
|
|
135
203
|
box-sizing: content-box;
|
|
136
|
-
margin-block: -11px;
|
|
137
204
|
border: 0;
|
|
138
205
|
background: none;
|
|
139
206
|
}
|
|
@@ -172,15 +239,17 @@
|
|
|
172
239
|
/*
|
|
173
240
|
* ── A finger is not a mouse ──────────────────────────────────────────────────────────
|
|
174
241
|
* Owner, 2026-08-25 and again 2026-09-08: *"make the corner expansion grabbable area
|
|
175
|
-
* bigger … for some reason it's hard to grab"*.
|
|
176
|
-
*
|
|
177
|
-
*
|
|
178
|
-
* phone is most of that box, and the grip sits in the one corner a thumb reaches across the
|
|
179
|
-
* whole screen to get to.
|
|
242
|
+
* bigger … for some reason it's hard to grab"*. 64px clears `DESIGN.md` §5's 44px floor for a
|
|
243
|
+
* POINTER; a fingertip's contact patch is ~9mm, which on a phone is most of that box, and the
|
|
244
|
+
* grip sits in the one corner a thumb reaches across the whole screen to get to.
|
|
180
245
|
*
|
|
181
246
|
* Coarse pointers only, so the desktop look — which the owner explicitly said was good — is
|
|
182
|
-
* untouched. `--cbmr-corner-size`
|
|
183
|
-
*
|
|
247
|
+
* untouched. Raising `--cbmr-corner-size` raises the rail with it, so the bigger grip still
|
|
248
|
+
* fits inside its strip rather than growing back up over the picture.
|
|
249
|
+
*
|
|
250
|
+
* 🔴 And this is where `.cbmr-bar` exists at all: the corner is a small target for a thumb,
|
|
251
|
+
* and on a portrait clip the picture's bottom edge is the one part of the stage whose position
|
|
252
|
+
* does not move with the file.
|
|
184
253
|
*/
|
|
185
254
|
@media (pointer: coarse) {
|
|
186
255
|
:root {
|
|
@@ -192,9 +261,13 @@
|
|
|
192
261
|
inline-size: 22px;
|
|
193
262
|
block-size: 22px;
|
|
194
263
|
}
|
|
264
|
+
.cbmr-corner::before {
|
|
265
|
+
inline-size: 40px;
|
|
266
|
+
block-size: 40px;
|
|
267
|
+
}
|
|
195
268
|
/* Same reasoning for the bar: the ink stays a hairline, the reach grows. */
|
|
196
269
|
.cbmr-bar {
|
|
270
|
+
display: flex;
|
|
197
271
|
padding: 15px 0;
|
|
198
|
-
margin-block: -15px;
|
|
199
272
|
}
|
|
200
273
|
}
|
|
@@ -263,12 +263,58 @@
|
|
|
263
263
|
cursor: default;
|
|
264
264
|
}
|
|
265
265
|
|
|
266
|
-
/*
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
266
|
+
/* The film, sized exactly like the `<img>` the picture editor puts in the same frame: contained,
|
|
267
|
+
centred, never overflowing the box it is previewed in. Written out here because `.cbpe-frame
|
|
268
|
+
img` cannot say it for an element that is not an image, and without it the preview is whatever
|
|
269
|
+
size the browser's default happens to make it — which for a phone clip is a postage stamp in
|
|
270
|
+
the middle of a black frame, i.e. the thing this dialog is for is invisible. */
|
|
271
|
+
.cbpe-frame video {
|
|
272
|
+
max-width: 100%;
|
|
273
|
+
max-height: 100%;
|
|
274
|
+
object-fit: contain;
|
|
275
|
+
transform-origin: center;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/* A quarter-turned clip is still laid out in its ORIGINAL box, so its width has to be read from
|
|
279
|
+
the container's HEIGHT and vice versa. Container query units are the only way to say that.
|
|
280
|
+
Set only for the ODD turns — a half turn does not change the box and pays for none of this.
|
|
281
|
+
|
|
282
|
+
🔴 An explicit SIZE, not a `max-*` bound. The same correction, for the same reason, as
|
|
283
|
+
`.cbmg-stage-turn[data-turned='true']` in `mediaGallery.css` (which documents the measurement):
|
|
284
|
+
a bound can only shrink, so a turned clip stayed whatever size it already was and the preview
|
|
285
|
+
showed a pillar the stage was about to show full-width. The preview and the stage have to
|
|
286
|
+
agree — a preview that under-sells the turn is a preview somebody rejects a correct edit on.
|
|
287
|
+
`img` as well as `video`: a clip that will not play falls back to its poster, and the poster
|
|
288
|
+
is turned by the same transform. */
|
|
289
|
+
.cbpe-frame-film[data-turned='true'] video,
|
|
290
|
+
.cbpe-frame-film[data-turned='true'] img {
|
|
270
291
|
max-width: none;
|
|
271
292
|
max-height: none;
|
|
272
|
-
max-block-size:
|
|
273
|
-
max-inline-size:
|
|
293
|
+
max-block-size: none;
|
|
294
|
+
max-inline-size: none;
|
|
295
|
+
width: 100cqb;
|
|
296
|
+
height: 100cqi;
|
|
297
|
+
aspect-ratio: auto;
|
|
298
|
+
object-fit: contain;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/* Why there is no moving picture, said ON the frame that would otherwise be black — the owner's
|
|
302
|
+
*"I see a black screen"*, which he could only report as a black screen because the dialog said
|
|
303
|
+
nothing. Centred over the ground rather than under the frame so it is read as being about the
|
|
304
|
+
picture, and `pointer-events: none` so it never eats a press meant for the film. */
|
|
305
|
+
.cbpe-frame-note {
|
|
306
|
+
position: absolute;
|
|
307
|
+
inset-inline: 1.5rem;
|
|
308
|
+
top: 50%;
|
|
309
|
+
transform: translateY(-50%);
|
|
310
|
+
margin: 0;
|
|
311
|
+
text-align: center;
|
|
312
|
+
text-wrap: balance;
|
|
313
|
+
font-size: 13px;
|
|
314
|
+
line-height: 1.5;
|
|
315
|
+
/* guardrails-ignore no-hardcoded-colors: sits ON the picture ground, which is true black in
|
|
316
|
+
both themes — the same argument as `.cbpe-hint` above. */
|
|
317
|
+
color: rgb(255 255 255 / 0.82);
|
|
318
|
+
text-shadow: 0 1px 2px rgb(0 0 0 / 0.6);
|
|
319
|
+
pointer-events: none;
|
|
274
320
|
}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/* Plain CSS, colocated with `VideoChapterEditor.tsx` and imported by it — the same
|
|
2
|
+
convention, and the same reason, as `videoCutEditor.css`: the editor is lazily imported
|
|
3
|
+
from the gallery, so these bytes ride the gallery's chunk instead of landing in whichever
|
|
4
|
+
ENTRY stylesheet happened to scan a utility class. Every colour is a theme token. */
|
|
5
|
+
|
|
6
|
+
.cbch {
|
|
7
|
+
display: flex;
|
|
8
|
+
flex-direction: column;
|
|
9
|
+
gap: 0.75rem;
|
|
10
|
+
min-height: 0;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.cbch-video {
|
|
14
|
+
inline-size: 100%;
|
|
15
|
+
max-block-size: 44vh;
|
|
16
|
+
background: var(--surface-2, var(--background));
|
|
17
|
+
border-radius: var(--radius-md, 8px);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/* The one authoring row: name the section, then mark it. In that order, because the button
|
|
21
|
+
is disabled until there is a name — see the component. */
|
|
22
|
+
.cbch-add {
|
|
23
|
+
display: flex;
|
|
24
|
+
align-items: center;
|
|
25
|
+
gap: 0.5rem;
|
|
26
|
+
flex-wrap: wrap;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.cbch-add-field {
|
|
30
|
+
flex: 1 1 14rem;
|
|
31
|
+
min-inline-size: 0;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/* Tabular figures, and this is not cosmetic: the playhead readout changes ten times a second,
|
|
35
|
+
and proportional digits make the whole row shuffle sideways under the controls beside it
|
|
36
|
+
while a clip plays. */
|
|
37
|
+
.cbch-playhead {
|
|
38
|
+
font-variant-numeric: tabular-nums;
|
|
39
|
+
font-size: 0.875rem;
|
|
40
|
+
color: var(--muted-foreground);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/* ── The strip ───────────────────────────────────────────────────────────────
|
|
44
|
+
What the scrub bar will look like once this is saved: the named sections, in place and to
|
|
45
|
+
scale. Not a scrub bar itself — the `<video>`'s own controls are that, and a second
|
|
46
|
+
draggable timeline would be two controls fighting for one gesture. */
|
|
47
|
+
.cbch-strip {
|
|
48
|
+
position: relative;
|
|
49
|
+
display: flex;
|
|
50
|
+
list-style: none;
|
|
51
|
+
margin: 0;
|
|
52
|
+
padding: 0;
|
|
53
|
+
inline-size: 100%;
|
|
54
|
+
block-size: 40px;
|
|
55
|
+
border-radius: var(--radius-md, 8px);
|
|
56
|
+
background: var(--surface-3, var(--surface-2));
|
|
57
|
+
border: 1px solid var(--border);
|
|
58
|
+
overflow: hidden;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/* The list item carries the WIDTH — the section's duration — and the button fills it. Split
|
|
62
|
+
in two so the width lives on the flex child rather than on a control that also has padding. */
|
|
63
|
+
.cbch-span-item {
|
|
64
|
+
min-inline-size: 0;
|
|
65
|
+
flex: 0 0 auto;
|
|
66
|
+
block-size: 100%;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/* The unnamed opening, when the first chapter is not at 0:00. Drawn, but not a control: there
|
|
70
|
+
is nothing to jump to and nothing to rename — it is the part that has no section yet. */
|
|
71
|
+
.cbch-lead {
|
|
72
|
+
flex: 0 0 auto;
|
|
73
|
+
block-size: 100%;
|
|
74
|
+
border-inline-end: 1px solid var(--border);
|
|
75
|
+
background: repeating-linear-gradient(
|
|
76
|
+
135deg,
|
|
77
|
+
transparent 0 6px,
|
|
78
|
+
color-mix(in srgb, var(--muted-foreground) 14%, transparent) 6px 12px
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.cbch-span {
|
|
83
|
+
display: flex;
|
|
84
|
+
align-items: center;
|
|
85
|
+
gap: 0.25rem;
|
|
86
|
+
/* `min-inline-size: 0` and no flex-grow: the inline width set per section is the truth. */
|
|
87
|
+
inline-size: 100%;
|
|
88
|
+
block-size: 100%;
|
|
89
|
+
padding-inline: 0.375rem;
|
|
90
|
+
border: 0;
|
|
91
|
+
/* A hairline between sections, so two adjacent ones read as two rather than one. */
|
|
92
|
+
border-inline-end: 1px solid var(--border);
|
|
93
|
+
background: var(--surface-1, var(--background));
|
|
94
|
+
color: var(--foreground);
|
|
95
|
+
font-size: 0.75rem;
|
|
96
|
+
white-space: nowrap;
|
|
97
|
+
overflow: hidden;
|
|
98
|
+
cursor: pointer;
|
|
99
|
+
transition: background 120ms ease;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.cbch-span-item:last-of-type .cbch-span {
|
|
103
|
+
border-inline-end: 0;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.cbch-span:hover {
|
|
107
|
+
background: var(--surface-2);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.cbch-span:focus-visible {
|
|
111
|
+
outline: 2px solid var(--ring, var(--muted-foreground));
|
|
112
|
+
outline-offset: -2px;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.cbch-span-label {
|
|
116
|
+
overflow: hidden;
|
|
117
|
+
text-overflow: ellipsis;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.cbch-strip-head {
|
|
121
|
+
position: absolute;
|
|
122
|
+
inset-block: 0;
|
|
123
|
+
inline-size: 2px;
|
|
124
|
+
background: var(--foreground);
|
|
125
|
+
/* Over the sections, but it must never eat a click meant for one. */
|
|
126
|
+
pointer-events: none;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.cbch-summary {
|
|
130
|
+
font-size: 0.875rem;
|
|
131
|
+
color: var(--muted-foreground);
|
|
132
|
+
margin: 0;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.cbch-list {
|
|
136
|
+
list-style: none;
|
|
137
|
+
margin: 0;
|
|
138
|
+
padding: 0;
|
|
139
|
+
display: flex;
|
|
140
|
+
flex-direction: column;
|
|
141
|
+
gap: 0.25rem;
|
|
142
|
+
max-block-size: 24vh;
|
|
143
|
+
/* guardrails-ignore no-raw-overflow: a Tailwind-free `.cbch-` list inside a lazily
|
|
144
|
+
imported editor, not a ScrollArea consumer — same as `videoCutEditor.css`. */
|
|
145
|
+
overflow-y: auto;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.cbch-row {
|
|
149
|
+
display: flex;
|
|
150
|
+
align-items: center;
|
|
151
|
+
gap: 0.5rem;
|
|
152
|
+
padding-inline: 0.25rem;
|
|
153
|
+
border-radius: var(--radius-sm, 6px);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.cbch-row:hover {
|
|
157
|
+
background: var(--surface-2);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.cbch-row-goto {
|
|
161
|
+
flex: 0 0 auto;
|
|
162
|
+
display: flex;
|
|
163
|
+
align-items: center;
|
|
164
|
+
gap: 0.375rem;
|
|
165
|
+
/* DESIGN.md §5's touch floor — a row you jump the playhead with is a real control. */
|
|
166
|
+
min-block-size: 44px;
|
|
167
|
+
padding-inline: 0.25rem;
|
|
168
|
+
border: 0;
|
|
169
|
+
background: none;
|
|
170
|
+
color: var(--muted-foreground);
|
|
171
|
+
font-variant-numeric: tabular-nums;
|
|
172
|
+
font-size: 0.875rem;
|
|
173
|
+
text-align: start;
|
|
174
|
+
cursor: pointer;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.cbch-row-goto:hover {
|
|
178
|
+
color: var(--foreground);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.cbch-row-goto:focus-visible {
|
|
182
|
+
outline: 2px solid var(--ring, var(--muted-foreground));
|
|
183
|
+
outline-offset: -2px;
|
|
184
|
+
border-radius: var(--radius-sm, 6px);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.cbch-row-title {
|
|
188
|
+
flex: 1 1 auto;
|
|
189
|
+
min-inline-size: 0;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
.cbch-empty {
|
|
193
|
+
margin: 0;
|
|
194
|
+
padding-block: 0.75rem;
|
|
195
|
+
text-align: center;
|
|
196
|
+
font-size: 0.875rem;
|
|
197
|
+
color: var(--muted-foreground);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.cbch-note {
|
|
201
|
+
font-size: 0.875rem;
|
|
202
|
+
color: var(--muted-foreground);
|
|
203
|
+
}
|