@bendyline/squisq-react 2.10.1 → 2.11.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.
@@ -343,6 +343,16 @@ function useMediaClipDurations(schedule, basePath, mediaProviderOverride) {
343
343
  import { useMemo as useMemo2 } from "react";
344
344
  import { resolveFontFamily } from "@bendyline/squisq/schemas";
345
345
  import { jsx as jsx2 } from "react/jsx-runtime";
346
+ function positionStyle(position) {
347
+ switch (position) {
348
+ case "top":
349
+ return { top: "8%" };
350
+ case "center":
351
+ return { top: "50%", transform: "translateY(-50%)" };
352
+ default:
353
+ return { bottom: "18%" };
354
+ }
355
+ }
346
356
  var TARGET_CHUNK_SIZE = 4;
347
357
  var MIN_CHUNK_SIZE = 2;
348
358
  var MAX_CHUNK_SIZE = 6;
@@ -394,7 +404,8 @@ function SocialCaptionOverlay({
394
404
  currentTime,
395
405
  enabled = true,
396
406
  theme,
397
- viewport
407
+ viewport,
408
+ position = "bottom"
398
409
  }) {
399
410
  const { chunks } = useMemo2(
400
411
  () => captions ? buildWordStream(captions) : { words: [], chunks: [] },
@@ -407,7 +418,7 @@ function SocialCaptionOverlay({
407
418
  className: "social-caption-overlay",
408
419
  style: {
409
420
  position: "absolute",
410
- bottom: "18%",
421
+ ...positionStyle(position),
411
422
  left: 0,
412
423
  right: 0,
413
424
  zIndex: 50,
@@ -469,7 +480,7 @@ function SocialCaptionOverlay({
469
480
  className: "social-caption-overlay",
470
481
  style: {
471
482
  position: "absolute",
472
- bottom: "18%",
483
+ ...positionStyle(position),
473
484
  left: 0,
474
485
  right: 0,
475
486
  zIndex: 50,
@@ -516,12 +527,23 @@ function SocialCaptionOverlay({
516
527
  // src/CaptionOverlay.tsx
517
528
  import { getCaptionAtTime } from "@bendyline/squisq/schemas";
518
529
  import { jsx as jsx3 } from "react/jsx-runtime";
530
+ function standardPositionStyle(position) {
531
+ switch (position) {
532
+ case "bottom":
533
+ return { bottom: "6px", left: "50%", transform: "translateX(-50%)" };
534
+ case "center":
535
+ return { top: "50%", left: "50%", transform: "translate(-50%, -50%)" };
536
+ default:
537
+ return { top: "6px", left: "50%", transform: "translateX(-50%)" };
538
+ }
539
+ }
519
540
  function CaptionOverlay({
520
541
  captions,
521
542
  currentTime,
522
543
  enabled = true,
523
544
  fontSize = 16,
524
545
  captionStyle = "standard",
546
+ captionPosition,
525
547
  theme,
526
548
  viewport
527
549
  }) {
@@ -533,7 +555,8 @@ function CaptionOverlay({
533
555
  currentTime,
534
556
  enabled,
535
557
  theme,
536
- viewport
558
+ viewport,
559
+ position: captionPosition ?? "bottom"
537
560
  }
538
561
  );
539
562
  }
@@ -545,9 +568,7 @@ function CaptionOverlay({
545
568
  className: "caption-overlay",
546
569
  style: {
547
570
  position: "absolute",
548
- top: "6px",
549
- left: "50%",
550
- transform: "translateX(-50%)",
571
+ ...standardPositionStyle(captionPosition ?? "top"),
551
572
  zIndex: 50,
552
573
  pointerEvents: "none",
553
574
  maxWidth: "100%",
@@ -2663,6 +2684,7 @@ function DocPlayerContent({
2663
2684
  theme,
2664
2685
  surface,
2665
2686
  captionStyle = "standard",
2687
+ captionPosition,
2666
2688
  videoPresentation,
2667
2689
  pipSize,
2668
2690
  pipShape,
@@ -2904,10 +2926,7 @@ function DocPlayerContent({
2904
2926
  const [isSlideshowPickerOpen, setIsSlideshowPickerOpen] = useState6(false);
2905
2927
  const slideshowCoverInitKeyRef = useRef7("");
2906
2928
  useEffect7(() => {
2907
- slideshowCoverInitKeyRef.current = "";
2908
- }, [doc]);
2909
- useEffect7(() => {
2910
- const initKey = `${isSlideshowMode}:${hasManagedCover}:${renderMode}`;
2929
+ const initKey = `${doc.articleId}:${isSlideshowMode}:${hasManagedCover}:${renderMode}`;
2911
2930
  if (slideshowCoverInitKeyRef.current === initKey) return;
2912
2931
  slideshowCoverInitKeyRef.current = initKey;
2913
2932
  if (isSlideshowMode && hasManagedCover && !renderMode) {
@@ -2916,7 +2935,7 @@ function DocPlayerContent({
2916
2935
  } else {
2917
2936
  setSlideshowCoverVisible(false);
2918
2937
  }
2919
- }, [isSlideshowMode, hasManagedCover, renderMode, pause]);
2938
+ }, [doc.articleId, isSlideshowMode, hasManagedCover, renderMode, pause]);
2920
2939
  const [coverForced, setCoverForced] = useState6(false);
2921
2940
  const [coverGraceActive, setCoverGraceActive] = useState6(false);
2922
2941
  const coverGraceTimer = useRef7();
@@ -3634,8 +3653,9 @@ function DocPlayerContent({
3634
3653
  captions: doc.captions,
3635
3654
  currentTime,
3636
3655
  enabled: captionsEnabled && (renderMode || isPlaying || currentTime > 0),
3637
- fontSize: 16,
3656
+ fontSize: Math.min(34, Math.max(16, Math.round(activeViewport.height * 0.026))),
3638
3657
  captionStyle: activeCaptionStyle,
3658
+ captionPosition,
3639
3659
  theme: effectiveTheme,
3640
3660
  viewport: activeViewport
3641
3661
  }
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { SquisqRenderAPI, VideoPresentation as VideoPresentation$1, PipSize, PipShape, PipPosition } from './player/index.js';
2
- export { BlockMarker, BlockRenderer, CaptionMode, CaptionOverlay, CaptionStyle, ControlsLayout, DisplayMode, DocControlsBottom, DocControlsOverlay, DocControlsSidebar, DocControlsSlideshow, DocPlayer, DocPlayerProps, DocPlayerWithSidebar, DocProgressBar, FlashcardFaceView, FlashcardFaceViewProps, FlashcardView, FlashcardViewProps, InlineAudioPlayer, InlineAudioPlayerProps, InlineVideoPlayer, InlineVideoPlayerProps, MediaClipLayer, MediaClipLayerProps, PlaybackActions, PlaybackState, RenderAudioSegmentInfo, RenderBlockInfo, RenderCaptionInfo, RenderChapterInfo, SlideNavActions, SocialCaptionOverlay, formatTime } from './player/index.js';
1
+ import { S as SquisqRenderAPI, V as VideoPresentation$1, P as PipSize, a as PipShape, b as PipPosition } from './player-DSMhm8SL.js';
2
+ export { B as BlockMarker, c as BlockRenderer, C as CaptionMode, d as CaptionOverlay, e as CaptionPosition, f as CaptionStyle, g as ControlsLayout, D as DisplayMode, h as DocControlsBottom, i as DocControlsOverlay, j as DocControlsSidebar, k as DocControlsSlideshow, l as DocPlayer, m as DocPlayerProps, n as DocPlayerWithSidebar, o as DocProgressBar, F as FlashcardFaceView, p as FlashcardFaceViewProps, q as FlashcardView, r as FlashcardViewProps, I as InlineAudioPlayer, s as InlineAudioPlayerProps, t as InlineVideoPlayer, u as InlineVideoPlayerProps, M as MediaClipLayer, v as MediaClipLayerProps, w as PlaybackActions, x as PlaybackState, R as RenderAudioSegmentInfo, y as RenderBlockInfo, z as RenderCaptionInfo, A as RenderChapterInfo, E as SlideNavActions, G as SocialCaptionOverlay, H as formatTime } from './player-DSMhm8SL.js';
3
3
  import { Theme, VideoPresentation, VideoPipSize, VideoPipShape, VideoPipPosition, Doc, ScheduledClip, MediaProvider } from '@bendyline/squisq/schemas';
4
4
  import { DashboardStyleId, ViewportConfig, CoverSlideTemplate, CoverSlidePlayback } from '@bendyline/squisq/doc';
5
5
  export { getAnimationStyle, getTransitionClass } from '@bendyline/squisq/doc';
@@ -43,11 +43,14 @@ import '@bendyline/squisq/jsonForm';
43
43
 
44
44
  interface MountOptions {
45
45
  /**
46
- * Rendering mode: 'slideshow' (interactive, default), 'static'
46
+ * Rendering mode: 'slideshow' (interactive, default), 'video' (timed
47
+ * auto-advance playback with scrubber — the movie mode), 'static'
47
48
  * (scrollable page), 'dashboard' (one canvas of arranged blocks), or
48
49
  * 'flashcards' (progressively revealed study deck).
49
50
  */
50
- mode?: 'slideshow' | 'static' | 'dashboard' | 'flashcards';
51
+ mode?: 'slideshow' | 'video' | 'static' | 'dashboard' | 'flashcards';
52
+ /** Loop playback when the timeline ends (video mode only, default: false). */
53
+ loop?: boolean;
51
54
  /** Dashboard-mode options (ignored by the other modes). */
52
55
  dashboard?: {
53
56
  /** Layout id or 'auto'. Overrides doc frontmatter. */
@@ -102,6 +105,8 @@ interface MountOptions {
102
105
  animationsEnabled?: boolean;
103
106
  /** Caption style: 'standard' or 'social'. Omit or set to undefined for no captions. */
104
107
  captionStyle?: 'standard' | 'social';
108
+ /** Caption placement over the frame; omit for the style's classic spot. */
109
+ captionPosition?: 'top' | 'center' | 'bottom';
105
110
  /** Show a Copy button on fenced code blocks in static mode (default: false). */
106
111
  showCodeCopyButton?: boolean;
107
112
  /** Optional host clipboard adapter; otherwise the browser Clipboard API is used. */
package/dist/index.js CHANGED
@@ -15,7 +15,7 @@ import {
15
15
  formatTime,
16
16
  resolveDocPlayerAppearance,
17
17
  useMediaClipDurations
18
- } from "./chunk-NNJLSQPW.js";
18
+ } from "./chunk-FTXPC5QW.js";
19
19
  import {
20
20
  BlockRenderer,
21
21
  CanvasSection,