@bendyline/squisq-editor-react 2.7.1 → 2.7.2

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.
@@ -22616,8 +22616,71 @@ function mermaidErrorMessage(error) {
22616
22616
  return message || "Unknown Mermaid rendering error.";
22617
22617
  }
22618
22618
 
22619
+ // src/mermaid/mermaidSurfaceTheme.ts
22620
+ import { useEffect as useEffect27, useMemo as useMemo29, useState as useState36 } from "react";
22621
+ import { relativeLuminance } from "@bendyline/squisq/schemas";
22622
+ var EDITOR_SURFACE = {
22623
+ light: {
22624
+ background: "#ffffff",
22625
+ backgroundLight: "#f5f5f5",
22626
+ text: "#1f2937",
22627
+ textMuted: "#6b7280"
22628
+ },
22629
+ dark: {
22630
+ background: "#111827",
22631
+ backgroundLight: "#1f2937",
22632
+ text: "#e5e7eb",
22633
+ textMuted: "#9ca3af"
22634
+ }
22635
+ };
22636
+ function mermaidSurfaceScheme(theme) {
22637
+ return relativeLuminance(theme.colors.background) < 0.5 ? "dark" : "light";
22638
+ }
22639
+ function adaptThemeToSurface(theme, scheme) {
22640
+ return { ...theme, colors: { ...theme.colors, ...EDITOR_SURFACE[scheme] } };
22641
+ }
22642
+ function readHostSurface(host) {
22643
+ const inheritance = host?.closest("[data-theme-inheritance]")?.dataset.themeInheritance;
22644
+ return {
22645
+ scheme: host?.closest("[data-theme]")?.dataset.theme === "dark" ? "dark" : "light",
22646
+ inheritsThemeColors: inheritance === "fonts-colors"
22647
+ };
22648
+ }
22649
+ function applyHostSurface(surface, theme) {
22650
+ return surface.inheritsThemeColors ? theme : adaptThemeToSurface(theme, surface.scheme);
22651
+ }
22652
+ function resolveMermaidSurfaceTheme(host, theme) {
22653
+ return applyHostSurface(readHostSurface(host), theme);
22654
+ }
22655
+ function useMermaidSurfaceTheme(host, theme) {
22656
+ const [surface, setSurface] = useState36(() => readHostSurface(host));
22657
+ useEffect27(() => {
22658
+ const sync = () => setSurface((current) => {
22659
+ const next = readHostSurface(host);
22660
+ return current.scheme === next.scheme && current.inheritsThemeColors === next.inheritsThemeColors ? current : next;
22661
+ });
22662
+ sync();
22663
+ if (typeof MutationObserver === "undefined") return;
22664
+ const observer = new MutationObserver(sync);
22665
+ const ancestors = new Set(
22666
+ [
22667
+ host?.closest("[data-theme]"),
22668
+ host?.closest("[data-theme-inheritance]")
22669
+ ].filter((element) => Boolean(element))
22670
+ );
22671
+ for (const ancestor of ancestors) {
22672
+ observer.observe(ancestor, {
22673
+ attributes: true,
22674
+ attributeFilter: ["data-theme", "data-theme-inheritance"]
22675
+ });
22676
+ }
22677
+ return () => observer.disconnect();
22678
+ }, [host]);
22679
+ return useMemo29(() => applyHostSurface(surface, theme), [surface, theme]);
22680
+ }
22681
+
22619
22682
  // src/mermaid/MermaidDiagramCanvas.tsx
22620
- import { useCallback as useCallback33, useEffect as useEffect27, useId as useId12, useLayoutEffect as useLayoutEffect5, useRef as useRef32, useState as useState36 } from "react";
22683
+ import { useCallback as useCallback33, useEffect as useEffect28, useId as useId12, useLayoutEffect as useLayoutEffect5, useRef as useRef32, useState as useState37 } from "react";
22621
22684
  import { jsx as jsx46, jsxs as jsxs35 } from "react/jsx-runtime";
22622
22685
  var renderSequence = 0;
22623
22686
  function excludesCanvasPan(target, viewport) {
@@ -22681,20 +22744,20 @@ function MermaidDiagramCanvas({
22681
22744
  const renameInputRef = useRef32(null);
22682
22745
  const panDragRef = useRef32(null);
22683
22746
  const renameHintId = useId12();
22684
- const [svg, setSvg] = useState36("");
22685
- const [model2, setModel] = useState36(null);
22686
- const [diagramType, setDiagramType] = useState36("mermaid");
22687
- const [error, setError] = useState36("");
22688
- const [rendering, setRendering] = useState36(true);
22689
- const [zoom, setZoom] = useState36(1);
22690
- const [viewMode, setViewMode] = useState36("fit");
22691
- const [contentSize, setContentSize] = useState36(null);
22692
- const [canvasSize, setCanvasSize] = useState36(null);
22693
- const [pan, setPan] = useState36({ x: 0, y: 0 });
22694
- const [panning, setPanning] = useState36(false);
22695
- const [selectionAnchor, setSelectionAnchor] = useState36(null);
22696
- const [renameValue, setRenameValue] = useState36("");
22697
- useEffect27(() => {
22747
+ const [svg, setSvg] = useState37("");
22748
+ const [model2, setModel] = useState37(null);
22749
+ const [diagramType, setDiagramType] = useState37("mermaid");
22750
+ const [error, setError] = useState37("");
22751
+ const [rendering, setRendering] = useState37(true);
22752
+ const [zoom, setZoom] = useState37(1);
22753
+ const [viewMode, setViewMode] = useState37("fit");
22754
+ const [contentSize, setContentSize] = useState37(null);
22755
+ const [canvasSize, setCanvasSize] = useState37(null);
22756
+ const [pan, setPan] = useState37({ x: 0, y: 0 });
22757
+ const [panning, setPanning] = useState37(false);
22758
+ const [selectionAnchor, setSelectionAnchor] = useState37(null);
22759
+ const [renameValue, setRenameValue] = useState37("");
22760
+ useEffect28(() => {
22698
22761
  if (!panning) return;
22699
22762
  const finish = () => {
22700
22763
  panDragRef.current = null;
@@ -22722,7 +22785,7 @@ function MermaidDiagramCanvas({
22722
22785
  window.removeEventListener("blur", finish);
22723
22786
  };
22724
22787
  }, [panning]);
22725
- useEffect27(() => {
22788
+ useEffect28(() => {
22726
22789
  let current = true;
22727
22790
  const id = `squisq-mermaid-svg-${++renderSequence}`;
22728
22791
  setRendering(true);
@@ -22993,7 +23056,7 @@ function MermaidDiagramCanvas({
22993
23056
  updateSelectionAnchor,
22994
23057
  zoom
22995
23058
  ]);
22996
- useEffect27(() => {
23059
+ useEffect28(() => {
22997
23060
  const scroll = scrollRef.current;
22998
23061
  if (!scroll) return;
22999
23062
  const update = () => updateSelectionAnchor();
@@ -23130,6 +23193,7 @@ function MermaidDiagramCanvas({
23130
23193
  {
23131
23194
  className: "squisq-mermaid-canvas",
23132
23195
  "aria-label": `${diagramType} diagram editor`,
23196
+ "data-surface": mermaidSurfaceScheme(theme),
23133
23197
  style: { background: theme.colors.backgroundLight, color: theme.colors.text },
23134
23198
  children: [
23135
23199
  /* @__PURE__ */ jsx46(
@@ -23397,7 +23461,7 @@ function CanvasAction({
23397
23461
  }
23398
23462
 
23399
23463
  // src/mermaid/MermaidShapePalette.tsx
23400
- import { useEffect as useEffect28, useLayoutEffect as useLayoutEffect6, useMemo as useMemo29, useRef as useRef33, useState as useState37 } from "react";
23464
+ import { useEffect as useEffect29, useLayoutEffect as useLayoutEffect6, useMemo as useMemo30, useRef as useRef33, useState as useState38 } from "react";
23401
23465
  import { jsx as jsx47, jsxs as jsxs36 } from "react/jsx-runtime";
23402
23466
  var CATEGORIES = ["Basic", "Process", "Data", "Documents", "Symbols"];
23403
23467
  var PALETTE_WIDTH = 360;
@@ -23405,10 +23469,10 @@ var PALETTE_MAX_HEIGHT = 520;
23405
23469
  var PALETTE_GAP = 6;
23406
23470
  var VIEWPORT_GUTTER = 8;
23407
23471
  function MermaidShapePalette({ selected, onPick, onClose }) {
23408
- const [query, setQuery] = useState37("");
23409
- const [position, setPosition] = useState37(null);
23472
+ const [query, setQuery] = useState38("");
23473
+ const [position, setPosition] = useState38(null);
23410
23474
  const ref = useRef33(null);
23411
- useEffect28(() => {
23475
+ useEffect29(() => {
23412
23476
  const onPointerDown = (event) => {
23413
23477
  const target = event.target;
23414
23478
  if (target?.closest(".squisq-scene-block-toolbar")) return;
@@ -23424,7 +23488,7 @@ function MermaidShapePalette({ selected, onPick, onClose }) {
23424
23488
  document.removeEventListener("keydown", onKeyDown);
23425
23489
  };
23426
23490
  }, [onClose]);
23427
- const sections = useMemo29(() => {
23491
+ const sections = useMemo30(() => {
23428
23492
  const normalized = query.trim().toLowerCase();
23429
23493
  return CATEGORIES.map((category) => ({
23430
23494
  category,
@@ -23579,7 +23643,7 @@ function MermaidShapeThumb({ shape }) {
23579
23643
  }
23580
23644
 
23581
23645
  // src/mermaid/mermaidData.ts
23582
- import { useEffect as useEffect30, useMemo as useMemo30, useState as useState39 } from "react";
23646
+ import { useEffect as useEffect31, useMemo as useMemo31, useState as useState40 } from "react";
23583
23647
 
23584
23648
  // src/mermaid/MermaidDiagramExtension.ts
23585
23649
  import { Extension as Extension5 } from "@tiptap/core";
@@ -23591,10 +23655,10 @@ import { createRoot as createRoot3 } from "react-dom/client";
23591
23655
  // src/mermaid/MermaidDiagramWidget.tsx
23592
23656
  import {
23593
23657
  useCallback as useCallback34,
23594
- useEffect as useEffect29,
23658
+ useEffect as useEffect30,
23595
23659
  useLayoutEffect as useLayoutEffect7,
23596
23660
  useRef as useRef34,
23597
- useState as useState38,
23661
+ useState as useState39,
23598
23662
  useSyncExternalStore
23599
23663
  } from "react";
23600
23664
 
@@ -23957,21 +24021,22 @@ function MermaidDiagramWidget({
23957
24021
  themeStore
23958
24022
  }) {
23959
24023
  const data = useMermaidDiagramData(editor, blockId);
23960
- const theme = useSyncExternalStore(
24024
+ const docTheme = useSyncExternalStore(
23961
24025
  themeStore?.subscribe ?? subscribeToDefaultTheme,
23962
24026
  themeStore?.getSnapshot ?? getDefaultTheme,
23963
24027
  themeStore?.getSnapshot ?? getDefaultTheme
23964
24028
  );
23965
- const [model2, setModel] = useState38(null);
23966
- const [selection, setSelection] = useState38(null);
23967
- const [renaming, setRenaming] = useState38(null);
23968
- const [connecting, setConnecting] = useState38(false);
23969
- const [connectSourceId, setConnectSourceId] = useState38(null);
23970
- const [openPopover, setOpenPopover] = useState38(null);
23971
- const [editNotice, setEditNotice] = useState38("");
23972
- const [maximized, setMaximized] = useState38(false);
23973
- const [height, setHeight] = useState38(null);
23974
- const [dragHeight, setDragHeight] = useState38(null);
24029
+ const theme = useMermaidSurfaceTheme(host, docTheme);
24030
+ const [model2, setModel] = useState39(null);
24031
+ const [selection, setSelection] = useState39(null);
24032
+ const [renaming, setRenaming] = useState39(null);
24033
+ const [connecting, setConnecting] = useState39(false);
24034
+ const [connectSourceId, setConnectSourceId] = useState39(null);
24035
+ const [openPopover, setOpenPopover] = useState39(null);
24036
+ const [editNotice, setEditNotice] = useState39("");
24037
+ const [maximized, setMaximized] = useState39(false);
24038
+ const [height, setHeight] = useState39(null);
24039
+ const [dragHeight, setDragHeight] = useState39(null);
23975
24040
  const inlineRef = useRef34(null);
23976
24041
  const effectiveHeight = dragHeight ?? height;
23977
24042
  const onModelChange = useCallback34((next) => {
@@ -24230,7 +24295,7 @@ function MermaidDiagramWidget({
24230
24295
  },
24231
24296
  [effectiveHeight]
24232
24297
  );
24233
- useEffect29(() => {
24298
+ useEffect30(() => {
24234
24299
  if (!editNotice) return;
24235
24300
  const timeout = window.setTimeout(() => setEditNotice(""), 7e3);
24236
24301
  return () => window.clearTimeout(timeout);
@@ -24467,7 +24532,7 @@ function MermaidDiagramWidget({
24467
24532
  ] });
24468
24533
  }
24469
24534
  function useDismissibleMermaidPopover(ref, onClose) {
24470
- useEffect29(() => {
24535
+ useEffect30(() => {
24471
24536
  const onPointerDown = (event) => {
24472
24537
  const target = event.target;
24473
24538
  if (target?.closest(".squisq-scene-block-toolbar")) return;
@@ -24485,7 +24550,7 @@ function useDismissibleMermaidPopover(ref, onClose) {
24485
24550
  }, [onClose, ref]);
24486
24551
  }
24487
24552
  function useClampedMermaidPopoverPosition(ref, preferredWidth, preferredMaxHeight) {
24488
- const [position, setPosition] = useState38(null);
24553
+ const [position, setPosition] = useState39(null);
24489
24554
  useLayoutEffect7(() => {
24490
24555
  const picker = ref.current;
24491
24556
  const anchor = picker?.parentElement;
@@ -24551,7 +24616,7 @@ function MermaidPropertiesPalette({
24551
24616
  onApply,
24552
24617
  onClose
24553
24618
  }) {
24554
- const [values, setValues] = useState38(
24619
+ const [values, setValues] = useState39(
24555
24620
  () => Object.fromEntries(properties.map((property) => [property.id, property.value]))
24556
24621
  );
24557
24622
  const ref = useRef34(null);
@@ -24845,15 +24910,15 @@ var MermaidDiagramExtension = Extension5.create({
24845
24910
 
24846
24911
  // src/mermaid/mermaidData.ts
24847
24912
  function useMermaidDiagramData(editor, blockId) {
24848
- const [version, setVersion] = useState39(0);
24849
- useEffect30(() => {
24913
+ const [version, setVersion] = useState40(0);
24914
+ useEffect31(() => {
24850
24915
  const onTransaction = () => setVersion((value) => value + 1);
24851
24916
  editor.on("transaction", onTransaction);
24852
24917
  return () => {
24853
24918
  editor.off("transaction", onTransaction);
24854
24919
  };
24855
24920
  }, [editor]);
24856
- return useMemo30(() => {
24921
+ return useMemo31(() => {
24857
24922
  const pos = findMermaidDiagramBlockPos(editor, blockId);
24858
24923
  if (pos === null) return null;
24859
24924
  const node2 = editor.state.doc.nodeAt(pos);
@@ -24870,20 +24935,20 @@ import { createElement as createElement10 } from "react";
24870
24935
  import { createRoot as createRoot4 } from "react-dom/client";
24871
24936
 
24872
24937
  // src/codeSnippet/CodeSnippetWidget.tsx
24873
- import { useCallback as useCallback35, useEffect as useEffect32, useState as useState41 } from "react";
24938
+ import { useCallback as useCallback35, useEffect as useEffect33, useState as useState42 } from "react";
24874
24939
 
24875
24940
  // src/codeSnippet/codeSnippetData.ts
24876
- import { useEffect as useEffect31, useMemo as useMemo31, useState as useState40 } from "react";
24941
+ import { useEffect as useEffect32, useMemo as useMemo32, useState as useState41 } from "react";
24877
24942
  function useCodeSnippetData(editor, blockId) {
24878
- const [version, setVersion] = useState40(0);
24879
- useEffect31(() => {
24943
+ const [version, setVersion] = useState41(0);
24944
+ useEffect32(() => {
24880
24945
  const onTransaction = () => setVersion((value) => value + 1);
24881
24946
  editor.on("transaction", onTransaction);
24882
24947
  return () => {
24883
24948
  editor.off("transaction", onTransaction);
24884
24949
  };
24885
24950
  }, [editor]);
24886
- return useMemo31(() => {
24951
+ return useMemo32(() => {
24887
24952
  const pos = findCodeSnippetBlockPos(editor, blockId);
24888
24953
  if (pos === null) return null;
24889
24954
  const node2 = editor.state.doc.nodeAt(pos);
@@ -24921,8 +24986,17 @@ function schemeFromHost(host) {
24921
24986
  return host?.closest("[data-theme]")?.dataset.theme === "dark" ? "dark" : "light";
24922
24987
  }
24923
24988
  function useHostColorScheme(host) {
24924
- const [scheme, setScheme] = useState41(() => schemeFromHost(host));
24925
- useEffect32(() => {
24989
+ const [scheme, setScheme] = useState42(
24990
+ () => host != null && !host.isConnected ? null : schemeFromHost(host)
24991
+ );
24992
+ useEffect33(() => {
24993
+ if (host != null && !host.isConnected) {
24994
+ setScheme(null);
24995
+ const raf = requestAnimationFrame(() => {
24996
+ if (host.isConnected) setScheme(schemeFromHost(host));
24997
+ });
24998
+ return () => cancelAnimationFrame(raf);
24999
+ }
24926
25000
  const themedAncestor = host?.closest("[data-theme]");
24927
25001
  setScheme(schemeFromHost(host));
24928
25002
  if (!themedAncestor || typeof MutationObserver === "undefined") return;
@@ -24933,8 +25007,8 @@ function useHostColorScheme(host) {
24933
25007
  return scheme;
24934
25008
  }
24935
25009
  function useEditorEditable(editor) {
24936
- const [editable, setEditable] = useState41(editor.isEditable);
24937
- useEffect32(() => {
25010
+ const [editable, setEditable] = useState42(editor.isEditable);
25011
+ useEffect33(() => {
24938
25012
  const sync = () => setEditable(editor.isEditable);
24939
25013
  editor.on("update", sync);
24940
25014
  editor.on("transaction", sync);
@@ -24955,7 +25029,7 @@ function CodeSnippetWidget({
24955
25029
  const { ready } = useMonacoLoader(data?.monacoLanguage);
24956
25030
  const colorScheme = useHostColorScheme(host);
24957
25031
  const editable = useEditorEditable(editor);
24958
- const [modelInstanceId] = useState41(allocateCodeSnippetModelInstanceId);
25032
+ const [modelInstanceId] = useState42(allocateCodeSnippetModelInstanceId);
24959
25033
  const handleChange = useCallback35(
24960
25034
  (value) => {
24961
25035
  if (!editable) return;
@@ -24985,7 +25059,7 @@ function CodeSnippetWidget({
24985
25059
  /* @__PURE__ */ jsx49(Icon, { icon: "fa-solid fa-file-code" }),
24986
25060
  /* @__PURE__ */ jsx49("span", { children: data.label })
24987
25061
  ] }) }),
24988
- /* @__PURE__ */ jsx49("div", { className: "squisq-code-snippet-editor", "aria-label": `${data.label} code editor`, children: ready ? /* @__PURE__ */ jsx49(
25062
+ /* @__PURE__ */ jsx49("div", { className: "squisq-code-snippet-editor", "aria-label": `${data.label} code editor`, children: ready && colorScheme !== null ? /* @__PURE__ */ jsx49(
24989
25063
  Ft,
24990
25064
  {
24991
25065
  path: `inmemory://squisq/code-snippet/${modelInstanceId}/${blockId}.${modelSuffix || "txt"}`,
@@ -25178,7 +25252,7 @@ import { createRoot as createRoot5 } from "react-dom/client";
25178
25252
  import { createElement as createElement11 } from "react";
25179
25253
 
25180
25254
  // src/fenceWidgets/HostFenceWidget.tsx
25181
- import { Component, useEffect as useEffect33, useMemo as useMemo32, useState as useState42 } from "react";
25255
+ import { Component, useEffect as useEffect34, useMemo as useMemo33, useState as useState43 } from "react";
25182
25256
  import { jsx as jsx50 } from "react/jsx-runtime";
25183
25257
  var HostFenceErrorBoundary = class extends Component {
25184
25258
  constructor() {
@@ -25193,15 +25267,15 @@ var HostFenceErrorBoundary = class extends Component {
25193
25267
  }
25194
25268
  };
25195
25269
  function HostFenceWidget({ editor, blockId, getRenderers, getTheme }) {
25196
- const [version, setVersion] = useState42(0);
25197
- useEffect33(() => {
25270
+ const [version, setVersion] = useState43(0);
25271
+ useEffect34(() => {
25198
25272
  const onUpdate = () => setVersion((v2) => v2 + 1);
25199
25273
  editor.on("transaction", onUpdate);
25200
25274
  return () => {
25201
25275
  editor.off("transaction", onUpdate);
25202
25276
  };
25203
25277
  }, [editor]);
25204
- const current = useMemo32(() => {
25278
+ const current = useMemo33(() => {
25205
25279
  const pos = findHostFenceBlockPos(editor, blockId);
25206
25280
  if (pos === null) return null;
25207
25281
  const node2 = editor.state.doc.nodeAt(pos);
@@ -25344,7 +25418,7 @@ var HostFenceExtension = Extension7.create({
25344
25418
  });
25345
25419
 
25346
25420
  // src/treeview/treeViewData.ts
25347
- import { useEffect as useEffect34, useMemo as useMemo33, useState as useState44 } from "react";
25421
+ import { useEffect as useEffect35, useMemo as useMemo34, useState as useState45 } from "react";
25348
25422
 
25349
25423
  // src/treeview/TreeViewExtension.ts
25350
25424
  import { Extension as Extension8 } from "@tiptap/core";
@@ -25361,7 +25435,7 @@ import {
25361
25435
  } from "@bendyline/squisq/doc";
25362
25436
 
25363
25437
  // src/treeview/TreeOutlineWidget.tsx
25364
- import { useCallback as useCallback36, useRef as useRef35, useState as useState43 } from "react";
25438
+ import { useCallback as useCallback36, useRef as useRef35, useState as useState44 } from "react";
25365
25439
 
25366
25440
  // src/treeview/treeViewCommands.ts
25367
25441
  import { parseTree, renderTree } from "@bendyline/squisq/doc";
@@ -25598,10 +25672,10 @@ function dropPositionForPointer(event) {
25598
25672
  }
25599
25673
  function TreeOutlineWidget({ editor, blockId }) {
25600
25674
  const view = useTreeViewData(editor, blockId);
25601
- const [collapsed, setCollapsed] = useState43(() => /* @__PURE__ */ new Set());
25675
+ const [collapsed, setCollapsed] = useState44(() => /* @__PURE__ */ new Set());
25602
25676
  const activeDragRef = useRef35(null);
25603
- const [draggedId, setDraggedId] = useState43(null);
25604
- const [dropTarget, setDropTarget] = useState43(null);
25677
+ const [draggedId, setDraggedId] = useState44(null);
25678
+ const [dropTarget, setDropTarget] = useState44(null);
25605
25679
  const dispatch = useCallback36(
25606
25680
  (cmd) => applyTreeCommand(editor, blockId, cmd),
25607
25681
  [editor, blockId]
@@ -25748,7 +25822,7 @@ function TreeRowView({
25748
25822
  const hasChildren = node2.children.length > 0;
25749
25823
  const isCollapsed = collapsed.has(node2.id);
25750
25824
  const isDir = node2.isDir || hasChildren;
25751
- const [draft, setDraft] = useState43(node2.label);
25825
+ const [draft, setDraft] = useState44(node2.label);
25752
25826
  const dropPosition = dropTarget?.id === node2.id ? dropTarget.position : null;
25753
25827
  const itemClassName = [
25754
25828
  "squisq-tree-item",
@@ -26052,15 +26126,15 @@ var TreeViewExtension = Extension8.create({
26052
26126
 
26053
26127
  // src/treeview/treeViewData.ts
26054
26128
  function useTreeViewData(editor, blockId) {
26055
- const [version, setVersion] = useState44(0);
26056
- useEffect34(() => {
26129
+ const [version, setVersion] = useState45(0);
26130
+ useEffect35(() => {
26057
26131
  const onUpdate = () => setVersion((v2) => v2 + 1);
26058
26132
  editor.on("transaction", onUpdate);
26059
26133
  return () => {
26060
26134
  editor.off("transaction", onUpdate);
26061
26135
  };
26062
26136
  }, [editor]);
26063
- return useMemo33(() => {
26137
+ return useMemo34(() => {
26064
26138
  const pos = findTreeBlockPos(editor, blockId);
26065
26139
  if (pos === null) return null;
26066
26140
  const node2 = editor.state.doc.nodeAt(pos);
@@ -26079,7 +26153,7 @@ function shouldPasteAsTreeFence(text) {
26079
26153
  }
26080
26154
 
26081
26155
  // src/timeline/timelineData.ts
26082
- import { useEffect as useEffect36, useMemo as useMemo35, useRef as useRef37, useState as useState46 } from "react";
26156
+ import { useEffect as useEffect37, useMemo as useMemo36, useRef as useRef37, useState as useState47 } from "react";
26083
26157
 
26084
26158
  // src/timeline/TimelineViewExtension.ts
26085
26159
  import { Extension as Extension9 } from "@tiptap/core";
@@ -26094,7 +26168,7 @@ import {
26094
26168
  } from "@bendyline/squisq/doc";
26095
26169
 
26096
26170
  // src/timeline/TimelineEditorWidget.tsx
26097
- import { useCallback as useCallback37, useEffect as useEffect35, useMemo as useMemo34, useRef as useRef36, useState as useState45 } from "react";
26171
+ import { useCallback as useCallback37, useEffect as useEffect36, useMemo as useMemo35, useRef as useRef36, useState as useState46 } from "react";
26098
26172
  import {
26099
26173
  asciiTimelineToTemplateData
26100
26174
  } from "@bendyline/squisq/doc";
@@ -26578,13 +26652,13 @@ import { Fragment as Fragment15, jsx as jsx52, jsxs as jsxs40 } from "react/jsx-
26578
26652
  var clamp01 = (value) => Math.max(0, Math.min(1, value));
26579
26653
  function TimelineEditorWidget({ editor, blockId }) {
26580
26654
  const view = useTimelineData(editor, blockId);
26581
- const [selectedEventId, setSelectedEventId] = useState45(null);
26582
- const [addingTrackId, setAddingTrackId] = useState45(null);
26583
- const [editingTrackId, setEditingTrackId] = useState45(null);
26584
- const [hover, setHover] = useState45(null);
26585
- const [dragged, setDragged] = useState45(null);
26655
+ const [selectedEventId, setSelectedEventId] = useState46(null);
26656
+ const [addingTrackId, setAddingTrackId] = useState46(null);
26657
+ const [editingTrackId, setEditingTrackId] = useState46(null);
26658
+ const [hover, setHover] = useState46(null);
26659
+ const [dragged, setDragged] = useState46(null);
26586
26660
  const suppressClickEventId = useRef36(null);
26587
- const [announcement, setAnnouncement] = useState45("");
26661
+ const [announcement, setAnnouncement] = useState46("");
26588
26662
  const dispatch = useCallback37(
26589
26663
  (command) => {
26590
26664
  const result = applyTimelineCommand(editor, blockId, command);
@@ -26598,7 +26672,7 @@ function TimelineEditorWidget({ editor, blockId }) {
26598
26672
  );
26599
26673
  const sourceText2 = view?.text;
26600
26674
  const sourceTimeline = view?.timeline;
26601
- const sourceSafe = useMemo34(
26675
+ const sourceSafe = useMemo35(
26602
26676
  () => sourceText2 && sourceTimeline ? isTimelineSourceSafeForSemanticEdit(sourceText2, sourceTimeline) : false,
26603
26677
  // `useTimelineData` publishes on every editor transaction so read-only
26604
26678
  // changes are observed. Unrelated transactions retain both primitive/model
@@ -26608,7 +26682,7 @@ function TimelineEditorWidget({ editor, blockId }) {
26608
26682
  );
26609
26683
  const editorEditable = editor.isEditable;
26610
26684
  const editable = editorEditable && sourceSafe;
26611
- const positioned = useMemo34(() => {
26685
+ const positioned = useMemo35(() => {
26612
26686
  if (!view) return [];
26613
26687
  const normalized = asciiTimelineToTemplateData(view.timeline).tracks;
26614
26688
  return view.timeline.tracks.flatMap((track, trackIndex) => {
@@ -26623,17 +26697,17 @@ function TimelineEditorWidget({ editor, blockId }) {
26623
26697
  );
26624
26698
  });
26625
26699
  }, [view]);
26626
- const displayedPositioned = useMemo34(
26700
+ const displayedPositioned = useMemo35(
26627
26701
  () => dragged ? positioned.map(
26628
26702
  (point) => point.event.id === dragged.eventId ? { ...point, position: dragged.position } : point
26629
26703
  ) : positioned,
26630
26704
  [dragged, positioned]
26631
26705
  );
26632
- const positionById = useMemo34(
26706
+ const positionById = useMemo35(
26633
26707
  () => new Map(displayedPositioned.map((point) => [point.event.id, point.position])),
26634
26708
  [displayedPositioned]
26635
26709
  );
26636
- const selected = useMemo34(() => {
26710
+ const selected = useMemo35(() => {
26637
26711
  if (!view || !selectedEventId) return null;
26638
26712
  for (const track of view.timeline.tracks) {
26639
26713
  const event = track.events.find((candidate) => candidate.id === selectedEventId);
@@ -26647,7 +26721,7 @@ function TimelineEditorWidget({ editor, blockId }) {
26647
26721
  }
26648
26722
  return null;
26649
26723
  }, [selectedEventId, view]);
26650
- useEffect35(() => {
26724
+ useEffect36(() => {
26651
26725
  if (!view) return;
26652
26726
  const ids = new Set(
26653
26727
  view.timeline.tracks.flatMap((track) => track.events.map((event) => event.id))
@@ -26655,13 +26729,13 @@ function TimelineEditorWidget({ editor, blockId }) {
26655
26729
  if (selectedEventId && ids.has(selectedEventId)) return;
26656
26730
  setSelectedEventId(view.timeline.tracks[0]?.events[0]?.id ?? null);
26657
26731
  }, [selectedEventId, view]);
26658
- useEffect35(() => {
26732
+ useEffect36(() => {
26659
26733
  if (editable) return;
26660
26734
  setAddingTrackId(null);
26661
26735
  setEditingTrackId(null);
26662
26736
  setHover(null);
26663
26737
  }, [editable]);
26664
- useEffect35(() => {
26738
+ useEffect36(() => {
26665
26739
  if (!editingTrackId || view?.timeline.tracks.some((track) => track.id === editingTrackId)) {
26666
26740
  return;
26667
26741
  }
@@ -27067,8 +27141,8 @@ function InlineTrackLabel({
27067
27141
  onStart,
27068
27142
  onFinish
27069
27143
  }) {
27070
- const [draft, setDraft] = useState45(label);
27071
- useEffect35(() => {
27144
+ const [draft, setDraft] = useState46(label);
27145
+ useEffect36(() => {
27072
27146
  if (editing) setDraft(label);
27073
27147
  }, [editing, label]);
27074
27148
  const commitLabel = () => {
@@ -27125,10 +27199,10 @@ function EventInspector({
27125
27199
  onDelete
27126
27200
  }) {
27127
27201
  const { event } = selected;
27128
- const [label, setLabel] = useState45(event.label);
27129
- const [description, setDescription] = useState45(event.description ?? "");
27130
- useEffect35(() => setLabel(event.label), [event.label]);
27131
- useEffect35(() => setDescription(event.description ?? ""), [event.description]);
27202
+ const [label, setLabel] = useState46(event.label);
27203
+ const [description, setDescription] = useState46(event.description ?? "");
27204
+ useEffect36(() => setLabel(event.label), [event.label]);
27205
+ useEffect36(() => setDescription(event.description ?? ""), [event.description]);
27132
27206
  const update = (patch) => dispatch(patch);
27133
27207
  const commitLabel = () => {
27134
27208
  const next = label.trim();
@@ -27433,9 +27507,9 @@ var TimelineViewExtension = Extension9.create({
27433
27507
 
27434
27508
  // src/timeline/timelineData.ts
27435
27509
  function useTimelineData(editor, blockId) {
27436
- const [version, setVersion] = useState46(0);
27510
+ const [version, setVersion] = useState47(0);
27437
27511
  const dataCache = useRef37(null);
27438
- useEffect36(() => {
27512
+ useEffect37(() => {
27439
27513
  const onEditorChange = () => setVersion((value) => value + 1);
27440
27514
  editor.on("transaction", onEditorChange);
27441
27515
  editor.on("update", onEditorChange);
@@ -27444,7 +27518,7 @@ function useTimelineData(editor, blockId) {
27444
27518
  editor.off("update", onEditorChange);
27445
27519
  };
27446
27520
  }, [editor]);
27447
- return useMemo35(() => {
27521
+ return useMemo36(() => {
27448
27522
  const pos = findTimelineBlockPos(editor, blockId);
27449
27523
  if (pos === null) return null;
27450
27524
  const node2 = editor.state.doc.nodeAt(pos);
@@ -27470,7 +27544,7 @@ function shouldPasteAsTimelineFence(text) {
27470
27544
  }
27471
27545
 
27472
27546
  // src/BlockPropertiesPopover.tsx
27473
- import { useEffect as useEffect37, useId as useId13, useRef as useRef38, useState as useState47 } from "react";
27547
+ import { useEffect as useEffect38, useId as useId13, useRef as useRef38, useState as useState48 } from "react";
27474
27548
  import { createPortal as createPortal9 } from "react-dom";
27475
27549
  import { jsx as jsx53, jsxs as jsxs41 } from "react/jsx-runtime";
27476
27550
  var TRANSITION_FLYOUT = ".squisq-transition-flyout";
@@ -27486,13 +27560,13 @@ function BlockPropertiesPopover({
27486
27560
  }) {
27487
27561
  const panelRef = useRef38(null);
27488
27562
  const panelId = `squisq-block-props-portal-${useId13().replace(/:/g, "")}`;
27489
- const [inner, setInner] = useState47(blockAttrs);
27490
- const [templateInner, setTemplateInner] = useState47(templateParams);
27491
- const [style, setStyle] = useState47(() => computeStyle(anchorRect));
27492
- useEffect37(() => {
27563
+ const [inner, setInner] = useState48(blockAttrs);
27564
+ const [templateInner, setTemplateInner] = useState48(templateParams);
27565
+ const [style, setStyle] = useState48(() => computeStyle(anchorRect));
27566
+ useEffect38(() => {
27493
27567
  requestAnimationFrame(() => setStyle(computeStyle(anchorRect, panelRef.current)));
27494
27568
  }, [anchorRect]);
27495
- useEffect37(() => {
27569
+ useEffect38(() => {
27496
27570
  const onKey = (e2) => {
27497
27571
  if (e2.key === "Escape") onClose();
27498
27572
  };
@@ -27654,7 +27728,7 @@ function persistFromWrite(bodyMd, state) {
27654
27728
  }
27655
27729
 
27656
27730
  // src/WysiwygEditor.tsx
27657
- import { useCallback as useCallback38, useEffect as useEffect41, useMemo as useMemo36, useRef as useRef40, useState as useState51 } from "react";
27731
+ import { useCallback as useCallback38, useEffect as useEffect42, useMemo as useMemo37, useRef as useRef40, useState as useState52 } from "react";
27658
27732
  import { useEditor as useEditor2, EditorContent as EditorContent2 } from "@tiptap/react";
27659
27733
  import { Selection } from "@tiptap/pm/state";
27660
27734
  import StarterKit2 from "@tiptap/starter-kit";
@@ -27890,7 +27964,7 @@ var InlineIcon = Node2.create({
27890
27964
  });
27891
27965
 
27892
27966
  // src/ImageNodeView.tsx
27893
- import { useEffect as useEffect38, useRef as useRef39, useState as useState48 } from "react";
27967
+ import { useEffect as useEffect39, useRef as useRef39, useState as useState49 } from "react";
27894
27968
  import { NodeViewWrapper, ReactNodeViewRenderer } from "@tiptap/react";
27895
27969
  import Image from "@tiptap/extension-image";
27896
27970
 
@@ -27910,16 +27984,16 @@ import { Fragment as Fragment16, jsx as jsx54, jsxs as jsxs42 } from "react/jsx-
27910
27984
  function ImageComponent({ node: node2, selected, editor, updateAttributes }) {
27911
27985
  const { src, alt, title, width } = node2.attrs;
27912
27986
  const { mediaProvider, imageDisplayMode, openImageEdit, mediaRevision } = useEditorContext();
27913
- const [resolvedSrc, setResolvedSrc] = useState48(src);
27914
- const [hovered, setHovered] = useState48(false);
27987
+ const [resolvedSrc, setResolvedSrc] = useState49(src);
27988
+ const [hovered, setHovered] = useState49(false);
27915
27989
  const imgRef = useRef39(null);
27916
- const [previewWidth, setPreviewWidth] = useState48(null);
27990
+ const [previewWidth, setPreviewWidth] = useState49(null);
27917
27991
  const isThumbnail = imageDisplayMode === "thumbnail";
27918
27992
  const isEditable = editor?.isEditable ?? true;
27919
27993
  const normalizedRelativePath = normalizeMalformedAssetUrl(src);
27920
27994
  const isRelative = src && !src.startsWith("blob:") && !src.startsWith("http") && !src.startsWith("data:") && !src.startsWith("/");
27921
27995
  const resolveAs = normalizedRelativePath ?? (isRelative ? src : null);
27922
- useEffect38(() => {
27996
+ useEffect39(() => {
27923
27997
  if (!mediaProvider || !resolveAs) {
27924
27998
  setResolvedSrc(src);
27925
27999
  return;
@@ -28098,15 +28172,15 @@ var ImageWithMediaProvider = Image.extend({
28098
28172
  // src/tiptap/TiptapVideo.tsx
28099
28173
  import { Node as Node3, mergeAttributes as mergeAttributes2 } from "@tiptap/core";
28100
28174
  import { NodeViewWrapper as NodeViewWrapper2, ReactNodeViewRenderer as ReactNodeViewRenderer2 } from "@tiptap/react";
28101
- import { useEffect as useEffect40, useState as useState50 } from "react";
28175
+ import { useEffect as useEffect41, useState as useState51 } from "react";
28102
28176
 
28103
28177
  // src/tiptap/useResolvedMediaSrc.ts
28104
- import { useEffect as useEffect39, useState as useState49 } from "react";
28178
+ import { useEffect as useEffect40, useState as useState50 } from "react";
28105
28179
  function useResolvedMediaSrc(src) {
28106
28180
  const { mediaProvider, mediaRevision } = useEditorContext();
28107
- const [resolved, setResolved] = useState49(src);
28181
+ const [resolved, setResolved] = useState50(src);
28108
28182
  const isRelative = !!src && !src.startsWith("blob:") && !src.startsWith("http:") && !src.startsWith("https:") && !src.startsWith("data:") && !src.startsWith("/");
28109
- useEffect39(() => {
28183
+ useEffect40(() => {
28110
28184
  if (!mediaProvider || !isRelative) {
28111
28185
  setResolved(src);
28112
28186
  return;
@@ -28157,9 +28231,9 @@ function VideoNodeView({ node: node2, updateAttributes, selected }) {
28157
28231
  const placement = normalizeVideoPlacement(rawPlacement);
28158
28232
  const lockToBlock = normalizeLockToBlock(rawLockToBlock);
28159
28233
  const resolvedSrc = useResolvedMediaSrc(src ?? "");
28160
- const [audioOnly, setAudioOnly] = useState50(false);
28234
+ const [audioOnly, setAudioOnly] = useState51(false);
28161
28235
  const resolvedPoster = useResolvedMediaSrc(poster ?? "");
28162
- useEffect40(() => {
28236
+ useEffect41(() => {
28163
28237
  setAudioOnly(false);
28164
28238
  }, [resolvedSrc]);
28165
28239
  const handleLoadedMetadata = (event) => {
@@ -28826,11 +28900,11 @@ function WysiwygEditor({
28826
28900
  mermaidThemeStoreRef.current = createMermaidThemeStore(activeTheme ?? DEFAULT_THEME4);
28827
28901
  }
28828
28902
  const mermaidThemeStore = mermaidThemeStoreRef.current;
28829
- useEffect41(() => {
28903
+ useEffect42(() => {
28830
28904
  mermaidThemeStore.setTheme(activeTheme ?? DEFAULT_THEME4);
28831
28905
  }, [activeTheme, mermaidThemeStore]);
28832
28906
  const { docTemplates, onDocTemplatesChange } = useDocCustomTemplates();
28833
- const [designerState, setDesignerState] = useState51(
28907
+ const [designerState, setDesignerState] = useState52(
28834
28908
  null
28835
28909
  );
28836
28910
  const handleDesignerSave = useCallback38(
@@ -28846,23 +28920,23 @@ function WysiwygEditor({
28846
28920
  [docTemplates, onDocTemplatesChange]
28847
28921
  );
28848
28922
  const mentionProviderRef = useRef40(mentionProvider);
28849
- useEffect41(() => {
28923
+ useEffect42(() => {
28850
28924
  mentionProviderRef.current = mentionProvider;
28851
28925
  }, [mentionProvider]);
28852
28926
  const fenceRenderersRef = useRef40(fenceRenderers);
28853
- useEffect41(() => {
28927
+ useEffect42(() => {
28854
28928
  fenceRenderersRef.current = fenceRenderers;
28855
28929
  }, [fenceRenderers]);
28856
28930
  const activeThemeRef = useRef40(activeTheme);
28857
- useEffect41(() => {
28931
+ useEffect42(() => {
28858
28932
  activeThemeRef.current = activeTheme;
28859
28933
  }, [activeTheme]);
28860
- const resolvedPlaceholder = useMemo36(() => placeholder ?? pickEmptyPrompt(), [placeholder]);
28934
+ const resolvedPlaceholder = useMemo37(() => placeholder ?? pickEmptyPrompt(), [placeholder]);
28861
28935
  const isExternalUpdate = useRef40(false);
28862
28936
  const lastSourceRef = useRef40(editorSource);
28863
28937
  const pendingLocalSourcesRef = useRef40([]);
28864
28938
  const mediaProviderRef = useRef40(mediaProvider);
28865
- useEffect41(() => {
28939
+ useEffect42(() => {
28866
28940
  mediaProviderRef.current = mediaProvider;
28867
28941
  }, [mediaProvider]);
28868
28942
  const frontmatterRef = useRef40(stripFrontmatter(editorSource).frontmatter);
@@ -28879,7 +28953,7 @@ function WysiwygEditor({
28879
28953
  }
28880
28954
  }
28881
28955
  const submitOnEnterRef = useRef40(submitOnEnter);
28882
- useEffect41(() => {
28956
+ useEffect42(() => {
28883
28957
  submitOnEnterRef.current = submitOnEnter;
28884
28958
  }, [submitOnEnter]);
28885
28959
  const editor = useEditor2({
@@ -29067,25 +29141,25 @@ function WysiwygEditor({
29067
29141
  }
29068
29142
  }
29069
29143
  });
29070
- useEffect41(() => {
29144
+ useEffect42(() => {
29071
29145
  if (editor) {
29072
29146
  setTiptapEditor(editor);
29073
29147
  }
29074
29148
  return () => setTiptapEditor(null);
29075
29149
  }, [editor, setTiptapEditor]);
29076
- useEffect41(() => {
29150
+ useEffect42(() => {
29077
29151
  if (editor) editor.setEditable(!readOnly);
29078
29152
  }, [editor, readOnly]);
29079
29153
  const containerRef = useRef40(null);
29080
- const [badgeMenu, setBadgeMenu] = useState51(null);
29081
- const [propsMenu, setPropsMenu] = useState51(null);
29154
+ const [badgeMenu, setBadgeMenu] = useState52(null);
29155
+ const [propsMenu, setPropsMenu] = useState52(null);
29082
29156
  const closeBadgeMenu = useCallback38(() => {
29083
29157
  setBadgeMenu(null);
29084
29158
  requestAnimationFrame(() => {
29085
29159
  if (editor && !editor.isDestroyed) editor.commands.focus();
29086
29160
  });
29087
29161
  }, [editor]);
29088
- useEffect41(() => {
29162
+ useEffect42(() => {
29089
29163
  if (!editor) return;
29090
29164
  const root = containerRef.current;
29091
29165
  if (!root) return;
@@ -29141,7 +29215,7 @@ function WysiwygEditor({
29141
29215
  root.addEventListener("mousedown", onClick);
29142
29216
  return () => root.removeEventListener("mousedown", onClick);
29143
29217
  }, [editor]);
29144
- useEffect41(() => {
29218
+ useEffect42(() => {
29145
29219
  if (!editor) return;
29146
29220
  const pendingIndex = pendingLocalSourcesRef.current.lastIndexOf(editorSource);
29147
29221
  if (pendingIndex >= 0) {
@@ -29173,7 +29247,7 @@ function WysiwygEditor({
29173
29247
  lastSourceRef.current = editorSource;
29174
29248
  isExternalUpdate.current = false;
29175
29249
  }, [editorSource, editor, wrapPolicyEnabled]);
29176
- const badgePreviewSource = useMemo36(() => {
29250
+ const badgePreviewSource = useMemo37(() => {
29177
29251
  if (!badgeMenu) return void 0;
29178
29252
  try {
29179
29253
  const previewDoc = markdownToDoc2(parseMarkdown6(editorSource), { autoTemplates: false });
@@ -29198,7 +29272,7 @@ function WysiwygEditor({
29198
29272
  previewSettings?.activeTheme,
29199
29273
  previewSettings?.activeViewport
29200
29274
  ]);
29201
- const themeStyle = useMemo36(() => {
29275
+ const themeStyle = useMemo37(() => {
29202
29276
  if (!activeTheme) return {};
29203
29277
  const out = {
29204
29278
  "--squisq-block-props-accent": activeTheme.colors.primary
@@ -29398,7 +29472,7 @@ function moveSelectionToDropPoint(view, event) {
29398
29472
  }
29399
29473
 
29400
29474
  // src/InlinePreviewGutter.tsx
29401
- import { useLayoutEffect as useLayoutEffect8, useMemo as useMemo38, useRef as useRef41, useState as useState53 } from "react";
29475
+ import { useLayoutEffect as useLayoutEffect8, useMemo as useMemo39, useRef as useRef41, useState as useState54 } from "react";
29402
29476
  import { VIEWPORT_PRESETS as VIEWPORT_PRESETS4 } from "@bendyline/squisq/schemas";
29403
29477
  import {
29404
29478
  flattenBlocks as flattenBlocks4,
@@ -29410,14 +29484,14 @@ import { extractPlainText as extractPlainText3, getChildren } from "@bendyline/s
29410
29484
  import { BlockRenderer as BlockRenderer3, MediaContext as MediaContext4 } from "@bendyline/squisq-react";
29411
29485
 
29412
29486
  // src/useHeadingLayout.ts
29413
- import { useCallback as useCallback39, useEffect as useEffect42, useMemo as useMemo37, useState as useState52 } from "react";
29487
+ import { useCallback as useCallback39, useEffect as useEffect43, useMemo as useMemo38, useState as useState53 } from "react";
29414
29488
  import { flattenBlocks as flattenBlocks3, hasTemplate } from "@bendyline/squisq/doc";
29415
29489
  function useHeadingLayout(refInsideWrapper) {
29416
29490
  const { doc, activeView, monacoEditor, tiptapEditor } = useEditorContext();
29417
- const flatBlocks = useMemo37(() => doc ? flattenBlocks3(doc.blocks) : [], [doc]);
29418
- const [entries, setEntries] = useState52([]);
29419
- const [pageEdges, setPageEdges] = useState52(null);
29420
- useEffect42(() => {
29491
+ const flatBlocks = useMemo38(() => doc ? flattenBlocks3(doc.blocks) : [], [doc]);
29492
+ const [entries, setEntries] = useState53([]);
29493
+ const [pageEdges, setPageEdges] = useState53(null);
29494
+ useEffect43(() => {
29421
29495
  if (activeView !== "wysiwyg") return;
29422
29496
  const node2 = refInsideWrapper.current;
29423
29497
  if (!node2) return;
@@ -29485,7 +29559,7 @@ function useHeadingLayout(refInsideWrapper) {
29485
29559
  window.removeEventListener("resize", recompute);
29486
29560
  };
29487
29561
  }, [activeView, flatBlocks, refInsideWrapper]);
29488
- useEffect42(() => {
29562
+ useEffect43(() => {
29489
29563
  if (activeView !== "raw") return;
29490
29564
  if (!monacoEditor) return;
29491
29565
  const node2 = refInsideWrapper.current;
@@ -29546,7 +29620,7 @@ function useHeadingLayout(refInsideWrapper) {
29546
29620
  window.removeEventListener("resize", recompute);
29547
29621
  };
29548
29622
  }, [activeView, monacoEditor, flatBlocks, refInsideWrapper]);
29549
- useEffect42(() => {
29623
+ useEffect43(() => {
29550
29624
  setEntries([]);
29551
29625
  setPageEdges(null);
29552
29626
  }, [activeView]);
@@ -29778,7 +29852,7 @@ function InlinePreviewGutter({
29778
29852
  const { entries: headingEntries, scrollToBlock } = useHeadingLayout(gutterRef);
29779
29853
  const previewSettings = usePreviewSettingsOptional();
29780
29854
  const activeTheme = previewSettings?.activeTheme ?? DEFAULT_THEME5;
29781
- const items = useMemo38(() => {
29855
+ const items = useMemo39(() => {
29782
29856
  if (!doc || !doc.blocks.length) return [];
29783
29857
  const flat = flattenBlocks4(doc.blocks);
29784
29858
  const totalBlocks = flat.length;
@@ -29835,12 +29909,12 @@ function InlinePreviewGutter({
29835
29909
  });
29836
29910
  return result;
29837
29911
  }, [doc, viewport, activeTheme]);
29838
- const connectorTops = useMemo38(() => {
29912
+ const connectorTops = useMemo39(() => {
29839
29913
  const m = /* @__PURE__ */ new Map();
29840
29914
  headingEntries.forEach((e2) => m.set(e2.block.id, e2.top));
29841
29915
  return m;
29842
29916
  }, [headingEntries]);
29843
- const [positions, setPositions] = useState53(/* @__PURE__ */ new Map());
29917
+ const [positions, setPositions] = useState54(/* @__PURE__ */ new Map());
29844
29918
  useLayoutEffect8(() => {
29845
29919
  if (items.length === 0) {
29846
29920
  setPositions((prev) => prev.size === 0 ? prev : /* @__PURE__ */ new Map());
@@ -30030,10 +30104,10 @@ import {
30030
30104
  // src/OutlinePanel.tsx
30031
30105
  import {
30032
30106
  useCallback as useCallback40,
30033
- useEffect as useEffect43,
30034
- useMemo as useMemo39,
30107
+ useEffect as useEffect44,
30108
+ useMemo as useMemo40,
30035
30109
  useRef as useRef42,
30036
- useState as useState54
30110
+ useState as useState55
30037
30111
  } from "react";
30038
30112
  import { flattenBlocks as flattenBlocks5, hasTemplate as hasTemplate2 } from "@bendyline/squisq/doc";
30039
30113
  import { extractPlainText as extractPlainText4 } from "@bendyline/squisq/markdown";
@@ -30136,7 +30210,7 @@ function splitTrailingLineGap(value) {
30136
30210
 
30137
30211
  // src/OutlinePanel.tsx
30138
30212
  import { jsx as jsx59, jsxs as jsxs46 } from "react/jsx-runtime";
30139
- var OUTLINE_RESPONSIVE_WIDTH = "clamp(260px, 30vw, 460px)";
30213
+ var OUTLINE_RESPONSIVE_WIDTH = "clamp(180px, 15vw, 260px)";
30140
30214
  var OUTLINE_DRAG_MIME = "application/x-squisq-outline-section";
30141
30215
  function OutlinePanel({ width, className, readOnly = false }) {
30142
30216
  const {
@@ -30152,9 +30226,9 @@ function OutlinePanel({ width, className, readOnly = false }) {
30152
30226
  const { scrollToBlock } = useHeadingLayout(paneRef);
30153
30227
  const cursorActiveId = useActiveOutlineBlockId();
30154
30228
  const activeDragRef = useRef42(null);
30155
- const [draggedBlockId, setDraggedBlockId] = useState54(null);
30156
- const [dropTarget, setDropTarget] = useState54(null);
30157
- const blockModeActiveId = useMemo39(() => {
30229
+ const [draggedBlockId, setDraggedBlockId] = useState55(null);
30230
+ const [dropTarget, setDropTarget] = useState55(null);
30231
+ const blockModeActiveId = useMemo40(() => {
30158
30232
  if (layoutMode !== "block" || activeBlockStartLine == null || !doc) return null;
30159
30233
  const match = flattenBlocks5(doc.blocks).find(
30160
30234
  (b) => b.sourceHeading?.position?.start.line === activeBlockStartLine
@@ -30419,12 +30493,12 @@ function OutlineNode({
30419
30493
  }
30420
30494
  function useActiveOutlineBlockId() {
30421
30495
  const { doc, activeView, tiptapEditor, monacoEditor } = useEditorContext();
30422
- const flatBlocks = useMemo39(() => doc ? flattenBlocks5(doc.blocks) : [], [doc]);
30423
- const [activeId, setActiveId] = useState54(null);
30424
- useEffect43(() => {
30496
+ const flatBlocks = useMemo40(() => doc ? flattenBlocks5(doc.blocks) : [], [doc]);
30497
+ const [activeId, setActiveId] = useState55(null);
30498
+ useEffect44(() => {
30425
30499
  setActiveId(null);
30426
30500
  }, [activeView]);
30427
- useEffect43(() => {
30501
+ useEffect44(() => {
30428
30502
  if (activeView !== "wysiwyg" || !tiptapEditor) return;
30429
30503
  const update = () => {
30430
30504
  const { from } = tiptapEditor.state.selection;
@@ -30446,7 +30520,7 @@ function useActiveOutlineBlockId() {
30446
30520
  tiptapEditor.off("update", update);
30447
30521
  };
30448
30522
  }, [activeView, tiptapEditor, flatBlocks]);
30449
- useEffect43(() => {
30523
+ useEffect44(() => {
30450
30524
  if (activeView !== "raw" || !monacoEditor) return;
30451
30525
  const update = () => {
30452
30526
  const line = monacoEditor.getPosition()?.lineNumber;
@@ -30497,7 +30571,7 @@ function bumpHeadingLevelInSource(source, line, delta) {
30497
30571
  }
30498
30572
 
30499
30573
  // src/codeContext/CodeContextZones.tsx
30500
- import { useCallback as useCallback42, useEffect as useEffect45, useMemo as useMemo41, useRef as useRef44, useState as useState55 } from "react";
30574
+ import { useCallback as useCallback42, useEffect as useEffect46, useMemo as useMemo42, useRef as useRef44, useState as useState56 } from "react";
30501
30575
  import { createPortal as createPortal10 } from "react-dom";
30502
30576
 
30503
30577
  // src/codeContext/diffContextSections.ts
@@ -30621,7 +30695,7 @@ function setOrdinal(zone, ordinal) {
30621
30695
  // src/codeContext/CodeContextSectionView.tsx
30622
30696
  import { parseMarkdown as parseMarkdown8 } from "@bendyline/squisq/markdown";
30623
30697
  import { MarkdownRenderer } from "@bendyline/squisq-react";
30624
- import { useCallback as useCallback41, useEffect as useEffect44, useMemo as useMemo40, useRef as useRef43 } from "react";
30698
+ import { useCallback as useCallback41, useEffect as useEffect45, useMemo as useMemo41, useRef as useRef43 } from "react";
30625
30699
  import { jsx as jsx60, jsxs as jsxs47 } from "react/jsx-runtime";
30626
30700
  function CodeContextSectionView({
30627
30701
  section,
@@ -30633,15 +30707,15 @@ function CodeContextSectionView({
30633
30707
  onMeasure
30634
30708
  }) {
30635
30709
  const rootRef = useRef43(null);
30636
- const stripNodes = useMemo40(
30710
+ const stripNodes = useMemo41(
30637
30711
  () => parseMarkdown8(section.summaryMarkdown).children,
30638
30712
  [section.summaryMarkdown]
30639
30713
  );
30640
- const bodyNodes = useMemo40(
30714
+ const bodyNodes = useMemo41(
30641
30715
  () => expanded && section.markdown ? parseMarkdown8(section.markdown).children : null,
30642
30716
  [expanded, section.markdown]
30643
30717
  );
30644
- useEffect44(() => {
30718
+ useEffect45(() => {
30645
30719
  const el = rootRef.current;
30646
30720
  if (!el || typeof ResizeObserver === "undefined") return;
30647
30721
  const report = () => {
@@ -30713,11 +30787,11 @@ function CodeContextSectionView({
30713
30787
  import { Fragment as Fragment18, jsx as jsx61 } from "react/jsx-runtime";
30714
30788
  function CodeContextZones({ options }) {
30715
30789
  const { monacoEditor } = useEditorContext();
30716
- const [manager, setManager] = useState55(null);
30717
- const [, setZonesVersion] = useState55(0);
30718
- const [expandedById, setExpandedById] = useState55({});
30790
+ const [manager, setManager] = useState56(null);
30791
+ const [, setZonesVersion] = useState56(0);
30792
+ const [expandedById, setExpandedById] = useState56({});
30719
30793
  const seenIds = useRef44(/* @__PURE__ */ new Set());
30720
- useEffect45(() => {
30794
+ useEffect46(() => {
30721
30795
  if (!monacoEditor) return;
30722
30796
  const mgr = new CodeContextZoneManager(monacoEditor);
30723
30797
  const off = mgr.onDidChangeZones(() => setZonesVersion((v2) => v2 + 1));
@@ -30730,7 +30804,7 @@ function CodeContextZones({ options }) {
30730
30804
  }, [monacoEditor]);
30731
30805
  const fileTop = options.fileTop;
30732
30806
  const sections = options.sections;
30733
- const resolved = useMemo41(() => {
30807
+ const resolved = useMemo42(() => {
30734
30808
  const out = [];
30735
30809
  if (fileTop) {
30736
30810
  out.push({ spec: { id: fileTop.id, line: 0, ordinal: 0 }, section: fileTop });
@@ -30740,7 +30814,7 @@ function CodeContextZones({ options }) {
30740
30814
  });
30741
30815
  return out;
30742
30816
  }, [fileTop, sections]);
30743
- useEffect45(() => {
30817
+ useEffect46(() => {
30744
30818
  if (!manager) return;
30745
30819
  manager.sync(resolved.map((r) => r.spec));
30746
30820
  setExpandedById((prev) => {
@@ -31176,7 +31250,7 @@ function placeClipInBlock(source, fromLine, targetHeadingLine, spec, startAt) {
31176
31250
  }
31177
31251
 
31178
31252
  // src/TimelineTrack.tsx
31179
- import { useCallback as useCallback44, useEffect as useEffect48, useMemo as useMemo42, useRef as useRef47, useState as useState58 } from "react";
31253
+ import { useCallback as useCallback44, useEffect as useEffect49, useMemo as useMemo43, useRef as useRef47, useState as useState59 } from "react";
31180
31254
  import {
31181
31255
  resolveMediaSchedule as resolveMediaSchedule2,
31182
31256
  getDocPlaybackDuration,
@@ -31335,7 +31409,7 @@ function resolveBlockVisual(doc, block, theme, viewport) {
31335
31409
  }
31336
31410
 
31337
31411
  // src/useTimelineClock.ts
31338
- import { useCallback as useCallback43, useEffect as useEffect46, useRef as useRef45, useState as useState56 } from "react";
31412
+ import { useCallback as useCallback43, useEffect as useEffect47, useRef as useRef45, useState as useState57 } from "react";
31339
31413
  function advanceTime(prev, dt, total) {
31340
31414
  if (total <= 0) return 0;
31341
31415
  return Math.min(total, Math.max(0, prev + dt));
@@ -31355,8 +31429,8 @@ function playTimelineMediaAt(root, time) {
31355
31429
  });
31356
31430
  }
31357
31431
  function useTimelineClock(total) {
31358
- const [currentTime, setCurrentTime] = useState56(0);
31359
- const [isPlaying, setIsPlaying] = useState56(false);
31432
+ const [currentTime, setCurrentTime] = useState57(0);
31433
+ const [isPlaying, setIsPlaying] = useState57(false);
31360
31434
  const rafRef = useRef45(null);
31361
31435
  const lastRef = useRef45(0);
31362
31436
  const currentTimeRef = useRef45(0);
@@ -31364,10 +31438,10 @@ function useTimelineClock(total) {
31364
31438
  const mediaHostRef = useRef45(null);
31365
31439
  currentTimeRef.current = currentTime;
31366
31440
  isPlayingRef.current = isPlaying;
31367
- useEffect46(() => {
31441
+ useEffect47(() => {
31368
31442
  setCurrentTime((t) => Math.min(t, Math.max(0, total)));
31369
31443
  }, [total]);
31370
- useEffect46(() => {
31444
+ useEffect47(() => {
31371
31445
  if (!isPlaying) return;
31372
31446
  lastRef.current = performance.now();
31373
31447
  const tick = (now) => {
@@ -31429,7 +31503,7 @@ function timelineMediaLabel(src, kind) {
31429
31503
  }
31430
31504
 
31431
31505
  // src/TimelineItemMenu.tsx
31432
- import { useEffect as useEffect47, useLayoutEffect as useLayoutEffect9, useRef as useRef46, useState as useState57 } from "react";
31506
+ import { useEffect as useEffect48, useLayoutEffect as useLayoutEffect9, useRef as useRef46, useState as useState58 } from "react";
31433
31507
  import { createPortal as createPortal11 } from "react-dom";
31434
31508
  import { Fragment as Fragment19, jsx as jsx64, jsxs as jsxs49 } from "react/jsx-runtime";
31435
31509
  function TimelineItemMenu({
@@ -31444,7 +31518,7 @@ function TimelineItemMenu({
31444
31518
  onClose
31445
31519
  }) {
31446
31520
  const panelRef = useRef46(null);
31447
- const [style, setStyle] = useState57(() => menuStyle(anchor));
31521
+ const [style, setStyle] = useState58(() => menuStyle(anchor));
31448
31522
  useLayoutEffect9(() => {
31449
31523
  const panel = panelRef.current;
31450
31524
  if (!panel) return;
@@ -31458,7 +31532,7 @@ function TimelineItemMenu({
31458
31532
  resizeObserver?.disconnect();
31459
31533
  };
31460
31534
  }, [anchor]);
31461
- useEffect47(() => {
31535
+ useEffect48(() => {
31462
31536
  const onKeyDown = (event) => {
31463
31537
  if (event.key !== "Escape") return;
31464
31538
  event.preventDefault();
@@ -31518,12 +31592,12 @@ function BlockMenu({
31518
31592
  onStartTime,
31519
31593
  onTransition
31520
31594
  }) {
31521
- const [explicitDuration, setExplicitDuration] = useState57(target.explicitDuration);
31522
- const [duration, setDuration] = useState57(formatNumber(target.duration));
31523
- const [startTime, setStartTime] = useState57(
31595
+ const [explicitDuration, setExplicitDuration] = useState58(target.explicitDuration);
31596
+ const [duration, setDuration] = useState58(formatNumber(target.duration));
31597
+ const [startTime, setStartTime] = useState58(
31524
31598
  target.startTime == null ? "" : formatNumber(target.startTime)
31525
31599
  );
31526
- const [transition, setTransition] = useState57(target.transition);
31600
+ const [transition, setTransition] = useState58(target.transition);
31527
31601
  const toggleAutotime = (autotimed) => {
31528
31602
  setExplicitDuration(!autotimed);
31529
31603
  if (autotimed) {
@@ -31595,11 +31669,11 @@ function VideoMenu({
31595
31669
  target,
31596
31670
  onPatch
31597
31671
  }) {
31598
- const [placement, setPlacement] = useState57(target.placement);
31599
- const [locked, setLocked] = useState57(target.lockToBlock);
31600
- const [pipSize, setPipSize] = useState57(target.pipSize ?? "");
31601
- const [pipShape, setPipShape] = useState57(target.pipShape ?? "");
31602
- const [pipPosition, setPipPosition] = useState57(target.pipPosition ?? "");
31672
+ const [placement, setPlacement] = useState58(target.placement);
31673
+ const [locked, setLocked] = useState58(target.lockToBlock);
31674
+ const [pipSize, setPipSize] = useState58(target.pipSize ?? "");
31675
+ const [pipShape, setPipShape] = useState58(target.pipShape ?? "");
31676
+ const [pipPosition, setPipPosition] = useState58(target.pipPosition ?? "");
31603
31677
  const placed = placement === "picture-in-picture" || placement === "overlay";
31604
31678
  const placementOptions = [
31605
31679
  target.canUseContentPlacement ? { value: "content", label: "In layout" } : { value: "default", label: "Default" },
@@ -31869,14 +31943,14 @@ function TimelineTrack({
31869
31943
  colorScheme
31870
31944
  } = useEditorContext();
31871
31945
  const doc = docProp ?? contextDoc;
31872
- const [drag, setDrag] = useState58(null);
31873
- const [itemMenu, setItemMenu] = useState58(null);
31874
- const [pxPerSecond, setPxPerSecond] = useState58(DEFAULT_PX_PER_SECOND);
31946
+ const [drag, setDrag] = useState59(null);
31947
+ const [itemMenu, setItemMenu] = useState59(null);
31948
+ const [pxPerSecond, setPxPerSecond] = useState59(DEFAULT_PX_PER_SECOND);
31875
31949
  const scrollRef = useRef47(null);
31876
- const blocks = useMemo42(() => doc ? flattenBlocks6(doc.blocks) : [], [doc]);
31950
+ const blocks = useMemo43(() => doc ? flattenBlocks6(doc.blocks) : [], [doc]);
31877
31951
  const previewSettings = usePreviewSettingsOptional();
31878
31952
  const previewTheme = previewSettings?.activeTheme ?? DEFAULT_THEME6;
31879
- const visualByBlock = useMemo42(() => {
31953
+ const visualByBlock = useMemo43(() => {
31880
31954
  const map = /* @__PURE__ */ new Map();
31881
31955
  if (doc) {
31882
31956
  for (const b of blocks) {
@@ -31886,16 +31960,16 @@ function TimelineTrack({
31886
31960
  }
31887
31961
  return map;
31888
31962
  }, [doc, blocks, previewTheme]);
31889
- const derivedClips = useMemo42(
31963
+ const derivedClips = useMemo43(
31890
31964
  () => doc ? resolveMediaSchedule2(doc) : [],
31891
31965
  [doc]
31892
31966
  );
31893
31967
  const clips = schedule ?? derivedClips;
31894
- const playbackClips = useMemo42(
31968
+ const playbackClips = useMemo43(
31895
31969
  () => doc ? collectTimelinePlaybackSchedule(doc, clips) : clips,
31896
31970
  [clips, doc]
31897
31971
  );
31898
- const total = useMemo42(() => doc ? getDocPlaybackDuration(doc) : 0, [doc]);
31972
+ const total = useMemo43(() => doc ? getDocPlaybackDuration(doc) : 0, [doc]);
31899
31973
  const width = Math.max(total * pxPerSecond, 200);
31900
31974
  const internalClock = useTimelineClock(total);
31901
31975
  const activeClock = clock ?? internalClock;
@@ -31904,8 +31978,8 @@ function TimelineTrack({
31904
31978
  setDrag(null);
31905
31979
  play();
31906
31980
  }, [play]);
31907
- const [scrubbing, setScrubbing] = useState58(false);
31908
- useEffect48(() => {
31981
+ const [scrubbing, setScrubbing] = useState59(false);
31982
+ useEffect49(() => {
31909
31983
  if (!scrubbing) return;
31910
31984
  const onMove = (e2) => {
31911
31985
  const scroll = scrollRef.current;
@@ -31922,7 +31996,7 @@ function TimelineTrack({
31922
31996
  window.removeEventListener("pointerup", onUp);
31923
31997
  };
31924
31998
  }, [scrubbing, pxPerSecond, seek]);
31925
- const rawClipById = useMemo42(() => {
31999
+ const rawClipById = useMemo43(() => {
31926
32000
  const map = /* @__PURE__ */ new Map();
31927
32001
  if (doc) {
31928
32002
  for (const b of flattenBlocks6(doc.blocks)) for (const m of b.media ?? []) map.set(m.id, m);
@@ -31943,7 +32017,7 @@ function TimelineTrack({
31943
32017
  [blocks]
31944
32018
  );
31945
32019
  const followedBlockRef = useRef47(null);
31946
- useEffect48(() => {
32020
+ useEffect49(() => {
31947
32021
  if (!isPlaying) {
31948
32022
  followedBlockRef.current = null;
31949
32023
  return;
@@ -31954,7 +32028,7 @@ function TimelineTrack({
31954
32028
  const line = headingLine(block);
31955
32029
  if (line != null) goToBlockByLine(line);
31956
32030
  }, [isPlaying, currentTime, blockAtTime, goToBlockByLine]);
31957
- useEffect48(() => {
32031
+ useEffect49(() => {
31958
32032
  if (!isPlaying) return;
31959
32033
  const scroll = scrollRef.current;
31960
32034
  if (!scroll) return;
@@ -32002,8 +32076,8 @@ function TimelineTrack({
32002
32076
  );
32003
32077
  const zoomIn = useCallback44(() => setPxPerSecond((s) => Math.min(ZOOM_MAX, s * ZOOM_FACTOR)), []);
32004
32078
  const zoomOut = useCallback44(() => setPxPerSecond((s) => Math.max(ZOOM_MIN, s / ZOOM_FACTOR)), []);
32005
- const [viewportWidth, setViewportWidth] = useState58(0);
32006
- useEffect48(() => {
32079
+ const [viewportWidth, setViewportWidth] = useState59(0);
32080
+ useEffect49(() => {
32007
32081
  const el = scrollRef.current;
32008
32082
  if (!el || typeof ResizeObserver === "undefined") return;
32009
32083
  const update = () => setViewportWidth(el.clientWidth);
@@ -32017,7 +32091,7 @@ function TimelineTrack({
32017
32091
  const dragRef = useRef47(null);
32018
32092
  dragRef.current = drag;
32019
32093
  const isDragging = drag != null && !drag.committed;
32020
- useEffect48(() => {
32094
+ useEffect49(() => {
32021
32095
  if (!isDragging) return;
32022
32096
  const onMove = (e2) => {
32023
32097
  const d = dragRef.current;
@@ -32048,7 +32122,7 @@ function TimelineTrack({
32048
32122
  window.removeEventListener("pointerup", onUp);
32049
32123
  };
32050
32124
  }, [isDragging]);
32051
- useEffect48(() => {
32125
+ useEffect49(() => {
32052
32126
  if (dragRef.current?.committed) setDrag(null);
32053
32127
  }, [doc]);
32054
32128
  const beginDrag = useCallback44(
@@ -32584,7 +32658,7 @@ function formatDur(seconds) {
32584
32658
  }
32585
32659
 
32586
32660
  // src/TimelineVideoPanel.tsx
32587
- import { useMemo as useMemo43 } from "react";
32661
+ import { useMemo as useMemo44 } from "react";
32588
32662
  import { MediaClipLayer as MediaClipLayer2 } from "@bendyline/squisq-react";
32589
32663
  import { jsx as jsx66, jsxs as jsxs51 } from "react/jsx-runtime";
32590
32664
  function TimelineVideoPanel({
@@ -32594,7 +32668,7 @@ function TimelineVideoPanel({
32594
32668
  basePath = "/",
32595
32669
  onClose
32596
32670
  }) {
32597
- const videos = useMemo43(() => schedule.filter((clip) => clip.kind === "video"), [schedule]);
32671
+ const videos = useMemo44(() => schedule.filter((clip) => clip.kind === "video"), [schedule]);
32598
32672
  const activeVideos = videos.filter(
32599
32673
  (clip) => currentTime >= clip.absoluteStart && currentTime < clip.absoluteEnd
32600
32674
  );
@@ -32648,12 +32722,12 @@ function formatClock3(seconds) {
32648
32722
  }
32649
32723
 
32650
32724
  // src/TimelineCompositionPanel.tsx
32651
- import { useMemo as useMemo44 } from "react";
32725
+ import { useMemo as useMemo45 } from "react";
32652
32726
  import { getDocPlaybackDuration as getDocPlaybackDuration2, resolveMediaSchedule as resolveMediaSchedule3 } from "@bendyline/squisq/schemas";
32653
32727
  import { DocPlayer } from "@bendyline/squisq-react";
32654
32728
 
32655
32729
  // src/usePreviewProjection.ts
32656
- import { useEffect as useEffect49, useState as useState59 } from "react";
32730
+ import { useEffect as useEffect50, useState as useState60 } from "react";
32657
32731
  import { resolveAudioMapping } from "@bendyline/squisq/doc";
32658
32732
  import { applyTransform } from "@bendyline/squisq/transform";
32659
32733
  function hasEquivalentAudio(left, right) {
@@ -32673,8 +32747,8 @@ function preserveEquivalentAudio(previous, next) {
32673
32747
  };
32674
32748
  }
32675
32749
  function usePreviewProjection(doc, transformStyle, workspaceContainer, documentTitle2) {
32676
- const [projection, setProjection] = useState59(null);
32677
- useEffect49(() => {
32750
+ const [projection, setProjection] = useState60(null);
32751
+ useEffect50(() => {
32678
32752
  if (!doc || !doc.blocks.length) {
32679
32753
  setProjection(null);
32680
32754
  return;
@@ -32740,11 +32814,11 @@ function TimelineCompositionPanel({
32740
32814
  );
32741
32815
  const contentDoc = projection?.contentDoc ?? null;
32742
32816
  const playerDoc = projection?.playerDoc ?? null;
32743
- const totalDuration = useMemo44(
32817
+ const totalDuration = useMemo45(
32744
32818
  () => playerDoc ? getDocPlaybackDuration2(playerDoc) : 0,
32745
32819
  [playerDoc]
32746
32820
  );
32747
- const effectiveVideoPresentation = useMemo44(() => {
32821
+ const effectiveVideoPresentation = useMemo45(() => {
32748
32822
  if (!playerDoc) return activeVideoPresentation;
32749
32823
  const activeVideo = resolveMediaSchedule3(playerDoc).find(
32750
32824
  (clip) => clip.kind === "video" && clock.currentTime >= clip.absoluteStart && clock.currentTime < clip.absoluteEnd
@@ -32753,7 +32827,7 @@ function TimelineCompositionPanel({
32753
32827
  if (activeVideo?.placement === "overlay") return "full-frame";
32754
32828
  return activeVideoPresentation;
32755
32829
  }, [activeVideoPresentation, clock.currentTime, playerDoc]);
32756
- const audioController = useMemo44(
32830
+ const audioController = useMemo45(
32757
32831
  () => ({
32758
32832
  currentTime: clock.currentTime,
32759
32833
  isPlaying: clock.isPlaying,
@@ -32934,7 +33008,7 @@ function TimelineToolbar({
32934
33008
  }
32935
33009
 
32936
33010
  // src/PlainHtmlPreview.tsx
32937
- import { useCallback as useCallback45, useEffect as useEffect50, useMemo as useMemo45, useRef as useRef48, useState as useState60 } from "react";
33011
+ import { useCallback as useCallback45, useEffect as useEffect51, useMemo as useMemo46, useRef as useRef48, useState as useState61 } from "react";
32938
33012
  import { parseMarkdown as parseMarkdown9 } from "@bendyline/squisq/markdown";
32939
33013
 
32940
33014
  // src/utils/collectInlineFontAwesomeCss.ts
@@ -33014,9 +33088,9 @@ function PlainHtmlPreview({
33014
33088
  },
33015
33089
  [onFrameChange]
33016
33090
  );
33017
- const mdDoc = useMemo45(() => parseMarkdown9(markdown), [markdown]);
33018
- const [resolvedImages, setResolvedImages] = useState60(null);
33019
- useEffect50(() => {
33091
+ const mdDoc = useMemo46(() => parseMarkdown9(markdown), [markdown]);
33092
+ const [resolvedImages, setResolvedImages] = useState61(null);
33093
+ useEffect51(() => {
33020
33094
  if (!mediaProvider) {
33021
33095
  setResolvedImages(null);
33022
33096
  return;
@@ -33044,16 +33118,16 @@ function PlainHtmlPreview({
33044
33118
  cancelled = true;
33045
33119
  };
33046
33120
  }, [mdDoc, mediaProvider, mediaRevision]);
33047
- const mergedImages = useMemo45(() => {
33121
+ const mergedImages = useMemo46(() => {
33048
33122
  if (!resolvedImages && !images) return void 0;
33049
33123
  const merged = /* @__PURE__ */ new Map();
33050
33124
  if (resolvedImages) for (const [k2, v2] of resolvedImages) merged.set(k2, v2);
33051
33125
  if (images) for (const [k2, v2] of images) merged.set(k2, v2);
33052
33126
  return merged;
33053
33127
  }, [resolvedImages, images]);
33054
- const iconsCss = useMemo45(() => collectInlineFontAwesomeCss(), []);
33055
- const [renderFn, setRenderFn] = useState60(() => cachedRender);
33056
- useEffect50(() => {
33128
+ const iconsCss = useMemo46(() => collectInlineFontAwesomeCss(), []);
33129
+ const [renderFn, setRenderFn] = useState61(() => cachedRender);
33130
+ useEffect51(() => {
33057
33131
  if (renderFn) return;
33058
33132
  let cancelled = false;
33059
33133
  loadRenderFn().then((fn) => {
@@ -33063,7 +33137,7 @@ function PlainHtmlPreview({
33063
33137
  cancelled = true;
33064
33138
  };
33065
33139
  }, [renderFn]);
33066
- const html = useMemo45(
33140
+ const html = useMemo46(
33067
33141
  () => renderFn ? renderFn(mdDoc, { title, images: mergedImages, theme, iconsCss }) : "",
33068
33142
  [renderFn, mdDoc, title, mergedImages, theme, iconsCss]
33069
33143
  );
@@ -33086,7 +33160,7 @@ function PlainHtmlPreview({
33086
33160
  frameDocument.addEventListener("click", handleClick, true);
33087
33161
  removeFrameLinkHandlerRef.current = () => frameDocument.removeEventListener("click", handleClick, true);
33088
33162
  }, [onLinkClick]);
33089
- useEffect50(() => {
33163
+ useEffect51(() => {
33090
33164
  installFrameLinkHandler();
33091
33165
  return () => removeFrameLinkHandlerRef.current();
33092
33166
  }, [html, installFrameLinkHandler]);
@@ -33182,11 +33256,11 @@ function PlainHtmlPreview({
33182
33256
  style2.remove();
33183
33257
  };
33184
33258
  }, [onCopyCode, showCodeCopyButton]);
33185
- useEffect50(() => {
33259
+ useEffect51(() => {
33186
33260
  installFrameCodeCopyControls();
33187
33261
  return () => removeFrameCodeCopyControlsRef.current();
33188
33262
  }, [html, installFrameCodeCopyControls]);
33189
- useEffect50(() => {
33263
+ useEffect51(() => {
33190
33264
  if (!globalKeyboardShortcuts) return;
33191
33265
  const handleKeyDown = (event) => {
33192
33266
  if (event.defaultPrevented || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey || event.key !== "ArrowDown" && event.key !== "ArrowUp") {
@@ -33265,7 +33339,7 @@ function collectImageRefs(doc) {
33265
33339
  }
33266
33340
 
33267
33341
  // src/PreviewPanel.tsx
33268
- import { useState as useState63, useEffect as useEffect54, useMemo as useMemo49, useCallback as useCallback49, useRef as useRef52 } from "react";
33342
+ import { useState as useState64, useEffect as useEffect55, useMemo as useMemo50, useCallback as useCallback49, useRef as useRef52 } from "react";
33269
33343
  import { createPortal as createPortal13 } from "react-dom";
33270
33344
  import { DocPlayer as DocPlayer2, LinearDocView as LinearDocView2, useMediaProvider as useMediaProvider2 } from "@bendyline/squisq-react";
33271
33345
  import { resolveTransformStyle as resolveTransformStyle2 } from "@bendyline/squisq/transform";
@@ -33404,12 +33478,12 @@ import {
33404
33478
  createContext as createContext5,
33405
33479
  useCallback as useCallback46,
33406
33480
  useContext as useContext5,
33407
- useEffect as useEffect51,
33481
+ useEffect as useEffect52,
33408
33482
  useId as useId14,
33409
33483
  useLayoutEffect as useLayoutEffect10,
33410
- useMemo as useMemo46,
33484
+ useMemo as useMemo47,
33411
33485
  useRef as useRef49,
33412
- useState as useState61
33486
+ useState as useState62
33413
33487
  } from "react";
33414
33488
  import { createPortal as createPortal12 } from "react-dom";
33415
33489
  import { jsx as jsx70, jsxs as jsxs54 } from "react/jsx-runtime";
@@ -33511,10 +33585,10 @@ function PresentationModeProvider({
33511
33585
  const { activeView, colorScheme, doc } = useEditorContext();
33512
33586
  const { activeTheme } = usePreviewSettings();
33513
33587
  const popupNameId = useId14().replace(/[^a-zA-Z0-9_-]/g, "");
33514
- const [selectedTarget, setSelectedTarget] = useState61("control");
33515
- const [activeTarget, setActiveTarget] = useState61(null);
33516
- const [popupRoot, setPopupRoot] = useState61(null);
33517
- const [error, setError] = useState61(null);
33588
+ const [selectedTarget, setSelectedTarget] = useState62("control");
33589
+ const [activeTarget, setActiveTarget] = useState62(null);
33590
+ const [popupRoot, setPopupRoot] = useState62(null);
33591
+ const [error, setError] = useState62(null);
33518
33592
  const activeTargetRef = useRef49(activeTarget);
33519
33593
  activeTargetRef.current = activeTarget;
33520
33594
  const previousActiveTargetRef = useRef49(null);
@@ -33522,7 +33596,7 @@ function PresentationModeProvider({
33522
33596
  const popupRef = useRef49(null);
33523
33597
  const popupCleanupRef = useRef49(null);
33524
33598
  const fullscreenSupported = typeof document !== "undefined" && typeof document.documentElement.requestFullscreen === "function";
33525
- const availableTargets = useMemo46(
33599
+ const availableTargets = useMemo47(
33526
33600
  () => [
33527
33601
  "control",
33528
33602
  ...allowWindow ? ["window"] : [],
@@ -33662,12 +33736,12 @@ function PresentationModeProvider({
33662
33736
  },
33663
33737
  [availableTargets, selectedTarget, stop]
33664
33738
  );
33665
- useEffect51(() => {
33739
+ useEffect52(() => {
33666
33740
  if (availableTargets.includes(selectedTarget)) return;
33667
33741
  setSelectedTarget("control");
33668
33742
  if (activeTargetRef.current !== null) void stop();
33669
33743
  }, [availableTargets, selectedTarget, stop]);
33670
- useEffect51(() => {
33744
+ useEffect52(() => {
33671
33745
  const root = rootRef.current;
33672
33746
  const ownerDocument = root?.ownerDocument;
33673
33747
  if (!root || !ownerDocument) return;
@@ -33679,7 +33753,7 @@ function PresentationModeProvider({
33679
33753
  ownerDocument.addEventListener("fullscreenchange", handleFullscreenChange);
33680
33754
  return () => ownerDocument.removeEventListener("fullscreenchange", handleFullscreenChange);
33681
33755
  }, [rootRef]);
33682
- useEffect51(() => {
33756
+ useEffect52(() => {
33683
33757
  const root = rootRef.current;
33684
33758
  if (!root) return;
33685
33759
  if (activeTarget) root.dataset.presentationMode = activeTarget;
@@ -33688,10 +33762,10 @@ function PresentationModeProvider({
33688
33762
  delete root.dataset.presentationMode;
33689
33763
  };
33690
33764
  }, [activeTarget, rootRef]);
33691
- useEffect51(() => {
33765
+ useEffect52(() => {
33692
33766
  if (activeView !== "preview" && activeTargetRef.current !== null) void stop();
33693
33767
  }, [activeView, stop]);
33694
- useEffect51(() => {
33768
+ useEffect52(() => {
33695
33769
  const previous = previousActiveTargetRef.current;
33696
33770
  previousActiveTargetRef.current = activeTarget;
33697
33771
  if (previous === null || activeTarget !== null) return;
@@ -33699,7 +33773,7 @@ function PresentationModeProvider({
33699
33773
  returnFocusRef.current = null;
33700
33774
  if (target?.isConnected) target.focus();
33701
33775
  }, [activeTarget]);
33702
- useEffect51(() => {
33776
+ useEffect52(() => {
33703
33777
  if (activeTarget !== "control") return;
33704
33778
  const ownerDocument = rootRef.current?.ownerDocument;
33705
33779
  if (!ownerDocument) return;
@@ -33711,12 +33785,12 @@ function PresentationModeProvider({
33711
33785
  ownerDocument.addEventListener("keydown", handleKeyDown);
33712
33786
  return () => ownerDocument.removeEventListener("keydown", handleKeyDown);
33713
33787
  }, [activeTarget, rootRef, stop]);
33714
- useEffect51(() => {
33788
+ useEffect52(() => {
33715
33789
  if (!error) return;
33716
33790
  const timer = window.setTimeout(() => setError(null), 6e3);
33717
33791
  return () => window.clearTimeout(timer);
33718
33792
  }, [error]);
33719
- useEffect51(
33793
+ useEffect52(
33720
33794
  () => () => {
33721
33795
  popupCleanupRef.current?.();
33722
33796
  const popup = popupRef.current;
@@ -33729,7 +33803,7 @@ function PresentationModeProvider({
33729
33803
  },
33730
33804
  [rootRef]
33731
33805
  );
33732
- const value = useMemo46(
33806
+ const value = useMemo47(
33733
33807
  () => ({
33734
33808
  selectedTarget,
33735
33809
  activeTarget,
@@ -33819,8 +33893,8 @@ function PresentationModeControl() {
33819
33893
  const { colorScheme } = useEditorContext();
33820
33894
  const triggerRef = useRef49(null);
33821
33895
  const menuRef = useRef49(null);
33822
- const [open, setOpen] = useState61(false);
33823
- const [anchor, setAnchor] = useState61(null);
33896
+ const [open, setOpen] = useState62(false);
33897
+ const [anchor, setAnchor] = useState62(null);
33824
33898
  const options = PRESENTATION_OPTIONS.filter((option) => availableTargets.includes(option.target));
33825
33899
  const selected = options.find((option) => option.target === selectedTarget) ?? PRESENTATION_OPTIONS[0];
33826
33900
  const updatePosition = useCallback46(() => {
@@ -33845,7 +33919,7 @@ function PresentationModeControl() {
33845
33919
  updatePosition();
33846
33920
  setOpen(true);
33847
33921
  }, [updatePosition]);
33848
- useEffect51(() => {
33922
+ useEffect52(() => {
33849
33923
  if (!open) return;
33850
33924
  const handlePointerDown = (event) => {
33851
33925
  const target = event.target;
@@ -33988,10 +34062,10 @@ import {
33988
34062
  createContext as createContext6,
33989
34063
  useCallback as useCallback47,
33990
34064
  useContext as useContext6,
33991
- useEffect as useEffect52,
33992
- useMemo as useMemo47,
34065
+ useEffect as useEffect53,
34066
+ useMemo as useMemo48,
33993
34067
  useRef as useRef50,
33994
- useState as useState62
34068
+ useState as useState63
33995
34069
  } from "react";
33996
34070
  import { jsx as jsx71, jsxs as jsxs55 } from "react/jsx-runtime";
33997
34071
  var PrintModeContext = createContext6(null);
@@ -34006,8 +34080,8 @@ function usePrintModeOptional() {
34006
34080
  function PrintModeProvider({ rootRef, children }) {
34007
34081
  const { activeView } = useEditorContext();
34008
34082
  const { activeTarget: presentationTarget, stop: stopPresentation } = usePresentationMode();
34009
- const [active, setActive] = useState62(false);
34010
- const [slidesPerPage, setSlidesPerPage] = useState62(1);
34083
+ const [active, setActive] = useState63(false);
34084
+ const [slidesPerPage, setSlidesPerPage] = useState63(1);
34011
34085
  const customPrintHandlerRef = useRef50(null);
34012
34086
  const printAncestorsRef = useRef50([]);
34013
34087
  const unmarkPrinting = useCallback47(() => {
@@ -34058,7 +34132,7 @@ function PrintModeProvider({ rootRef, children }) {
34058
34132
  markPrinting();
34059
34133
  ownerWindow.print();
34060
34134
  }, [markPrinting, rootRef]);
34061
- useEffect52(() => {
34135
+ useEffect53(() => {
34062
34136
  const root = rootRef.current;
34063
34137
  if (!root) return;
34064
34138
  if (active) root.dataset.printPreview = "true";
@@ -34067,10 +34141,10 @@ function PrintModeProvider({ rootRef, children }) {
34067
34141
  delete root.dataset.printPreview;
34068
34142
  };
34069
34143
  }, [active, rootRef]);
34070
- useEffect52(() => {
34144
+ useEffect53(() => {
34071
34145
  if (activeView !== "preview" && active) close();
34072
34146
  }, [active, activeView, close]);
34073
- useEffect52(() => {
34147
+ useEffect53(() => {
34074
34148
  if (!active) return;
34075
34149
  const ownerWindow = rootRef.current?.ownerDocument.defaultView;
34076
34150
  const ownerDocument = rootRef.current?.ownerDocument;
@@ -34092,7 +34166,7 @@ function PrintModeProvider({ rootRef, children }) {
34092
34166
  handleAfterPrint();
34093
34167
  };
34094
34168
  }, [active, close, markPrinting, rootRef, unmarkPrinting]);
34095
- const value = useMemo47(
34169
+ const value = useMemo48(
34096
34170
  () => ({
34097
34171
  active,
34098
34172
  slidesPerPage,
@@ -34161,7 +34235,7 @@ function PrintPreviewToolbar() {
34161
34235
  }
34162
34236
 
34163
34237
  // src/print/PrintPreview.tsx
34164
- import { useCallback as useCallback48, useEffect as useEffect53, useMemo as useMemo48, useRef as useRef51 } from "react";
34238
+ import { useCallback as useCallback48, useEffect as useEffect54, useMemo as useMemo49, useRef as useRef51 } from "react";
34165
34239
  import {
34166
34240
  BlockRenderer as BlockRenderer5,
34167
34241
  LinearDocView,
@@ -34200,7 +34274,7 @@ function PrintPreview({
34200
34274
  documentFrameRef.current = frame;
34201
34275
  }, []);
34202
34276
  const { blocks } = useDocPlayback(previewDoc, 0, { viewport, theme });
34203
- const coverBlock = useMemo48(() => {
34277
+ const coverBlock = useMemo49(() => {
34204
34278
  if (!showCover || !previewDoc?.startBlock) return null;
34205
34279
  const context = createTemplateContext2(theme, 0, 1, viewport);
34206
34280
  return {
@@ -34212,7 +34286,7 @@ function PrintPreview({
34212
34286
  };
34213
34287
  }, [previewDoc?.startBlock, showCover, theme, viewport]);
34214
34288
  const isTextDocument = displayMode === "page" || displayMode === "narrate";
34215
- useEffect53(() => {
34289
+ useEffect54(() => {
34216
34290
  if (!isTextDocument) return registerPrintHandler(null);
34217
34291
  return registerPrintHandler(() => {
34218
34292
  const frameWindow = documentFrameRef.current?.contentWindow;
@@ -34339,7 +34413,7 @@ function PreviewPanel({
34339
34413
  } = usePreviewSettings();
34340
34414
  const mainSurfaceRef = useRef52(null);
34341
34415
  const popupSurfaceRef = useRef52(null);
34342
- const [playbackState, setPlaybackState] = useState63(null);
34416
+ const [playbackState, setPlaybackState] = useState64(null);
34343
34417
  const handlePlaybackStateChange = useCallback49((next) => {
34344
34418
  setPlaybackState(next);
34345
34419
  }, []);
@@ -34351,7 +34425,7 @@ function PreviewPanel({
34351
34425
  );
34352
34426
  const previewDoc = previewProjection?.playerDoc ?? null;
34353
34427
  const contentDoc = previewProjection?.contentDoc ?? null;
34354
- const followerAudioController = useMemo49(() => {
34428
+ const followerAudioController = useMemo50(() => {
34355
34429
  if (!playbackState || !previewDoc) return null;
34356
34430
  const noOp = () => Promise.resolve();
34357
34431
  return {
@@ -34370,18 +34444,18 @@ function PreviewPanel({
34370
34444
  restart: noOp
34371
34445
  };
34372
34446
  }, [playbackState, previewDoc]);
34373
- const documentMarkdown = useMemo49(
34447
+ const documentMarkdown = useMemo50(
34374
34448
  () => activeTransformStyle && contentDoc ? buildDocumentPreviewMarkdown(contentDoc) : markdownSource,
34375
34449
  [activeTransformStyle, contentDoc, markdownSource]
34376
34450
  );
34377
34451
  const isDocumentMode = activeDisplayMode === "page";
34378
34452
  const isPageMode = activeDisplayMode === "linear";
34379
34453
  const isNarrateMode = activeDisplayMode === "narrate";
34380
- useEffect54(() => {
34454
+ useEffect55(() => {
34381
34455
  if (presentation?.activeTarget === "window") return;
34382
34456
  setPlaybackState(null);
34383
34457
  }, [presentation?.activeTarget]);
34384
- useEffect54(() => {
34458
+ useEffect55(() => {
34385
34459
  if (presentation?.activeTarget !== "window" || !presentation.popupRoot) return;
34386
34460
  const mainRoot = mainSurfaceRef.current;
34387
34461
  const followerRoot = popupSurfaceRef.current;
@@ -34615,7 +34689,7 @@ function PreviewPanel({
34615
34689
  }
34616
34690
 
34617
34691
  // src/MediaBin.tsx
34618
- import { useState as useState64, useEffect as useEffect55, useRef as useRef53, useCallback as useCallback50 } from "react";
34692
+ import { useState as useState65, useEffect as useEffect56, useRef as useRef53, useCallback as useCallback50 } from "react";
34619
34693
  import { jsx as jsx74, jsxs as jsxs58 } from "react/jsx-runtime";
34620
34694
  function formatSize(bytes) {
34621
34695
  if (bytes < 1024) return `${bytes} B`;
@@ -34680,12 +34754,12 @@ function MediaBin({
34680
34754
  isRecorderOpen = false,
34681
34755
  allowBinaryDownloads = true
34682
34756
  }) {
34683
- const [entries, setEntries] = useState64([]);
34684
- const [thumbUrls, setThumbUrls] = useState64({});
34685
- const [loading, setLoading] = useState64(false);
34686
- const [isDropActive, setIsDropActive] = useState64(false);
34687
- const [downloadingPath, setDownloadingPath] = useState64(null);
34688
- const [contextMenu, setContextMenu] = useState64(null);
34757
+ const [entries, setEntries] = useState65([]);
34758
+ const [thumbUrls, setThumbUrls] = useState65({});
34759
+ const [loading, setLoading] = useState65(false);
34760
+ const [isDropActive, setIsDropActive] = useState65(false);
34761
+ const [downloadingPath, setDownloadingPath] = useState65(null);
34762
+ const [contextMenu, setContextMenu] = useState65(null);
34689
34763
  const fileInputRef = useRef53(null);
34690
34764
  const contextMenuRef = useRef53(null);
34691
34765
  const dropDepthRef = useRef53(0);
@@ -34707,7 +34781,7 @@ function MediaBin({
34707
34781
  },
34708
34782
  [onCountChange]
34709
34783
  );
34710
- useEffect55(() => {
34784
+ useEffect56(() => {
34711
34785
  if (!contextMenu) return;
34712
34786
  const handlePointerDown = (event) => {
34713
34787
  if (contextMenuRef.current?.contains(event.target)) return;
@@ -34728,7 +34802,7 @@ function MediaBin({
34728
34802
  window.removeEventListener("resize", close);
34729
34803
  };
34730
34804
  }, [contextMenu]);
34731
- useEffect55(() => {
34805
+ useEffect56(() => {
34732
34806
  if (!mediaProvider) {
34733
34807
  setEntries([]);
34734
34808
  setThumbUrls({});
@@ -35070,7 +35144,7 @@ ${formatSize(entry.size)}`,
35070
35144
  }
35071
35145
 
35072
35146
  // src/DropZoneOverlay.tsx
35073
- import { useState as useState65 } from "react";
35147
+ import { useState as useState66 } from "react";
35074
35148
  import { Fragment as Fragment21, jsx as jsx75, jsxs as jsxs59 } from "react/jsx-runtime";
35075
35149
  function DropZoneOverlay({
35076
35150
  dragContentType,
@@ -35127,7 +35201,7 @@ function DropZone({
35127
35201
  disabled,
35128
35202
  variant
35129
35203
  }) {
35130
- const [isHovering, setIsHovering] = useState65(false);
35204
+ const [isHovering, setIsHovering] = useState66(false);
35131
35205
  const props = zoneProps(target);
35132
35206
  return /* @__PURE__ */ jsxs59(
35133
35207
  "div",
@@ -35171,7 +35245,7 @@ function DropZone({
35171
35245
  }
35172
35246
 
35173
35247
  // src/Tooltip.tsx
35174
- import { useEffect as useEffect56, useLayoutEffect as useLayoutEffect11, useRef as useRef54, useState as useState66 } from "react";
35248
+ import { useEffect as useEffect57, useLayoutEffect as useLayoutEffect11, useRef as useRef54, useState as useState67 } from "react";
35175
35249
  import { createPortal as createPortal14 } from "react-dom";
35176
35250
 
35177
35251
  // src/tooltipPlacement.ts
@@ -35187,7 +35261,7 @@ function clampTooltipLeft(anchorX, tooltipWidth, viewportWidth, edgePadding = ED
35187
35261
  import { jsx as jsx76 } from "react/jsx-runtime";
35188
35262
  var SHOW_DELAY_MS = 180;
35189
35263
  function TooltipLayer() {
35190
- const [state, setState3] = useState66(null);
35264
+ const [state, setState3] = useState67(null);
35191
35265
  const tooltipRef = useRef54(null);
35192
35266
  const timerRef = useRef54(null);
35193
35267
  const currentTargetRef = useRef54(null);
@@ -35203,7 +35277,7 @@ function TooltipLayer() {
35203
35277
  node2.style.left = `${left}px`;
35204
35278
  node2.style.visibility = "visible";
35205
35279
  }, [state]);
35206
- useEffect56(() => {
35280
+ useEffect57(() => {
35207
35281
  const clearTimer = () => {
35208
35282
  if (timerRef.current) {
35209
35283
  clearTimeout(timerRef.current);
@@ -35289,10 +35363,10 @@ function TooltipLayer() {
35289
35363
  }
35290
35364
 
35291
35365
  // src/EditorShell.tsx
35292
- import { useEffect as useEffect57, useRef as useRef55, useState as useState67, useCallback as useCallback51, useMemo as useMemo51 } from "react";
35366
+ import { useEffect as useEffect58, useRef as useRef55, useState as useState68, useCallback as useCallback51, useMemo as useMemo52 } from "react";
35293
35367
 
35294
35368
  // src/BlockPreviewPanel.tsx
35295
- import { useMemo as useMemo50 } from "react";
35369
+ import { useMemo as useMemo51 } from "react";
35296
35370
  import { VIEWPORT_PRESETS as VIEWPORT_PRESETS7 } from "@bendyline/squisq/schemas";
35297
35371
  import { flattenBlocks as flattenBlocks7, DEFAULT_THEME as DEFAULT_THEME7 } from "@bendyline/squisq/doc";
35298
35372
  import { jsx as jsx77 } from "react/jsx-runtime";
@@ -35301,13 +35375,13 @@ function BlockPreviewPanel({ basePath = "/" }) {
35301
35375
  const previewSettings = usePreviewSettingsOptional();
35302
35376
  const theme = previewSettings?.activeTheme ?? DEFAULT_THEME7;
35303
35377
  const viewport = previewSettings?.activeViewport ?? VIEWPORT_PRESETS7.landscape;
35304
- const block = useMemo50(() => {
35378
+ const block = useMemo51(() => {
35305
35379
  if (!doc) return null;
35306
35380
  const blocks = flattenBlocks7(doc.blocks);
35307
35381
  if (blocks.length === 0) return null;
35308
35382
  return blocks.find((b) => b.sourceHeading?.position?.start.line === activeBlockStartLine) ?? blocks[0];
35309
35383
  }, [doc, activeBlockStartLine]);
35310
- const visual = useMemo50(
35384
+ const visual = useMemo51(
35311
35385
  () => doc && block ? resolveBlockVisual(doc, block, theme, viewport) : null,
35312
35386
  [doc, block, theme, viewport]
35313
35387
  );
@@ -35645,7 +35719,7 @@ function EditorShell({
35645
35719
  themeOverride = null
35646
35720
  }) {
35647
35721
  const effectiveContainer = workspaceContainer ?? null;
35648
- const effectiveMediaProvider = useMemo51(() => {
35722
+ const effectiveMediaProvider = useMemo52(() => {
35649
35723
  if (mediaProvider !== void 0) return mediaProvider;
35650
35724
  if (effectiveContainer) return createMediaProviderFromContainer(effectiveContainer);
35651
35725
  return void 0;
@@ -35847,7 +35921,7 @@ function EditorShellInner({
35847
35921
  workspaceContainer
35848
35922
  );
35849
35923
  const timelineDoc = timelineProjection?.contentDoc ?? doc;
35850
- const timelineRawSchedule = useMemo51(
35924
+ const timelineRawSchedule = useMemo52(
35851
35925
  () => timelineDoc ? resolveMediaSchedule4(timelineDoc) : [],
35852
35926
  [timelineDoc]
35853
35927
  );
@@ -35856,19 +35930,19 @@ function EditorShellInner({
35856
35930
  basePath,
35857
35931
  mediaProvider ?? null
35858
35932
  );
35859
- const timelineDuration = useMemo51(
35933
+ const timelineDuration = useMemo52(
35860
35934
  () => timelineDoc ? getDocPlaybackDuration3(timelineDoc, {
35861
35935
  intrinsicDuration: (clip) => timelineClipDurations.get(clip.src)
35862
35936
  }) : 0,
35863
35937
  [timelineDoc, timelineClipDurations]
35864
35938
  );
35865
- const timelineSchedule = useMemo51(
35939
+ const timelineSchedule = useMemo52(
35866
35940
  () => timelineDoc ? resolveMediaSchedule4(timelineDoc, {
35867
35941
  intrinsicDuration: (clip) => timelineClipDurations.get(clip.src)
35868
35942
  }) : [],
35869
35943
  [timelineDoc, timelineClipDurations]
35870
35944
  );
35871
- const timelineVideoSchedule = useMemo51(
35945
+ const timelineVideoSchedule = useMemo52(
35872
35946
  () => timelineDoc ? [
35873
35947
  ...timelineSchedule.filter((clip) => clip.kind === "video"),
35874
35948
  ...collectEmbeddedVideoSchedule(timelineDoc)
@@ -35877,15 +35951,15 @@ function EditorShellInner({
35877
35951
  );
35878
35952
  const timelineClock = useTimelineClock(isTimelineMode ? timelineDuration : 0);
35879
35953
  const hasTimelineVideo = timelineVideoSchedule.length > 0;
35880
- const [timelineVideoVisible, setTimelineVideoVisible] = useState67(false);
35881
- const [timelineCompositionVisible, setTimelineCompositionVisible] = useState67(false);
35954
+ const [timelineVideoVisible, setTimelineVideoVisible] = useState68(false);
35955
+ const [timelineCompositionVisible, setTimelineCompositionVisible] = useState68(false);
35882
35956
  const timelinePreviewCount = Number(timelineVideoVisible) + Number(timelineCompositionVisible);
35883
- const [showFiles, setShowFiles] = useState67(false);
35884
- const [mediaRefreshKey, setMediaRefreshKey] = useState67(0);
35885
- const [mediaCount, setMediaCount] = useState67(0);
35886
- const [mediaBinRecorderOpen, setMediaBinRecorderOpen] = useState67(false);
35957
+ const [showFiles, setShowFiles] = useState68(false);
35958
+ const [mediaRefreshKey, setMediaRefreshKey] = useState68(0);
35959
+ const [mediaCount, setMediaCount] = useState68(0);
35960
+ const [mediaBinRecorderOpen, setMediaBinRecorderOpen] = useState68(false);
35887
35961
  const mediaListRefreshKey = mediaRefreshKey + mediaRevision;
35888
- const usedMediaPaths = useMemo51(
35962
+ const usedMediaPaths = useMemo52(
35889
35963
  () => collectMediaReferencesFromMarkdown(markdownSource),
35890
35964
  [markdownSource]
35891
35965
  );
@@ -35895,13 +35969,13 @@ function EditorShellInner({
35895
35969
  }
35896
35970
  const imageEditFallbackContainer = imageEditFallbackContainerRef.current;
35897
35971
  const isDark = colorScheme === "dark";
35898
- useEffect57(() => {
35972
+ useEffect58(() => {
35899
35973
  if (!isTimelineMode || !hasTimelineVideo) setTimelineVideoVisible(false);
35900
35974
  }, [isTimelineMode, hasTimelineVideo]);
35901
- useEffect57(() => {
35975
+ useEffect58(() => {
35902
35976
  if (!isTimelineMode || !doc?.blocks.length) setTimelineCompositionVisible(false);
35903
35977
  }, [isTimelineMode, doc]);
35904
- useEffect57(() => {
35978
+ useEffect58(() => {
35905
35979
  if (!mediaProvider) {
35906
35980
  setMediaCount(0);
35907
35981
  return;
@@ -36010,7 +36084,7 @@ ${snippet}` : snippet);
36010
36084
  onDrop: handleFileDrop,
36011
36085
  enabled: !readOnly
36012
36086
  });
36013
- useEffect57(() => {
36087
+ useEffect58(() => {
36014
36088
  onChange?.(markdownSource);
36015
36089
  }, [markdownSource, onChange]);
36016
36090
  const handleShellKeyDown = useCallback51(
@@ -36365,7 +36439,7 @@ function ImageEditModal({
36365
36439
  useModalDialog({ rootRef: modalRef, dialogRef: surfaceRef, onClose });
36366
36440
  const extension = relativePath.split(/[?#]/, 1)[0]?.split(".").pop()?.toLowerCase();
36367
36441
  const saveFormat = extension === "png" ? "png" : extension === "jpg" || extension === "jpeg" ? "jpeg" : extension === "webp" ? "webp" : null;
36368
- const sidecar = useMemo51(() => {
36442
+ const sidecar = useMemo52(() => {
36369
36443
  const sanitized = relativePath.replace(/[^a-zA-Z0-9._-]+/g, "_");
36370
36444
  let hash = 2166136261;
36371
36445
  for (let i = 0; i < relativePath.length; i++) {
@@ -36376,9 +36450,9 @@ function ImageEditModal({
36376
36450
  const parent = container ?? new MemoryContentContainer();
36377
36451
  return scopeContainer(parent, `.imageEdits/${scopedName}`);
36378
36452
  }, [container, relativePath]);
36379
- const [initialSrc, setInitialSrc] = useState67(null);
36380
- const [resolveError, setResolveError] = useState67(null);
36381
- useEffect57(() => {
36453
+ const [initialSrc, setInitialSrc] = useState68(null);
36454
+ const [resolveError, setResolveError] = useState68(null);
36455
+ useEffect58(() => {
36382
36456
  let cancelled = false;
36383
36457
  setInitialSrc(null);
36384
36458
  setResolveError(null);
@@ -36583,6 +36657,10 @@ export {
36583
36657
  renderMermaidDiagram,
36584
36658
  inspectMermaidSource,
36585
36659
  mermaidErrorMessage,
36660
+ mermaidSurfaceScheme,
36661
+ adaptThemeToSurface,
36662
+ resolveMermaidSurfaceTheme,
36663
+ useMermaidSurfaceTheme,
36586
36664
  MermaidDiagramCanvas,
36587
36665
  MermaidShapePalette,
36588
36666
  useMermaidDiagramData,