@bendyline/squisq-react 2.8.0 → 2.9.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/{chunk-LAL43UUN.js → chunk-2Y7F3S6M.js} +729 -194
- package/dist/{chunk-UJEHDVQO.js → chunk-G6FVNYNW.js} +2 -1
- package/dist/{chunk-IQGW6SA6.js → chunk-NGQQKH7J.js} +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.js +7 -3
- package/dist/layers/index.js +1 -1
- package/dist/page/index.js +2 -2
- package/dist/player/index.d.ts +37 -5
- package/dist/player/index.js +7 -3
- package/dist/squisq-player.full.global.js +405 -404
- package/dist/squisq-player.global.js +68 -67
- package/dist/standalone-source.js +1 -1
- package/dist/styles/index.css +312 -0
- package/package.json +2 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
BlockRenderer,
|
|
3
3
|
LinearDocView
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-NGQQKH7J.js";
|
|
5
5
|
import {
|
|
6
6
|
useAudioSync,
|
|
7
7
|
useDocPlayback,
|
|
@@ -11,6 +11,9 @@ import {
|
|
|
11
11
|
import {
|
|
12
12
|
useAutoSurface
|
|
13
13
|
} from "./chunk-TT6ENR6T.js";
|
|
14
|
+
import {
|
|
15
|
+
MarkdownRenderer
|
|
16
|
+
} from "./chunk-ESI3P77P.js";
|
|
14
17
|
import {
|
|
15
18
|
useMediaProvider,
|
|
16
19
|
useMediaUrl,
|
|
@@ -1514,10 +1517,525 @@ function DashboardView({
|
|
|
1514
1517
|
);
|
|
1515
1518
|
}
|
|
1516
1519
|
|
|
1520
|
+
// src/FlashcardView.tsx
|
|
1521
|
+
import {
|
|
1522
|
+
useCallback as useCallback3,
|
|
1523
|
+
useEffect as useEffect5,
|
|
1524
|
+
useMemo as useMemo4,
|
|
1525
|
+
useRef as useRef5,
|
|
1526
|
+
useState as useState4
|
|
1527
|
+
} from "react";
|
|
1528
|
+
import { resolveFontFamily as resolveFontFamily2, VIEWPORT_PRESETS as VIEWPORT_PRESETS2 } from "@bendyline/squisq/schemas";
|
|
1529
|
+
import {
|
|
1530
|
+
materializeBlockLayers,
|
|
1531
|
+
materializeFlashcards,
|
|
1532
|
+
resolvePageBlock,
|
|
1533
|
+
resolveThemeForDoc as resolveThemeForDoc2
|
|
1534
|
+
} from "@bendyline/squisq/doc";
|
|
1535
|
+
import { Fragment as Fragment3, jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1536
|
+
var VISUAL_TEMPLATES = /* @__PURE__ */ new Set([
|
|
1537
|
+
"diagram",
|
|
1538
|
+
"tree",
|
|
1539
|
+
"timeline",
|
|
1540
|
+
"map",
|
|
1541
|
+
"drawing",
|
|
1542
|
+
"layout",
|
|
1543
|
+
"barChart",
|
|
1544
|
+
"columnChart",
|
|
1545
|
+
"pieChart",
|
|
1546
|
+
"donutChart",
|
|
1547
|
+
"lineChart",
|
|
1548
|
+
"areaChart",
|
|
1549
|
+
"scatterChart"
|
|
1550
|
+
]);
|
|
1551
|
+
function resolveVisualBlock(block, theme, viewport, customTemplates) {
|
|
1552
|
+
const resolved = resolvePageBlock(block);
|
|
1553
|
+
const visualTemplate = !!resolved.templateName && (VISUAL_TEMPLATES.has(resolved.templateName) || !!customTemplates?.some((definition) => definition.name === resolved.templateName));
|
|
1554
|
+
if (!visualTemplate) return null;
|
|
1555
|
+
const materializationBlock = resolved.templateBlock ?? block;
|
|
1556
|
+
const { layers, source } = materializeBlockLayers(materializationBlock, {
|
|
1557
|
+
theme,
|
|
1558
|
+
viewport,
|
|
1559
|
+
customTemplates,
|
|
1560
|
+
persistentLayers: false
|
|
1561
|
+
});
|
|
1562
|
+
if (layers.length === 0 || source === "fallback") return null;
|
|
1563
|
+
return { ...materializationBlock, layers };
|
|
1564
|
+
}
|
|
1565
|
+
function FaceBlock({
|
|
1566
|
+
block,
|
|
1567
|
+
depth,
|
|
1568
|
+
theme,
|
|
1569
|
+
basePath,
|
|
1570
|
+
showCodeCopyButton,
|
|
1571
|
+
onCopyCode,
|
|
1572
|
+
fenceRenderers,
|
|
1573
|
+
viewport,
|
|
1574
|
+
customTemplates
|
|
1575
|
+
}) {
|
|
1576
|
+
const Heading = depth === 0 ? "h2" : depth === 1 ? "h3" : "h4";
|
|
1577
|
+
const visualBlock = useMemo4(
|
|
1578
|
+
() => resolveVisualBlock(block, theme, viewport, customTemplates),
|
|
1579
|
+
[block, customTemplates, theme, viewport]
|
|
1580
|
+
);
|
|
1581
|
+
return /* @__PURE__ */ jsxs5("section", { className: "squisq-flashcards__content-block", "data-source-block-id": block.id, children: [
|
|
1582
|
+
!visualBlock && block.title && /* @__PURE__ */ jsx8(Heading, { className: "squisq-flashcards__content-title", children: block.title }),
|
|
1583
|
+
!visualBlock && block.contents && block.contents.length > 0 && /* @__PURE__ */ jsx8(
|
|
1584
|
+
MarkdownRenderer,
|
|
1585
|
+
{
|
|
1586
|
+
nodes: block.contents,
|
|
1587
|
+
theme,
|
|
1588
|
+
showCodeCopyButton,
|
|
1589
|
+
onCopyCode,
|
|
1590
|
+
fenceRenderers
|
|
1591
|
+
}
|
|
1592
|
+
),
|
|
1593
|
+
(visualBlock || block.layers && block.layers.length > 0) && /* @__PURE__ */ jsx8(
|
|
1594
|
+
"div",
|
|
1595
|
+
{
|
|
1596
|
+
className: "squisq-flashcards__canvas",
|
|
1597
|
+
style: { aspectRatio: `${viewport.width} / ${viewport.height}` },
|
|
1598
|
+
children: /* @__PURE__ */ jsx8(
|
|
1599
|
+
BlockRenderer,
|
|
1600
|
+
{
|
|
1601
|
+
block: visualBlock ?? block,
|
|
1602
|
+
blockTime: Math.max(0, block.duration ?? 0),
|
|
1603
|
+
basePath,
|
|
1604
|
+
viewport,
|
|
1605
|
+
animationsEnabled: false,
|
|
1606
|
+
theme,
|
|
1607
|
+
muted: true
|
|
1608
|
+
}
|
|
1609
|
+
)
|
|
1610
|
+
}
|
|
1611
|
+
),
|
|
1612
|
+
!visualBlock && block.children?.map((child) => /* @__PURE__ */ jsx8(
|
|
1613
|
+
FaceBlock,
|
|
1614
|
+
{
|
|
1615
|
+
block: child,
|
|
1616
|
+
depth: depth + 1,
|
|
1617
|
+
theme,
|
|
1618
|
+
basePath,
|
|
1619
|
+
showCodeCopyButton,
|
|
1620
|
+
onCopyCode,
|
|
1621
|
+
fenceRenderers,
|
|
1622
|
+
viewport,
|
|
1623
|
+
customTemplates
|
|
1624
|
+
},
|
|
1625
|
+
child.id
|
|
1626
|
+
))
|
|
1627
|
+
] });
|
|
1628
|
+
}
|
|
1629
|
+
function FaceContent(props) {
|
|
1630
|
+
return /* @__PURE__ */ jsx8("div", { className: "squisq-flashcards__face-content", children: props.face.blocks.map((block) => /* @__PURE__ */ jsx8(FaceBlock, { block, depth: 0, ...props }, block.id)) });
|
|
1631
|
+
}
|
|
1632
|
+
function FlashcardFaceView(props) {
|
|
1633
|
+
return /* @__PURE__ */ jsx8(FaceContent, { ...props, viewport: props.viewport ?? VIEWPORT_PRESETS2.landscape });
|
|
1634
|
+
}
|
|
1635
|
+
function hashSeed(value) {
|
|
1636
|
+
let hash = 2166136261;
|
|
1637
|
+
for (let index = 0; index < value.length; index++) {
|
|
1638
|
+
hash ^= value.charCodeAt(index);
|
|
1639
|
+
hash = Math.imul(hash, 16777619);
|
|
1640
|
+
}
|
|
1641
|
+
return hash >>> 0;
|
|
1642
|
+
}
|
|
1643
|
+
function shuffled(values, seed) {
|
|
1644
|
+
const result = [...values];
|
|
1645
|
+
let state = hashSeed(seed) || 1;
|
|
1646
|
+
const random = () => {
|
|
1647
|
+
state += 1831565813;
|
|
1648
|
+
let next = state;
|
|
1649
|
+
next = Math.imul(next ^ next >>> 15, next | 1);
|
|
1650
|
+
next ^= next + Math.imul(next ^ next >>> 7, next | 61);
|
|
1651
|
+
return ((next ^ next >>> 14) >>> 0) / 4294967296;
|
|
1652
|
+
};
|
|
1653
|
+
for (let index = result.length - 1; index > 0; index--) {
|
|
1654
|
+
const other = Math.floor(random() * (index + 1));
|
|
1655
|
+
[result[index], result[other]] = [result[other], result[index]];
|
|
1656
|
+
}
|
|
1657
|
+
return result;
|
|
1658
|
+
}
|
|
1659
|
+
function ChoiceContent(props) {
|
|
1660
|
+
return /* @__PURE__ */ jsx8(FaceContent, { ...props, face: props.choice.content });
|
|
1661
|
+
}
|
|
1662
|
+
function isInteractiveTarget(target) {
|
|
1663
|
+
return target instanceof Element && !!target.closest('button, a, input, select, textarea, [contenteditable="true"]');
|
|
1664
|
+
}
|
|
1665
|
+
function FlashcardView({
|
|
1666
|
+
doc,
|
|
1667
|
+
theme,
|
|
1668
|
+
basePath = ".",
|
|
1669
|
+
source = "auto",
|
|
1670
|
+
shuffle: initialShuffle = false,
|
|
1671
|
+
globalKeyboardShortcuts = false,
|
|
1672
|
+
showCodeCopyButton = false,
|
|
1673
|
+
onCopyCode,
|
|
1674
|
+
fenceRenderers,
|
|
1675
|
+
viewport = VIEWPORT_PRESETS2.landscape,
|
|
1676
|
+
className
|
|
1677
|
+
}) {
|
|
1678
|
+
const activeTheme = useMemo4(() => theme ?? resolveThemeForDoc2(doc), [doc, theme]);
|
|
1679
|
+
const deck = useMemo4(() => materializeFlashcards(doc, { source }), [doc, source]);
|
|
1680
|
+
const [shuffleEnabled, setShuffleEnabled] = useState4(initialShuffle);
|
|
1681
|
+
const [sessionSeed, setSessionSeed] = useState4(1);
|
|
1682
|
+
const [cardIndex, setCardIndex] = useState4(0);
|
|
1683
|
+
const [revealed, setRevealed] = useState4(false);
|
|
1684
|
+
const [selectedChoiceId, setSelectedChoiceId] = useState4(null);
|
|
1685
|
+
const [ratings, setRatings] = useState4({});
|
|
1686
|
+
const [retryIds, setRetryIds] = useState4(null);
|
|
1687
|
+
const cardViewportRef = useRef5(null);
|
|
1688
|
+
const orderedCards = useMemo4(
|
|
1689
|
+
() => shuffleEnabled ? shuffled(deck.cards, `${doc.articleId}:${sessionSeed}`) : [...deck.cards],
|
|
1690
|
+
[deck.cards, doc.articleId, sessionSeed, shuffleEnabled]
|
|
1691
|
+
);
|
|
1692
|
+
const sessionCards = useMemo4(
|
|
1693
|
+
() => retryIds ? retryIds.map((id) => orderedCards.find((card) => card.id === id)).filter((card) => !!card) : orderedCards,
|
|
1694
|
+
[orderedCards, retryIds]
|
|
1695
|
+
);
|
|
1696
|
+
const currentCard = sessionCards[cardIndex];
|
|
1697
|
+
const finished = sessionCards.length > 0 && cardIndex >= sessionCards.length;
|
|
1698
|
+
const resetPosition = useCallback3(() => {
|
|
1699
|
+
setCardIndex(0);
|
|
1700
|
+
setRevealed(false);
|
|
1701
|
+
setSelectedChoiceId(null);
|
|
1702
|
+
}, []);
|
|
1703
|
+
const restart = useCallback3(() => {
|
|
1704
|
+
setRatings({});
|
|
1705
|
+
setRetryIds(null);
|
|
1706
|
+
resetPosition();
|
|
1707
|
+
setSessionSeed((seed) => seed + 1);
|
|
1708
|
+
}, [resetPosition]);
|
|
1709
|
+
useEffect5(() => {
|
|
1710
|
+
setRatings({});
|
|
1711
|
+
setRetryIds(null);
|
|
1712
|
+
resetPosition();
|
|
1713
|
+
}, [deck, resetPosition]);
|
|
1714
|
+
useEffect5(() => {
|
|
1715
|
+
if (cardViewportRef.current) cardViewportRef.current.scrollTop = 0;
|
|
1716
|
+
}, [cardIndex, retryIds]);
|
|
1717
|
+
const revealAnswer = useCallback3(() => {
|
|
1718
|
+
if (!currentCard) return;
|
|
1719
|
+
setRevealed(true);
|
|
1720
|
+
if (currentCard.kind === "multiple-choice" && selectedChoiceId === null) {
|
|
1721
|
+
setRatings((current) => ({ ...current, [currentCard.id]: "again" }));
|
|
1722
|
+
}
|
|
1723
|
+
}, [currentCard, selectedChoiceId]);
|
|
1724
|
+
const nextCard = useCallback3(() => {
|
|
1725
|
+
if (!currentCard) return;
|
|
1726
|
+
if (!revealed) {
|
|
1727
|
+
revealAnswer();
|
|
1728
|
+
return;
|
|
1729
|
+
}
|
|
1730
|
+
setCardIndex((index) => index + 1);
|
|
1731
|
+
setRevealed(false);
|
|
1732
|
+
setSelectedChoiceId(null);
|
|
1733
|
+
}, [currentCard, revealAnswer, revealed]);
|
|
1734
|
+
const previousCard = useCallback3(() => {
|
|
1735
|
+
if (finished) {
|
|
1736
|
+
setCardIndex(Math.max(0, sessionCards.length - 1));
|
|
1737
|
+
setRevealed(true);
|
|
1738
|
+
return;
|
|
1739
|
+
}
|
|
1740
|
+
if (revealed) {
|
|
1741
|
+
setRevealed(false);
|
|
1742
|
+
setSelectedChoiceId(null);
|
|
1743
|
+
return;
|
|
1744
|
+
}
|
|
1745
|
+
if (cardIndex > 0) {
|
|
1746
|
+
setCardIndex((index) => index - 1);
|
|
1747
|
+
setRevealed(true);
|
|
1748
|
+
setSelectedChoiceId(null);
|
|
1749
|
+
}
|
|
1750
|
+
}, [cardIndex, finished, revealed, sessionCards.length]);
|
|
1751
|
+
const choose = useCallback3(
|
|
1752
|
+
(choice) => {
|
|
1753
|
+
if (!currentCard || revealed) return;
|
|
1754
|
+
setSelectedChoiceId(choice.id);
|
|
1755
|
+
setRevealed(true);
|
|
1756
|
+
setRatings((current) => ({
|
|
1757
|
+
...current,
|
|
1758
|
+
[currentCard.id]: choice.correct ? "got-it" : "again"
|
|
1759
|
+
}));
|
|
1760
|
+
},
|
|
1761
|
+
[currentCard, revealed]
|
|
1762
|
+
);
|
|
1763
|
+
const rate = useCallback3(
|
|
1764
|
+
(rating) => {
|
|
1765
|
+
if (!currentCard) return;
|
|
1766
|
+
setRatings((current) => ({ ...current, [currentCard.id]: rating }));
|
|
1767
|
+
setCardIndex((index) => index + 1);
|
|
1768
|
+
setRevealed(false);
|
|
1769
|
+
setSelectedChoiceId(null);
|
|
1770
|
+
},
|
|
1771
|
+
[currentCard]
|
|
1772
|
+
);
|
|
1773
|
+
const handleShortcut = useCallback3(
|
|
1774
|
+
(event) => {
|
|
1775
|
+
if (event.defaultPrevented || isInteractiveTarget(event.target)) return;
|
|
1776
|
+
if (/^[1-9]$/.test(event.key) && currentCard?.kind === "multiple-choice" && !revealed) {
|
|
1777
|
+
const choice = currentCard.choices?.[Number(event.key) - 1];
|
|
1778
|
+
if (choice) {
|
|
1779
|
+
event.preventDefault();
|
|
1780
|
+
choose(choice);
|
|
1781
|
+
}
|
|
1782
|
+
return;
|
|
1783
|
+
}
|
|
1784
|
+
if (event.key === "ArrowLeft") {
|
|
1785
|
+
event.preventDefault();
|
|
1786
|
+
previousCard();
|
|
1787
|
+
} else if (event.key === "ArrowRight" || event.key === " " || event.key === "Enter") {
|
|
1788
|
+
event.preventDefault();
|
|
1789
|
+
nextCard();
|
|
1790
|
+
}
|
|
1791
|
+
},
|
|
1792
|
+
[choose, currentCard, nextCard, previousCard, revealed]
|
|
1793
|
+
);
|
|
1794
|
+
useEffect5(() => {
|
|
1795
|
+
if (!globalKeyboardShortcuts) return;
|
|
1796
|
+
const listener = (event) => handleShortcut(event);
|
|
1797
|
+
document.addEventListener("keydown", listener);
|
|
1798
|
+
return () => document.removeEventListener("keydown", listener);
|
|
1799
|
+
}, [globalKeyboardShortcuts, handleShortcut]);
|
|
1800
|
+
const faceProps = {
|
|
1801
|
+
theme: activeTheme,
|
|
1802
|
+
basePath,
|
|
1803
|
+
showCodeCopyButton,
|
|
1804
|
+
onCopyCode,
|
|
1805
|
+
fenceRenderers,
|
|
1806
|
+
viewport,
|
|
1807
|
+
customTemplates: doc.customTemplates
|
|
1808
|
+
};
|
|
1809
|
+
const titleFont = resolveFontFamily2(activeTheme.typography.titleFont, "Georgia, serif");
|
|
1810
|
+
const bodyFont = resolveFontFamily2(activeTheme.typography.bodyFont, "system-ui, sans-serif");
|
|
1811
|
+
const rootStyle = {
|
|
1812
|
+
"--squisq-flashcards-bg": activeTheme.colors.background,
|
|
1813
|
+
"--squisq-flashcards-surface": activeTheme.colors.backgroundLight,
|
|
1814
|
+
"--squisq-flashcards-text": activeTheme.colors.text,
|
|
1815
|
+
"--squisq-flashcards-muted": activeTheme.colors.textMuted,
|
|
1816
|
+
"--squisq-flashcards-primary": activeTheme.colors.primary,
|
|
1817
|
+
"--squisq-flashcards-secondary": activeTheme.colors.secondary,
|
|
1818
|
+
"--squisq-flashcards-highlight": activeTheme.colors.highlight,
|
|
1819
|
+
"--squisq-flashcards-warning": activeTheme.colors.warning,
|
|
1820
|
+
"--squisq-flashcards-radius": `${activeTheme.style.borderRadius ?? 18}px`,
|
|
1821
|
+
"--squisq-flashcards-title-font": titleFont,
|
|
1822
|
+
"--squisq-flashcards-body-font": bodyFont
|
|
1823
|
+
};
|
|
1824
|
+
const missedIds = deck.cards.filter((card) => ratings[card.id] === "again").map((card) => card.id);
|
|
1825
|
+
const gotItCount = deck.cards.filter((card) => ratings[card.id] === "got-it").length;
|
|
1826
|
+
if (deck.cards.length === 0) {
|
|
1827
|
+
return /* @__PURE__ */ jsx8(
|
|
1828
|
+
"div",
|
|
1829
|
+
{
|
|
1830
|
+
className: `squisq-flashcards squisq-flashcards--empty${className ? ` ${className}` : ""}`,
|
|
1831
|
+
style: rootStyle,
|
|
1832
|
+
role: "region",
|
|
1833
|
+
"aria-label": "Flashcards",
|
|
1834
|
+
children: /* @__PURE__ */ jsxs5("div", { className: "squisq-flashcards__empty-card", children: [
|
|
1835
|
+
/* @__PURE__ */ jsx8("h2", { children: "No complete flashcards yet" }),
|
|
1836
|
+
/* @__PURE__ */ jsx8("p", { children: "Add an answer beneath a heading, or nest an answer block under a question." }),
|
|
1837
|
+
deck.diagnostics.length > 0 && /* @__PURE__ */ jsx8("ul", { children: deck.diagnostics.map((diagnostic, index) => /* @__PURE__ */ jsx8("li", { children: diagnostic.message }, `${diagnostic.blockId}-${diagnostic.code}-${index}`)) })
|
|
1838
|
+
] })
|
|
1839
|
+
}
|
|
1840
|
+
);
|
|
1841
|
+
}
|
|
1842
|
+
if (finished) {
|
|
1843
|
+
return /* @__PURE__ */ jsx8(
|
|
1844
|
+
"div",
|
|
1845
|
+
{
|
|
1846
|
+
className: `squisq-flashcards${className ? ` ${className}` : ""}`,
|
|
1847
|
+
style: rootStyle,
|
|
1848
|
+
role: "region",
|
|
1849
|
+
"aria-label": "Flashcard session summary",
|
|
1850
|
+
tabIndex: 0,
|
|
1851
|
+
onKeyDown: globalKeyboardShortcuts ? void 0 : handleShortcut,
|
|
1852
|
+
children: /* @__PURE__ */ jsxs5("div", { className: "squisq-flashcards__summary", children: [
|
|
1853
|
+
/* @__PURE__ */ jsx8("span", { className: "squisq-flashcards__eyebrow", children: "Session complete" }),
|
|
1854
|
+
/* @__PURE__ */ jsxs5("h2", { children: [
|
|
1855
|
+
gotItCount,
|
|
1856
|
+
" remembered"
|
|
1857
|
+
] }),
|
|
1858
|
+
/* @__PURE__ */ jsx8("p", { children: missedIds.length === 0 ? `You completed all ${deck.cards.length} cards.` : `${missedIds.length} ${missedIds.length === 1 ? "card needs" : "cards need"} another look.` }),
|
|
1859
|
+
/* @__PURE__ */ jsxs5("div", { className: "squisq-flashcards__summary-actions", children: [
|
|
1860
|
+
missedIds.length > 0 && /* @__PURE__ */ jsx8(
|
|
1861
|
+
"button",
|
|
1862
|
+
{
|
|
1863
|
+
type: "button",
|
|
1864
|
+
className: "squisq-flashcards__button squisq-flashcards__button--primary",
|
|
1865
|
+
onClick: () => {
|
|
1866
|
+
setRetryIds(missedIds);
|
|
1867
|
+
resetPosition();
|
|
1868
|
+
},
|
|
1869
|
+
children: "Retry missed"
|
|
1870
|
+
}
|
|
1871
|
+
),
|
|
1872
|
+
/* @__PURE__ */ jsx8("button", { type: "button", className: "squisq-flashcards__button", onClick: restart, children: "Study again" }),
|
|
1873
|
+
/* @__PURE__ */ jsx8("button", { type: "button", className: "squisq-flashcards__button", onClick: previousCard, children: "Previous card" })
|
|
1874
|
+
] })
|
|
1875
|
+
] })
|
|
1876
|
+
}
|
|
1877
|
+
);
|
|
1878
|
+
}
|
|
1879
|
+
const choices = currentCard?.choices ? shuffled(currentCard.choices, `${currentCard.id}:${sessionSeed}`) : [];
|
|
1880
|
+
const selectedChoice = choices.find((choice) => choice.id === selectedChoiceId);
|
|
1881
|
+
return /* @__PURE__ */ jsxs5(
|
|
1882
|
+
"div",
|
|
1883
|
+
{
|
|
1884
|
+
className: `squisq-flashcards${className ? ` ${className}` : ""}`,
|
|
1885
|
+
style: rootStyle,
|
|
1886
|
+
role: "region",
|
|
1887
|
+
"aria-label": "Flashcards",
|
|
1888
|
+
tabIndex: 0,
|
|
1889
|
+
onKeyDown: globalKeyboardShortcuts ? void 0 : handleShortcut,
|
|
1890
|
+
children: [
|
|
1891
|
+
/* @__PURE__ */ jsxs5("header", { className: "squisq-flashcards__header", children: [
|
|
1892
|
+
/* @__PURE__ */ jsxs5("div", { className: "squisq-flashcards__deck-copy", children: [
|
|
1893
|
+
/* @__PURE__ */ jsx8("span", { className: "squisq-flashcards__eyebrow", children: "Flashcards" }),
|
|
1894
|
+
deck.title && /* @__PURE__ */ jsx8("h1", { children: deck.title })
|
|
1895
|
+
] }),
|
|
1896
|
+
/* @__PURE__ */ jsxs5("div", { className: "squisq-flashcards__tools", children: [
|
|
1897
|
+
/* @__PURE__ */ jsx8(
|
|
1898
|
+
"button",
|
|
1899
|
+
{
|
|
1900
|
+
type: "button",
|
|
1901
|
+
className: "squisq-flashcards__tool",
|
|
1902
|
+
"aria-pressed": shuffleEnabled,
|
|
1903
|
+
onClick: () => {
|
|
1904
|
+
setShuffleEnabled((enabled) => !enabled);
|
|
1905
|
+
restart();
|
|
1906
|
+
},
|
|
1907
|
+
children: "Shuffle"
|
|
1908
|
+
}
|
|
1909
|
+
),
|
|
1910
|
+
/* @__PURE__ */ jsx8("button", { type: "button", className: "squisq-flashcards__tool", onClick: restart, children: "Restart" })
|
|
1911
|
+
] })
|
|
1912
|
+
] }),
|
|
1913
|
+
/* @__PURE__ */ jsxs5("div", { className: "squisq-flashcards__progress-row", children: [
|
|
1914
|
+
/* @__PURE__ */ jsxs5("span", { children: [
|
|
1915
|
+
"Card ",
|
|
1916
|
+
cardIndex + 1,
|
|
1917
|
+
" of ",
|
|
1918
|
+
sessionCards.length
|
|
1919
|
+
] }),
|
|
1920
|
+
/* @__PURE__ */ jsx8("span", { children: revealed ? "Answer revealed" : "Question" })
|
|
1921
|
+
] }),
|
|
1922
|
+
/* @__PURE__ */ jsx8("div", { className: "squisq-flashcards__progress", "aria-hidden": "true", children: /* @__PURE__ */ jsx8(
|
|
1923
|
+
"span",
|
|
1924
|
+
{
|
|
1925
|
+
style: { width: `${(cardIndex + (revealed ? 1 : 0)) / sessionCards.length * 100}%` }
|
|
1926
|
+
}
|
|
1927
|
+
) }),
|
|
1928
|
+
/* @__PURE__ */ jsxs5(
|
|
1929
|
+
"main",
|
|
1930
|
+
{
|
|
1931
|
+
ref: cardViewportRef,
|
|
1932
|
+
className: "squisq-flashcards__card",
|
|
1933
|
+
"data-card-kind": currentCard.kind,
|
|
1934
|
+
"aria-label": "Scrollable flashcard content",
|
|
1935
|
+
tabIndex: 0,
|
|
1936
|
+
children: [
|
|
1937
|
+
currentCard.label && /* @__PURE__ */ jsx8("div", { className: "squisq-flashcards__label", children: currentCard.label }),
|
|
1938
|
+
/* @__PURE__ */ jsx8("section", { className: "squisq-flashcards__front", "aria-label": "Question", children: /* @__PURE__ */ jsx8(FaceContent, { ...faceProps, face: currentCard.front }) }),
|
|
1939
|
+
currentCard.kind === "multiple-choice" && /* @__PURE__ */ jsx8("div", { className: "squisq-flashcards__choices", role: "group", "aria-label": "Answer choices", children: choices.map((choice, index) => {
|
|
1940
|
+
const selected = selectedChoiceId === choice.id;
|
|
1941
|
+
const status = revealed ? choice.correct ? "correct" : selected ? "incorrect" : "idle" : "idle";
|
|
1942
|
+
return /* @__PURE__ */ jsxs5(
|
|
1943
|
+
"button",
|
|
1944
|
+
{
|
|
1945
|
+
type: "button",
|
|
1946
|
+
className: "squisq-flashcards__choice",
|
|
1947
|
+
"data-choice-status": status,
|
|
1948
|
+
"aria-pressed": selected,
|
|
1949
|
+
disabled: revealed,
|
|
1950
|
+
onClick: () => choose(choice),
|
|
1951
|
+
children: [
|
|
1952
|
+
/* @__PURE__ */ jsx8("span", { className: "squisq-flashcards__choice-key", "aria-hidden": "true", children: index + 1 }),
|
|
1953
|
+
/* @__PURE__ */ jsx8(ChoiceContent, { ...faceProps, choice })
|
|
1954
|
+
]
|
|
1955
|
+
},
|
|
1956
|
+
choice.id
|
|
1957
|
+
);
|
|
1958
|
+
}) }),
|
|
1959
|
+
revealed && currentCard.kind === "basic" && /* @__PURE__ */ jsxs5("section", { className: "squisq-flashcards__answer", "aria-label": "Answer", children: [
|
|
1960
|
+
/* @__PURE__ */ jsx8("span", { className: "squisq-flashcards__answer-label", children: "Answer" }),
|
|
1961
|
+
/* @__PURE__ */ jsx8(FaceContent, { ...faceProps, face: currentCard.back })
|
|
1962
|
+
] }),
|
|
1963
|
+
revealed && currentCard.kind === "multiple-choice" && /* @__PURE__ */ jsxs5(
|
|
1964
|
+
"div",
|
|
1965
|
+
{
|
|
1966
|
+
className: "squisq-flashcards__feedback",
|
|
1967
|
+
"data-correct": selectedChoice?.correct === true,
|
|
1968
|
+
"aria-live": "polite",
|
|
1969
|
+
children: [
|
|
1970
|
+
/* @__PURE__ */ jsx8("strong", { children: selectedChoice === void 0 ? "Answer revealed" : selectedChoice.correct ? "Correct" : "Not quite" }),
|
|
1971
|
+
!selectedChoice?.correct && /* @__PURE__ */ jsxs5("div", { className: "squisq-flashcards__correct-answer", children: [
|
|
1972
|
+
/* @__PURE__ */ jsx8("span", { children: "The correct answer is" }),
|
|
1973
|
+
/* @__PURE__ */ jsx8(FaceContent, { ...faceProps, face: currentCard.back })
|
|
1974
|
+
] })
|
|
1975
|
+
]
|
|
1976
|
+
}
|
|
1977
|
+
),
|
|
1978
|
+
revealed && currentCard.explanation && /* @__PURE__ */ jsxs5("section", { className: "squisq-flashcards__explanation", "aria-label": "Explanation", children: [
|
|
1979
|
+
/* @__PURE__ */ jsx8("span", { className: "squisq-flashcards__answer-label", children: "Explanation" }),
|
|
1980
|
+
/* @__PURE__ */ jsx8(FaceContent, { ...faceProps, face: currentCard.explanation })
|
|
1981
|
+
] })
|
|
1982
|
+
]
|
|
1983
|
+
}
|
|
1984
|
+
),
|
|
1985
|
+
/* @__PURE__ */ jsxs5("footer", { className: "squisq-flashcards__footer", children: [
|
|
1986
|
+
/* @__PURE__ */ jsx8(
|
|
1987
|
+
"button",
|
|
1988
|
+
{
|
|
1989
|
+
type: "button",
|
|
1990
|
+
className: "squisq-flashcards__button",
|
|
1991
|
+
disabled: cardIndex === 0 && !revealed,
|
|
1992
|
+
onClick: previousCard,
|
|
1993
|
+
children: "Previous"
|
|
1994
|
+
}
|
|
1995
|
+
),
|
|
1996
|
+
/* @__PURE__ */ jsx8("div", { className: "squisq-flashcards__primary-actions", children: revealed && currentCard.kind === "basic" ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
1997
|
+
/* @__PURE__ */ jsx8(
|
|
1998
|
+
"button",
|
|
1999
|
+
{
|
|
2000
|
+
type: "button",
|
|
2001
|
+
className: "squisq-flashcards__button",
|
|
2002
|
+
onClick: () => rate("again"),
|
|
2003
|
+
children: "Again"
|
|
2004
|
+
}
|
|
2005
|
+
),
|
|
2006
|
+
/* @__PURE__ */ jsx8(
|
|
2007
|
+
"button",
|
|
2008
|
+
{
|
|
2009
|
+
type: "button",
|
|
2010
|
+
className: "squisq-flashcards__button squisq-flashcards__button--primary",
|
|
2011
|
+
onClick: () => rate("got-it"),
|
|
2012
|
+
children: "Got it"
|
|
2013
|
+
}
|
|
2014
|
+
)
|
|
2015
|
+
] }) : /* @__PURE__ */ jsx8(
|
|
2016
|
+
"button",
|
|
2017
|
+
{
|
|
2018
|
+
type: "button",
|
|
2019
|
+
className: "squisq-flashcards__button squisq-flashcards__button--primary",
|
|
2020
|
+
onClick: nextCard,
|
|
2021
|
+
children: revealed ? cardIndex === sessionCards.length - 1 ? "Finish" : "Next card" : "Reveal answer"
|
|
2022
|
+
}
|
|
2023
|
+
) })
|
|
2024
|
+
] }),
|
|
2025
|
+
/* @__PURE__ */ jsxs5("p", { className: "squisq-flashcards__shortcut-hint", children: [
|
|
2026
|
+
"Use \u2190 and \u2192 to navigate, Space to reveal",
|
|
2027
|
+
currentCard.kind === "multiple-choice" ? ", or 1\u20139 to answer" : "",
|
|
2028
|
+
"."
|
|
2029
|
+
] })
|
|
2030
|
+
]
|
|
2031
|
+
}
|
|
2032
|
+
);
|
|
2033
|
+
}
|
|
2034
|
+
|
|
1517
2035
|
// src/docPlayer/playerAppearance.ts
|
|
1518
2036
|
import {
|
|
1519
2037
|
resolveCoverSlideSettings,
|
|
1520
|
-
resolveThemeForDoc as
|
|
2038
|
+
resolveThemeForDoc as resolveThemeForDoc3
|
|
1521
2039
|
} from "@bendyline/squisq/doc";
|
|
1522
2040
|
function readFrontmatterSetting(frontmatter, canonical, legacy) {
|
|
1523
2041
|
if (!frontmatter) return void 0;
|
|
@@ -1575,7 +2093,7 @@ function resolveDocPlayerAppearance(doc, overrides = {}) {
|
|
|
1575
2093
|
...overrides.coverSlidePlayback !== void 0 ? { playback: overrides.coverSlidePlayback } : {}
|
|
1576
2094
|
});
|
|
1577
2095
|
return {
|
|
1578
|
-
theme: overrides.theme ??
|
|
2096
|
+
theme: overrides.theme ?? resolveThemeForDoc3(doc),
|
|
1579
2097
|
videoPresentation: overrides.videoPresentation ?? resolveVideoPresentation(
|
|
1580
2098
|
readFrontmatterSetting(frontmatter, "squisq-video-presentation", "video-presentation")
|
|
1581
2099
|
) ?? "background",
|
|
@@ -1593,14 +2111,14 @@ function resolveDocPlayerAppearance(doc, overrides = {}) {
|
|
|
1593
2111
|
|
|
1594
2112
|
// src/DocPlayer.tsx
|
|
1595
2113
|
import {
|
|
1596
|
-
Fragment as
|
|
2114
|
+
Fragment as Fragment4,
|
|
1597
2115
|
useId as useId2,
|
|
1598
|
-
useRef as
|
|
1599
|
-
useState as
|
|
1600
|
-
useEffect as
|
|
2116
|
+
useRef as useRef7,
|
|
2117
|
+
useState as useState6,
|
|
2118
|
+
useEffect as useEffect7,
|
|
1601
2119
|
useLayoutEffect as useLayoutEffect2,
|
|
1602
|
-
useCallback as
|
|
1603
|
-
useMemo as
|
|
2120
|
+
useCallback as useCallback5,
|
|
2121
|
+
useMemo as useMemo5
|
|
1604
2122
|
} from "react";
|
|
1605
2123
|
import { flushSync } from "react-dom";
|
|
1606
2124
|
import {
|
|
@@ -1612,7 +2130,7 @@ import {
|
|
|
1612
2130
|
import { applySurface, pipStyleVars } from "@bendyline/squisq/schemas";
|
|
1613
2131
|
|
|
1614
2132
|
// src/hooks/useSlideSwipe.ts
|
|
1615
|
-
import { useCallback as
|
|
2133
|
+
import { useCallback as useCallback4, useEffect as useEffect6, useRef as useRef6, useState as useState5 } from "react";
|
|
1616
2134
|
var DISTANCE_RATIO = 0.3;
|
|
1617
2135
|
var FLICK_VELOCITY = 0.5;
|
|
1618
2136
|
var MIN_FLICK_DISTANCE = 12;
|
|
@@ -1636,16 +2154,16 @@ function decideSwipe({
|
|
|
1636
2154
|
}
|
|
1637
2155
|
function useSlideSwipe(opts) {
|
|
1638
2156
|
const settleMs = opts.settleMs ?? DEFAULT_SETTLE_MS;
|
|
1639
|
-
const [offsetPx, setOffsetPx] =
|
|
1640
|
-
const [phase, setPhase] =
|
|
1641
|
-
const optsRef =
|
|
2157
|
+
const [offsetPx, setOffsetPx] = useState5(0);
|
|
2158
|
+
const [phase, setPhase] = useState5("idle");
|
|
2159
|
+
const optsRef = useRef6(opts);
|
|
1642
2160
|
optsRef.current = opts;
|
|
1643
|
-
const dragRef =
|
|
1644
|
-
const phaseRef =
|
|
2161
|
+
const dragRef = useRef6(null);
|
|
2162
|
+
const phaseRef = useRef6("idle");
|
|
1645
2163
|
phaseRef.current = phase;
|
|
1646
|
-
const settleTimer =
|
|
1647
|
-
const settleRaf =
|
|
1648
|
-
const clearPending =
|
|
2164
|
+
const settleTimer = useRef6(null);
|
|
2165
|
+
const settleRaf = useRef6(null);
|
|
2166
|
+
const clearPending = useCallback4(() => {
|
|
1649
2167
|
if (settleTimer.current != null) {
|
|
1650
2168
|
clearTimeout(settleTimer.current);
|
|
1651
2169
|
settleTimer.current = null;
|
|
@@ -1655,7 +2173,7 @@ function useSlideSwipe(opts) {
|
|
|
1655
2173
|
settleRaf.current = null;
|
|
1656
2174
|
}
|
|
1657
2175
|
}, []);
|
|
1658
|
-
const onPointerDown =
|
|
2176
|
+
const onPointerDown = useCallback4((e) => {
|
|
1659
2177
|
const o = optsRef.current;
|
|
1660
2178
|
if (!o.enabled) return;
|
|
1661
2179
|
if (phaseRef.current === "settling") return;
|
|
@@ -1675,7 +2193,7 @@ function useSlideSwipe(opts) {
|
|
|
1675
2193
|
setPhase("dragging");
|
|
1676
2194
|
setOffsetPx(0);
|
|
1677
2195
|
}, []);
|
|
1678
|
-
|
|
2196
|
+
useEffect6(() => {
|
|
1679
2197
|
function currentWidth() {
|
|
1680
2198
|
return optsRef.current.containerRef.current?.getBoundingClientRect().width ?? 0;
|
|
1681
2199
|
}
|
|
@@ -1745,7 +2263,7 @@ function useSlideSwipe(opts) {
|
|
|
1745
2263
|
window.removeEventListener("pointercancel", onCancel);
|
|
1746
2264
|
};
|
|
1747
2265
|
}, [settleMs]);
|
|
1748
|
-
|
|
2266
|
+
useEffect6(() => {
|
|
1749
2267
|
if (!opts.enabled) {
|
|
1750
2268
|
dragRef.current = null;
|
|
1751
2269
|
clearPending();
|
|
@@ -1753,7 +2271,7 @@ function useSlideSwipe(opts) {
|
|
|
1753
2271
|
setOffsetPx(0);
|
|
1754
2272
|
}
|
|
1755
2273
|
}, [opts.enabled, clearPending]);
|
|
1756
|
-
|
|
2274
|
+
useEffect6(() => clearPending, [clearPending]);
|
|
1757
2275
|
return { offsetPx, phase, onPointerDown };
|
|
1758
2276
|
}
|
|
1759
2277
|
|
|
@@ -1762,7 +2280,7 @@ import {
|
|
|
1762
2280
|
expandCoverBlock,
|
|
1763
2281
|
createTemplateContext,
|
|
1764
2282
|
markdownToDoc,
|
|
1765
|
-
VIEWPORT_PRESETS as
|
|
2283
|
+
VIEWPORT_PRESETS as VIEWPORT_PRESETS3
|
|
1766
2284
|
} from "@bendyline/squisq/doc";
|
|
1767
2285
|
import { parseMarkdown } from "@bendyline/squisq/markdown";
|
|
1768
2286
|
|
|
@@ -2052,7 +2570,7 @@ function seekVideoToFrame(video, targetTime, timeoutMs = DEFAULT_VIDEO_FRAME_TIM
|
|
|
2052
2570
|
}
|
|
2053
2571
|
|
|
2054
2572
|
// src/DocPlayer.tsx
|
|
2055
|
-
import { jsx as
|
|
2573
|
+
import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
2056
2574
|
function isDevEnvironment() {
|
|
2057
2575
|
try {
|
|
2058
2576
|
return typeof process !== "undefined" && process.env.NODE_ENV !== "production";
|
|
@@ -2084,15 +2602,30 @@ function waitForVisualUpdate() {
|
|
|
2084
2602
|
}
|
|
2085
2603
|
function DocPlayer(props) {
|
|
2086
2604
|
const { doc, markdown } = props;
|
|
2087
|
-
const markdownDoc =
|
|
2605
|
+
const markdownDoc = useMemo5(
|
|
2088
2606
|
() => !doc && markdown !== void 0 ? markdownToDoc(parseMarkdown(markdown)) : void 0,
|
|
2089
2607
|
[doc, markdown]
|
|
2090
2608
|
);
|
|
2091
2609
|
const resolvedDoc = doc ?? markdownDoc;
|
|
2092
2610
|
if (!resolvedDoc) {
|
|
2093
|
-
return /* @__PURE__ */
|
|
2611
|
+
return /* @__PURE__ */ jsx9("div", { className: "doc-player doc-player--empty" });
|
|
2094
2612
|
}
|
|
2095
|
-
|
|
2613
|
+
if (props.displayMode === "flashcards") {
|
|
2614
|
+
return /* @__PURE__ */ jsx9("div", { className: "doc-player doc-player--flashcards", children: /* @__PURE__ */ jsx9(
|
|
2615
|
+
FlashcardView,
|
|
2616
|
+
{
|
|
2617
|
+
doc: resolvedDoc,
|
|
2618
|
+
basePath: props.basePath,
|
|
2619
|
+
theme: props.theme,
|
|
2620
|
+
globalKeyboardShortcuts: props.globalKeyboardShortcuts,
|
|
2621
|
+
showCodeCopyButton: props.showCodeCopyButton,
|
|
2622
|
+
onCopyCode: props.onCopyCode,
|
|
2623
|
+
fenceRenderers: props.fenceRenderers,
|
|
2624
|
+
viewport: props.forceViewport
|
|
2625
|
+
}
|
|
2626
|
+
) });
|
|
2627
|
+
}
|
|
2628
|
+
return /* @__PURE__ */ jsx9(DocPlayerContent, { ...props, doc: resolvedDoc });
|
|
2096
2629
|
}
|
|
2097
2630
|
function DocPlayerContent({
|
|
2098
2631
|
doc,
|
|
@@ -2143,20 +2676,20 @@ function DocPlayerContent({
|
|
|
2143
2676
|
const isSlideshowMode = displayMode === "slideshow";
|
|
2144
2677
|
const isLinearMode = displayMode === "linear";
|
|
2145
2678
|
const isDashboardMode = displayMode === "dashboard";
|
|
2146
|
-
const audioRef =
|
|
2147
|
-
const containerRef =
|
|
2679
|
+
const audioRef = useRef7(null);
|
|
2680
|
+
const containerRef = useRef7(null);
|
|
2148
2681
|
const playerId = `squisq-player-${useId2().replace(/:/g, "")}`;
|
|
2149
|
-
const [tapFeedback, setTapFeedback] =
|
|
2150
|
-
const tapFeedbackTimer =
|
|
2682
|
+
const [tapFeedback, setTapFeedback] = useState6(null);
|
|
2683
|
+
const tapFeedbackTimer = useRef7();
|
|
2151
2684
|
const { viewport } = useViewportOrientation();
|
|
2152
|
-
const activeViewport = forceViewport || (renderMode ?
|
|
2685
|
+
const activeViewport = forceViewport || (renderMode ? VIEWPORT_PRESETS3.landscape : viewport);
|
|
2153
2686
|
const activeOrientation = activeViewport.height > activeViewport.width ? "portrait" : "landscape";
|
|
2154
|
-
const isDebugMode =
|
|
2687
|
+
const isDebugMode = useMemo5(() => {
|
|
2155
2688
|
if (typeof window === "undefined") return false;
|
|
2156
2689
|
const params = new URLSearchParams(window.location.search);
|
|
2157
2690
|
return params.get("debug") === "true";
|
|
2158
2691
|
}, []);
|
|
2159
|
-
const syntheticDuration =
|
|
2692
|
+
const syntheticDuration = useMemo5(
|
|
2160
2693
|
() => audioMode === "synthetic" ? getDocPlaybackDuration(doc) : 0,
|
|
2161
2694
|
[audioMode, doc]
|
|
2162
2695
|
);
|
|
@@ -2169,7 +2702,7 @@ function DocPlayerContent({
|
|
|
2169
2702
|
syntheticDuration
|
|
2170
2703
|
);
|
|
2171
2704
|
const audio = externalAudioController || internalAudio;
|
|
2172
|
-
|
|
2705
|
+
useEffect7(() => {
|
|
2173
2706
|
if (warnedMissingStyles || !isDevEnvironment()) return;
|
|
2174
2707
|
const el = containerRef.current;
|
|
2175
2708
|
if (!el || typeof getComputedStyle !== "function") return;
|
|
@@ -2197,16 +2730,16 @@ function DocPlayerContent({
|
|
|
2197
2730
|
skipToSegment: _skipToSegment,
|
|
2198
2731
|
restart
|
|
2199
2732
|
} = audio;
|
|
2200
|
-
const [renderClock, setRenderClock] =
|
|
2733
|
+
const [renderClock, setRenderClock] = useState6(null);
|
|
2201
2734
|
const renderTimeOverride = renderClock?.doc === doc ? renderClock.time : null;
|
|
2202
2735
|
const currentTime = renderMode ? renderTimeOverride ?? audioCurrentTime : audioCurrentTime;
|
|
2203
|
-
const rawSchedule =
|
|
2736
|
+
const rawSchedule = useMemo5(() => resolveMediaSchedule(doc), [doc]);
|
|
2204
2737
|
const clipDurations = useMediaClipDurations(rawSchedule, basePath);
|
|
2205
|
-
const mediaSchedule =
|
|
2738
|
+
const mediaSchedule = useMemo5(
|
|
2206
2739
|
() => resolveMediaSchedule(doc, { intrinsicDuration: (clip) => clipDurations.get(clip.src) }),
|
|
2207
2740
|
[doc, clipDurations]
|
|
2208
2741
|
);
|
|
2209
|
-
const startActiveTimelineMedia =
|
|
2742
|
+
const startActiveTimelineMedia = useCallback5(() => {
|
|
2210
2743
|
if (renderMode) return;
|
|
2211
2744
|
const root = containerRef.current;
|
|
2212
2745
|
if (!root) return;
|
|
@@ -2219,21 +2752,21 @@ function DocPlayerContent({
|
|
|
2219
2752
|
});
|
|
2220
2753
|
});
|
|
2221
2754
|
}, [renderMode]);
|
|
2222
|
-
const playWithTimelineMedia =
|
|
2755
|
+
const playWithTimelineMedia = useCallback5(() => {
|
|
2223
2756
|
startActiveTimelineMedia();
|
|
2224
2757
|
return play();
|
|
2225
2758
|
}, [play, startActiveTimelineMedia]);
|
|
2226
|
-
const toggleWithTimelineMedia =
|
|
2759
|
+
const toggleWithTimelineMedia = useCallback5(() => {
|
|
2227
2760
|
if (!isPlaying) startActiveTimelineMedia();
|
|
2228
2761
|
return toggle();
|
|
2229
2762
|
}, [isPlaying, startActiveTimelineMedia, toggle]);
|
|
2230
|
-
const currentTimeRef =
|
|
2763
|
+
const currentTimeRef = useRef7(currentTime);
|
|
2231
2764
|
currentTimeRef.current = currentTime;
|
|
2232
|
-
const committedRenderTimeRef =
|
|
2233
|
-
const renderCommitWaitersRef =
|
|
2234
|
-
const totalDurationRef =
|
|
2765
|
+
const committedRenderTimeRef = useRef7(currentTime);
|
|
2766
|
+
const renderCommitWaitersRef = useRef7([]);
|
|
2767
|
+
const totalDurationRef = useRef7(totalDuration);
|
|
2235
2768
|
totalDurationRef.current = totalDuration;
|
|
2236
|
-
const expandedBlocksLenRef =
|
|
2769
|
+
const expandedBlocksLenRef = useRef7(0);
|
|
2237
2770
|
useLayoutEffect2(() => {
|
|
2238
2771
|
committedRenderTimeRef.current = currentTime;
|
|
2239
2772
|
const pending = renderCommitWaitersRef.current;
|
|
@@ -2243,14 +2776,14 @@ function DocPlayerContent({
|
|
|
2243
2776
|
return false;
|
|
2244
2777
|
});
|
|
2245
2778
|
}, [currentTime]);
|
|
2246
|
-
|
|
2779
|
+
useEffect7(
|
|
2247
2780
|
() => () => {
|
|
2248
2781
|
const error = new Error("DocPlayer unmounted before the requested frame committed.");
|
|
2249
2782
|
renderCommitWaitersRef.current.splice(0).forEach((waiter) => waiter.reject(error));
|
|
2250
2783
|
},
|
|
2251
2784
|
[]
|
|
2252
2785
|
);
|
|
2253
|
-
const waitForRenderCommit =
|
|
2786
|
+
const waitForRenderCommit = useCallback5((time) => {
|
|
2254
2787
|
if (Math.abs(committedRenderTimeRef.current - time) <= RENDER_TIME_EPSILON_SECONDS) {
|
|
2255
2788
|
return Promise.resolve();
|
|
2256
2789
|
}
|
|
@@ -2258,7 +2791,7 @@ function DocPlayerContent({
|
|
|
2258
2791
|
renderCommitWaitersRef.current.push({ time, resolve, reject });
|
|
2259
2792
|
});
|
|
2260
2793
|
}, []);
|
|
2261
|
-
const handleContainerClick =
|
|
2794
|
+
const handleContainerClick = useCallback5(
|
|
2262
2795
|
(e) => {
|
|
2263
2796
|
if (renderMode || isLinearMode) return;
|
|
2264
2797
|
const target = e.target;
|
|
@@ -2283,7 +2816,7 @@ function DocPlayerContent({
|
|
|
2283
2816
|
);
|
|
2284
2817
|
const autoSurface = useAutoSurface(surface === "auto");
|
|
2285
2818
|
const resolvedSurface = surface === "auto" ? autoSurface : surface;
|
|
2286
|
-
const appearance =
|
|
2819
|
+
const appearance = useMemo5(
|
|
2287
2820
|
() => resolveDocPlayerAppearance(doc, {
|
|
2288
2821
|
theme,
|
|
2289
2822
|
videoPresentation,
|
|
@@ -2308,13 +2841,13 @@ function DocPlayerContent({
|
|
|
2308
2841
|
coverSlidePlayback
|
|
2309
2842
|
]
|
|
2310
2843
|
);
|
|
2311
|
-
const effectiveTheme =
|
|
2844
|
+
const effectiveTheme = useMemo5(() => {
|
|
2312
2845
|
const base = appearance.theme;
|
|
2313
2846
|
return resolvedSurface ? applySurface(base, resolvedSurface) : base;
|
|
2314
2847
|
}, [appearance.theme, resolvedSurface]);
|
|
2315
|
-
const resolvedPipStyle =
|
|
2848
|
+
const resolvedPipStyle = useMemo5(() => pipStyleVars(effectiveTheme), [effectiveTheme]);
|
|
2316
2849
|
const pipVars = resolvedPipStyle;
|
|
2317
|
-
const pipFrameStyle =
|
|
2850
|
+
const pipFrameStyle = useMemo5(
|
|
2318
2851
|
() => ({
|
|
2319
2852
|
border: resolvedPipStyle["--squisq-pip-border"],
|
|
2320
2853
|
borderRadius: resolvedPipStyle["--squisq-pip-radius"],
|
|
@@ -2344,7 +2877,7 @@ function DocPlayerContent({
|
|
|
2344
2877
|
// remove authored slides from the default loss-averse projection.
|
|
2345
2878
|
useAudioSegmentTiming: audioMode !== "synthetic"
|
|
2346
2879
|
});
|
|
2347
|
-
const coverBlock =
|
|
2880
|
+
const coverBlock = useMemo5(() => {
|
|
2348
2881
|
const startBlockConfig = doc.startBlock;
|
|
2349
2882
|
if (!appearance.showCoverSlide) return null;
|
|
2350
2883
|
if (!startBlockConfig) return null;
|
|
@@ -2367,13 +2900,13 @@ function DocPlayerContent({
|
|
|
2367
2900
|
appearance.coverSlideTemplate
|
|
2368
2901
|
]);
|
|
2369
2902
|
const hasManagedCover = !!coverBlock;
|
|
2370
|
-
const [slideshowCoverVisible, setSlideshowCoverVisible] =
|
|
2371
|
-
const [isSlideshowPickerOpen, setIsSlideshowPickerOpen] =
|
|
2372
|
-
const slideshowCoverInitKeyRef =
|
|
2373
|
-
|
|
2903
|
+
const [slideshowCoverVisible, setSlideshowCoverVisible] = useState6(false);
|
|
2904
|
+
const [isSlideshowPickerOpen, setIsSlideshowPickerOpen] = useState6(false);
|
|
2905
|
+
const slideshowCoverInitKeyRef = useRef7("");
|
|
2906
|
+
useEffect7(() => {
|
|
2374
2907
|
slideshowCoverInitKeyRef.current = "";
|
|
2375
2908
|
}, [doc]);
|
|
2376
|
-
|
|
2909
|
+
useEffect7(() => {
|
|
2377
2910
|
const initKey = `${isSlideshowMode}:${hasManagedCover}:${renderMode}`;
|
|
2378
2911
|
if (slideshowCoverInitKeyRef.current === initKey) return;
|
|
2379
2912
|
slideshowCoverInitKeyRef.current = initKey;
|
|
@@ -2384,12 +2917,12 @@ function DocPlayerContent({
|
|
|
2384
2917
|
setSlideshowCoverVisible(false);
|
|
2385
2918
|
}
|
|
2386
2919
|
}, [isSlideshowMode, hasManagedCover, renderMode, pause]);
|
|
2387
|
-
const [coverForced, setCoverForced] =
|
|
2388
|
-
const [coverGraceActive, setCoverGraceActive] =
|
|
2389
|
-
const coverGraceTimer =
|
|
2390
|
-
const coverWasShowing =
|
|
2391
|
-
const hasPlayedOnce =
|
|
2392
|
-
|
|
2920
|
+
const [coverForced, setCoverForced] = useState6(false);
|
|
2921
|
+
const [coverGraceActive, setCoverGraceActive] = useState6(false);
|
|
2922
|
+
const coverGraceTimer = useRef7();
|
|
2923
|
+
const coverWasShowing = useRef7(false);
|
|
2924
|
+
const hasPlayedOnce = useRef7(false);
|
|
2925
|
+
useEffect7(() => {
|
|
2393
2926
|
hasPlayedOnce.current = false;
|
|
2394
2927
|
coverWasShowing.current = false;
|
|
2395
2928
|
clearTimeout(coverGraceTimer.current);
|
|
@@ -2398,7 +2931,7 @@ function DocPlayerContent({
|
|
|
2398
2931
|
}, [doc]);
|
|
2399
2932
|
const atRest = !!(coverBlock && !isSlideshowMode && !isPlaying && currentTime === 0 && !hasPlayedOnce.current && !renderMode && !autoPlay);
|
|
2400
2933
|
if (atRest) coverWasShowing.current = true;
|
|
2401
|
-
|
|
2934
|
+
useEffect7(() => {
|
|
2402
2935
|
if (isPlaying && coverWasShowing.current && coverBlock && !renderMode && !isSlideshowMode) {
|
|
2403
2936
|
coverWasShowing.current = false;
|
|
2404
2937
|
hasPlayedOnce.current = true;
|
|
@@ -2409,8 +2942,8 @@ function DocPlayerContent({
|
|
|
2409
2942
|
);
|
|
2410
2943
|
}
|
|
2411
2944
|
}, [isPlaying, coverBlock, renderMode, isSlideshowMode, appearance.coverSlideDuration]);
|
|
2412
|
-
|
|
2413
|
-
|
|
2945
|
+
useEffect7(() => () => clearTimeout(coverGraceTimer.current), []);
|
|
2946
|
+
useEffect7(() => () => clearTimeout(tapFeedbackTimer.current), []);
|
|
2414
2947
|
const showVideoCoverBlock = !isSlideshowMode && !isLinearMode && !!coverBlock && (coverForced || coverGraceActive || !isPlaying && currentTime === 0 && !hasPlayedOnce.current && !renderMode && !autoPlay);
|
|
2415
2948
|
const effectiveSlideshowCoverVisible = coverVisible ?? slideshowCoverVisible;
|
|
2416
2949
|
const showSlideshowCover = !!(isSlideshowMode && !isLinearMode && !renderMode && coverBlock && effectiveSlideshowCoverVisible);
|
|
@@ -2418,20 +2951,20 @@ function DocPlayerContent({
|
|
|
2418
2951
|
const slideshowHasCover = !!(isSlideshowMode && !renderMode && coverBlock);
|
|
2419
2952
|
const slideshowSlideIndex = slideshowHasCover ? effectiveSlideshowCoverVisible ? 0 : currentBlockIndex + 1 : currentBlockIndex;
|
|
2420
2953
|
const slideshowTotalSlides = slideshowHasCover ? expandedBlocks.length + 1 : expandedBlocks.length;
|
|
2421
|
-
const hasAutoPlayed =
|
|
2422
|
-
|
|
2954
|
+
const hasAutoPlayed = useRef7(false);
|
|
2955
|
+
useEffect7(() => {
|
|
2423
2956
|
hasAutoPlayed.current = false;
|
|
2424
2957
|
}, [doc]);
|
|
2425
|
-
|
|
2958
|
+
useEffect7(() => {
|
|
2426
2959
|
if (isAudioReady && autoPlay && !hasAutoPlayed.current) {
|
|
2427
2960
|
hasAutoPlayed.current = true;
|
|
2428
2961
|
playWithTimelineMedia();
|
|
2429
2962
|
}
|
|
2430
2963
|
}, [isAudioReady, autoPlay, playWithTimelineMedia]);
|
|
2431
|
-
|
|
2964
|
+
useEffect7(() => {
|
|
2432
2965
|
onTimeUpdate?.(currentTime);
|
|
2433
2966
|
}, [currentTime, onTimeUpdate]);
|
|
2434
|
-
|
|
2967
|
+
useEffect7(() => {
|
|
2435
2968
|
if (isEnded) {
|
|
2436
2969
|
onEnded?.();
|
|
2437
2970
|
if (loop && !isSlideshowMode && !isLinearMode && !isDashboardMode) {
|
|
@@ -2439,8 +2972,8 @@ function DocPlayerContent({
|
|
|
2439
2972
|
}
|
|
2440
2973
|
}
|
|
2441
2974
|
}, [isEnded, isDashboardMode, isLinearMode, isSlideshowMode, loop, onEnded, restart]);
|
|
2442
|
-
const liveRenderAPIRef =
|
|
2443
|
-
const stableRenderAPIRef =
|
|
2975
|
+
const liveRenderAPIRef = useRef7(null);
|
|
2976
|
+
const stableRenderAPIRef = useRef7(null);
|
|
2444
2977
|
if (!stableRenderAPIRef.current) {
|
|
2445
2978
|
const current = () => {
|
|
2446
2979
|
const api = liveRenderAPIRef.current;
|
|
@@ -2461,7 +2994,7 @@ function DocPlayerContent({
|
|
|
2461
2994
|
};
|
|
2462
2995
|
}
|
|
2463
2996
|
const stableRenderAPI = stableRenderAPIRef.current;
|
|
2464
|
-
|
|
2997
|
+
useEffect7(() => {
|
|
2465
2998
|
if (isDashboardMode || !renderMode && !isDebugMode) {
|
|
2466
2999
|
liveRenderAPIRef.current = null;
|
|
2467
3000
|
return;
|
|
@@ -2591,7 +3124,7 @@ function DocPlayerContent({
|
|
|
2591
3124
|
waitForRenderCommit,
|
|
2592
3125
|
isDashboardMode
|
|
2593
3126
|
]);
|
|
2594
|
-
|
|
3127
|
+
useEffect7(() => {
|
|
2595
3128
|
if (isDashboardMode) return;
|
|
2596
3129
|
if (!renderMode && !isDebugMode || !containerRef.current) {
|
|
2597
3130
|
onRenderAPIReady?.(null);
|
|
@@ -2601,20 +3134,20 @@ function DocPlayerContent({
|
|
|
2601
3134
|
return () => onRenderAPIReady?.(null);
|
|
2602
3135
|
}, [renderMode, isDebugMode, isDashboardMode, onRenderAPIReady, stableRenderAPI]);
|
|
2603
3136
|
const defaultMode = captionsEnabledProp === false ? "off" : captionStyle || "standard";
|
|
2604
|
-
const [captionMode, setCaptionMode] =
|
|
2605
|
-
|
|
3137
|
+
const [captionMode, setCaptionMode] = useState6(defaultMode);
|
|
3138
|
+
useEffect7(() => {
|
|
2606
3139
|
setCaptionMode(defaultMode);
|
|
2607
3140
|
}, [defaultMode]);
|
|
2608
3141
|
const captionsEnabled = captionMode !== "off";
|
|
2609
3142
|
const activeCaptionStyle = captionMode === "social" ? "social" : "standard";
|
|
2610
|
-
const setCaptionsEnabled =
|
|
3143
|
+
const setCaptionsEnabled = useCallback5(
|
|
2611
3144
|
(enabled) => {
|
|
2612
3145
|
setCaptionMode(enabled ? captionStyle || "standard" : "off");
|
|
2613
3146
|
onCaptionsToggle?.(enabled);
|
|
2614
3147
|
},
|
|
2615
3148
|
[onCaptionsToggle, captionStyle]
|
|
2616
3149
|
);
|
|
2617
|
-
const cycleCaptionMode =
|
|
3150
|
+
const cycleCaptionMode = useCallback5(() => {
|
|
2618
3151
|
setCaptionMode((prev) => {
|
|
2619
3152
|
const next = prev === "off" ? "standard" : prev === "standard" ? "social" : "off";
|
|
2620
3153
|
onCaptionsToggle?.(next !== "off");
|
|
@@ -2622,8 +3155,8 @@ function DocPlayerContent({
|
|
|
2622
3155
|
});
|
|
2623
3156
|
}, [onCaptionsToggle]);
|
|
2624
3157
|
const hasCaptions = doc.captions && doc.captions.phrases.length > 0;
|
|
2625
|
-
const segmentTitleMap =
|
|
2626
|
-
const playbackState =
|
|
3158
|
+
const segmentTitleMap = useMemo5(() => buildSegmentTitleMap(doc), [doc]);
|
|
3159
|
+
const playbackState = useMemo5(
|
|
2627
3160
|
() => ({
|
|
2628
3161
|
isPlaying,
|
|
2629
3162
|
currentTime,
|
|
@@ -2666,7 +3199,7 @@ function DocPlayerContent({
|
|
|
2666
3199
|
expandedBlocks.length
|
|
2667
3200
|
]
|
|
2668
3201
|
);
|
|
2669
|
-
const playbackActions =
|
|
3202
|
+
const playbackActions = useMemo5(
|
|
2670
3203
|
() => ({
|
|
2671
3204
|
toggle: toggleWithTimelineMedia,
|
|
2672
3205
|
restart,
|
|
@@ -2684,7 +3217,7 @@ function DocPlayerContent({
|
|
|
2684
3217
|
onFullscreenToggle
|
|
2685
3218
|
]
|
|
2686
3219
|
);
|
|
2687
|
-
const slideNavActions =
|
|
3220
|
+
const slideNavActions = useMemo5(
|
|
2688
3221
|
() => ({
|
|
2689
3222
|
nextSlide: () => {
|
|
2690
3223
|
if (slideshowHasCover && slideshowCoverVisible) {
|
|
@@ -2749,7 +3282,7 @@ function DocPlayerContent({
|
|
|
2749
3282
|
[currentBlockIndex, expandedBlocks, seekTo, pause, slideshowHasCover, slideshowCoverVisible]
|
|
2750
3283
|
);
|
|
2751
3284
|
const swipeEnabled = isSlideshowMode && !isLinearMode && !renderMode && enableSwipe;
|
|
2752
|
-
const armContextFreeSwipeEntry =
|
|
3285
|
+
const armContextFreeSwipeEntry = useCallback5(
|
|
2753
3286
|
(destinationSlideIndex) => {
|
|
2754
3287
|
const destinationBlockIndex = destinationSlideIndex - (slideshowHasCover ? 1 : 0);
|
|
2755
3288
|
const destinationBlock = expandedBlocks[destinationBlockIndex];
|
|
@@ -2757,11 +3290,11 @@ function DocPlayerContent({
|
|
|
2757
3290
|
},
|
|
2758
3291
|
[expandedBlocks, slideshowHasCover, suppressOutgoingForNextBlock]
|
|
2759
3292
|
);
|
|
2760
|
-
const handleSwipeNext =
|
|
3293
|
+
const handleSwipeNext = useCallback5(() => {
|
|
2761
3294
|
armContextFreeSwipeEntry(slideshowSlideIndex + 1);
|
|
2762
3295
|
slideNavActions.nextSlide();
|
|
2763
3296
|
}, [armContextFreeSwipeEntry, slideshowSlideIndex, slideNavActions]);
|
|
2764
|
-
const handleSwipePrev =
|
|
3297
|
+
const handleSwipePrev = useCallback5(() => {
|
|
2765
3298
|
armContextFreeSwipeEntry(slideshowSlideIndex - 1);
|
|
2766
3299
|
slideNavActions.prevSlide();
|
|
2767
3300
|
}, [armContextFreeSwipeEntry, slideshowSlideIndex, slideNavActions]);
|
|
@@ -2773,13 +3306,13 @@ function DocPlayerContent({
|
|
|
2773
3306
|
onNext: handleSwipeNext,
|
|
2774
3307
|
onPrev: handleSwipePrev
|
|
2775
3308
|
});
|
|
2776
|
-
|
|
3309
|
+
useEffect7(() => {
|
|
2777
3310
|
onPlaybackStateChange?.(playbackState);
|
|
2778
3311
|
}, [playbackState, onPlaybackStateChange]);
|
|
2779
|
-
|
|
3312
|
+
useEffect7(() => {
|
|
2780
3313
|
onControlsReady?.({ play: playWithTimelineMedia, pause, ...playbackActions });
|
|
2781
3314
|
}, [playWithTimelineMedia, pause, playbackActions, onControlsReady]);
|
|
2782
|
-
const getBlockTitle =
|
|
3315
|
+
const getBlockTitle = useCallback5((block) => {
|
|
2783
3316
|
const docBlock = block;
|
|
2784
3317
|
if (isTemplateBlock2(docBlock)) {
|
|
2785
3318
|
const props = docBlock;
|
|
@@ -2803,7 +3336,7 @@ function DocPlayerContent({
|
|
|
2803
3336
|
}
|
|
2804
3337
|
return block.id.replace(/-/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
2805
3338
|
}, []);
|
|
2806
|
-
const slideshowPickerItems =
|
|
3339
|
+
const slideshowPickerItems = useMemo5(() => {
|
|
2807
3340
|
const blockItems = expandedBlocks.map((block, index) => ({
|
|
2808
3341
|
id: block.id,
|
|
2809
3342
|
label: String(index + 1),
|
|
@@ -2819,7 +3352,7 @@ function DocPlayerContent({
|
|
|
2819
3352
|
...blockItems
|
|
2820
3353
|
];
|
|
2821
3354
|
}, [coverBlock, expandedBlocks, getBlockTitle, slideshowHasCover]);
|
|
2822
|
-
const blockMarkers =
|
|
3355
|
+
const blockMarkers = useMemo5(() => {
|
|
2823
3356
|
if (!totalDuration || !expandedBlocks.length) return [];
|
|
2824
3357
|
let prevSegment = -1;
|
|
2825
3358
|
return expandedBlocks.map((block, index) => {
|
|
@@ -2834,13 +3367,13 @@ function DocPlayerContent({
|
|
|
2834
3367
|
};
|
|
2835
3368
|
});
|
|
2836
3369
|
}, [expandedBlocks, totalDuration, getBlockTitle]);
|
|
2837
|
-
|
|
3370
|
+
useEffect7(() => {
|
|
2838
3371
|
if (blockMarkers.length > 0) {
|
|
2839
3372
|
onBlockMarkers?.(blockMarkers);
|
|
2840
3373
|
}
|
|
2841
3374
|
}, [blockMarkers, onBlockMarkers]);
|
|
2842
3375
|
expandedBlocksLenRef.current = isSlideshowMode ? slideshowTotalSlides : expandedBlocks.length;
|
|
2843
|
-
const handleKeyboardShortcut =
|
|
3376
|
+
const handleKeyboardShortcut = useCallback5(
|
|
2844
3377
|
(e, global) => {
|
|
2845
3378
|
if (e.defaultPrevented || e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) return;
|
|
2846
3379
|
const target = e.target instanceof Element ? e.target : null;
|
|
@@ -2915,11 +3448,11 @@ function DocPlayerContent({
|
|
|
2915
3448
|
onFullscreenToggle
|
|
2916
3449
|
]
|
|
2917
3450
|
);
|
|
2918
|
-
const handleKeyDown =
|
|
3451
|
+
const handleKeyDown = useCallback5(
|
|
2919
3452
|
(e) => handleKeyboardShortcut(e, false),
|
|
2920
3453
|
[handleKeyboardShortcut]
|
|
2921
3454
|
);
|
|
2922
|
-
|
|
3455
|
+
useEffect7(() => {
|
|
2923
3456
|
if (!globalKeyboardShortcuts || renderMode || isLinearMode || isDashboardMode) return;
|
|
2924
3457
|
const handleDocumentKeyDown = (event) => {
|
|
2925
3458
|
handleKeyboardShortcut(event, true);
|
|
@@ -2928,7 +3461,7 @@ function DocPlayerContent({
|
|
|
2928
3461
|
return () => document.removeEventListener("keydown", handleDocumentKeyDown);
|
|
2929
3462
|
}, [globalKeyboardShortcuts, handleKeyboardShortcut, isDashboardMode, isLinearMode, renderMode]);
|
|
2930
3463
|
if (isLinearMode) {
|
|
2931
|
-
return /* @__PURE__ */
|
|
3464
|
+
return /* @__PURE__ */ jsx9(
|
|
2932
3465
|
"div",
|
|
2933
3466
|
{
|
|
2934
3467
|
ref: containerRef,
|
|
@@ -2940,7 +3473,7 @@ function DocPlayerContent({
|
|
|
2940
3473
|
height: "100%",
|
|
2941
3474
|
overflow: "hidden"
|
|
2942
3475
|
},
|
|
2943
|
-
children: /* @__PURE__ */
|
|
3476
|
+
children: /* @__PURE__ */ jsx9(
|
|
2944
3477
|
LinearDocView,
|
|
2945
3478
|
{
|
|
2946
3479
|
doc,
|
|
@@ -2958,7 +3491,7 @@ function DocPlayerContent({
|
|
|
2958
3491
|
);
|
|
2959
3492
|
}
|
|
2960
3493
|
if (isDashboardMode) {
|
|
2961
|
-
return /* @__PURE__ */
|
|
3494
|
+
return /* @__PURE__ */ jsx9(
|
|
2962
3495
|
"div",
|
|
2963
3496
|
{
|
|
2964
3497
|
ref: containerRef,
|
|
@@ -2971,7 +3504,7 @@ function DocPlayerContent({
|
|
|
2971
3504
|
margin: "0 auto",
|
|
2972
3505
|
overflow: "hidden"
|
|
2973
3506
|
},
|
|
2974
|
-
children: /* @__PURE__ */
|
|
3507
|
+
children: /* @__PURE__ */ jsx9(
|
|
2975
3508
|
DashboardView,
|
|
2976
3509
|
{
|
|
2977
3510
|
doc,
|
|
@@ -2991,7 +3524,7 @@ function DocPlayerContent({
|
|
|
2991
3524
|
}
|
|
2992
3525
|
);
|
|
2993
3526
|
}
|
|
2994
|
-
return /* @__PURE__ */
|
|
3527
|
+
return /* @__PURE__ */ jsxs6(
|
|
2995
3528
|
"div",
|
|
2996
3529
|
{
|
|
2997
3530
|
ref: containerRef,
|
|
@@ -3019,8 +3552,8 @@ function DocPlayerContent({
|
|
|
3019
3552
|
touchAction: swipeEnabled ? "pan-y" : void 0
|
|
3020
3553
|
},
|
|
3021
3554
|
children: [
|
|
3022
|
-
/* @__PURE__ */
|
|
3023
|
-
/* @__PURE__ */
|
|
3555
|
+
/* @__PURE__ */ jsx9("audio", { ref: audioRef, preload: "auto", muted }),
|
|
3556
|
+
/* @__PURE__ */ jsx9(
|
|
3024
3557
|
MediaClipLayer,
|
|
3025
3558
|
{
|
|
3026
3559
|
schedule: mediaSchedule,
|
|
@@ -3037,8 +3570,8 @@ function DocPlayerContent({
|
|
|
3037
3570
|
pipFrameStyle
|
|
3038
3571
|
}
|
|
3039
3572
|
),
|
|
3040
|
-
/* @__PURE__ */
|
|
3041
|
-
showCoverBlock && coverBlock && /* @__PURE__ */
|
|
3573
|
+
/* @__PURE__ */ jsxs6("div", { className: "doc-player__viewport", children: [
|
|
3574
|
+
showCoverBlock && coverBlock && /* @__PURE__ */ jsx9("div", { className: "doc-player__block doc-player__block--cover", children: /* @__PURE__ */ jsx9(
|
|
3042
3575
|
BlockRenderer,
|
|
3043
3576
|
{
|
|
3044
3577
|
block: coverBlock,
|
|
@@ -3055,7 +3588,7 @@ function DocPlayerContent({
|
|
|
3055
3588
|
// reconciles one block's layers onto another's (templates reuse layer
|
|
3056
3589
|
// ids like `title`/`background`), which would otherwise reuse stale
|
|
3057
3590
|
// DOM / skip entrance animations mid-transition.
|
|
3058
|
-
/* @__PURE__ */
|
|
3591
|
+
/* @__PURE__ */ jsx9("div", { className: "doc-player__block doc-player__block--previous", children: /* @__PURE__ */ jsx9(
|
|
3059
3592
|
BlockRenderer,
|
|
3060
3593
|
{
|
|
3061
3594
|
block: previousBlock,
|
|
@@ -3069,7 +3602,7 @@ function DocPlayerContent({
|
|
|
3069
3602
|
theme: effectiveTheme
|
|
3070
3603
|
}
|
|
3071
3604
|
) }, previousBlock.id),
|
|
3072
|
-
currentBlock && /* @__PURE__ */
|
|
3605
|
+
currentBlock && /* @__PURE__ */ jsx9(
|
|
3073
3606
|
"div",
|
|
3074
3607
|
{
|
|
3075
3608
|
className: `doc-player__block doc-player__block--active${swipe.phase !== "idle" ? ` doc-player__block--${swipe.phase}` : ""}`,
|
|
@@ -3078,7 +3611,7 @@ function DocPlayerContent({
|
|
|
3078
3611
|
...swipe.phase !== "idle" ? { transform: `translateX(${swipe.offsetPx}px)` } : {},
|
|
3079
3612
|
...showCoverBlock ? { opacity: 0, pointerEvents: "none" } : {}
|
|
3080
3613
|
} : void 0,
|
|
3081
|
-
children: /* @__PURE__ */
|
|
3614
|
+
children: /* @__PURE__ */ jsx9(
|
|
3082
3615
|
BlockRenderer,
|
|
3083
3616
|
{
|
|
3084
3617
|
block: currentBlock,
|
|
@@ -3095,7 +3628,7 @@ function DocPlayerContent({
|
|
|
3095
3628
|
},
|
|
3096
3629
|
currentBlock.id
|
|
3097
3630
|
),
|
|
3098
|
-
hasCaptions && (renderMode ? captionsEnabled : true) && /* @__PURE__ */
|
|
3631
|
+
hasCaptions && (renderMode ? captionsEnabled : true) && /* @__PURE__ */ jsx9(
|
|
3099
3632
|
CaptionOverlay,
|
|
3100
3633
|
{
|
|
3101
3634
|
captions: doc.captions,
|
|
@@ -3107,7 +3640,7 @@ function DocPlayerContent({
|
|
|
3107
3640
|
viewport: activeViewport
|
|
3108
3641
|
}
|
|
3109
3642
|
),
|
|
3110
|
-
isDebugMode && /* @__PURE__ */
|
|
3643
|
+
isDebugMode && /* @__PURE__ */ jsxs6(
|
|
3111
3644
|
"div",
|
|
3112
3645
|
{
|
|
3113
3646
|
className: "doc-player__debug",
|
|
@@ -3128,27 +3661,27 @@ function DocPlayerContent({
|
|
|
3128
3661
|
textAlign: "left"
|
|
3129
3662
|
},
|
|
3130
3663
|
children: [
|
|
3131
|
-
/* @__PURE__ */
|
|
3132
|
-
/* @__PURE__ */
|
|
3133
|
-
/* @__PURE__ */
|
|
3664
|
+
/* @__PURE__ */ jsx9("div", { style: { color: "#ffcc00", fontWeight: "bold", marginBottom: "4px" }, children: "DEBUG MODE" }),
|
|
3665
|
+
/* @__PURE__ */ jsxs6("div", { children: [
|
|
3666
|
+
/* @__PURE__ */ jsx9("span", { style: { color: "#888" }, children: "template:" }),
|
|
3134
3667
|
" ",
|
|
3135
|
-
/* @__PURE__ */
|
|
3668
|
+
/* @__PURE__ */ jsx9("span", { style: { color: "#ff6b6b" }, children: currentBlock?.template ?? "raw" })
|
|
3136
3669
|
] }),
|
|
3137
|
-
/* @__PURE__ */
|
|
3138
|
-
/* @__PURE__ */
|
|
3670
|
+
/* @__PURE__ */ jsxs6("div", { children: [
|
|
3671
|
+
/* @__PURE__ */ jsx9("span", { style: { color: "#888" }, children: "block:" }),
|
|
3139
3672
|
" ",
|
|
3140
3673
|
currentBlockIndex + 1,
|
|
3141
3674
|
"/",
|
|
3142
3675
|
expandedBlocks.length,
|
|
3143
3676
|
" ",
|
|
3144
|
-
/* @__PURE__ */
|
|
3677
|
+
/* @__PURE__ */ jsxs6("span", { style: { color: "#666" }, children: [
|
|
3145
3678
|
"(",
|
|
3146
3679
|
currentBlock?.id || "none",
|
|
3147
3680
|
")"
|
|
3148
3681
|
] })
|
|
3149
3682
|
] }),
|
|
3150
|
-
/* @__PURE__ */
|
|
3151
|
-
/* @__PURE__ */
|
|
3683
|
+
/* @__PURE__ */ jsxs6("div", { children: [
|
|
3684
|
+
/* @__PURE__ */ jsx9("span", { style: { color: "#888" }, children: "time:" }),
|
|
3152
3685
|
" ",
|
|
3153
3686
|
currentTime.toFixed(2),
|
|
3154
3687
|
"s /",
|
|
@@ -3156,7 +3689,7 @@ function DocPlayerContent({
|
|
|
3156
3689
|
totalDuration.toFixed(1),
|
|
3157
3690
|
"s",
|
|
3158
3691
|
" ",
|
|
3159
|
-
/* @__PURE__ */
|
|
3692
|
+
/* @__PURE__ */ jsxs6("span", { style: { color: "#666" }, children: [
|
|
3160
3693
|
"(progress: ",
|
|
3161
3694
|
(docProgress * 100).toFixed(1),
|
|
3162
3695
|
"%, scriptDur: ",
|
|
@@ -3164,8 +3697,8 @@ function DocPlayerContent({
|
|
|
3164
3697
|
")"
|
|
3165
3698
|
] })
|
|
3166
3699
|
] }),
|
|
3167
|
-
/* @__PURE__ */
|
|
3168
|
-
/* @__PURE__ */
|
|
3700
|
+
/* @__PURE__ */ jsxs6("div", { children: [
|
|
3701
|
+
/* @__PURE__ */ jsx9("span", { style: { color: "#888" }, children: "blockTime:" }),
|
|
3169
3702
|
" ",
|
|
3170
3703
|
blockTime.toFixed(2),
|
|
3171
3704
|
"s /",
|
|
@@ -3173,58 +3706,58 @@ function DocPlayerContent({
|
|
|
3173
3706
|
(currentBlock?.duration || 0).toFixed(1),
|
|
3174
3707
|
"s"
|
|
3175
3708
|
] }),
|
|
3176
|
-
/* @__PURE__ */
|
|
3177
|
-
/* @__PURE__ */
|
|
3709
|
+
/* @__PURE__ */ jsxs6("div", { children: [
|
|
3710
|
+
/* @__PURE__ */ jsx9("span", { style: { color: "#888" }, children: "segment:" }),
|
|
3178
3711
|
" ",
|
|
3179
3712
|
currentSegment,
|
|
3180
3713
|
"/",
|
|
3181
3714
|
doc.audio.segments.length - 1,
|
|
3182
3715
|
" ",
|
|
3183
|
-
/* @__PURE__ */
|
|
3716
|
+
/* @__PURE__ */ jsxs6("span", { style: { color: "#666" }, children: [
|
|
3184
3717
|
"(",
|
|
3185
3718
|
doc.audio.segments[currentSegment]?.name || "none",
|
|
3186
3719
|
")"
|
|
3187
3720
|
] })
|
|
3188
3721
|
] }),
|
|
3189
|
-
/* @__PURE__ */
|
|
3190
|
-
/* @__PURE__ */
|
|
3722
|
+
/* @__PURE__ */ jsxs6("div", { children: [
|
|
3723
|
+
/* @__PURE__ */ jsx9("span", { style: { color: "#888" }, children: "viewport:" }),
|
|
3191
3724
|
" ",
|
|
3192
3725
|
activeViewport.name || `${activeViewport.width}x${activeViewport.height}`,
|
|
3193
3726
|
" ",
|
|
3194
|
-
/* @__PURE__ */
|
|
3727
|
+
/* @__PURE__ */ jsxs6("span", { style: { color: "#666" }, children: [
|
|
3195
3728
|
"(",
|
|
3196
3729
|
activeOrientation,
|
|
3197
3730
|
")"
|
|
3198
3731
|
] })
|
|
3199
3732
|
] }),
|
|
3200
|
-
/* @__PURE__ */
|
|
3201
|
-
/* @__PURE__ */
|
|
3733
|
+
/* @__PURE__ */ jsxs6("div", { children: [
|
|
3734
|
+
/* @__PURE__ */ jsx9("span", { style: { color: "#888" }, children: "playing:" }),
|
|
3202
3735
|
" ",
|
|
3203
|
-
/* @__PURE__ */
|
|
3204
|
-
showCoverBlock && /* @__PURE__ */
|
|
3736
|
+
/* @__PURE__ */ jsx9("span", { style: { color: isPlaying ? "#4ade80" : "#f87171" }, children: isPlaying ? "yes" : "no" }),
|
|
3737
|
+
showCoverBlock && /* @__PURE__ */ jsx9("span", { style: { color: "#60a5fa" }, children: " (cover)" })
|
|
3205
3738
|
] }),
|
|
3206
3739
|
hasCaptions && (() => {
|
|
3207
3740
|
const debugPhrase = getCaptionAtTime2(doc.captions, currentTime);
|
|
3208
3741
|
const debugEnabled = captionsEnabled && (isPlaying || currentTime > 0);
|
|
3209
|
-
return /* @__PURE__ */
|
|
3210
|
-
/* @__PURE__ */
|
|
3211
|
-
/* @__PURE__ */
|
|
3742
|
+
return /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
3743
|
+
/* @__PURE__ */ jsxs6("div", { children: [
|
|
3744
|
+
/* @__PURE__ */ jsx9("span", { style: { color: "#888" }, children: "captions:" }),
|
|
3212
3745
|
" ",
|
|
3213
3746
|
doc.captions?.phrases.length || 0,
|
|
3214
3747
|
" phrases",
|
|
3215
3748
|
" ",
|
|
3216
|
-
/* @__PURE__ */
|
|
3749
|
+
/* @__PURE__ */ jsxs6("span", { style: { color: captionsEnabled ? "#4ade80" : "#666" }, children: [
|
|
3217
3750
|
"(",
|
|
3218
3751
|
captionsEnabled ? "on" : "off",
|
|
3219
3752
|
")"
|
|
3220
3753
|
] })
|
|
3221
3754
|
] }),
|
|
3222
|
-
/* @__PURE__ */
|
|
3223
|
-
/* @__PURE__ */
|
|
3755
|
+
/* @__PURE__ */ jsxs6("div", { children: [
|
|
3756
|
+
/* @__PURE__ */ jsx9("span", { style: { color: "#888" }, children: "cc.enabled:" }),
|
|
3224
3757
|
" ",
|
|
3225
|
-
/* @__PURE__ */
|
|
3758
|
+
/* @__PURE__ */ jsx9("span", { style: { color: debugEnabled ? "#4ade80" : "#f87171" }, children: String(debugEnabled) }),
|
|
3226
3759
|
" ",
|
|
3227
|
-
/* @__PURE__ */
|
|
3760
|
+
/* @__PURE__ */ jsxs6("span", { style: { color: "#666" }, children: [
|
|
3228
3761
|
"(playing=",
|
|
3229
3762
|
String(isPlaying),
|
|
3230
3763
|
" t>0=",
|
|
@@ -3232,15 +3765,15 @@ function DocPlayerContent({
|
|
|
3232
3765
|
")"
|
|
3233
3766
|
] })
|
|
3234
3767
|
] }),
|
|
3235
|
-
/* @__PURE__ */
|
|
3236
|
-
/* @__PURE__ */
|
|
3768
|
+
/* @__PURE__ */ jsxs6("div", { children: [
|
|
3769
|
+
/* @__PURE__ */ jsx9("span", { style: { color: "#888" }, children: "cc.phrase:" }),
|
|
3237
3770
|
" ",
|
|
3238
|
-
/* @__PURE__ */
|
|
3771
|
+
/* @__PURE__ */ jsx9("span", { style: { color: debugPhrase ? "#4ade80" : "#f87171" }, children: debugPhrase ? `"${debugPhrase.text.slice(0, 30)}..."` : "null" })
|
|
3239
3772
|
] }),
|
|
3240
|
-
debugPhrase && /* @__PURE__ */
|
|
3241
|
-
/* @__PURE__ */
|
|
3773
|
+
debugPhrase && /* @__PURE__ */ jsxs6("div", { children: [
|
|
3774
|
+
/* @__PURE__ */ jsx9("span", { style: { color: "#888" }, children: "cc.range:" }),
|
|
3242
3775
|
" ",
|
|
3243
|
-
/* @__PURE__ */
|
|
3776
|
+
/* @__PURE__ */ jsxs6("span", { style: { color: "#60a5fa" }, children: [
|
|
3244
3777
|
debugPhrase.startTime.toFixed(2),
|
|
3245
3778
|
"-",
|
|
3246
3779
|
debugPhrase.endTime.toFixed(2)
|
|
@@ -3252,7 +3785,7 @@ function DocPlayerContent({
|
|
|
3252
3785
|
}
|
|
3253
3786
|
)
|
|
3254
3787
|
] }),
|
|
3255
|
-
!isAvailable && unavailableMessage && /* @__PURE__ */
|
|
3788
|
+
!isAvailable && unavailableMessage && /* @__PURE__ */ jsxs6(
|
|
3256
3789
|
"div",
|
|
3257
3790
|
{
|
|
3258
3791
|
className: "doc-player__unavailable",
|
|
@@ -3273,12 +3806,12 @@ function DocPlayerContent({
|
|
|
3273
3806
|
zIndex: 50
|
|
3274
3807
|
},
|
|
3275
3808
|
children: [
|
|
3276
|
-
/* @__PURE__ */
|
|
3277
|
-
/* @__PURE__ */
|
|
3809
|
+
/* @__PURE__ */ jsx9("span", { style: { fontSize: "32px" }, children: "\u{1F50A}" }),
|
|
3810
|
+
/* @__PURE__ */ jsx9("span", { children: unavailableMessage })
|
|
3278
3811
|
]
|
|
3279
3812
|
}
|
|
3280
3813
|
),
|
|
3281
|
-
!renderMode && !isSlideshowMode && showControls && /* @__PURE__ */
|
|
3814
|
+
!renderMode && !isSlideshowMode && showControls && /* @__PURE__ */ jsx9(
|
|
3282
3815
|
DocControlsOverlay,
|
|
3283
3816
|
{
|
|
3284
3817
|
state: playbackState,
|
|
@@ -3288,7 +3821,7 @@ function DocPlayerContent({
|
|
|
3288
3821
|
getBlockTitle
|
|
3289
3822
|
}
|
|
3290
3823
|
),
|
|
3291
|
-
!renderMode && !isSlideshowMode && !showControls && showScrubber && /* @__PURE__ */
|
|
3824
|
+
!renderMode && !isSlideshowMode && !showControls && showScrubber && /* @__PURE__ */ jsx9(
|
|
3292
3825
|
"div",
|
|
3293
3826
|
{
|
|
3294
3827
|
className: "doc-player__scrubber",
|
|
@@ -3303,7 +3836,7 @@ function DocPlayerContent({
|
|
|
3303
3836
|
alignItems: "center",
|
|
3304
3837
|
zIndex: 100
|
|
3305
3838
|
},
|
|
3306
|
-
children: /* @__PURE__ */
|
|
3839
|
+
children: /* @__PURE__ */ jsx9(
|
|
3307
3840
|
DocProgressBar,
|
|
3308
3841
|
{
|
|
3309
3842
|
state: playbackState,
|
|
@@ -3315,7 +3848,7 @@ function DocPlayerContent({
|
|
|
3315
3848
|
)
|
|
3316
3849
|
}
|
|
3317
3850
|
),
|
|
3318
|
-
!renderMode && isSlideshowMode && showControls && /* @__PURE__ */
|
|
3851
|
+
!renderMode && isSlideshowMode && showControls && /* @__PURE__ */ jsx9(
|
|
3319
3852
|
DocControlsSlideshow,
|
|
3320
3853
|
{
|
|
3321
3854
|
state: playbackState,
|
|
@@ -3325,14 +3858,14 @@ function DocPlayerContent({
|
|
|
3325
3858
|
onPickerOpenChange: setIsSlideshowPickerOpen
|
|
3326
3859
|
}
|
|
3327
3860
|
),
|
|
3328
|
-
!isSlideshowMode && tapFeedback && /* @__PURE__ */
|
|
3861
|
+
!isSlideshowMode && tapFeedback && /* @__PURE__ */ jsx9("div", { className: "doc-player__tap-feedback", children: /* @__PURE__ */ jsx9("svg", { viewBox: "0 0 24 24", fill: "white", width: "48", height: "48", children: tapFeedback === "pause" ? /* @__PURE__ */ jsx9("path", { d: "M6 19h4V5H6v14zm8-14v14h4V5h-4z" }) : /* @__PURE__ */ jsx9("path", { d: "M8 5v14l11-7z" }) }) }, tapFeedback)
|
|
3329
3862
|
]
|
|
3330
3863
|
}
|
|
3331
3864
|
);
|
|
3332
3865
|
}
|
|
3333
3866
|
|
|
3334
3867
|
// src/DocControlsBottom.tsx
|
|
3335
|
-
import { jsx as
|
|
3868
|
+
import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
3336
3869
|
function DocControlsBottom({
|
|
3337
3870
|
state,
|
|
3338
3871
|
actions,
|
|
@@ -3340,32 +3873,32 @@ function DocControlsBottom({
|
|
|
3340
3873
|
expandedBlocks,
|
|
3341
3874
|
getBlockTitle
|
|
3342
3875
|
}) {
|
|
3343
|
-
return /* @__PURE__ */
|
|
3344
|
-
/* @__PURE__ */
|
|
3876
|
+
return /* @__PURE__ */ jsxs7("div", { className: "doc-controls-bottom", children: [
|
|
3877
|
+
/* @__PURE__ */ jsx10(
|
|
3345
3878
|
"button",
|
|
3346
3879
|
{
|
|
3347
3880
|
className: "bottom-ctrl-btn",
|
|
3348
3881
|
onClick: actions.restart,
|
|
3349
3882
|
title: "Restart",
|
|
3350
3883
|
"aria-label": "Restart from beginning",
|
|
3351
|
-
children: /* @__PURE__ */
|
|
3884
|
+
children: /* @__PURE__ */ jsx10("svg", { viewBox: "0 0 24 24", fill: "currentColor", width: "18", height: "18", children: /* @__PURE__ */ jsx10("path", { d: "M12 5V1L7 6l5 5V7c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6H4c0 4.42 3.58 8 8 8s8-3.58 8-8-3.58-8-8-8z" }) })
|
|
3352
3885
|
}
|
|
3353
3886
|
),
|
|
3354
|
-
/* @__PURE__ */
|
|
3887
|
+
/* @__PURE__ */ jsx10(
|
|
3355
3888
|
"button",
|
|
3356
3889
|
{
|
|
3357
3890
|
className: "bottom-ctrl-btn bottom-play-btn",
|
|
3358
3891
|
onClick: actions.toggle,
|
|
3359
3892
|
"aria-label": state.isPlaying ? "Pause" : "Play",
|
|
3360
|
-
children: state.isPlaying ? /* @__PURE__ */
|
|
3893
|
+
children: state.isPlaying ? /* @__PURE__ */ jsx10("svg", { viewBox: "0 0 24 24", fill: "currentColor", width: "20", height: "20", children: /* @__PURE__ */ jsx10("path", { d: "M6 19h4V5H6v14zm8-14v14h4V5h-4z" }) }) : /* @__PURE__ */ jsx10("svg", { viewBox: "0 0 24 24", fill: "currentColor", width: "20", height: "20", children: /* @__PURE__ */ jsx10("path", { d: "M8 5v14l11-7z" }) })
|
|
3361
3894
|
}
|
|
3362
3895
|
),
|
|
3363
|
-
/* @__PURE__ */
|
|
3896
|
+
/* @__PURE__ */ jsxs7("span", { className: "bottom-time", children: [
|
|
3364
3897
|
formatTime(state.currentTime),
|
|
3365
3898
|
" / ",
|
|
3366
3899
|
formatTime(state.totalDuration)
|
|
3367
3900
|
] }),
|
|
3368
|
-
/* @__PURE__ */
|
|
3901
|
+
/* @__PURE__ */ jsx10(
|
|
3369
3902
|
DocProgressBar,
|
|
3370
3903
|
{
|
|
3371
3904
|
state,
|
|
@@ -3375,92 +3908,92 @@ function DocControlsBottom({
|
|
|
3375
3908
|
getBlockTitle
|
|
3376
3909
|
}
|
|
3377
3910
|
),
|
|
3378
|
-
/* @__PURE__ */
|
|
3911
|
+
/* @__PURE__ */ jsxs7("span", { className: "bottom-segment", children: [
|
|
3379
3912
|
state.currentBlockIndex + 1,
|
|
3380
3913
|
"/",
|
|
3381
3914
|
state.totalBlocks
|
|
3382
3915
|
] }),
|
|
3383
|
-
state.hasCaptions && /* @__PURE__ */
|
|
3916
|
+
state.hasCaptions && /* @__PURE__ */ jsx10(
|
|
3384
3917
|
"button",
|
|
3385
3918
|
{
|
|
3386
3919
|
className: `bottom-ctrl-btn ${state.captionMode !== "off" ? "bottom-ctrl-btn--active" : ""}`,
|
|
3387
3920
|
onClick: () => actions.cycleCaptionMode(),
|
|
3388
3921
|
title: state.captionMode === "off" ? "Captions: Off" : state.captionMode === "standard" ? "Captions: Standard" : "Captions: Social",
|
|
3389
3922
|
"aria-label": "Cycle caption style",
|
|
3390
|
-
children: /* @__PURE__ */
|
|
3923
|
+
children: /* @__PURE__ */ jsx10("svg", { viewBox: "0 0 24 24", fill: "currentColor", width: "18", height: "18", children: /* @__PURE__ */ jsx10("path", { d: "M19 4H5a2 2 0 00-2 2v12a2 2 0 002 2h14a2 2 0 002-2V6a2 2 0 00-2-2zm-8 7H9.5v-.5h-2v3h2V13H11v1a1 1 0 01-1 1H7a1 1 0 01-1-1v-4a1 1 0 011-1h3a1 1 0 011 1v1zm7 0h-1.5v-.5h-2v3h2V13H18v1a1 1 0 01-1 1h-3a1 1 0 01-1-1v-4a1 1 0 011-1h3a1 1 0 011 1v1z" }) })
|
|
3391
3924
|
}
|
|
3392
3925
|
),
|
|
3393
|
-
actions.toggleFullscreen && /* @__PURE__ */
|
|
3926
|
+
actions.toggleFullscreen && /* @__PURE__ */ jsx10(
|
|
3394
3927
|
"button",
|
|
3395
3928
|
{
|
|
3396
3929
|
className: `bottom-ctrl-btn ${state.isFullscreen ? "bottom-ctrl-btn--active" : ""}`,
|
|
3397
3930
|
onClick: actions.toggleFullscreen,
|
|
3398
3931
|
title: state.isFullscreen ? "Exit fullscreen (F)" : "Fullscreen (F)",
|
|
3399
3932
|
"aria-label": state.isFullscreen ? "Exit fullscreen" : "Enter fullscreen",
|
|
3400
|
-
children: state.isFullscreen ? /* @__PURE__ */
|
|
3933
|
+
children: state.isFullscreen ? /* @__PURE__ */ jsx10("svg", { viewBox: "0 0 24 24", fill: "currentColor", width: "18", height: "18", children: /* @__PURE__ */ jsx10("path", { d: "M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z" }) }) : /* @__PURE__ */ jsx10("svg", { viewBox: "0 0 24 24", fill: "currentColor", width: "18", height: "18", children: /* @__PURE__ */ jsx10("path", { d: "M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z" }) })
|
|
3401
3934
|
}
|
|
3402
3935
|
)
|
|
3403
3936
|
] });
|
|
3404
3937
|
}
|
|
3405
3938
|
|
|
3406
3939
|
// src/DocControlsSidebar.tsx
|
|
3407
|
-
import { jsx as
|
|
3940
|
+
import { jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
3408
3941
|
function DocControlsSidebar({ state, actions }) {
|
|
3409
|
-
return /* @__PURE__ */
|
|
3410
|
-
/* @__PURE__ */
|
|
3942
|
+
return /* @__PURE__ */ jsxs8("div", { className: "doc-controls-sidebar", children: [
|
|
3943
|
+
/* @__PURE__ */ jsx11(
|
|
3411
3944
|
"button",
|
|
3412
3945
|
{
|
|
3413
3946
|
className: "sidebar-ctrl-btn",
|
|
3414
3947
|
onClick: actions.restart,
|
|
3415
3948
|
title: "Restart",
|
|
3416
3949
|
"aria-label": "Restart from beginning",
|
|
3417
|
-
children: /* @__PURE__ */
|
|
3950
|
+
children: /* @__PURE__ */ jsx11("svg", { viewBox: "0 0 24 24", fill: "currentColor", width: "20", height: "20", children: /* @__PURE__ */ jsx11("path", { d: "M12 5V1L7 6l5 5V7c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6H4c0 4.42 3.58 8 8 8s8-3.58 8-8-3.58-8-8-8z" }) })
|
|
3418
3951
|
}
|
|
3419
3952
|
),
|
|
3420
|
-
/* @__PURE__ */
|
|
3953
|
+
/* @__PURE__ */ jsx11(
|
|
3421
3954
|
"button",
|
|
3422
3955
|
{
|
|
3423
3956
|
className: "sidebar-ctrl-btn sidebar-play-btn",
|
|
3424
3957
|
onClick: actions.toggle,
|
|
3425
3958
|
"aria-label": state.isPlaying ? "Pause" : "Play",
|
|
3426
|
-
children: state.isPlaying ? /* @__PURE__ */
|
|
3959
|
+
children: state.isPlaying ? /* @__PURE__ */ jsx11("svg", { viewBox: "0 0 24 24", fill: "currentColor", width: "22", height: "22", children: /* @__PURE__ */ jsx11("path", { d: "M6 19h4V5H6v14zm8-14v14h4V5h-4z" }) }) : /* @__PURE__ */ jsx11("svg", { viewBox: "0 0 24 24", fill: "currentColor", width: "22", height: "22", children: /* @__PURE__ */ jsx11("path", { d: "M8 5v14l11-7z" }) })
|
|
3427
3960
|
}
|
|
3428
3961
|
),
|
|
3429
|
-
/* @__PURE__ */
|
|
3430
|
-
/* @__PURE__ */
|
|
3431
|
-
/* @__PURE__ */
|
|
3962
|
+
/* @__PURE__ */ jsxs8("div", { className: "sidebar-time", children: [
|
|
3963
|
+
/* @__PURE__ */ jsx11("div", { children: formatTime(state.currentTime) }),
|
|
3964
|
+
/* @__PURE__ */ jsx11("div", { className: "sidebar-time-total", children: formatTime(state.totalDuration) })
|
|
3432
3965
|
] }),
|
|
3433
|
-
/* @__PURE__ */
|
|
3966
|
+
/* @__PURE__ */ jsxs8("div", { className: "sidebar-segment", children: [
|
|
3434
3967
|
state.currentBlockIndex + 1,
|
|
3435
3968
|
"/",
|
|
3436
3969
|
state.totalBlocks
|
|
3437
3970
|
] }),
|
|
3438
|
-
state.hasCaptions && /* @__PURE__ */
|
|
3971
|
+
state.hasCaptions && /* @__PURE__ */ jsx11(
|
|
3439
3972
|
"button",
|
|
3440
3973
|
{
|
|
3441
3974
|
className: `sidebar-ctrl-btn ${state.captionMode !== "off" ? "sidebar-ctrl-btn--active" : ""}`,
|
|
3442
3975
|
onClick: () => actions.cycleCaptionMode(),
|
|
3443
3976
|
title: state.captionMode === "off" ? "Captions: Off" : state.captionMode === "standard" ? "Captions: Standard" : "Captions: Social",
|
|
3444
3977
|
"aria-label": "Cycle caption style",
|
|
3445
|
-
children: /* @__PURE__ */
|
|
3978
|
+
children: /* @__PURE__ */ jsx11("svg", { viewBox: "0 0 24 24", fill: "currentColor", width: "20", height: "20", children: /* @__PURE__ */ jsx11("path", { d: "M19 4H5a2 2 0 00-2 2v12a2 2 0 002 2h14a2 2 0 002-2V6a2 2 0 00-2-2zm-8 7H9.5v-.5h-2v3h2V13H11v1a1 1 0 01-1 1H7a1 1 0 01-1-1v-4a1 1 0 011-1h3a1 1 0 011 1v1zm7 0h-1.5v-.5h-2v3h2V13H18v1a1 1 0 01-1 1h-3a1 1 0 01-1-1v-4a1 1 0 011-1h3a1 1 0 011 1v1z" }) })
|
|
3446
3979
|
}
|
|
3447
3980
|
),
|
|
3448
|
-
actions.toggleFullscreen && /* @__PURE__ */
|
|
3981
|
+
actions.toggleFullscreen && /* @__PURE__ */ jsx11(
|
|
3449
3982
|
"button",
|
|
3450
3983
|
{
|
|
3451
3984
|
className: `sidebar-ctrl-btn ${state.isFullscreen ? "sidebar-ctrl-btn--active" : ""}`,
|
|
3452
3985
|
onClick: actions.toggleFullscreen,
|
|
3453
3986
|
title: state.isFullscreen ? "Exit fullscreen (F)" : "Fullscreen (F)",
|
|
3454
3987
|
"aria-label": state.isFullscreen ? "Exit fullscreen" : "Enter fullscreen",
|
|
3455
|
-
children: state.isFullscreen ? /* @__PURE__ */
|
|
3988
|
+
children: state.isFullscreen ? /* @__PURE__ */ jsx11("svg", { viewBox: "0 0 24 24", fill: "currentColor", width: "20", height: "20", children: /* @__PURE__ */ jsx11("path", { d: "M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z" }) }) : /* @__PURE__ */ jsx11("svg", { viewBox: "0 0 24 24", fill: "currentColor", width: "20", height: "20", children: /* @__PURE__ */ jsx11("path", { d: "M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z" }) })
|
|
3456
3989
|
}
|
|
3457
3990
|
)
|
|
3458
3991
|
] });
|
|
3459
3992
|
}
|
|
3460
3993
|
|
|
3461
3994
|
// src/DocPlayerWithSidebar.tsx
|
|
3462
|
-
import { useRef as
|
|
3463
|
-
import { jsx as
|
|
3995
|
+
import { useRef as useRef8, useState as useState7, useCallback as useCallback6, useEffect as useEffect8 } from "react";
|
|
3996
|
+
import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
3464
3997
|
var DEFAULT_STATE = {
|
|
3465
3998
|
isPlaying: false,
|
|
3466
3999
|
currentTime: 0,
|
|
@@ -3492,11 +4025,11 @@ function DocPlayerWithSidebar({
|
|
|
3492
4025
|
onPlayingChange,
|
|
3493
4026
|
theme
|
|
3494
4027
|
}) {
|
|
3495
|
-
const stateRef =
|
|
3496
|
-
const actionsRef =
|
|
3497
|
-
const wasPlayingRef =
|
|
3498
|
-
const [, setTick] =
|
|
3499
|
-
const handleStateChange =
|
|
4028
|
+
const stateRef = useRef8(DEFAULT_STATE);
|
|
4029
|
+
const actionsRef = useRef8(null);
|
|
4030
|
+
const wasPlayingRef = useRef8(false);
|
|
4031
|
+
const [, setTick] = useState7(0);
|
|
4032
|
+
const handleStateChange = useCallback6(
|
|
3500
4033
|
(state) => {
|
|
3501
4034
|
stateRef.current = state;
|
|
3502
4035
|
if (onPlayingChange && state.isPlaying !== wasPlayingRef.current) {
|
|
@@ -3507,7 +4040,7 @@ function DocPlayerWithSidebar({
|
|
|
3507
4040
|
},
|
|
3508
4041
|
[onPlayingChange]
|
|
3509
4042
|
);
|
|
3510
|
-
const handleControlsReady =
|
|
4043
|
+
const handleControlsReady = useCallback6(
|
|
3511
4044
|
(controls) => {
|
|
3512
4045
|
const isFirst = !actionsRef.current;
|
|
3513
4046
|
actionsRef.current = controls;
|
|
@@ -3515,15 +4048,15 @@ function DocPlayerWithSidebar({
|
|
|
3515
4048
|
},
|
|
3516
4049
|
[]
|
|
3517
4050
|
);
|
|
3518
|
-
|
|
4051
|
+
useEffect8(() => {
|
|
3519
4052
|
const interval = setInterval(() => {
|
|
3520
4053
|
if (!stateRef.current.isPlaying) return;
|
|
3521
4054
|
setTick((t) => t + 1);
|
|
3522
4055
|
}, 250);
|
|
3523
4056
|
return () => clearInterval(interval);
|
|
3524
4057
|
}, []);
|
|
3525
|
-
return /* @__PURE__ */
|
|
3526
|
-
/* @__PURE__ */
|
|
4058
|
+
return /* @__PURE__ */ jsxs9("div", { className: "doc-player-sidebar-layout", children: [
|
|
4059
|
+
/* @__PURE__ */ jsx12("div", { className: "doc-player-sidebar-layout__video", children: /* @__PURE__ */ jsx12(
|
|
3527
4060
|
DocPlayer,
|
|
3528
4061
|
{
|
|
3529
4062
|
doc,
|
|
@@ -3546,7 +4079,7 @@ function DocPlayerWithSidebar({
|
|
|
3546
4079
|
forceViewport
|
|
3547
4080
|
}
|
|
3548
4081
|
) }),
|
|
3549
|
-
actionsRef.current && /* @__PURE__ */
|
|
4082
|
+
actionsRef.current && /* @__PURE__ */ jsx12(DocControlsSidebar, { state: stateRef.current, actions: actionsRef.current })
|
|
3550
4083
|
] });
|
|
3551
4084
|
}
|
|
3552
4085
|
|
|
@@ -3560,6 +4093,8 @@ export {
|
|
|
3560
4093
|
DocControlsOverlay,
|
|
3561
4094
|
DocControlsSlideshow,
|
|
3562
4095
|
DashboardView,
|
|
4096
|
+
FlashcardFaceView,
|
|
4097
|
+
FlashcardView,
|
|
3563
4098
|
resolveDocPlayerAppearance,
|
|
3564
4099
|
DocPlayer,
|
|
3565
4100
|
DocControlsBottom,
|