cursedbelt 5.74.0 → 5.74.1
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/Page.d.ts.map +1 -1
- package/dist/react/components/Page.js +10 -1
- package/dist/react/components/Page.js.map +1 -1
- package/dist/react/media/DenseGalleryShell.d.ts.map +1 -1
- package/dist/react/media/DenseGalleryShell.js +73 -9
- package/dist/react/media/DenseGalleryShell.js.map +1 -1
- package/dist/react/media/HoverScrubVideoThumb.d.ts +11 -9
- package/dist/react/media/HoverScrubVideoThumb.d.ts.map +1 -1
- package/dist/react/media/HoverScrubVideoThumb.js +98 -25
- package/dist/react/media/HoverScrubVideoThumb.js.map +1 -1
- package/dist/react/media/denseGallery.css +103 -7
- package/dist/react/media-gallery/GalleryTable.js +7 -9
- package/dist/react/media-gallery/GalleryTable.js.map +1 -1
- package/dist/react/media-gallery/MediaGallery.d.ts.map +1 -1
- package/dist/react/media-gallery/MediaGallery.js +19 -7
- package/dist/react/media-gallery/MediaGallery.js.map +1 -1
- package/dist/react/media-gallery/playbackPreferences.d.ts +2 -2
- package/dist/react/media-gallery/playbackPreferences.js +2 -2
- package/dist/styles-areas/core.css +8 -6
- package/dist/styles-utilities.css +8 -0
- package/package.json +1 -1
- package/src/react/components/Page.tsx +11 -1
- package/src/react/media/DenseGalleryShell.tsx +90 -6
- package/src/react/media/HoverScrubVideoThumb.spec.tsx +82 -0
- package/src/react/media/HoverScrubVideoThumb.tsx +116 -28
- package/src/react/media/denseGallery.css +103 -7
- package/src/react/media-gallery/GalleryTable.tsx +7 -9
- package/src/react/media-gallery/MediaGallery.tsx +18 -7
- package/src/react/media-gallery/playbackPreferences.ts +2 -2
- package/src/styles-areas/core.css +8 -6
- package/src/styles-utilities.css +8 -0
|
@@ -36,7 +36,7 @@ import type { DragEvent } from 'react';
|
|
|
36
36
|
import { type ReactNode, useCallback, useEffect, useRef, useState } from 'react';
|
|
37
37
|
import { CATEGORY_LABEL } from '../components/FileTypeIcon.js';
|
|
38
38
|
import { useResizeObserver } from '../hooks/useResizeObserver.js';
|
|
39
|
-
import {
|
|
39
|
+
import { useScrubPreview } from '../media/HoverScrubVideoThumb.js';
|
|
40
40
|
import { releaseVideo, useInView, useSettled } from '../media/previewGate.js';
|
|
41
41
|
import { createdLabel, type MediaCache, ThumbImg, useItemMedia } from './galleryItemMedia.js';
|
|
42
42
|
import { galleryItemCategory } from './mediaGalleryModel.js';
|
|
@@ -393,8 +393,7 @@ function SortHeader({
|
|
|
393
393
|
* tile and is written in Tailwind utilities; this module is deliberately Tailwind-free (see
|
|
394
394
|
* `mediaGallery.css`'s opening paragraph — binary-server's inspector has no Tailwind build, so
|
|
395
395
|
* a Tailwind component here renders unstyled in half the fleet). What the two DO share is the
|
|
396
|
-
* arithmetic: `useScrubPreview` steps the same five offsets
|
|
397
|
-
* coarse-pointer decision, both imported rather than re-derived.
|
|
396
|
+
* arithmetic: `useScrubPreview` steps the same five offsets, imported rather than re-derived.
|
|
398
397
|
*
|
|
399
398
|
* 🔴 It replaces the poster rather than sitting on top of it, because at 56×40 there is no room
|
|
400
399
|
* for a stack — and it attaches the element only while previewing, so a table of four hundred
|
|
@@ -481,14 +480,13 @@ function GalleryTableRow({
|
|
|
481
480
|
* to preview it."* Before this, neither half was true in table view.
|
|
482
481
|
*/
|
|
483
482
|
const [hovering, setHovering] = useState(false);
|
|
484
|
-
const canHover = useCanHover();
|
|
485
483
|
const previewSrc = category === 'video' ? (media.streamUrl ?? media.url) : undefined;
|
|
486
|
-
// `autoPreview`
|
|
487
|
-
//
|
|
488
|
-
// 🔴
|
|
489
|
-
//
|
|
484
|
+
// `autoPreview` runs on a touch screen too, exactly as the grid tile's does (2026-10-10: the
|
|
485
|
+
// phone's "Preview all" lit up and nothing moved — `HoverScrubVideoThumb`'s `autoPlay` note).
|
|
486
|
+
// 🔴 It waits until the row is on screen and has SETTLED there (`previewGate.ts`), the same
|
|
487
|
+
// gate the grid tile uses — a table scrolled past fast must not open a stream per row.
|
|
490
488
|
const thumbRef = useRef<HTMLButtonElement | null>(null);
|
|
491
|
-
const autoReady = useSettled(useInView(thumbRef, previewSrc != null && autoPreview
|
|
489
|
+
const autoReady = useSettled(useInView(thumbRef, previewSrc != null && autoPreview));
|
|
492
490
|
const previewing = previewSrc != null && (autoReady || hovering);
|
|
493
491
|
|
|
494
492
|
return (
|
|
@@ -86,7 +86,7 @@ import {
|
|
|
86
86
|
type SourceFault,
|
|
87
87
|
sourceFaultMessage,
|
|
88
88
|
} from '../media/sourceFault.js';
|
|
89
|
-
import { HoverScrubVideoThumb } from '../media/HoverScrubVideoThumb.js';
|
|
89
|
+
import { HoverScrubVideoThumb, useCanHover } from '../media/HoverScrubVideoThumb.js';
|
|
90
90
|
import { isPlayPauseSpace } from '../media/playerSpaceKey.js';
|
|
91
91
|
import {
|
|
92
92
|
LIGHT_RANGE,
|
|
@@ -582,6 +582,15 @@ function TileShell({
|
|
|
582
582
|
}) {
|
|
583
583
|
const selected = selection?.selected === true;
|
|
584
584
|
const quiet = selection !== undefined && !selection.armed;
|
|
585
|
+
/*
|
|
586
|
+
* 🔴 Draggable only where a pointer can HOVER. On iOS a press-and-hold on a draggable
|
|
587
|
+
* element lifts it for drag-and-drop, and a press-and-hold on a tile is the video PREVIEW
|
|
588
|
+
* there (owner, 2026-10-10: *"holding down on a thumbnail should make it start previewing the
|
|
589
|
+
* video"* — `HoverScrubVideoThumb`'s `held`). A phone has nowhere to drop a tile anyway: the
|
|
590
|
+
* folder tree is a closed drawer while the grid is on screen.
|
|
591
|
+
*/
|
|
592
|
+
const canHover = useCanHover();
|
|
593
|
+
const dragHere = canHover ? drag : undefined;
|
|
585
594
|
return (
|
|
586
595
|
<div
|
|
587
596
|
className={`cbmg-selectable${selected ? ' is-selected' : ''}${stageMark ? ' is-playing' : ''}${quiet ? ' cbmg-selectable--quiet' : ''}`}
|
|
@@ -595,11 +604,11 @@ function TileShell({
|
|
|
595
604
|
// a drag, some treat the pointer-down as a press and never fire dragstart at all.
|
|
596
605
|
// Dragging the wrapper also means the drag image is the whole tile, which is what a
|
|
597
606
|
// person is aiming at.
|
|
598
|
-
{...(
|
|
607
|
+
{...(dragHere
|
|
599
608
|
? {
|
|
600
609
|
draggable: true,
|
|
601
|
-
onDragStart: (event: DragEvent<HTMLDivElement>) =>
|
|
602
|
-
onDragEnd: () =>
|
|
610
|
+
onDragStart: (event: DragEvent<HTMLDivElement>) => dragHere.onDragStart(event),
|
|
611
|
+
onDragEnd: () => dragHere.onDragEnd?.(),
|
|
603
612
|
}
|
|
604
613
|
: {})}
|
|
605
614
|
>
|
|
@@ -796,8 +805,8 @@ function RawGalleryTile({
|
|
|
796
805
|
video={video}
|
|
797
806
|
onOpen={onOpen}
|
|
798
807
|
previewMode='scrub'
|
|
799
|
-
// The whole grid previewing at once, on request
|
|
800
|
-
//
|
|
808
|
+
// The whole grid previewing at once, on request — on a phone too; the tile's gate keeps
|
|
809
|
+
// it to the tiles on screen.
|
|
801
810
|
autoPlay={autoPreview ?? false}
|
|
802
811
|
// A stored turn turns the TILE too — otherwise the grid is a wall of sideways films
|
|
803
812
|
// whose detail view is upright, which reads as the fix not having worked.
|
|
@@ -3224,7 +3233,9 @@ export function MediaGallery({
|
|
|
3224
3233
|
// guardrails-ignore no-raw-action-button: back-to-grid navigation, styled by
|
|
3225
3234
|
// the dense gallery's own plain CSS (plugin-media-gallery precedent).
|
|
3226
3235
|
type='button'
|
|
3227
|
-
|
|
3236
|
+
// `cbgd-action-lead`: on a phone it leads the row (`denseGallery.css`), so the way
|
|
3237
|
+
// out is never on a folded line.
|
|
3238
|
+
className={cn(RAW_BUTTON, 'cbgd-order-btn is-icon cbgd-action-lead')}
|
|
3228
3239
|
aria-label='Back to grid'
|
|
3229
3240
|
onClick={() => select(null)}
|
|
3230
3241
|
>
|
|
@@ -204,8 +204,8 @@ const THUMB_AUTOPLAY_KEY = 'cbmg:thumb-autoplay';
|
|
|
204
204
|
* a toggle, which is a thing you turn on; a default-on preview is a thing you have to
|
|
205
205
|
* discover in order to turn off.
|
|
206
206
|
*
|
|
207
|
-
*
|
|
208
|
-
*
|
|
207
|
+
* On a phone it previews too (2026-10-10 — a pressed "Preview all" that moved nothing was the
|
|
208
|
+
* bug), and {@link HoverScrubVideoThumb}'s on-screen gate keeps it to the tiles in view.
|
|
209
209
|
*/
|
|
210
210
|
export function readThumbAutoplay(): boolean {
|
|
211
211
|
try {
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* after an app's responsive variant (task 2124). An app that imports every area gets exactly
|
|
16
16
|
* what `cursedbelt/styles-utilities.css` emits — proved rule by rule in
|
|
17
17
|
* src/stylesAreas.spec.ts, which is also what fails when this file is stale.
|
|
18
|
-
*
|
|
18
|
+
* 922 candidate(s).
|
|
19
19
|
*
|
|
20
20
|
* Written by scripts/generateAreaStyles.ts (`bun run styles:areas`), which
|
|
21
21
|
* `bun run build` runs. The map of what is in which area, and why the areas are
|
|
@@ -38,11 +38,13 @@
|
|
|
38
38
|
@source inline("[&_[data-icon]]:text-accent [&_[data-icon]]:text-destructive [&_[data-icon]]:text-success");
|
|
39
39
|
@source inline("[&_[data-icon]]:text-warning [&_sup]:leading-none [&_svg]:shrink-0 [&_svg]:size-12");
|
|
40
40
|
@source inline("[&_svg]:size-4 [&_svg]:size-5 [&_svg]:size-6 [--cbfk-sticky-top:-1rem]");
|
|
41
|
-
@source inline("[-webkit-touch-callout:none]
|
|
42
|
-
@source inline("
|
|
43
|
-
@source inline("
|
|
44
|
-
@source inline("
|
|
45
|
-
@source inline("
|
|
41
|
+
@source inline("[-webkit-touch-callout:none] [@media(orientation:landscape)_and_(max-height:500px)]:py-1.5");
|
|
42
|
+
@source inline("[@media(orientation:landscape)_and_(max-height:500px)]:text-h3 a absolute act active");
|
|
43
|
+
@source inline("active:bg-accent active:scale-100 active:scale-[var(--press-scale)]");
|
|
44
|
+
@source inline("active:scale-[var(--press-scale-surface)] alert alert-icon align align-middle an animate");
|
|
45
|
+
@source inline("animate-in animate-progress-indeterminate animate-pulse animate-spin aria");
|
|
46
|
+
@source inline("aria-[invalid=true]:border-field-error aria-[invalid=true]:ring-field-error/30 aria-disabled");
|
|
47
|
+
@source inline("aria-disabled:active:scale-100 aria-disabled:cursor-not-allowed");
|
|
46
48
|
@source inline("aria-disabled:hover:bg-transparent aria-disabled:opacity-30 aria-disabled:opacity-50");
|
|
47
49
|
@source inline("aria-disabled:pointer-events-none aria-pressed aria-pressed:bg-accent/10 aria-pressed:border");
|
|
48
50
|
@source inline("aria-pressed:border-accent aria-pressed:text-accent auto auto-cols-[minmax(min-content,1fr)] b");
|
package/src/styles-utilities.css
CHANGED
|
@@ -5451,6 +5451,14 @@
|
|
|
5451
5451
|
width: calc(var(--spacing) * 3.5);
|
|
5452
5452
|
height: calc(var(--spacing) * 3.5);
|
|
5453
5453
|
}
|
|
5454
|
+
@media (orientation:landscape) and (max-height:500px) {
|
|
5455
|
+
.\[\@media\(orientation\:landscape\)_and_\(max-height\:500px\)\]\:py-1\.5 {
|
|
5456
|
+
padding-block: calc(var(--spacing) * 1.5);
|
|
5457
|
+
}
|
|
5458
|
+
.\[\@media\(orientation\:landscape\)_and_\(max-height\:500px\)\]\:text-h3 {
|
|
5459
|
+
font-size: clamp(1.125rem, 1rem + 0.5vw, 1.25rem);
|
|
5460
|
+
}
|
|
5461
|
+
}
|
|
5454
5462
|
}
|
|
5455
5463
|
@property --tw-translate-x {
|
|
5456
5464
|
syntax: "*";
|