cursedbelt 5.47.0 → 5.48.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/media/DenseGalleryShell.d.ts +8 -1
- package/dist/react/media/DenseGalleryShell.d.ts.map +1 -1
- package/dist/react/media/DenseGalleryShell.js +33 -8
- package/dist/react/media/DenseGalleryShell.js.map +1 -1
- package/dist/react/media/VideoPlayer.d.ts +12 -1
- package/dist/react/media/VideoPlayer.d.ts.map +1 -1
- package/dist/react/media/VideoPlayer.js +30 -2
- package/dist/react/media/VideoPlayer.js.map +1 -1
- package/dist/react/media/controlBar.d.ts +3 -2
- package/dist/react/media/controlBar.d.ts.map +1 -1
- package/dist/react/media/controlBar.js +16 -10
- package/dist/react/media/controlBar.js.map +1 -1
- package/dist/react/media/denseGallery.css +56 -18
- package/dist/react/media/videoPlayer.css +2 -1
- package/dist/react/media-gallery/MediaGallery.d.ts.map +1 -1
- package/dist/react/media-gallery/MediaGallery.js +8 -4
- package/dist/react/media-gallery/MediaGallery.js.map +1 -1
- package/package.json +1 -1
- package/src/react/media/DenseGalleryShell.spec.tsx +9 -7
- package/src/react/media/DenseGalleryShell.tsx +53 -11
- package/src/react/media/VideoPlayer.tsx +78 -2
- package/src/react/media/controlBar.tsx +17 -10
- package/src/react/media/denseGallery.css +56 -18
- package/src/react/media/videoPlayer.css +2 -1
- package/src/react/media-gallery/MediaGallery.spec.tsx +4 -4
- package/src/react/media-gallery/MediaGallery.tsx +12 -0
|
@@ -622,34 +622,72 @@
|
|
|
622
622
|
overflow: hidden;
|
|
623
623
|
background: var(--background);
|
|
624
624
|
}
|
|
625
|
-
/*
|
|
626
|
-
|
|
625
|
+
/*
|
|
626
|
+
* ── 🔴 Full window: the picture as big as the WINDOW, the files still below it ──────────
|
|
627
|
+
*
|
|
628
|
+
* Owner, 2026-10-02: *"I do not want the video size limited by anything other than the size
|
|
629
|
+
* of the window. This may mean I have to scroll to see anything under the video at all …
|
|
630
|
+
* and that is ok."* So the detail view covers the whole window (`fixed`, over the app's own
|
|
631
|
+
* toolstrip, sidebar and activity column — none of which this module could otherwise reach),
|
|
632
|
+
* stays the scroll container the related grid virtualises against, and the frame is exactly
|
|
633
|
+
* one window tall and wide. The stage letterboxes inside it as it always does, which is what
|
|
634
|
+
* keeps the aspect ratio and every edge of the picture on screen.
|
|
635
|
+
*
|
|
636
|
+
* `--z-overlay`, not higher: a menu or tooltip opened from here is `--z-popover`, and a
|
|
637
|
+
* dialog portalled to <body> comes later in the document at the same layer, so both still
|
|
638
|
+
* draw over it.
|
|
639
|
+
*
|
|
640
|
+
* Until 2026-10-02 this filled the plugin's container instead, and hid the related grid.
|
|
641
|
+
*/
|
|
627
642
|
.cbgd-watch-full {
|
|
628
|
-
|
|
643
|
+
position: fixed;
|
|
644
|
+
inset: 0;
|
|
645
|
+
z-index: var(--z-overlay, 1000);
|
|
646
|
+
height: auto;
|
|
629
647
|
}
|
|
630
648
|
.cbgd-watch-full .cbgd-watch-top {
|
|
631
|
-
display:
|
|
632
|
-
|
|
633
|
-
flex: 1;
|
|
634
|
-
min-height: 0;
|
|
635
|
-
height: 100%;
|
|
636
|
-
}
|
|
637
|
-
.cbgd-watch-full .cbgd-watch-main {
|
|
638
|
-
flex: 1;
|
|
639
|
-
min-height: 0;
|
|
649
|
+
display: block;
|
|
650
|
+
padding: 0;
|
|
640
651
|
}
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
652
|
+
/* Pinning a band that is the whole window would leave nothing to scroll into view. */
|
|
653
|
+
.cbgd-watch-sticky.cbgd-watch-full .cbgd-watch-top {
|
|
654
|
+
position: static;
|
|
655
|
+
max-height: none;
|
|
656
|
+
overflow: visible;
|
|
644
657
|
}
|
|
645
658
|
.cbgd-watch-full .cbgd-watch-player-box {
|
|
646
|
-
|
|
647
|
-
|
|
659
|
+
width: 100%;
|
|
660
|
+
max-width: none;
|
|
661
|
+
height: 100dvh;
|
|
662
|
+
}
|
|
663
|
+
.cbgd-watch-full .cbgd-watch-titlebar {
|
|
664
|
+
padding-inline: 10px;
|
|
648
665
|
}
|
|
649
|
-
.cbgd-watch-full .cbgd-watch-rail,
|
|
650
666
|
.cbgd-watch-full .cbgd-related {
|
|
667
|
+
padding-top: 6px;
|
|
668
|
+
}
|
|
669
|
+
.cbgd-watch-full .cbgd-watch-rail {
|
|
651
670
|
display: none;
|
|
652
671
|
}
|
|
672
|
+
/* The way out for a stage with no control bar of its own (a picture, a document, the native
|
|
673
|
+
`<video controls>`): pinned to the window's corner, quiet until it is wanted. A Vidstack
|
|
674
|
+
video carries its toggle in its own bar instead — `stageOffersFullStageToggle`. */
|
|
675
|
+
.cbgd-full-exit {
|
|
676
|
+
position: fixed;
|
|
677
|
+
top: 12px;
|
|
678
|
+
right: 12px;
|
|
679
|
+
opacity: 0.6;
|
|
680
|
+
transition: opacity 120ms ease;
|
|
681
|
+
}
|
|
682
|
+
/* Solid, because what is under it is a picture of any colour. */
|
|
683
|
+
.cbgd-full-exit .cbgd-order-btn {
|
|
684
|
+
background: var(--background);
|
|
685
|
+
color: var(--foreground);
|
|
686
|
+
}
|
|
687
|
+
.cbgd-full-exit:hover,
|
|
688
|
+
.cbgd-full-exit:focus-within {
|
|
689
|
+
opacity: 1;
|
|
690
|
+
}
|
|
653
691
|
/*
|
|
654
692
|
* An image stage (photo detail) — a letterbox of CONSTANT height.
|
|
655
693
|
*
|
|
@@ -23,7 +23,8 @@
|
|
|
23
23
|
/* Vidstack sizes its icons through `.vds-icon`; the pair only needs to match the seek
|
|
24
24
|
buttons beside them, which are 80% of the play button. */
|
|
25
25
|
.cbvp-step .vds-icon,
|
|
26
|
-
.cbvp-section .vds-icon
|
|
26
|
+
.cbvp-section .vds-icon,
|
|
27
|
+
.cbvp-fill-window .vds-icon {
|
|
27
28
|
width: var(--media-button-icon-size, 80%);
|
|
28
29
|
height: var(--media-button-icon-size, 80%);
|
|
29
30
|
}
|
|
@@ -358,7 +358,7 @@ describe('MediaGallery detail view', () => {
|
|
|
358
358
|
expect(getByRole('button', { name: 'Open beach.jpg' })).toBeDefined();
|
|
359
359
|
// Download + fullscreen affordances.
|
|
360
360
|
expect(getByRole('link', { name: /download/i }).getAttribute('href')).toBe('/files/img1');
|
|
361
|
-
expect(getByRole('button', { name:
|
|
361
|
+
expect(getByRole('button', { name: 'Full window' })).toBeDefined();
|
|
362
362
|
// Back to grid returns to browse.
|
|
363
363
|
fireEvent.click(getByRole('button', { name: 'Back to grid' }));
|
|
364
364
|
expect(container.querySelector('.cbgd-root')).not.toBeNull();
|
|
@@ -1770,7 +1770,7 @@ describe('🔴 double-clicking the stage', () => {
|
|
|
1770
1770
|
fireEvent.doubleClick(frameOf(view.container));
|
|
1771
1771
|
expect(isFull(view.container)).toBe(true);
|
|
1772
1772
|
// The titlebar's own control agrees — one state, two ways into it.
|
|
1773
|
-
expect(view.getByRole('button', { name:
|
|
1773
|
+
expect(view.getByRole('button', { name: 'Full window' }).getAttribute('aria-pressed')).toBe('true');
|
|
1774
1774
|
|
|
1775
1775
|
fireEvent.doubleClick(frameOf(view.container));
|
|
1776
1776
|
expect(isFull(view.container)).toBe(false);
|
|
@@ -1786,7 +1786,7 @@ describe('🔴 double-clicking the stage', () => {
|
|
|
1786
1786
|
test('🔴 …but a video DOES leave the shell fullscreen, because the player stood down', () => {
|
|
1787
1787
|
const view = render(<MediaGallery items={ITEMS} nativeVideoStage />);
|
|
1788
1788
|
fireEvent.click(view.getByRole('button', { name: 'Open clip.mp4' }));
|
|
1789
|
-
fireEvent.click(view.getByRole('button', { name:
|
|
1789
|
+
fireEvent.click(view.getByRole('button', { name: 'Full window' }));
|
|
1790
1790
|
expect(isFull(view.container)).toBe(true);
|
|
1791
1791
|
fireEvent.doubleClick(frameOf(view.container));
|
|
1792
1792
|
expect(isFull(view.container)).toBe(false);
|
|
@@ -2386,7 +2386,7 @@ describe('MediaGallery — the toolbar is icons, and the words are its names', (
|
|
|
2386
2386
|
'Picture',
|
|
2387
2387
|
'Delete this item',
|
|
2388
2388
|
'Back to grid',
|
|
2389
|
-
'
|
|
2389
|
+
'Full window',
|
|
2390
2390
|
]) {
|
|
2391
2391
|
expect(view.getByRole('button', { name }), `no control named "${name}"`).toBeDefined();
|
|
2392
2392
|
}
|
|
@@ -1359,6 +1359,8 @@ function GalleryStage({
|
|
|
1359
1359
|
onStep,
|
|
1360
1360
|
canStep,
|
|
1361
1361
|
fullscreenOnDoubleClick,
|
|
1362
|
+
fillWindow,
|
|
1363
|
+
onFillWindowChange,
|
|
1362
1364
|
}: {
|
|
1363
1365
|
item: MediaGalleryItem;
|
|
1364
1366
|
mediaCache: MediaCache;
|
|
@@ -1377,6 +1379,9 @@ function GalleryStage({
|
|
|
1377
1379
|
canStep?: boolean;
|
|
1378
1380
|
/** False while the SHELL is fullscreen — see `VideoPlayerProps.fullscreenOnDoubleClick`. */
|
|
1379
1381
|
fullscreenOnDoubleClick?: boolean;
|
|
1382
|
+
/** The shell's full-window state, toggled from the player's own bar — see `fillWindowSlots`. */
|
|
1383
|
+
fillWindow?: boolean;
|
|
1384
|
+
onFillWindowChange?: (next: boolean) => void;
|
|
1380
1385
|
}) {
|
|
1381
1386
|
const category = galleryItemCategory(item);
|
|
1382
1387
|
const { media, resolving, refresh } = useItemMedia(item, mediaCache);
|
|
@@ -1444,6 +1449,7 @@ function GalleryStage({
|
|
|
1444
1449
|
{...(repeat ? {} : { onEnded })}
|
|
1445
1450
|
{...(onStep ? { onStep, canStep: canStep !== false } : {})}
|
|
1446
1451
|
{...(fullscreenOnDoubleClick === false ? { fullscreenOnDoubleClick: false } : {})}
|
|
1452
|
+
{...(onFillWindowChange ? { fillWindow: fillWindow === true, onFillWindowChange } : {})}
|
|
1447
1453
|
/>
|
|
1448
1454
|
</React.Suspense>
|
|
1449
1455
|
);
|
|
@@ -2719,6 +2725,10 @@ export function MediaGallery({
|
|
|
2719
2725
|
`⤢ Fullscreen` is what a double-click means on it. Owner, 2026-09-11:
|
|
2720
2726
|
*"Doubleclicking an image to toggle full screen is not working at all."* */
|
|
2721
2727
|
stageOwnsDoubleClick={category === 'video'}
|
|
2728
|
+
/* A Vidstack video carries its own full-window toggle in its control bar, so the
|
|
2729
|
+
shell's floating way out would be a second one over the same picture. The native
|
|
2730
|
+
`<video controls>` stage has no bar of ours, so it keeps the shell's. */
|
|
2731
|
+
stageOffersFullStageToggle={category === 'video' && !nativeVideoStage}
|
|
2722
2732
|
title={selected.name}
|
|
2723
2733
|
meta={
|
|
2724
2734
|
// The date joins the line rather than replacing what was there — beside the title is
|
|
@@ -2767,6 +2777,8 @@ export function MediaGallery({
|
|
|
2767
2777
|
screen video should change back … to non-full screen view") has exactly one
|
|
2768
2778
|
meaning. `DenseGalleryDetail` handles it from the frame instead. */
|
|
2769
2779
|
fullscreenOnDoubleClick={!fullStage}
|
|
2780
|
+
fillWindow={fullStage}
|
|
2781
|
+
onFillWindowChange={setFullStage}
|
|
2770
2782
|
repeat={runRepeatsOne(playbackEnd)}
|
|
2771
2783
|
// 🔴 `advance`, not `step(1)`. The arrows wrap and the RUN does not: `next`
|
|
2772
2784
|
// stops after the last item, `all` starts over, `shuffle` draws from the pass.
|