@bendyline/squisq-editor-react 2.11.23 → 2.11.25

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.
@@ -717,7 +717,10 @@ function languagesFromRequestKey(requestKey) {
717
717
  async function loadMonacoProfile(requestKey, languageServices) {
718
718
  const monaco = await loadMonacoModule();
719
719
  if (!loadedLanguageProfiles.has(requestKey)) {
720
- await monaco.loadMonacoLanguages(languagesFromRequestKey(requestKey), { languageServices });
720
+ await Promise.all([
721
+ preloadMonacoSuggestions(),
722
+ monaco.loadMonacoLanguages(languagesFromRequestKey(requestKey), { languageServices })
723
+ ]);
721
724
  loadedLanguageProfiles.add(requestKey);
722
725
  }
723
726
  return monaco;
@@ -1097,7 +1100,7 @@ function VersionHistoryPanel() {
1097
1100
  }
1098
1101
 
1099
1102
  // src/ThemePicker.tsx
1100
- import { useCallback as useCallback2, useEffect as useEffect4, useId, useMemo as useMemo2, useRef as useRef3, useState as useState3 } from "react";
1103
+ import { useCallback as useCallback2, useEffect as useEffect4, useId, useLayoutEffect, useMemo as useMemo2, useRef as useRef3, useState as useState3 } from "react";
1101
1104
  import { createPortal } from "react-dom";
1102
1105
  import {
1103
1106
  getThemeSummaries,
@@ -1257,7 +1260,14 @@ function ThemePicker({
1257
1260
  const handleSelect = (id) => {
1258
1261
  onChange(id);
1259
1262
  setOpen(false);
1263
+ triggerRef.current?.focus();
1260
1264
  };
1265
+ useLayoutEffect(() => {
1266
+ if (!open) return;
1267
+ const options = popoverRef.current?.querySelectorAll('[role="option"]');
1268
+ const selected = popoverRef.current?.querySelector('[aria-selected="true"]');
1269
+ (selected ?? options?.[0])?.focus();
1270
+ }, [open]);
1261
1271
  const popover = open ? createPortal(
1262
1272
  /* @__PURE__ */ jsxs2(
1263
1273
  "div",
@@ -1268,6 +1278,24 @@ function ThemePicker({
1268
1278
  role: "listbox",
1269
1279
  "aria-label": ariaLabel,
1270
1280
  style: popoverStyle,
1281
+ onKeyDown: (event) => {
1282
+ if (event.key === "Tab") {
1283
+ setOpen(false);
1284
+ triggerRef.current?.focus();
1285
+ return;
1286
+ }
1287
+ if (!["ArrowDown", "ArrowUp", "ArrowLeft", "ArrowRight", "Home", "End"].includes(
1288
+ event.key
1289
+ ))
1290
+ return;
1291
+ event.preventDefault();
1292
+ const options = [
1293
+ ...event.currentTarget.querySelectorAll('[role="option"]')
1294
+ ];
1295
+ const current = options.indexOf(document.activeElement);
1296
+ const next = event.key === "Home" ? 0 : event.key === "End" ? options.length - 1 : event.key === "ArrowUp" || event.key === "ArrowLeft" ? Math.max(0, current - 1) : Math.min(options.length - 1, current + 1);
1297
+ options[next]?.focus();
1298
+ },
1271
1299
  children: [
1272
1300
  includeDefault && inheritedEntry && /* @__PURE__ */ jsxs2(
1273
1301
  "button",
@@ -1400,7 +1428,8 @@ function ThemePicker({
1400
1428
  ]
1401
1429
  }
1402
1430
  ),
1403
- document.body
1431
+ // Keep choices inside the modal's focus and accessibility boundary.
1432
+ triggerRef.current?.closest('[role="dialog"][aria-modal="true"]') ?? document.body
1404
1433
  ) : null;
1405
1434
  return /* @__PURE__ */ jsxs2(Fragment, { children: [
1406
1435
  /* @__PURE__ */ jsxs2(
@@ -1410,6 +1439,12 @@ function ThemePicker({
1410
1439
  type: "button",
1411
1440
  className: `squisq-theme-picker-trigger squisq-theme-picker-trigger--${variant}${open ? " squisq-theme-picker-trigger--open" : ""}`,
1412
1441
  onClick: handleToggle,
1442
+ onKeyDown: (event) => {
1443
+ if (event.key !== "ArrowDown" && event.key !== "ArrowUp") return;
1444
+ event.preventDefault();
1445
+ updatePosition();
1446
+ setOpen(true);
1447
+ },
1413
1448
  "aria-haspopup": "listbox",
1414
1449
  "aria-expanded": open,
1415
1450
  "aria-controls": open ? popoverId : void 0,
@@ -2379,7 +2414,7 @@ function CustomThemeDialog({ value, onChange, onSave, onClose }) {
2379
2414
  }
2380
2415
 
2381
2416
  // src/PreviewModeMenu.tsx
2382
- import { useCallback as useCallback8, useEffect as useEffect8, useId as useId2, useLayoutEffect as useLayoutEffect2, useRef as useRef7, useState as useState8 } from "react";
2417
+ import { useCallback as useCallback8, useEffect as useEffect8, useId as useId2, useLayoutEffect as useLayoutEffect3, useRef as useRef7, useState as useState8 } from "react";
2383
2418
  import { createPortal as createPortal3 } from "react-dom";
2384
2419
 
2385
2420
  // src/PreviewControls.tsx
@@ -2390,7 +2425,7 @@ import {
2390
2425
  useState as useState7,
2391
2426
  useMemo as useMemo6,
2392
2427
  useEffect as useEffect7,
2393
- useLayoutEffect,
2428
+ useLayoutEffect as useLayoutEffect2,
2394
2429
  useRef as useRef6
2395
2430
  } from "react";
2396
2431
  import { createPortal as createPortal2 } from "react-dom";
@@ -3761,7 +3796,7 @@ function PreviewToolbarControls({
3761
3796
  setPopoverOpen(false);
3762
3797
  setPopoverAnchor(null);
3763
3798
  }, []);
3764
- useLayoutEffect(() => {
3799
+ useLayoutEffect2(() => {
3765
3800
  const root = rootRef.current;
3766
3801
  const probe = probeRef.current;
3767
3802
  if (!root || !probe) return;
@@ -3802,7 +3837,7 @@ function PreviewToolbarControls({
3802
3837
  document.addEventListener("mousedown", handler);
3803
3838
  return () => document.removeEventListener("mousedown", handler);
3804
3839
  }, [closePopover, popoverOpen]);
3805
- useLayoutEffect(() => {
3840
+ useLayoutEffect2(() => {
3806
3841
  if (!popoverOpen) return;
3807
3842
  updatePopoverPosition();
3808
3843
  }, [popoverOpen, updatePopoverPosition, visibleCount]);
@@ -4315,7 +4350,7 @@ function PreviewModeMenu({ openRequest = 0 }) {
4315
4350
  window.removeEventListener("scroll", updatePosition, true);
4316
4351
  };
4317
4352
  }, [closeMenu, open, updatePosition]);
4318
- useLayoutEffect2(() => {
4353
+ useLayoutEffect3(() => {
4319
4354
  if (!open || !anchor) return;
4320
4355
  const selected = menuRef.current?.querySelector('[aria-checked="true"]');
4321
4356
  const first = menuRef.current?.querySelector('[role="menuitemradio"]');
@@ -4352,6 +4387,10 @@ function PreviewModeMenu({ openRequest = 0 }) {
4352
4387
  "aria-label": "Use mode",
4353
4388
  style: { top: anchor.top, left: anchor.left },
4354
4389
  onKeyDown: (event) => {
4390
+ if (event.key === "Tab") {
4391
+ closeMenu(true);
4392
+ return;
4393
+ }
4355
4394
  if (!["ArrowDown", "ArrowUp", "Home", "End"].includes(event.key)) return;
4356
4395
  event.preventDefault();
4357
4396
  const items = Array.from(
@@ -4374,6 +4413,7 @@ function PreviewModeMenu({ openRequest = 0 }) {
4374
4413
  type: "button",
4375
4414
  className: `squisq-use-mode-menu-item${selected ? " squisq-use-mode-menu-item--selected" : ""}`,
4376
4415
  role: "menuitemradio",
4416
+ tabIndex: -1,
4377
4417
  "aria-checked": selected,
4378
4418
  "aria-labelledby": labelId,
4379
4419
  "aria-describedby": summaryId,
@@ -4402,13 +4442,61 @@ function PreviewModeMenu({ openRequest = 0 }) {
4402
4442
  }
4403
4443
 
4404
4444
  // src/ViewMenuPanel.tsx
4405
- import { useCallback as useCallback10, useEffect as useEffect11, useId as useId3, useRef as useRef11, useState as useState12 } from "react";
4445
+ import { useCallback as useCallback10, useEffect as useEffect11, useLayoutEffect as useLayoutEffect6, useRef as useRef11, useState as useState13 } from "react";
4446
+ import { createPortal as createPortal6 } from "react-dom";
4447
+
4448
+ // src/useAnchoredPopover.ts
4449
+ import { useLayoutEffect as useLayoutEffect4, useState as useState9 } from "react";
4450
+ function useAnchoredPopover(open, triggerRef, popoverRef) {
4451
+ const [style, setStyle] = useState9({ position: "fixed", visibility: "hidden" });
4452
+ useLayoutEffect4(() => {
4453
+ if (!open) return;
4454
+ const position = () => {
4455
+ const trigger = triggerRef.current;
4456
+ const popover = popoverRef.current;
4457
+ if (!trigger || !popover) return;
4458
+ const rect = trigger.getBoundingClientRect();
4459
+ const below = Math.max(0, window.innerHeight - rect.bottom - 12);
4460
+ const above = Math.max(0, rect.top - 12);
4461
+ const flip = popover.scrollHeight > below && above > below;
4462
+ const height = Math.min(popover.scrollHeight + 2, flip ? above : below);
4463
+ setStyle({
4464
+ position: "fixed",
4465
+ visibility: "visible",
4466
+ margin: 0,
4467
+ right: "auto",
4468
+ bottom: "auto",
4469
+ left: Math.max(
4470
+ 8,
4471
+ Math.min(rect.right - popover.offsetWidth, window.innerWidth - popover.offsetWidth - 8)
4472
+ ),
4473
+ top: flip ? rect.top - height - 4 : rect.bottom + 4,
4474
+ maxHeight: height,
4475
+ maxWidth: "calc(100vw - 16px)",
4476
+ boxSizing: "border-box",
4477
+ overflowY: "auto"
4478
+ });
4479
+ };
4480
+ const scroll = (event) => {
4481
+ if (event.target instanceof Node && popoverRef.current?.contains(event.target)) return;
4482
+ position();
4483
+ };
4484
+ position();
4485
+ window.addEventListener("resize", position);
4486
+ window.addEventListener("scroll", scroll, true);
4487
+ return () => {
4488
+ window.removeEventListener("resize", position);
4489
+ window.removeEventListener("scroll", scroll, true);
4490
+ };
4491
+ }, [open, triggerRef, popoverRef]);
4492
+ return style;
4493
+ }
4406
4494
 
4407
4495
  // src/proofing/ProofingContext.tsx
4408
4496
  import { createContext as createContext3, useContext as useContext3 } from "react";
4409
4497
 
4410
4498
  // src/proofing/useProofing.ts
4411
- import { useCallback as useCallback9, useEffect as useEffect9, useMemo as useMemo7, useRef as useRef8, useState as useState9 } from "react";
4499
+ import { useCallback as useCallback9, useEffect as useEffect9, useMemo as useMemo7, useRef as useRef8, useState as useState10 } from "react";
4412
4500
  import {
4413
4501
  blankProtectedSpans,
4414
4502
  buildJoinedText,
@@ -4507,7 +4595,7 @@ function collectTextblockRuns(doc) {
4507
4595
  node2.descendants((child, offset) => {
4508
4596
  if (child.isText && child.text) {
4509
4597
  if (child.marks.some((mark) => mark.type.name === "code")) {
4510
- text += " ".repeat(child.text.length);
4598
+ text += "\0".repeat(child.text.length);
4511
4599
  return true;
4512
4600
  }
4513
4601
  const from = text.length;
@@ -4637,16 +4725,16 @@ function useProofing() {
4637
4725
  versioning,
4638
4726
  saveVersion
4639
4727
  } = useEditorContext();
4640
- const [status, setStatus] = useState9("idle");
4641
- const [errorMessage, setErrorMessage] = useState9(null);
4642
- const [sessionEnabled, setSessionEnabled] = useState9(null);
4643
- const [panelVisible, setPanelVisible] = useState9(false);
4644
- const [findings, setFindings] = useState9([]);
4645
- const [findingsView, setFindingsView] = useState9("wysiwyg");
4646
- const [activeFindingId, setActiveFindingId] = useState9(null);
4647
- const [menuAnchor, setMenuAnchor] = useState9(null);
4648
- const [hoverAnchor, setHoverAnchor] = useState9(null);
4649
- const [retryNonce, setRetryNonce] = useState9(0);
4728
+ const [status, setStatus] = useState10("idle");
4729
+ const [errorMessage, setErrorMessage] = useState10(null);
4730
+ const [sessionEnabled, setSessionEnabled] = useState10(null);
4731
+ const [panelVisible, setPanelVisible] = useState10(false);
4732
+ const [findings, setFindings] = useState10([]);
4733
+ const [findingsView, setFindingsView] = useState10("wysiwyg");
4734
+ const [activeFindingId, setActiveFindingId] = useState10(null);
4735
+ const [menuAnchor, setMenuAnchor] = useState10(null);
4736
+ const [hoverAnchor, setHoverAnchor] = useState10(null);
4737
+ const [retryNonce, setRetryNonce] = useState10(0);
4650
4738
  const providerRef = useRef8(null);
4651
4739
  const ownedRef = useRef8(false);
4652
4740
  const statusRef = useRef8("idle");
@@ -5397,7 +5485,7 @@ function useProofing() {
5397
5485
  }
5398
5486
 
5399
5487
  // src/proofing/ProofingMenu.tsx
5400
- import { useEffect as useEffect10, useRef as useRef9, useState as useState10 } from "react";
5488
+ import { useEffect as useEffect10, useRef as useRef9, useState as useState11 } from "react";
5401
5489
  import { createPortal as createPortal4 } from "react-dom";
5402
5490
  import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
5403
5491
  var MAX_SUGGESTIONS = 5;
@@ -5428,8 +5516,8 @@ function ProofingMenu({
5428
5516
  onClose
5429
5517
  }) {
5430
5518
  const menuRef = useRef9(null);
5431
- const [style, setStyle] = useState10(() => computeStyle(anchor));
5432
- const [focusIndex, setFocusIndex] = useState10(0);
5519
+ const [style, setStyle] = useState11(() => computeStyle(anchor));
5520
+ const [focusIndex, setFocusIndex] = useState11(0);
5433
5521
  useEffect10(() => {
5434
5522
  requestAnimationFrame(() => setStyle(computeStyle(anchor, menuRef.current)));
5435
5523
  }, [anchor]);
@@ -5522,7 +5610,7 @@ function ProofingMenu({
5522
5610
  }
5523
5611
 
5524
5612
  // src/proofing/ProofingTooltip.tsx
5525
- import { useLayoutEffect as useLayoutEffect3, useRef as useRef10, useState as useState11 } from "react";
5613
+ import { useLayoutEffect as useLayoutEffect5, useRef as useRef10, useState as useState12 } from "react";
5526
5614
  import { createPortal as createPortal5 } from "react-dom";
5527
5615
  import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
5528
5616
  var MAX_SUGGESTIONS2 = 3;
@@ -5556,8 +5644,8 @@ function ProofingTooltip({
5556
5644
  onRelease
5557
5645
  }) {
5558
5646
  const tooltipRef = useRef10(null);
5559
- const [style, setStyle] = useState11(() => computeStyle2(anchor));
5560
- useLayoutEffect3(() => {
5647
+ const [style, setStyle] = useState12(() => computeStyle2(anchor));
5648
+ useLayoutEffect5(() => {
5561
5649
  setStyle(computeStyle2(anchor, tooltipRef.current));
5562
5650
  }, [anchor, finding.id]);
5563
5651
  const suggestions = finding.suggestions.slice(0, MAX_SUGGESTIONS2);
@@ -5723,19 +5811,28 @@ function ViewMenuPanel() {
5723
5811
  setBlockTagVisibility,
5724
5812
  themeInheritance,
5725
5813
  setThemeInheritance,
5814
+ colorScheme,
5726
5815
  layoutMode,
5727
5816
  setLayoutMode
5728
5817
  } = useEditorContext();
5729
5818
  const proofingState = useProofingState();
5730
- const [open, setOpen] = useState12(false);
5819
+ const [open, setOpen] = useState13(false);
5731
5820
  const containerRef = useRef11(null);
5732
5821
  const triggerRef = useRef11(null);
5822
+ const menuRef = useRef11(null);
5823
+ const initialFocus = useRef11("first");
5824
+ const popoverStyle = useAnchoredPopover(open, triggerRef, menuRef);
5733
5825
  const close = useCallback10(() => setOpen(false), []);
5734
5826
  useEscapeDismissal(open, close, triggerRef);
5827
+ useLayoutEffect6(() => {
5828
+ if (!open || popoverStyle.visibility === "hidden") return;
5829
+ const items = menuRef.current?.querySelectorAll('[role^="menuitem"]');
5830
+ if (items?.length) items[initialFocus.current === "last" ? items.length - 1 : 0]?.focus();
5831
+ }, [open, popoverStyle.visibility]);
5735
5832
  useEffect11(() => {
5736
5833
  if (!open) return;
5737
5834
  const handler = (e2) => {
5738
- if (containerRef.current && !containerRef.current.contains(e2.target)) {
5835
+ if (containerRef.current && !containerRef.current.contains(e2.target) && !menuRef.current?.contains(e2.target)) {
5739
5836
  setOpen(false);
5740
5837
  }
5741
5838
  };
@@ -5762,78 +5859,116 @@ function ViewMenuPanel() {
5762
5859
  "aria-label": "View options",
5763
5860
  "aria-expanded": open,
5764
5861
  "aria-haspopup": "menu",
5765
- onClick: () => setOpen((v2) => !v2),
5862
+ onClick: () => {
5863
+ initialFocus.current = "first";
5864
+ setOpen((v2) => !v2);
5865
+ },
5866
+ onKeyDown: (event) => {
5867
+ if (event.key !== "ArrowDown" && event.key !== "ArrowUp") return;
5868
+ event.preventDefault();
5869
+ initialFocus.current = event.key === "ArrowUp" ? "last" : "first";
5870
+ setOpen(true);
5871
+ },
5766
5872
  children: /* @__PURE__ */ jsx12(Icon, { icon: "fa-solid fa-eye" })
5767
5873
  }
5768
5874
  ),
5769
- open && /* @__PURE__ */ jsxs11("div", { className: "squisq-view-menu-popover", role: "menu", "aria-label": "View options", children: [
5770
- /* @__PURE__ */ jsx12(
5771
- MenuRadioGroup,
5772
- {
5773
- label: "View",
5774
- value: layoutMode,
5775
- onChange: (v2) => setLayoutMode(v2),
5776
- options: [
5777
- { value: "document", label: "Document" },
5778
- { value: "block", label: "Block-at-a-time" },
5779
- { value: "timeline", label: "Timeline" }
5780
- ]
5781
- }
5782
- ),
5783
- /* @__PURE__ */ jsx12("div", { className: "squisq-view-menu-separator", role: "separator" }),
5784
- /* @__PURE__ */ jsx12(MenuToggle, { label: "Show outline", checked: outlineVisible, onChange: toggleOutline }),
5785
- /* @__PURE__ */ jsx12(
5786
- MenuToggle,
5787
- {
5788
- label: "Show block previews",
5789
- checked: inlinePreviewVisible,
5790
- onChange: toggleInlinePreview
5791
- }
5792
- ),
5793
- /* @__PURE__ */ jsx12(
5794
- MenuRadioGroup,
5875
+ open && createPortal6(
5876
+ /* @__PURE__ */ jsxs11(
5877
+ "div",
5795
5878
  {
5796
- label: "Show block tags",
5797
- value: blockTagVisibility,
5798
- onChange: (v2) => setBlockTagVisibility(v2),
5799
- options: [
5800
- { value: "none", label: "No inline block tags" },
5801
- { value: "active", label: "Selected/hovered block" },
5802
- { value: "always", label: "Always show" }
5879
+ ref: menuRef,
5880
+ style: popoverStyle,
5881
+ "data-theme": colorScheme,
5882
+ className: "squisq-view-menu-popover",
5883
+ role: "menu",
5884
+ "aria-label": "View options",
5885
+ onKeyDown: (event) => {
5886
+ if (event.key === "Tab") {
5887
+ close();
5888
+ triggerRef.current?.focus();
5889
+ return;
5890
+ }
5891
+ if (!["ArrowDown", "ArrowUp", "Home", "End"].includes(event.key)) return;
5892
+ event.preventDefault();
5893
+ const items = [
5894
+ ...event.currentTarget.querySelectorAll('[role^="menuitem"]')
5895
+ ];
5896
+ const current = items.indexOf(document.activeElement);
5897
+ const next = event.key === "Home" ? 0 : event.key === "End" ? items.length - 1 : event.key === "ArrowUp" ? (current - 1 + items.length) % items.length : (current + 1) % items.length;
5898
+ items[next]?.focus();
5899
+ },
5900
+ children: [
5901
+ /* @__PURE__ */ jsx12(
5902
+ MenuRadioGroup,
5903
+ {
5904
+ label: "View",
5905
+ value: layoutMode,
5906
+ onChange: (v2) => setLayoutMode(v2),
5907
+ options: [
5908
+ { value: "document", label: "Document" },
5909
+ { value: "block", label: "Block-at-a-time" },
5910
+ { value: "timeline", label: "Timeline" }
5911
+ ]
5912
+ }
5913
+ ),
5914
+ /* @__PURE__ */ jsx12("div", { className: "squisq-view-menu-separator", role: "separator" }),
5915
+ /* @__PURE__ */ jsx12(MenuToggle, { label: "Show outline", checked: outlineVisible, onChange: toggleOutline }),
5916
+ /* @__PURE__ */ jsx12(
5917
+ MenuToggle,
5918
+ {
5919
+ label: "Show block previews",
5920
+ checked: inlinePreviewVisible,
5921
+ onChange: toggleInlinePreview
5922
+ }
5923
+ ),
5924
+ /* @__PURE__ */ jsx12(
5925
+ MenuRadioGroup,
5926
+ {
5927
+ label: "Show block tags",
5928
+ value: blockTagVisibility,
5929
+ onChange: (v2) => setBlockTagVisibility(v2),
5930
+ options: [
5931
+ { value: "none", label: "No inline block tags" },
5932
+ { value: "active", label: "Selected/hovered block" },
5933
+ { value: "always", label: "Always show" }
5934
+ ]
5935
+ }
5936
+ ),
5937
+ /* @__PURE__ */ jsx12(
5938
+ MenuToggle,
5939
+ {
5940
+ label: "Show status bar",
5941
+ checked: statusBarVisible,
5942
+ onChange: toggleStatusBar
5943
+ }
5944
+ ),
5945
+ proofingState && /* @__PURE__ */ jsx12(
5946
+ MenuToggle,
5947
+ {
5948
+ label: "Check spelling & grammar",
5949
+ checked: proofingState.enabled,
5950
+ onChange: () => proofingState.setEnabled(!proofingState.enabled)
5951
+ }
5952
+ ),
5953
+ /* @__PURE__ */ jsx12("div", { className: "squisq-view-menu-separator", role: "separator" }),
5954
+ /* @__PURE__ */ jsx12(
5955
+ MenuRadioGroup,
5956
+ {
5957
+ label: "Editor styling from theme",
5958
+ value: themeInheritance,
5959
+ onChange: (v2) => setThemeInheritance(v2),
5960
+ options: [
5961
+ { value: "none", label: "Don't inherit" },
5962
+ { value: "fonts", label: "Fonts only" },
5963
+ { value: "fonts-colors", label: "Fonts & colors" }
5964
+ ]
5965
+ }
5966
+ )
5803
5967
  ]
5804
5968
  }
5805
5969
  ),
5806
- /* @__PURE__ */ jsx12(
5807
- MenuToggle,
5808
- {
5809
- label: "Show status bar",
5810
- checked: statusBarVisible,
5811
- onChange: toggleStatusBar
5812
- }
5813
- ),
5814
- proofingState && /* @__PURE__ */ jsx12(
5815
- MenuToggle,
5816
- {
5817
- label: "Check spelling & grammar",
5818
- checked: proofingState.enabled,
5819
- onChange: () => proofingState.setEnabled(!proofingState.enabled)
5820
- }
5821
- ),
5822
- /* @__PURE__ */ jsx12("div", { className: "squisq-view-menu-separator", role: "separator" }),
5823
- /* @__PURE__ */ jsx12(
5824
- MenuRadioGroup,
5825
- {
5826
- label: "Editor styling from theme",
5827
- value: themeInheritance,
5828
- onChange: (v2) => setThemeInheritance(v2),
5829
- options: [
5830
- { value: "none", label: "Don't inherit" },
5831
- { value: "fonts", label: "Fonts only" },
5832
- { value: "fonts-colors", label: "Fonts & colors" }
5833
- ]
5834
- }
5835
- )
5836
- ] })
5970
+ triggerRef.current?.closest('[role="dialog"][aria-modal="true"]') ?? document.body
5971
+ )
5837
5972
  ] });
5838
5973
  }
5839
5974
  function MenuToggle({
@@ -5841,18 +5976,21 @@ function MenuToggle({
5841
5976
  checked,
5842
5977
  onChange
5843
5978
  }) {
5844
- return /* @__PURE__ */ jsxs11("label", { className: "squisq-view-menu-row", role: "menuitemcheckbox", "aria-checked": checked, children: [
5845
- /* @__PURE__ */ jsx12(
5846
- "input",
5847
- {
5848
- type: "checkbox",
5849
- className: "squisq-view-menu-checkbox",
5850
- checked,
5851
- onChange
5852
- }
5853
- ),
5854
- /* @__PURE__ */ jsx12("span", { className: "squisq-view-menu-label", children: label })
5855
- ] });
5979
+ return /* @__PURE__ */ jsxs11(
5980
+ "button",
5981
+ {
5982
+ type: "button",
5983
+ tabIndex: -1,
5984
+ className: "squisq-view-menu-row",
5985
+ role: "menuitemcheckbox",
5986
+ "aria-checked": checked,
5987
+ onClick: onChange,
5988
+ children: [
5989
+ /* @__PURE__ */ jsx12("span", { className: "squisq-view-menu-checkbox", "aria-hidden": "true", children: checked ? "\u2713" : "" }),
5990
+ /* @__PURE__ */ jsx12("span", { className: "squisq-view-menu-label", children: label })
5991
+ ]
5992
+ }
5993
+ );
5856
5994
  }
5857
5995
  function MenuRadioGroup({
5858
5996
  label,
@@ -5860,35 +5998,27 @@ function MenuRadioGroup({
5860
5998
  onChange,
5861
5999
  options
5862
6000
  }) {
5863
- const name = useId3();
5864
6001
  return /* @__PURE__ */ jsxs11(
5865
6002
  "div",
5866
6003
  {
5867
6004
  className: "squisq-view-menu-row squisq-view-menu-row--radios",
5868
- role: "radiogroup",
6005
+ role: "group",
5869
6006
  "aria-label": label,
5870
6007
  children: [
5871
6008
  /* @__PURE__ */ jsx12("span", { className: "squisq-view-menu-label", children: label }),
5872
6009
  options.map((o) => {
5873
6010
  const checked = o.value === value;
5874
6011
  return /* @__PURE__ */ jsxs11(
5875
- "label",
6012
+ "button",
5876
6013
  {
6014
+ type: "button",
6015
+ tabIndex: -1,
5877
6016
  className: "squisq-view-menu-radio-row",
5878
6017
  role: "menuitemradio",
5879
6018
  "aria-checked": checked,
6019
+ onClick: () => onChange(o.value),
5880
6020
  children: [
5881
- /* @__PURE__ */ jsx12(
5882
- "input",
5883
- {
5884
- type: "radio",
5885
- className: "squisq-view-menu-radio",
5886
- name,
5887
- value: o.value,
5888
- checked,
5889
- onChange: () => onChange(o.value)
5890
- }
5891
- ),
6021
+ /* @__PURE__ */ jsx12("span", { className: "squisq-view-menu-radio", "aria-hidden": "true", children: checked ? "\u25CF" : "" }),
5892
6022
  /* @__PURE__ */ jsx12("span", { className: "squisq-view-menu-radio-label", children: o.label })
5893
6023
  ]
5894
6024
  },
@@ -5901,7 +6031,7 @@ function MenuRadioGroup({
5901
6031
  }
5902
6032
 
5903
6033
  // src/TransformMenu.tsx
5904
- import { useCallback as useCallback11, useEffect as useEffect12, useMemo as useMemo8, useRef as useRef12, useState as useState13 } from "react";
6034
+ import { useCallback as useCallback11, useEffect as useEffect12, useMemo as useMemo8, useRef as useRef12, useState as useState14 } from "react";
5905
6035
  import {
5906
6036
  MARKDOWN_SOURCE_TRANSFORMS,
5907
6037
  DEFAULT_WRAP_WIDTH,
@@ -5939,9 +6069,9 @@ function TransformMenu() {
5939
6069
  versioning,
5940
6070
  saveVersion
5941
6071
  } = useEditorContext();
5942
- const [open, setOpen] = useState13(false);
5943
- const [width, setWidth] = useState13(DEFAULT_WRAP_WIDTH);
5944
- const [status, setStatus] = useState13("");
6072
+ const [open, setOpen] = useState14(false);
6073
+ const [width, setWidth] = useState14(DEFAULT_WRAP_WIDTH);
6074
+ const [status, setStatus] = useState14("");
5945
6075
  const containerRef = useRef12(null);
5946
6076
  const triggerRef = useRef12(null);
5947
6077
  const close = useCallback11(() => setOpen(false), []);
@@ -6107,7 +6237,7 @@ import {
6107
6237
  useContext as useContext4,
6108
6238
  useEffect as useEffect13,
6109
6239
  useMemo as useMemo9,
6110
- useState as useState14
6240
+ useState as useState15
6111
6241
  } from "react";
6112
6242
 
6113
6243
  // src/customTemplates/library.ts
@@ -6174,7 +6304,7 @@ function CustomTemplateProvider({
6174
6304
  onDocTemplatesChange,
6175
6305
  children
6176
6306
  }) {
6177
- const [libraryTemplates, setLibraryTemplates] = useState14(
6307
+ const [libraryTemplates, setLibraryTemplates] = useState15(
6178
6308
  () => listLibraryTemplates()
6179
6309
  );
6180
6310
  useEffect13(() => {
@@ -6247,8 +6377,8 @@ function useCustomTemplates() {
6247
6377
  }
6248
6378
 
6249
6379
  // src/TemplatePicker.tsx
6250
- import { useEffect as useEffect14, useId as useId4, useMemo as useMemo11, useRef as useRef13, useState as useState15 } from "react";
6251
- import { createPortal as createPortal6 } from "react-dom";
6380
+ import { useEffect as useEffect14, useId as useId3, useMemo as useMemo11, useRef as useRef13, useState as useState16 } from "react";
6381
+ import { createPortal as createPortal7 } from "react-dom";
6252
6382
  import { TEMPLATE_METADATA, resolveTemplateName } from "@bendyline/squisq/doc";
6253
6383
  import { extractPlainText as extractPlainText2 } from "@bendyline/squisq/markdown";
6254
6384
 
@@ -6680,7 +6810,7 @@ var TEMPLATE_GALLERY_PORTAL_SELECTOR = "[data-squisq-template-gallery-portal]";
6680
6810
  var TEMPLATE_GALLERY_DIALOG_ID = "squisq-template-gallery-dialog";
6681
6811
  var TEMPLATE_GALLERY_PORTAL_ID_PREFIX = "squisq-template-gallery-portal";
6682
6812
  function useTemplateGalleryPortalId() {
6683
- return `${TEMPLATE_GALLERY_PORTAL_ID_PREFIX}-${useId4().replace(/:/g, "")}`;
6813
+ return `${TEMPLATE_GALLERY_PORTAL_ID_PREFIX}-${useId3().replace(/:/g, "")}`;
6684
6814
  }
6685
6815
  var W3 = 56;
6686
6816
  var H3 = 40;
@@ -7276,12 +7406,12 @@ function TemplatePicker({
7276
7406
  onOpenDesigner,
7277
7407
  previewSource
7278
7408
  }) {
7279
- const [open, setOpen] = useState15(false);
7280
- const [dialogStyle, setDialogStyle] = useState15({});
7409
+ const [open, setOpen] = useState16(false);
7410
+ const [dialogStyle, setDialogStyle] = useState16({});
7281
7411
  const containerRef = useRef13(null);
7282
7412
  const triggerRef = useRef13(null);
7283
7413
  const dialogRef = useRef13(null);
7284
- const dialogId = `${TEMPLATE_GALLERY_DIALOG_ID}-${useId4().replace(/:/g, "")}`;
7414
+ const dialogId = `${TEMPLATE_GALLERY_DIALOG_ID}-${useId3().replace(/:/g, "")}`;
7285
7415
  useEscapeDismissal(open, () => setOpen(false), triggerRef);
7286
7416
  const updateDialogBounds = () => {
7287
7417
  if (!triggerRef.current) return;
@@ -7334,7 +7464,7 @@ function TemplatePicker({
7334
7464
  }
7335
7465
  );
7336
7466
  }
7337
- const gallery = open ? createPortal6(
7467
+ const gallery = open ? createPortal7(
7338
7468
  /* @__PURE__ */ jsx18(
7339
7469
  TemplateGalleryDialog,
7340
7470
  {
@@ -7414,7 +7544,7 @@ function TemplateGalleryDialog({
7414
7544
  onClose
7415
7545
  }) {
7416
7546
  const panelRef = useRef13(null);
7417
- const titleId = useId4();
7547
+ const titleId = useId3();
7418
7548
  useModalDialog({ rootRef: dialogRef, dialogRef: panelRef, returnFocusRef, onClose });
7419
7549
  return /* @__PURE__ */ jsx18(
7420
7550
  "div",
@@ -7522,7 +7652,7 @@ function TemplateGalleryBody({
7522
7652
  previewSource
7523
7653
  }) {
7524
7654
  const galleryId = useTemplateGalleryPortalId();
7525
- const [query, setQuery] = useState15("");
7655
+ const [query, setQuery] = useState16("");
7526
7656
  const searchRef = useRef13(null);
7527
7657
  const customCtx = useCustomTemplates();
7528
7658
  const customTemplates = useMemo11(() => customCtx?.allTemplates ?? [], [customCtx]);
@@ -7744,9 +7874,9 @@ function TemplateBadgePopover({
7744
7874
  onOpenDesigner,
7745
7875
  previewSource
7746
7876
  }) {
7747
- const [style, setStyle] = useState15(() => computeDialogStyle(anchorRect));
7877
+ const [style, setStyle] = useState16(() => computeDialogStyle(anchorRect));
7748
7878
  const dialogRef = useRef13(null);
7749
- const dialogId = `${TEMPLATE_GALLERY_DIALOG_ID}-${useId4().replace(/:/g, "")}`;
7879
+ const dialogId = `${TEMPLATE_GALLERY_DIALOG_ID}-${useId3().replace(/:/g, "")}`;
7750
7880
  useEffect14(() => {
7751
7881
  const frame = requestAnimationFrame(() => setStyle(computeDialogStyle(anchorRect)));
7752
7882
  return () => cancelAnimationFrame(frame);
@@ -7775,7 +7905,7 @@ function TemplateBadgePopover({
7775
7905
  onClose();
7776
7906
  };
7777
7907
  const dialogTitle = templateDialogTitle(previewSource);
7778
- return createPortal6(
7908
+ return createPortal7(
7779
7909
  /* @__PURE__ */ jsx18(
7780
7910
  TemplateGalleryDialog,
7781
7911
  {
@@ -8085,8 +8215,8 @@ function transitionLabel(value) {
8085
8215
  }
8086
8216
 
8087
8217
  // src/TransitionPicker.tsx
8088
- import { useEffect as useEffect15, useMemo as useMemo12, useRef as useRef14, useState as useState16 } from "react";
8089
- import { createPortal as createPortal7 } from "react-dom";
8218
+ import { useEffect as useEffect15, useMemo as useMemo12, useRef as useRef14, useState as useState17 } from "react";
8219
+ import { createPortal as createPortal8 } from "react-dom";
8090
8220
  import { getTransitionClass } from "@bendyline/squisq-react";
8091
8221
  import { jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
8092
8222
  var TRANSITION_FLYOUT_PORTAL_ID = "squisq-transition-flyout-portal";
@@ -8097,8 +8227,8 @@ function TransitionPicker({
8097
8227
  colorScheme = "light",
8098
8228
  accentColor
8099
8229
  }) {
8100
- const [open, setOpen] = useState16(false);
8101
- const [style, setStyle] = useState16({});
8230
+ const [open, setOpen] = useState17(false);
8231
+ const [style, setStyle] = useState17({});
8102
8232
  const triggerRef = useRef14(null);
8103
8233
  useEscapeDismissal(open, () => setOpen(false), triggerRef);
8104
8234
  const updatePosition = () => {
@@ -8146,7 +8276,7 @@ function TransitionPicker({
8146
8276
  window.removeEventListener("resize", handler);
8147
8277
  };
8148
8278
  }, [open]);
8149
- const flyout = open ? createPortal7(
8279
+ const flyout = open ? createPortal8(
8150
8280
  /* @__PURE__ */ jsx19(
8151
8281
  TransitionFlyout,
8152
8282
  {
@@ -8202,7 +8332,7 @@ function TransitionFlyout({
8202
8332
  onChange,
8203
8333
  colorScheme
8204
8334
  }) {
8205
- const [query, setQuery] = useState16("");
8335
+ const [query, setQuery] = useState17("");
8206
8336
  const searchRef = useRef14(null);
8207
8337
  useEffect15(() => {
8208
8338
  searchRef.current?.focus();
@@ -8340,7 +8470,7 @@ function TransitionOption({
8340
8470
  direction,
8341
8471
  onSelect
8342
8472
  }) {
8343
- const [previewing, setPreviewing] = useState16(false);
8473
+ const [previewing, setPreviewing] = useState17(false);
8344
8474
  const animClass = previewing && entry.value ? getTransitionClass(entry.value, true, normalizeDir(direction)) : "";
8345
8475
  return /* @__PURE__ */ jsx19(
8346
8476
  "button",
@@ -8361,7 +8491,7 @@ function normalizeDir(direction) {
8361
8491
  }
8362
8492
 
8363
8493
  // src/DocumentSettingsDialog.tsx
8364
- import { useCallback as useCallback13, useId as useId5, useMemo as useMemo13, useRef as useRef15, useState as useState17 } from "react";
8494
+ import { useCallback as useCallback13, useId as useId4, useMemo as useMemo13, useRef as useRef15, useState as useState18 } from "react";
8365
8495
  import {
8366
8496
  inferDocumentTitle,
8367
8497
  parseMarkdown as parseMarkdown2,
@@ -8417,11 +8547,11 @@ function DocumentSettingsDialog({
8417
8547
  FRONTMATTER_SETTING_KEYS.captions.canonical,
8418
8548
  FRONTMATTER_SETTING_KEYS.captions.legacy
8419
8549
  );
8420
- const [title, setTitle] = useState17(currentTitle);
8421
- const [subtitle, setSubtitle] = useState17(currentSubtitle);
8422
- const [theme, setTheme] = useState17(currentTheme);
8423
- const [transform, setTransform] = useState17(currentTransform);
8424
- const [captions, setCaptions] = useState17(currentCaptions);
8550
+ const [title, setTitle] = useState18(currentTitle);
8551
+ const [subtitle, setSubtitle] = useState18(currentSubtitle);
8552
+ const [theme, setTheme] = useState18(currentTheme);
8553
+ const [transform, setTransform] = useState18(currentTransform);
8554
+ const [captions, setCaptions] = useState18(currentCaptions);
8425
8555
  const proofingState = useProofingState();
8426
8556
  const currentProofing = readFm(
8427
8557
  frontmatter,
@@ -8433,14 +8563,14 @@ function DocumentSettingsDialog({
8433
8563
  PROOF_FRONTMATTER_KEYS3.dialect.canonical,
8434
8564
  PROOF_FRONTMATTER_KEYS3.dialect.legacy
8435
8565
  );
8436
- const [proofingEnabled, setProofingEnabled] = useState17(
8566
+ const [proofingEnabled, setProofingEnabled] = useState18(
8437
8567
  typeof frontmatter?.[PROOF_FRONTMATTER_KEYS3.enabled.canonical] === "boolean" ? String(frontmatter[PROOF_FRONTMATTER_KEYS3.enabled.canonical]) : currentProofing === "true" || currentProofing === "false" ? currentProofing : ""
8438
8568
  );
8439
- const [proofDialect, setProofDialect] = useState17(currentProofDialect);
8569
+ const [proofDialect, setProofDialect] = useState18(currentProofDialect);
8440
8570
  const overlayRef = useRef15(null);
8441
8571
  const dialogRef = useRef15(null);
8442
8572
  const titleRef = useRef15(null);
8443
- const headingId = useId5();
8573
+ const headingId = useId4();
8444
8574
  useModalDialog({ rootRef: overlayRef, dialogRef, initialFocusRef: titleRef, onClose });
8445
8575
  const handleBackdrop = useCallback13(
8446
8576
  (e2) => {
@@ -9923,7 +10053,7 @@ function searchPickerEntries(query, limit = 80) {
9923
10053
  }
9924
10054
 
9925
10055
  // src/EmojiPicker.tsx
9926
- import { useEffect as useEffect16, useMemo as useMemo14, useRef as useRef16, useState as useState18 } from "react";
10056
+ import { useEffect as useEffect16, useMemo as useMemo14, useRef as useRef16, useState as useState19 } from "react";
9927
10057
  import { jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
9928
10058
  var LIGHT_PALETTE = {
9929
10059
  bg: "#fff",
@@ -9975,8 +10105,8 @@ function EmojiPicker({
9975
10105
  theme = "light"
9976
10106
  }) {
9977
10107
  const palette = theme === "dark" ? DARK_PALETTE : LIGHT_PALETTE;
9978
- const [activeCategory, setActiveCategory] = useState18(PICKER_CATEGORIES[0].id);
9979
- const [query, setQuery] = useState18("");
10108
+ const [activeCategory, setActiveCategory] = useState19(PICKER_CATEGORIES[0].id);
10109
+ const [query, setQuery] = useState19("");
9980
10110
  const popoverRef = useRef16(null);
9981
10111
  useEscapeDismissal(open, onClose, anchorRef);
9982
10112
  const searchInputRef = useRef16(null);
@@ -10162,7 +10292,7 @@ function EmojiPicker({
10162
10292
  }
10163
10293
 
10164
10294
  // src/hooks/useFileDrop.ts
10165
- import { useCallback as useCallback14, useEffect as useEffect17, useRef as useRef17, useState as useState19 } from "react";
10295
+ import { useCallback as useCallback14, useEffect as useEffect17, useRef as useRef17, useState as useState20 } from "react";
10166
10296
  var MEDIA_EXTENSIONS = /* @__PURE__ */ new Set([
10167
10297
  "png",
10168
10298
  "apng",
@@ -10244,8 +10374,8 @@ function classifyDataTransferItems(items) {
10244
10374
  return null;
10245
10375
  }
10246
10376
  function useFileDrop({ onDrop, enabled = true }) {
10247
- const [isDragging, setIsDragging] = useState19(false);
10248
- const [dragContentType, setDragContentType] = useState19(null);
10377
+ const [isDragging, setIsDragging] = useState20(false);
10378
+ const [dragContentType, setDragContentType] = useState20(null);
10249
10379
  const dragCounterRef = useRef17(0);
10250
10380
  const inPageDragRef = useRef17(false);
10251
10381
  useEffect17(() => {
@@ -10780,7 +10910,7 @@ async function addFileToDocument(file, target, storage) {
10780
10910
  }
10781
10911
 
10782
10912
  // src/videoEmbed/VideoEmbedDialog.tsx
10783
- import { useCallback as useCallback16, useEffect as useEffect18, useId as useId6, useMemo as useMemo16, useRef as useRef18, useState as useState20 } from "react";
10913
+ import { useCallback as useCallback16, useEffect as useEffect18, useId as useId5, useMemo as useMemo16, useRef as useRef18, useState as useState21 } from "react";
10784
10914
  import {
10785
10915
  VIDEO_EMBED_PROVIDERS,
10786
10916
  parseVideoEmbedInput as parseVideoEmbedInput2
@@ -10813,14 +10943,14 @@ function VideoEmbedDialog({
10813
10943
  onConfirm,
10814
10944
  onClose
10815
10945
  }) {
10816
- const [input, setInput] = useState20(initialInput);
10817
- const [title, setTitle] = useState20(initialTitle);
10946
+ const [input, setInput] = useState21(initialInput);
10947
+ const [title, setTitle] = useState21(initialTitle);
10818
10948
  const titleTouched = useRef18(initialTitle.trim() !== "");
10819
10949
  const inputRef = useRef18(null);
10820
10950
  const overlayRef = useRef18(null);
10821
10951
  const dialogRef = useRef18(null);
10822
- const headingId = useId6();
10823
- const statusId = useId6();
10952
+ const headingId = useId5();
10953
+ const statusId = useId5();
10824
10954
  useModalDialog({ rootRef: overlayRef, dialogRef, initialFocusRef: inputRef, onClose });
10825
10955
  const parsed = useMemo16(() => parseVideoEmbedInput2(input), [input]);
10826
10956
  const hasInput = input.trim() !== "";
@@ -11778,12 +11908,12 @@ function MermaidDiagramTypeThumbnail({ preview }) {
11778
11908
  // src/Toolbar.tsx
11779
11909
  import {
11780
11910
  useCallback as useCallback31,
11781
- useEffect as useEffect28,
11782
- useLayoutEffect as useLayoutEffect6,
11911
+ useEffect as useEffect29,
11912
+ useLayoutEffect as useLayoutEffect9,
11783
11913
  useMemo as useMemo24,
11784
11914
  useReducer as useReducer2,
11785
11915
  useRef as useRef33,
11786
- useState as useState36
11916
+ useState as useState38
11787
11917
  } from "react";
11788
11918
  import { VIEWPORT_PRESETS as VIEWPORT_PRESETS3 } from "@bendyline/squisq/schemas";
11789
11919
  import { DEFAULT_THEME, flattenBlocks } from "@bendyline/squisq/doc";
@@ -12167,7 +12297,7 @@ ${videoTag}` : videoTag);
12167
12297
  }
12168
12298
 
12169
12299
  // src/speech/DictationButton.tsx
12170
- import { useEffect as useEffect19, useRef as useRef19, useState as useState21, useSyncExternalStore } from "react";
12300
+ import { useEffect as useEffect19, useRef as useRef19, useState as useState22, useSyncExternalStore } from "react";
12171
12301
  import { jsx as jsx25, jsxs as jsxs20 } from "react/jsx-runtime";
12172
12302
  var ERROR_AUTO_DISMISS_MS = 1e4;
12173
12303
  var ANNOUNCEMENTS = {
@@ -12219,7 +12349,7 @@ function DictationButtonView({ state }) {
12219
12349
  const { status, error, toggle, dismissError, levels } = state;
12220
12350
  const active = status !== "idle";
12221
12351
  const busy = status === "preparing" || status === "transcribing";
12222
- const [announcement, setAnnouncement] = useState21("");
12352
+ const [announcement, setAnnouncement] = useState22("");
12223
12353
  const previousStatus = useRef19(status);
12224
12354
  useEffect19(() => {
12225
12355
  if (previousStatus.current === status) return;
@@ -12326,7 +12456,7 @@ function findBlockSliceByHeadingIndex(source, headingIndex) {
12326
12456
  }
12327
12457
 
12328
12458
  // src/LinkDialog.tsx
12329
- import { useCallback as useCallback18, useEffect as useEffect20, useId as useId7, useMemo as useMemo18, useRef as useRef20, useState as useState22 } from "react";
12459
+ import { useCallback as useCallback18, useEffect as useEffect20, useId as useId6, useMemo as useMemo18, useRef as useRef20, useState as useState23 } from "react";
12330
12460
  import { sanitizeUrl } from "@bendyline/squisq/markdown";
12331
12461
  import { jsx as jsx26, jsxs as jsxs21 } from "react/jsx-runtime";
12332
12462
  function schemeForMessage(raw) {
@@ -12342,19 +12472,19 @@ function LinkDialog({
12342
12472
  documentLinkProvider,
12343
12473
  linkSchemes
12344
12474
  }) {
12345
- const [text, setText] = useState22(initialText);
12346
- const [url, setUrl] = useState22(initialUrl);
12347
- const [tab, setTab] = useState22("url");
12348
- const [docQuery, setDocQuery] = useState22("");
12349
- const [docResults, setDocResults] = useState22([]);
12350
- const [docLoading, setDocLoading] = useState22(false);
12475
+ const [text, setText] = useState23(initialText);
12476
+ const [url, setUrl] = useState23(initialUrl);
12477
+ const [tab, setTab] = useState23("url");
12478
+ const [docQuery, setDocQuery] = useState23("");
12479
+ const [docResults, setDocResults] = useState23([]);
12480
+ const [docLoading, setDocLoading] = useState23(false);
12351
12481
  const textRef = useRef20(null);
12352
12482
  const urlRef = useRef20(null);
12353
12483
  const docSearchRef = useRef20(null);
12354
12484
  const overlayRef = useRef20(null);
12355
12485
  const dialogRef = useRef20(null);
12356
- const headingId = useId7();
12357
- const urlErrorId = useId7();
12486
+ const headingId = useId6();
12487
+ const urlErrorId = useId6();
12358
12488
  const initialFocusRef = initialText ? urlRef : textRef;
12359
12489
  useModalDialog({ rootRef: overlayRef, dialogRef, initialFocusRef, onClose });
12360
12490
  useEffect20(() => {
@@ -12575,26 +12705,26 @@ function LinkDialog({
12575
12705
  }
12576
12706
 
12577
12707
  // src/customTemplates/CustomLayoutManager.tsx
12578
- import { useCallback as useCallback28, useId as useId11, useRef as useRef31, useState as useState33 } from "react";
12579
- import { createPortal as createPortal10 } from "react-dom";
12708
+ import { useCallback as useCallback28, useId as useId10, useRef as useRef31, useState as useState34 } from "react";
12709
+ import { createPortal as createPortal11 } from "react-dom";
12580
12710
 
12581
12711
  // src/customTemplates/TemplateDesigner.tsx
12582
- import { useCallback as useCallback27, useId as useId10, useMemo as useMemo23, useRef as useRef30, useState as useState32 } from "react";
12583
- import { createPortal as createPortal9 } from "react-dom";
12712
+ import { useCallback as useCallback27, useId as useId9, useMemo as useMemo23, useRef as useRef30, useState as useState33 } from "react";
12713
+ import { createPortal as createPortal10 } from "react-dom";
12584
12714
  import { MediaContext as MediaContext3 } from "@bendyline/squisq-react";
12585
12715
 
12586
12716
  // src/scene/Scene.tsx
12587
12717
  import {
12588
12718
  useCallback as useCallback24,
12589
12719
  useEffect as useEffect22,
12590
- useLayoutEffect as useLayoutEffect4,
12720
+ useLayoutEffect as useLayoutEffect7,
12591
12721
  useMemo as useMemo20,
12592
12722
  useRef as useRef24,
12593
- useState as useState26
12723
+ useState as useState27
12594
12724
  } from "react";
12595
12725
 
12596
12726
  // src/scene/hooks/useScenePanZoom.ts
12597
- import { useCallback as useCallback19, useRef as useRef21, useState as useState23 } from "react";
12727
+ import { useCallback as useCallback19, useRef as useRef21, useState as useState24 } from "react";
12598
12728
 
12599
12729
  // src/scene/fitScale.ts
12600
12730
  function calculateFitScale(content, container, maxScale = 1) {
@@ -12609,7 +12739,7 @@ var IDENTITY_TRANSFORM = Object.freeze({ tx: 0, ty: 0, scale: 1 });
12609
12739
  var MIN_SCALE = 0.02;
12610
12740
  var MAX_SCALE = 8;
12611
12741
  function useScenePanZoom(initial = IDENTITY_TRANSFORM) {
12612
- const [transform, setTransformState] = useState23(initial);
12742
+ const [transform, setTransformState] = useState24(initial);
12613
12743
  const ref = useRef21(transform);
12614
12744
  ref.current = transform;
12615
12745
  const setTransform = useCallback19((t) => {
@@ -12678,9 +12808,9 @@ function clamp(n, lo, hi) {
12678
12808
  }
12679
12809
 
12680
12810
  // src/scene/hooks/useSceneSelection.ts
12681
- import { useCallback as useCallback20, useState as useState24 } from "react";
12811
+ import { useCallback as useCallback20, useState as useState25 } from "react";
12682
12812
  function useSceneSelection(initial = []) {
12683
- const [selection, setSelectionState] = useState24(() => new Set(initial));
12813
+ const [selection, setSelectionState] = useState25(() => new Set(initial));
12684
12814
  const setSelection = useCallback20((ids) => {
12685
12815
  setSelectionState(new Set(ids));
12686
12816
  }, []);
@@ -12770,7 +12900,7 @@ function anchorOffsets(anchor, w, h2) {
12770
12900
  }
12771
12901
 
12772
12902
  // src/scene/SceneViewport.tsx
12773
- import { forwardRef, useId as useId8 } from "react";
12903
+ import { forwardRef, useId as useId7 } from "react";
12774
12904
  import { jsx as jsx27, jsxs as jsxs22 } from "react/jsx-runtime";
12775
12905
  var BASE_GRID_STEP = 24;
12776
12906
  var MIN_SCREEN_STEP = 18;
@@ -12796,7 +12926,7 @@ var SceneViewport = forwardRef(function SceneViewport2({
12796
12926
  children
12797
12927
  }, ref) {
12798
12928
  const t = transform;
12799
- const gridId = `squisq-scene-dot-grid-${useId8().replace(/:/g, "")}`;
12929
+ const gridId = `squisq-scene-dot-grid-${useId7().replace(/:/g, "")}`;
12800
12930
  const grid = dotGrid(t.scale);
12801
12931
  const groupTransform = `translate(${t.tx} ${t.ty}) scale(${t.scale})`;
12802
12932
  return /* @__PURE__ */ jsxs22(
@@ -13086,9 +13216,9 @@ function rectIntersects(a, b) {
13086
13216
  }
13087
13217
 
13088
13218
  // src/scene/text/useSceneTextEditing.ts
13089
- import { useCallback as useCallback22, useRef as useRef22, useState as useState25 } from "react";
13219
+ import { useCallback as useCallback22, useRef as useRef22, useState as useState26 } from "react";
13090
13220
  function useSceneTextEditing(config3) {
13091
- const [editingId, setEditingId] = useState25(null);
13221
+ const [editingId, setEditingId] = useState26(null);
13092
13222
  const activeRef = useRef22(false);
13093
13223
  activeRef.current = editingId != null;
13094
13224
  const begin = useCallback22(
@@ -13287,7 +13417,7 @@ function Scene(props) {
13287
13417
  } = props;
13288
13418
  const layerRenderer = renderLayer ?? defaultRenderLayer;
13289
13419
  const textEdit = useSceneTextEditing(textEditing);
13290
- const [internalActiveId, setInternalActiveId] = useState26(tools[0]?.id ?? "select");
13420
+ const [internalActiveId, setInternalActiveId] = useState27(tools[0]?.id ?? "select");
13291
13421
  const activeId = controlledActiveId ?? internalActiveId;
13292
13422
  const setActiveTool = useCallback24(
13293
13423
  (id) => {
@@ -13302,7 +13432,7 @@ function Scene(props) {
13302
13432
  );
13303
13433
  const panZoom = useScenePanZoom();
13304
13434
  const { fitBox, zoomAt } = panZoom;
13305
- const [viewMode, setViewMode] = useState26("fit");
13435
+ const [viewMode, setViewMode] = useState27("fit");
13306
13436
  const selection = useSceneSelection();
13307
13437
  const setSceneSelection = selection.setSelection;
13308
13438
  const { hit } = useSceneHitTest();
@@ -13376,7 +13506,7 @@ function Scene(props) {
13376
13506
  },
13377
13507
  [panZoom]
13378
13508
  );
13379
- const [, setDragTick] = useState26(0);
13509
+ const [, setDragTick] = useState27(0);
13380
13510
  const pointerActive = useRef24(false);
13381
13511
  const bumpTick = useCallback24(() => setDragTick((t) => t + 1), []);
13382
13512
  const handlePointerDown = useCallback24(
@@ -13488,10 +13618,10 @@ function Scene(props) {
13488
13618
  root.addEventListener("keydown", onKey);
13489
13619
  return () => root.removeEventListener("keydown", onKey);
13490
13620
  }, [tools, activeTool, setActiveTool, textEdit.activeRef, bumpTick]);
13491
- const [containerSize, setContainerSize] = useState26(
13621
+ const [containerSize, setContainerSize] = useState27(
13492
13622
  null
13493
13623
  );
13494
- useLayoutEffect4(() => {
13624
+ useLayoutEffect7(() => {
13495
13625
  if (!containerRef.current) return;
13496
13626
  const el = containerRef.current;
13497
13627
  const measure = () => {
@@ -13710,10 +13840,10 @@ import { createElement as createElement6 } from "react";
13710
13840
  import { parsePandocAttrTokens as parsePandocAttrTokens6 } from "@bendyline/squisq/markdown";
13711
13841
 
13712
13842
  // src/scene/SceneBlockWidget.tsx
13713
- import { useEffect as useEffect26, useMemo as useMemo22, useRef as useRef28, useState as useState30 } from "react";
13843
+ import { useEffect as useEffect26, useMemo as useMemo22, useRef as useRef28, useState as useState31 } from "react";
13714
13844
 
13715
13845
  // src/scene/adapters/LayoutAdapter.ts
13716
- import { useEffect as useEffect23, useRef as useRef25, useState as useState27 } from "react";
13846
+ import { useEffect as useEffect23, useRef as useRef25, useState as useState28 } from "react";
13717
13847
  import { computeLayoutLayers } from "@bendyline/squisq/doc";
13718
13848
 
13719
13849
  // src/scene/adapters/blockLayers.ts
@@ -14052,7 +14182,7 @@ function stripBraces2(s) {
14052
14182
  // src/scene/adapters/LayoutAdapter.ts
14053
14183
  var SCENE_VIEWPORT = { width: 1920, height: 1080 };
14054
14184
  function useLayoutAdapter(editor, headingPos, options = {}) {
14055
- const [, setVersion] = useState27(0);
14185
+ const [, setVersion] = useState28(0);
14056
14186
  useEffect23(() => {
14057
14187
  const onUpdate = () => setVersion((v2) => v2 + 1);
14058
14188
  editor.on("transaction", onUpdate);
@@ -14259,7 +14389,7 @@ function nextLayoutId(editor, parentPos, kind) {
14259
14389
  }
14260
14390
 
14261
14391
  // src/scene/adapters/DrawingAdapter.ts
14262
- import { useCallback as useCallback25, useEffect as useEffect24, useMemo as useMemo21, useRef as useRef26, useState as useState28, createElement as createElement5 } from "react";
14392
+ import { useCallback as useCallback25, useEffect as useEffect24, useMemo as useMemo21, useRef as useRef26, useState as useState29, createElement as createElement5 } from "react";
14263
14393
  import { computeDrawingLayout } from "@bendyline/squisq/doc";
14264
14394
 
14265
14395
  // src/scene/tools/PathTool.ts
@@ -14915,7 +15045,7 @@ function createDrawShapeTool(options) {
14915
15045
  }
14916
15046
 
14917
15047
  // src/scene/layers/DiagramEdges.tsx
14918
- import { useId as useId9 } from "react";
15048
+ import { useId as useId8 } from "react";
14919
15049
  import { connectorPath, markerPath } from "@bendyline/squisq/doc";
14920
15050
  import { Fragment as Fragment9, jsx as jsx32, jsxs as jsxs26 } from "react/jsx-runtime";
14921
15051
  var MARKER_STYLES = ["arrow", "open", "diamond", "circle", "square"];
@@ -14930,7 +15060,7 @@ function DiagramEdges({
14930
15060
  onEdgeClick
14931
15061
  }) {
14932
15062
  const boxById = boxesOf(nodes);
14933
- const markerPrefix = useId9().replace(/:/g, "");
15063
+ const markerPrefix = useId8().replace(/:/g, "");
14934
15064
  const defaultRouting = variant === "straight" ? "straight" : "curved";
14935
15065
  return /* @__PURE__ */ jsxs26("g", { className: "squisq-scene-edges", children: [
14936
15066
  /* @__PURE__ */ jsx32("defs", { children: ["start", "end"].flatMap(
@@ -15179,7 +15309,7 @@ function headingText(node2) {
15179
15309
  // src/scene/adapters/DrawingAdapter.ts
15180
15310
  var ENDPOINT_HIT_RADIUS = 18;
15181
15311
  function useDrawingAdapter(editor, headingPos, options = {}) {
15182
- const [, setVersion] = useState28(0);
15312
+ const [, setVersion] = useState29(0);
15183
15313
  useEffect24(() => {
15184
15314
  const onUpdate = () => setVersion((v2) => v2 + 1);
15185
15315
  editor.on("transaction", onUpdate);
@@ -15211,7 +15341,7 @@ function useDrawingAdapter(editor, headingPos, options = {}) {
15211
15341
  ...c.dasharray ? { dasharray: c.dasharray } : {},
15212
15342
  routing: c.routing
15213
15343
  }));
15214
- const [selectedEdgeId, setSelectedEdgeId] = useState28(null);
15344
+ const [selectedEdgeId, setSelectedEdgeId] = useState29(null);
15215
15345
  const pendingKindRef = useRef26("rectangle");
15216
15346
  const setPendingKind = useCallback25((kind) => {
15217
15347
  pendingKindRef.current = kind;
@@ -15621,13 +15751,13 @@ function SceneBlockToolbar({
15621
15751
  }
15622
15752
 
15623
15753
  // src/scene/SceneSideToolbar.tsx
15624
- import { useLayoutEffect as useLayoutEffect5, useRef as useRef27, useState as useState29 } from "react";
15754
+ import { useLayoutEffect as useLayoutEffect8, useRef as useRef27, useState as useState30 } from "react";
15625
15755
  import { jsx as jsx35 } from "react/jsx-runtime";
15626
15756
  var SIDE_TOOLBAR_FIT_PX = 12 + 180 + 4;
15627
15757
  function SceneSideToolbar({ children }) {
15628
15758
  const wrapRef = useRef27(null);
15629
- const [collapsed, setCollapsed] = useState29(false);
15630
- useLayoutEffect5(() => {
15759
+ const [collapsed, setCollapsed] = useState30(false);
15760
+ useLayoutEffect8(() => {
15631
15761
  const wrap = wrapRef.current;
15632
15762
  if (!wrap) return;
15633
15763
  const shell = wrap.closest(".squisq-scene-shell");
@@ -15673,7 +15803,7 @@ function SceneSideToolbar({ children }) {
15673
15803
 
15674
15804
  // src/diagram/DiagramMaximizedOverlay.tsx
15675
15805
  import { useEffect as useEffect25 } from "react";
15676
- import { createPortal as createPortal8 } from "react-dom";
15806
+ import { createPortal as createPortal9 } from "react-dom";
15677
15807
  import { jsx as jsx36 } from "react/jsx-runtime";
15678
15808
  function DiagramMaximizedOverlay({ host, onClose, children }) {
15679
15809
  useEffect25(() => {
@@ -15690,7 +15820,7 @@ function DiagramMaximizedOverlay({ host, onClose, children }) {
15690
15820
  }, [onClose]);
15691
15821
  const target = host ?? (typeof document !== "undefined" ? document.body : null);
15692
15822
  if (!target) return null;
15693
- return createPortal8(
15823
+ return createPortal9(
15694
15824
  /* @__PURE__ */ jsx36("div", { className: "squisq-diagram-maximized-overlay", children: /* @__PURE__ */ jsx36("div", { className: "squisq-diagram-maximized-content", children }) }),
15695
15825
  target
15696
15826
  );
@@ -15711,7 +15841,7 @@ function SceneBlockWidget({
15711
15841
  host,
15712
15842
  textChannel
15713
15843
  }) {
15714
- const [parentPos, setParentPos] = useState30(
15844
+ const [parentPos, setParentPos] = useState31(
15715
15845
  () => findSceneHeadingPos(editor, headingKey, mode) ?? fallbackParentPos
15716
15846
  );
15717
15847
  useEffect26(() => {
@@ -15758,10 +15888,10 @@ function SceneBlockWidget({
15758
15888
  }),
15759
15889
  [isDrawing, textChannel]
15760
15890
  );
15761
- const [maximized, setMaximized] = useState30(false);
15762
- const [activeToolId, setActiveToolId] = useState30("select");
15763
- const [paletteOpen, setPaletteOpen] = useState30(false);
15764
- const [selectedLayerId, setSelectedLayerId] = useState30(null);
15891
+ const [maximized, setMaximized] = useState31(false);
15892
+ const [activeToolId, setActiveToolId] = useState31("select");
15893
+ const [paletteOpen, setPaletteOpen] = useState31(false);
15894
+ const [selectedLayerId, setSelectedLayerId] = useState31(null);
15765
15895
  const selectedShapeId = isDrawing && selectedLayerId ? shapeIdFromLayerId(selectedLayerId) : null;
15766
15896
  const canvas = /* @__PURE__ */ jsx37(
15767
15897
  Scene,
@@ -16402,9 +16532,9 @@ function buildDiagramScene(nodes, edges) {
16402
16532
  }
16403
16533
 
16404
16534
  // src/customTemplates/useMemoryLayerAdapter.ts
16405
- import { useCallback as useCallback26, useState as useState31 } from "react";
16535
+ import { useCallback as useCallback26, useState as useState32 } from "react";
16406
16536
  function useMemoryLayerAdapter(options) {
16407
- const [layers, setLayers] = useState31(() => options.initial ?? []);
16537
+ const [layers, setLayers] = useState32(() => options.initial ?? []);
16408
16538
  const dispatch = useCallback26((cmd) => {
16409
16539
  setLayers((current) => applyCommand(current, cmd));
16410
16540
  }, []);
@@ -17213,12 +17343,12 @@ function TemplateDesigner({
17213
17343
  }) {
17214
17344
  const overlayRef = useRef30(null);
17215
17345
  const dialogRef = useRef30(null);
17216
- const titleId = useId10();
17346
+ const titleId = useId9();
17217
17347
  useModalDialog({ rootRef: overlayRef, dialogRef, onClose });
17218
- const [name, setName] = useState32(initial?.name ?? "");
17219
- const [label, setLabel] = useState32(initial?.label ?? "");
17220
- const [description, setDescription] = useState32(initial?.description ?? "");
17221
- const [nameAutoDerived, setNameAutoDerived] = useState32(!initial?.name);
17348
+ const [name, setName] = useState33(initial?.name ?? "");
17349
+ const [label, setLabel] = useState33(initial?.label ?? "");
17350
+ const [description, setDescription] = useState33(initial?.description ?? "");
17351
+ const [nameAutoDerived, setNameAutoDerived] = useState33(!initial?.name);
17222
17352
  const handleLabelChange = useCallback27(
17223
17353
  (value) => {
17224
17354
  setLabel(value);
@@ -17238,7 +17368,7 @@ function TemplateDesigner({
17238
17368
  },
17239
17369
  [label]
17240
17370
  );
17241
- const [previewViewportId, setPreviewViewportId] = useState32(
17371
+ const [previewViewportId, setPreviewViewportId] = useState33(
17242
17372
  "landscape"
17243
17373
  );
17244
17374
  const tools = useMemo23(
@@ -17289,7 +17419,7 @@ function TemplateDesigner({
17289
17419
  },
17290
17420
  [adapter, addMediaBackgrounds]
17291
17421
  );
17292
- const [selectedLayerId, setSelectedLayerId] = useState32(null);
17422
+ const [selectedLayerId, setSelectedLayerId] = useState33(null);
17293
17423
  const selectedLayer = adapter.layers.find((l2) => l2.id === selectedLayerId) ?? null;
17294
17424
  const handleLayerAttr = useCallback27(
17295
17425
  (path, value) => {
@@ -17298,7 +17428,7 @@ function TemplateDesigner({
17298
17428
  },
17299
17429
  [adapter, selectedLayerId]
17300
17430
  );
17301
- const [activeToolId, setActiveToolId] = useState32("select");
17431
+ const [activeToolId, setActiveToolId] = useState33("select");
17302
17432
  const currentViewport = VIEWPORT_OPTIONS.find((v2) => v2.id === previewViewportId)?.viewport ?? DESIGN_CANVAS;
17303
17433
  const validate = () => {
17304
17434
  const slug = name.trim();
@@ -17465,7 +17595,7 @@ function TemplateDesigner({
17465
17595
  }
17466
17596
  );
17467
17597
  if (embedded) return panel;
17468
- return createPortal9(
17598
+ return createPortal10(
17469
17599
  /* @__PURE__ */ jsx41(
17470
17600
  "div",
17471
17601
  {
@@ -17489,9 +17619,9 @@ function CustomLayoutManager({ onClose }) {
17489
17619
  const { mediaProvider, colorScheme } = useEditorContext();
17490
17620
  const overlayRef = useRef31(null);
17491
17621
  const dialogRef = useRef31(null);
17492
- const titleId = useId11();
17622
+ const titleId = useId10();
17493
17623
  useModalDialog({ rootRef: overlayRef, dialogRef, onClose });
17494
- return createPortal10(
17624
+ return createPortal11(
17495
17625
  /* @__PURE__ */ jsx42(
17496
17626
  "div",
17497
17627
  {
@@ -17552,7 +17682,7 @@ function ManagerContent({
17552
17682
  mediaProvider
17553
17683
  }) {
17554
17684
  const { docTemplates, libraryTemplates, upsertDocTemplate, upsertLibraryTemplate } = ctx;
17555
- const [selection, setSelection] = useState33(() => {
17685
+ const [selection, setSelection] = useState34(() => {
17556
17686
  if (docTemplates[0]) return { source: "doc", name: docTemplates[0].name };
17557
17687
  if (libraryTemplates[0]) return { source: "library", name: libraryTemplates[0].name };
17558
17688
  return "new";
@@ -17623,10 +17753,10 @@ function ManagerContent({
17623
17753
  }
17624
17754
 
17625
17755
  // src/Toolbar.tsx
17626
- import { createPortal as createPortal11 } from "react-dom";
17756
+ import { createPortal as createPortal12 } from "react-dom";
17627
17757
 
17628
17758
  // src/toolbar/EditorViewTabs.tsx
17629
- import { useReducer } from "react";
17759
+ import { useEffect as useEffect27, useReducer, useState as useState35 } from "react";
17630
17760
 
17631
17761
  // src/platformShortcuts.ts
17632
17762
  function resolvePlatform(explicitPlatform) {
@@ -17638,6 +17768,20 @@ function platformShortcut(key, platform) {
17638
17768
  return /Mac|iPhone|iPad|iPod/i.test(resolvePlatform(platform)) ? `\u2318${key.replace("Shift+", "\u21E7")}` : `Ctrl+${key}`;
17639
17769
  }
17640
17770
 
17771
+ // src/viewTabKeyboard.ts
17772
+ function navigateViewTabs(event) {
17773
+ if (!["ArrowLeft", "ArrowRight", "Home", "End"].includes(event.key)) return null;
17774
+ const tabs = [
17775
+ ...event.currentTarget.closest('[role="tablist"]')?.querySelectorAll('[role="tab"]') ?? []
17776
+ ];
17777
+ if (!tabs.length) return null;
17778
+ event.preventDefault();
17779
+ const current = tabs.indexOf(event.currentTarget);
17780
+ const next = event.key === "Home" ? 0 : event.key === "End" ? tabs.length - 1 : (current + (event.key === "ArrowLeft" ? -1 : 1) + tabs.length) % tabs.length;
17781
+ tabs[next]?.focus();
17782
+ return next;
17783
+ }
17784
+
17641
17785
  // src/toolbar/EditorViewTabs.tsx
17642
17786
  import { Fragment as Fragment13, jsx as jsx43, jsxs as jsxs34 } from "react/jsx-runtime";
17643
17787
  var VIEWS = [
@@ -17650,6 +17794,8 @@ function EditorViewTabs({
17650
17794
  hostMode
17651
17795
  }) {
17652
17796
  const { editorMode, activeView, setActiveView } = useEditorContext();
17797
+ const [focusedView, setFocusedView] = useState35(activeView);
17798
+ useEffect27(() => setFocusedView(activeView), [activeView]);
17653
17799
  const previewSettings = usePreviewSettingsOptional();
17654
17800
  const [useModeMenuRequest, requestUseModeMenu] = useReducer((count) => count + 1, 0);
17655
17801
  const visibleViews = VIEWS.filter((v2) => {
@@ -17659,59 +17805,71 @@ function EditorViewTabs({
17659
17805
  return true;
17660
17806
  });
17661
17807
  const showViewTabs = visibleViews.length > 1;
17662
- return /* @__PURE__ */ jsx43(Fragment13, { children: showViewTabs && /* @__PURE__ */ jsx43("div", { className: "squisq-toolbar-view-tabs", role: "tablist", "aria-label": "Editor view", children: visibleViews.map((view) => {
17663
- const viewLabel = view.id === "preview" && previewSettings ? displayModeLabel(previewSettings.activeDisplayMode) : view.label;
17664
- const tab = /* @__PURE__ */ jsxs34(
17665
- "button",
17666
- {
17667
- role: "tab",
17668
- "data-view": view.id,
17669
- "aria-selected": activeView === view.id,
17670
- className: `squisq-toolbar-view-tab${activeView === view.id ? " squisq-toolbar-view-tab--active" : ""}`,
17671
- onClick: () => {
17672
- if (view.id === "preview" && activeView === "preview" && previewSettings) {
17673
- requestUseModeMenu();
17674
- return;
17675
- }
17676
- setActiveView(view.id);
17677
- },
17678
- "data-tooltip": `${viewLabel} (${platformShortcut(`Shift+${view.shortcutKey}`)})`,
17679
- children: [
17680
- /* @__PURE__ */ jsx43(
17681
- "span",
17682
- {
17683
- className: "squisq-toolbar-view-tab-label squisq-toolbar-view-tab-label--long",
17684
- "data-label": viewLabel,
17685
- children: viewLabel
17686
- }
17687
- ),
17688
- view.shortLabel && view.shortLabel !== view.label && /* @__PURE__ */ jsx43(
17689
- "span",
17690
- {
17691
- className: "squisq-toolbar-view-tab-label squisq-toolbar-view-tab-label--short",
17692
- "data-label": view.shortLabel,
17693
- children: view.shortLabel
17808
+ return /* @__PURE__ */ jsx43(Fragment13, { children: showViewTabs && /* @__PURE__ */ jsxs34("div", { className: "squisq-toolbar-view-tabs", children: [
17809
+ /* @__PURE__ */ jsx43("div", { className: "squisq-toolbar-view-tab-list", role: "tablist", "aria-label": "Editor view", children: visibleViews.map((view) => {
17810
+ const viewLabel = view.id === "preview" && previewSettings ? displayModeLabel(previewSettings.activeDisplayMode) : view.label;
17811
+ const tab = /* @__PURE__ */ jsxs34(
17812
+ "button",
17813
+ {
17814
+ type: "button",
17815
+ role: "tab",
17816
+ tabIndex: focusedView === view.id ? 0 : -1,
17817
+ onFocus: () => setFocusedView(view.id),
17818
+ "data-view": view.id,
17819
+ "aria-selected": activeView === view.id,
17820
+ onKeyDown: (event) => {
17821
+ navigateViewTabs(event);
17822
+ },
17823
+ className: `squisq-toolbar-view-tab${activeView === view.id ? " squisq-toolbar-view-tab--active" : ""}`,
17824
+ onClick: () => {
17825
+ if (view.id === "preview" && activeView === "preview" && previewSettings) {
17826
+ requestUseModeMenu();
17827
+ return;
17694
17828
  }
17695
- )
17696
- ]
17829
+ setActiveView(view.id);
17830
+ },
17831
+ "data-tooltip": `${viewLabel} (${platformShortcut(`Shift+${view.shortcutKey}`)})`,
17832
+ children: [
17833
+ /* @__PURE__ */ jsx43(
17834
+ "span",
17835
+ {
17836
+ className: "squisq-toolbar-view-tab-label squisq-toolbar-view-tab-label--long",
17837
+ "data-label": viewLabel,
17838
+ children: viewLabel
17839
+ }
17840
+ ),
17841
+ view.shortLabel && view.shortLabel !== view.label && /* @__PURE__ */ jsx43(
17842
+ "span",
17843
+ {
17844
+ className: "squisq-toolbar-view-tab-label squisq-toolbar-view-tab-label--short",
17845
+ "data-label": view.shortLabel,
17846
+ children: view.shortLabel
17847
+ }
17848
+ )
17849
+ ]
17850
+ }
17851
+ );
17852
+ if (view.id !== "preview" || !previewSettings) {
17853
+ return /* @__PURE__ */ jsx43("div", { className: "squisq-toolbar-view-tab-wrap", role: "presentation", children: tab }, view.id);
17697
17854
  }
17698
- );
17699
- if (view.id !== "preview" || !previewSettings) {
17700
- return /* @__PURE__ */ jsx43("div", { className: "squisq-toolbar-view-tab-wrap", role: "presentation", children: tab }, view.id);
17701
- }
17702
- return /* @__PURE__ */ jsxs34(
17855
+ return /* @__PURE__ */ jsx43(
17856
+ "div",
17857
+ {
17858
+ className: `squisq-toolbar-view-tab-wrap squisq-toolbar-use-tab${activeView === "preview" ? " squisq-toolbar-use-tab--active" : ""}`,
17859
+ role: "presentation",
17860
+ children: tab
17861
+ },
17862
+ view.id
17863
+ );
17864
+ }) }),
17865
+ previewSettings && visibleViews.some((view) => view.id === "preview") && /* @__PURE__ */ jsx43(
17703
17866
  "div",
17704
17867
  {
17705
- className: `squisq-toolbar-view-tab-wrap squisq-toolbar-use-tab${activeView === "preview" ? " squisq-toolbar-use-tab--active" : ""}`,
17706
- role: "presentation",
17707
- children: [
17708
- tab,
17709
- /* @__PURE__ */ jsx43(PreviewModeMenu, { openRequest: useModeMenuRequest })
17710
- ]
17711
- },
17712
- view.id
17713
- );
17714
- }) }) });
17868
+ className: `squisq-toolbar-use-menu${activeView === "preview" ? " squisq-toolbar-use-tab--active" : ""}`,
17869
+ children: /* @__PURE__ */ jsx43(PreviewModeMenu, { openRequest: useModeMenuRequest })
17870
+ }
17871
+ )
17872
+ ] }) });
17715
17873
  }
17716
17874
 
17717
17875
  // src/mediaEntries.ts
@@ -17735,7 +17893,7 @@ function filterVisibleMediaEntries(entries) {
17735
17893
  }
17736
17894
 
17737
17895
  // src/videoEmbed/useVideoEmbedDialog.tsx
17738
- import { useCallback as useCallback29, useState as useState34 } from "react";
17896
+ import { useCallback as useCallback29, useState as useState36 } from "react";
17739
17897
  import { findBlockVideoEmbed, parseMarkdown as parseMarkdown4 } from "@bendyline/squisq/markdown";
17740
17898
  import { jsx as jsx44 } from "react/jsx-runtime";
17741
17899
  function isBlank(line) {
@@ -17774,7 +17932,7 @@ function videoEmbedAtCaret(activeView, tiptapEditor, monacoEditor) {
17774
17932
  }
17775
17933
  function useVideoEmbedDialog() {
17776
17934
  const { activeView, tiptapEditor, monacoEditor, insertAtCursor } = useEditorContext();
17777
- const [state, setState3] = useState34(null);
17935
+ const [state, setState3] = useState36(null);
17778
17936
  const open = useCallback29(() => {
17779
17937
  setState3(
17780
17938
  videoEmbedAtCaret(activeView, tiptapEditor, monacoEditor) ?? {
@@ -17934,7 +18092,7 @@ function selectionToTaskListMarkdown(text) {
17934
18092
  }
17935
18093
 
17936
18094
  // src/find/FindToolbar.tsx
17937
- import { useCallback as useCallback30, useEffect as useEffect27, useId as useId12, useRef as useRef32, useState as useState35 } from "react";
18095
+ import { useCallback as useCallback30, useEffect as useEffect28, useId as useId11, useRef as useRef32, useState as useState37 } from "react";
17938
18096
 
17939
18097
  // src/find/FindHighlightExtension.ts
17940
18098
  import { Extension as Extension3 } from "@tiptap/core";
@@ -18100,18 +18258,18 @@ function FindToolbar({
18100
18258
  focusRequest = 0
18101
18259
  }) {
18102
18260
  const { activeView, markdownSource, tiptapEditor, monacoEditor, findRequest } = useEditorContext();
18103
- const [initial] = useState35(
18261
+ const [initial] = useState37(
18104
18262
  () => initialFindState(findRequest, activeView, tiptapEditor, monacoEditor)
18105
18263
  );
18106
- const [query, setQuery] = useState35(initial.query);
18107
- const [matchCase, setMatchCase] = useState35(initial.matchCase ?? false);
18108
- const [wholeWord, setWholeWord] = useState35(initial.wholeWord ?? false);
18109
- const [selectedIndex, setSelectedIndex] = useState35(initial.occurrence ?? 0);
18110
- const [matchCount, setMatchCount] = useState35(0);
18111
- const [replacement, setReplacement] = useState35("");
18264
+ const [query, setQuery] = useState37(initial.query);
18265
+ const [matchCase, setMatchCase] = useState37(initial.matchCase ?? false);
18266
+ const [wholeWord, setWholeWord] = useState37(initial.wholeWord ?? false);
18267
+ const [selectedIndex, setSelectedIndex] = useState37(initial.occurrence ?? 0);
18268
+ const [matchCount, setMatchCount] = useState37(0);
18269
+ const [replacement, setReplacement] = useState37("");
18112
18270
  const inputRef = useRef32(null);
18113
18271
  const replaceInputRef = useRef32(null);
18114
- const reactId = useId12().replace(/[^a-zA-Z0-9_-]/g, "");
18272
+ const reactId = useId11().replace(/[^a-zA-Z0-9_-]/g, "");
18115
18273
  const previewHighlightName = `squisq-find-${reactId}`;
18116
18274
  const previewSelectedName = `${previewHighlightName}-selected`;
18117
18275
  const canReplace = allowReplace && activeView !== "preview";
@@ -18119,15 +18277,15 @@ function FindToolbar({
18119
18277
  const options = { matchCase, wholeWord };
18120
18278
  const lastNavigationRef = useRef32("");
18121
18279
  const pendingRevealRef = useRef32(false);
18122
- useEffect27(() => {
18280
+ useEffect28(() => {
18123
18281
  inputRef.current?.focus();
18124
18282
  inputRef.current?.select();
18125
18283
  }, [focusRequest]);
18126
- useEffect27(() => {
18284
+ useEffect28(() => {
18127
18285
  if (showReplace) replaceInputRef.current?.focus();
18128
18286
  }, [showReplace, focusRequest]);
18129
18287
  const appliedRequestRef = useRef32(findRequest);
18130
- useEffect27(() => {
18288
+ useEffect28(() => {
18131
18289
  if (!findRequest || findRequest === appliedRequestRef.current) return;
18132
18290
  appliedRequestRef.current = findRequest;
18133
18291
  setQuery(findRequest.query);
@@ -18135,14 +18293,14 @@ function FindToolbar({
18135
18293
  setWholeWord(findRequest.wholeWord ?? false);
18136
18294
  setSelectedIndex(findRequest.occurrence ?? 0);
18137
18295
  }, [findRequest]);
18138
- useEffect27(() => {
18296
+ useEffect28(() => {
18139
18297
  const style = document.createElement("style");
18140
18298
  style.dataset.squisqFindHighlight = reactId;
18141
18299
  style.textContent = `::highlight(${previewHighlightName}) { background: var(--squisq-find-match, #fde68a); color: inherit; } ::highlight(${previewSelectedName}) { background: var(--squisq-find-match-current, #f59e0b); color: var(--squisq-find-match-text, #111827); }`;
18142
18300
  document.head.append(style);
18143
18301
  return () => style.remove();
18144
18302
  }, [previewHighlightName, previewSelectedName, reactId]);
18145
- useEffect27(() => {
18303
+ useEffect28(() => {
18146
18304
  let cleanup = () => {
18147
18305
  };
18148
18306
  let count = 0;
@@ -19363,15 +19521,15 @@ function Toolbar({
19363
19521
  insertAtCursor
19364
19522
  } = useEditorContext();
19365
19523
  const previewSettings = usePreviewSettingsOptional();
19366
- const [recorderOpen, setRecorderOpen] = useState36(false);
19367
- const [docNarrationOpen, setDocNarrationOpen] = useState36(false);
19524
+ const [recorderOpen, setRecorderOpen] = useState38(false);
19525
+ const [docNarrationOpen, setDocNarrationOpen] = useState38(false);
19368
19526
  const formattingEditor = activeSceneText?.editor ?? tiptapEditor;
19369
19527
  const sceneTextLevel = activeSceneText?.level ?? null;
19370
19528
  const isCodeMode = editorMode === "code";
19371
19529
  const showDocumentChrome = !isCodeMode && hostMode !== "chat";
19372
- const [scannedFileCount, setScannedFileCount] = useState36(0);
19530
+ const [scannedFileCount, setScannedFileCount] = useState38(0);
19373
19531
  const resolvedFileCount = fileCount ?? scannedFileCount;
19374
- useEffect28(() => {
19532
+ useEffect29(() => {
19375
19533
  if (fileCount !== void 0) return;
19376
19534
  if (!mediaProvider) {
19377
19535
  setScannedFileCount(0);
@@ -19392,10 +19550,10 @@ function Toolbar({
19392
19550
  }, [fileCount, mediaProvider, mediaRevision, showFiles]);
19393
19551
  const imageInputRef = useRef33(null);
19394
19552
  const fileInputRef = useRef33(null);
19395
- const [linkDialog, setLinkDialog] = useState36(null);
19553
+ const [linkDialog, setLinkDialog] = useState38(null);
19396
19554
  const { open: openVideoEmbedDialog, element: videoEmbedDialog } = useVideoEmbedDialog();
19397
19555
  const emojiButtonRef = useRef33(null);
19398
- const [emojiPickerAnchor, setEmojiPickerAnchor] = useState36(null);
19556
+ const [emojiPickerAnchor, setEmojiPickerAnchor] = useState38(null);
19399
19557
  const openEmojiPicker = useCallback31(() => {
19400
19558
  const btn = emojiButtonRef.current;
19401
19559
  if (!btn) return;
@@ -19424,10 +19582,10 @@ function Toolbar({
19424
19582
  const mermaidTypeMenuRef = useRef33(null);
19425
19583
  const chartTypeMenuRef = useRef33(null);
19426
19584
  const insertMenuTriggerRectRef = useRef33(null);
19427
- const [insertMenuAnchor, setInsertMenuAnchor] = useState36(null);
19428
- const [codeSnippetMenuAnchor, setCodeSnippetMenuAnchor] = useState36(null);
19429
- const [mermaidTypeMenuAnchor, setMermaidTypeMenuAnchor] = useState36(null);
19430
- const [chartTypeMenuAnchor, setChartTypeMenuAnchor] = useState36(null);
19585
+ const [insertMenuAnchor, setInsertMenuAnchor] = useState38(null);
19586
+ const [codeSnippetMenuAnchor, setCodeSnippetMenuAnchor] = useState38(null);
19587
+ const [mermaidTypeMenuAnchor, setMermaidTypeMenuAnchor] = useState38(null);
19588
+ const [chartTypeMenuAnchor, setChartTypeMenuAnchor] = useState38(null);
19431
19589
  const openInsertMenu = useCallback31((trigger) => {
19432
19590
  const btn = trigger ?? insertMenuButtonRef.current;
19433
19591
  if (!btn) return;
@@ -19502,30 +19660,36 @@ function Toolbar({
19502
19660
  setChartTypeMenuAnchor(null);
19503
19661
  }, []);
19504
19662
  const actionsRef = useRef33(null);
19505
- const [collapsedKey, setCollapsedKey] = useState36("");
19506
- const [clippedContextualKey, setClippedContextualKey] = useState36("");
19663
+ const [collapsedKey, setCollapsedKey] = useState38("");
19664
+ const [clippedContextualKey, setClippedContextualKey] = useState38("");
19507
19665
  const itemWidthsRef = useRef33(/* @__PURE__ */ new Map());
19508
19666
  const chromeOnLaneRowRef = useRef33(/* @__PURE__ */ new Map());
19509
19667
  const collapsedCountRef = useRef33(0);
19510
- const [showOverflow, setShowOverflow] = useState36(false);
19668
+ const [showOverflow, setShowOverflow] = useState38(false);
19511
19669
  const overflowRef = useRef33(null);
19670
+ const overflowMenuRef = useRef33(null);
19671
+ const overflowStyle = useAnchoredPopover(showOverflow, overflowTriggerRef, overflowMenuRef);
19672
+ useLayoutEffect9(() => {
19673
+ if (showOverflow && overflowStyle.visibility === "visible")
19674
+ overflowMenuRef.current?.querySelector("button:not(:disabled)")?.focus();
19675
+ }, [showOverflow, overflowStyle.visibility]);
19512
19676
  useEscapeDismissal(showOverflow, () => setShowOverflow(false), overflowTriggerRef);
19513
19677
  useEscapeDismissal(insertMenuAnchor !== null, closeInsertMenu, insertMenuReturnFocusRef);
19514
- const [showDocSettings, setShowDocSettings] = useState36(false);
19515
- const [showLayoutManager, setShowLayoutManager] = useState36(false);
19516
- useEffect28(() => {
19678
+ const [showDocSettings, setShowDocSettings] = useState38(false);
19679
+ const [showLayoutManager, setShowLayoutManager] = useState38(false);
19680
+ useEffect29(() => {
19517
19681
  if (!findMode) return;
19518
19682
  setShowOverflow(false);
19519
19683
  closeInsertMenu();
19520
19684
  closeEmojiPicker();
19521
19685
  }, [closeEmojiPicker, closeInsertMenu, findMode]);
19522
19686
  const toolbarRootRef = useRef33(null);
19523
- const [replaceOpen, setReplaceOpen] = useState36(false);
19524
- const [findFocusRequest, setFindFocusRequest] = useState36(0);
19525
- useEffect28(() => {
19687
+ const [replaceOpen, setReplaceOpen] = useState38(false);
19688
+ const [findFocusRequest, setFindFocusRequest] = useState38(0);
19689
+ useEffect29(() => {
19526
19690
  if (!findMode) setReplaceOpen(false);
19527
19691
  }, [findMode]);
19528
- useEffect28(() => {
19692
+ useEffect29(() => {
19529
19693
  if (!findShortcut || editorMode === "image") return;
19530
19694
  const apple = isApplePlatform();
19531
19695
  const onKeyDown = (event) => {
@@ -19550,7 +19714,7 @@ function Toolbar({
19550
19714
  const clippedContextual = new Set(
19551
19715
  actionsLaneShown && clippedContextualKey ? clippedContextualKey.split("|") : []
19552
19716
  );
19553
- useEffect28(() => {
19717
+ useEffect29(() => {
19554
19718
  const container = actionsRef.current;
19555
19719
  if (!container) return;
19556
19720
  const toolbar = container.parentElement;
@@ -19655,11 +19819,12 @@ function Toolbar({
19655
19819
  mo.disconnect();
19656
19820
  };
19657
19821
  }, [activeView, actionsLaneShown]);
19658
- useEffect28(() => {
19822
+ useEffect29(() => {
19659
19823
  if (!showOverflow) return;
19660
19824
  const handleClick = (e2) => {
19661
19825
  const target = e2.target;
19662
- if (overflowRef.current?.contains(target)) return;
19826
+ if (overflowRef.current?.contains(target) || overflowMenuRef.current?.contains(target))
19827
+ return;
19663
19828
  if (target instanceof Element && target.closest(`${TEMPLATE_GALLERY_PORTAL_SELECTOR}, #${TRANSITION_FLYOUT_PORTAL_ID}`)) {
19664
19829
  return;
19665
19830
  }
@@ -19668,7 +19833,7 @@ function Toolbar({
19668
19833
  document.addEventListener("mousedown", handleClick);
19669
19834
  return () => document.removeEventListener("mousedown", handleClick);
19670
19835
  }, [showOverflow]);
19671
- useEffect28(() => {
19836
+ useEffect29(() => {
19672
19837
  if (!insertMenuAnchor) return;
19673
19838
  const handleClick = (e2) => {
19674
19839
  if (insertMenuButtonRef.current?.contains(e2.target)) return;
@@ -19682,7 +19847,7 @@ function Toolbar({
19682
19847
  return () => document.removeEventListener("mousedown", handleClick);
19683
19848
  }, [insertMenuAnchor, closeInsertMenu]);
19684
19849
  const insertMenuOpen = insertMenuAnchor !== null;
19685
- useLayoutEffect6(() => {
19850
+ useLayoutEffect9(() => {
19686
19851
  if (!insertMenuOpen) return;
19687
19852
  const menu = insertMenuRef.current;
19688
19853
  const triggerRect = insertMenuTriggerRectRef.current;
@@ -19703,25 +19868,8 @@ function Toolbar({
19703
19868
  return { ...current, top, maxHeight, placement };
19704
19869
  });
19705
19870
  }, [insertMenuOpen]);
19706
- const [overflowPlacement, setOverflowPlacement] = useState36("down");
19707
- useEffect28(() => {
19708
- if (!showOverflow || !overflowRef.current) return;
19709
- const trigger = overflowRef.current.querySelector(
19710
- ".squisq-toolbar-overflow-trigger"
19711
- );
19712
- if (!trigger) return;
19713
- const rect = trigger.getBoundingClientRect();
19714
- const spaceBelow = window.innerHeight - rect.bottom;
19715
- const spaceAbove = rect.top;
19716
- const ESTIMATED_MENU_HEIGHT = 260;
19717
- if (spaceBelow < ESTIMATED_MENU_HEIGHT && spaceAbove > spaceBelow) {
19718
- setOverflowPlacement("up");
19719
- } else {
19720
- setOverflowPlacement("down");
19721
- }
19722
- }, [showOverflow]);
19723
19871
  const [, forceUpdate] = useReducer2((c) => c + 1, 0);
19724
- useEffect28(() => {
19872
+ useEffect29(() => {
19725
19873
  if (!formattingEditor) return;
19726
19874
  formattingEditor.on("transaction", forceUpdate);
19727
19875
  return () => {
@@ -20326,7 +20474,7 @@ ${TASK_LIST_MARKDOWN}
20326
20474
  },
20327
20475
  [activeView, tiptapEditor, monacoEditor, markdownSource, setMarkdownSource, closeEmojiPicker]
20328
20476
  );
20329
- useEffect28(() => {
20477
+ useEffect29(() => {
20330
20478
  const onKeyDown = (e2) => {
20331
20479
  if (!(e2.ctrlKey || e2.metaKey) || e2.altKey || e2.shiftKey) return;
20332
20480
  if (e2.key.toLowerCase() !== "k") return;
@@ -20416,8 +20564,8 @@ ${TASK_LIST_MARKDOWN}
20416
20564
  "emoji"
20417
20565
  ]);
20418
20566
  const BLOCK_SCENE_BUTTONS = /* @__PURE__ */ new Set([...INLINE_SCENE_BUTTONS, "ul", "ol", "quote", "codeblock"]);
20419
- const [dataCardFocused, setDataCardFocused] = useState36(false);
20420
- useEffect28(() => {
20567
+ const [dataCardFocused, setDataCardFocused] = useState38(false);
20568
+ useEffect29(() => {
20421
20569
  let timer = null;
20422
20570
  const update = () => {
20423
20571
  if (timer !== null) clearTimeout(timer);
@@ -20476,10 +20624,10 @@ ${TASK_LIST_MARKDOWN}
20476
20624
  const isInTable = isWysiwyg ? tiptapEditor.isActive("table") : false;
20477
20625
  const wysiwygTemplate = isWysiwyg ? tiptapEditor.isActive("heading") ? tiptapEditor.getAttributes("heading")?.dataTemplate ?? "" : null : null;
20478
20626
  const isRawView = activeView === "raw";
20479
- const [rawTemplate, setRawTemplate] = useState36(null);
20480
- const [rawHeadingLine, setRawHeadingLine] = useState36(null);
20481
- const [rawTransition, setRawTransition] = useState36(EMPTY_TRANSITION);
20482
- useEffect28(() => {
20627
+ const [rawTemplate, setRawTemplate] = useState38(null);
20628
+ const [rawHeadingLine, setRawHeadingLine] = useState38(null);
20629
+ const [rawTransition, setRawTransition] = useState38(EMPTY_TRANSITION);
20630
+ useEffect29(() => {
20483
20631
  if (!isRawView || !monacoEditor) {
20484
20632
  setRawTemplate(null);
20485
20633
  setRawHeadingLine(null);
@@ -20528,8 +20676,8 @@ ${TASK_LIST_MARKDOWN}
20528
20676
  contentSub.dispose();
20529
20677
  };
20530
20678
  }, [isRawView, monacoEditor]);
20531
- const [wysiwygHeadingIndex, setWysiwygHeadingIndex] = useState36(null);
20532
- useEffect28(() => {
20679
+ const [wysiwygHeadingIndex, setWysiwygHeadingIndex] = useState38(null);
20680
+ useEffect29(() => {
20533
20681
  if (!isWysiwyg || !tiptapEditor) {
20534
20682
  setWysiwygHeadingIndex(null);
20535
20683
  return;
@@ -21052,193 +21200,199 @@ ${TASK_LIST_MARKDOWN}
21052
21200
  children: "\xB7\xB7\xB7"
21053
21201
  }
21054
21202
  ),
21055
- showOverflow && /* @__PURE__ */ jsxs37(
21056
- "div",
21057
- {
21058
- className: `squisq-toolbar-overflow-menu squisq-toolbar-overflow-menu--${overflowPlacement}`,
21059
- children: [
21060
- collapsedFormatButtons.map((btn) => {
21061
- const active = btn.id === "emoji" ? emojiPickerAnchor !== null : formatActive && formattingEditor ? isTiptapActive(formattingEditor, btn.id) : false;
21062
- const disabled = FILE_STORING_BUTTONS.has(btn.id) && !mediaProvider || !buttonAllowed(btn.id);
21063
- return /* @__PURE__ */ jsxs37(
21203
+ showOverflow && createPortal12(
21204
+ /* @__PURE__ */ jsxs37(
21205
+ "div",
21206
+ {
21207
+ ref: overflowMenuRef,
21208
+ className: "squisq-toolbar-overflow-menu",
21209
+ "data-theme": colorScheme,
21210
+ style: overflowStyle,
21211
+ children: [
21212
+ collapsedFormatButtons.map((btn) => {
21213
+ const active = btn.id === "emoji" ? emojiPickerAnchor !== null : formatActive && formattingEditor ? isTiptapActive(formattingEditor, btn.id) : false;
21214
+ const disabled = FILE_STORING_BUTTONS.has(btn.id) && !mediaProvider || !buttonAllowed(btn.id);
21215
+ return /* @__PURE__ */ jsxs37(
21216
+ "button",
21217
+ {
21218
+ ref: btn.id === "emoji" ? emojiButtonRef : void 0,
21219
+ className: `squisq-toolbar-overflow-item${active ? " squisq-toolbar-overflow-item--active" : ""}`,
21220
+ onClick: () => {
21221
+ handleAction(btn.id);
21222
+ if (btn.id !== "emoji") setShowOverflow(false);
21223
+ },
21224
+ disabled,
21225
+ children: [
21226
+ /* @__PURE__ */ jsx48("span", { className: "squisq-toolbar-overflow-icon", children: buttonIcon(btn) }),
21227
+ /* @__PURE__ */ jsx48("span", { children: btn.title })
21228
+ ]
21229
+ },
21230
+ btn.id
21231
+ );
21232
+ }),
21233
+ showInsertInOverflow && /* @__PURE__ */ jsxs37(
21064
21234
  "button",
21065
21235
  {
21066
- ref: btn.id === "emoji" ? emojiButtonRef : void 0,
21067
- className: `squisq-toolbar-overflow-item${active ? " squisq-toolbar-overflow-item--active" : ""}`,
21068
- onClick: () => {
21069
- handleAction(btn.id);
21070
- if (btn.id !== "emoji") setShowOverflow(false);
21236
+ className: `squisq-toolbar-overflow-item${insertMenuAnchor ? " squisq-toolbar-overflow-item--active" : ""}`,
21237
+ onClick: (event) => {
21238
+ if (insertMenuAnchor) {
21239
+ closeInsertMenu();
21240
+ } else {
21241
+ openInsertMenu(event.currentTarget);
21242
+ }
21243
+ setShowOverflow(false);
21071
21244
  },
21072
- disabled,
21245
+ "aria-haspopup": "menu",
21246
+ "aria-expanded": insertMenuAnchor !== null,
21073
21247
  children: [
21074
- /* @__PURE__ */ jsx48("span", { className: "squisq-toolbar-overflow-icon", children: buttonIcon(btn) }),
21075
- /* @__PURE__ */ jsx48("span", { children: btn.title })
21248
+ /* @__PURE__ */ jsx48("span", { className: "squisq-toolbar-overflow-icon", children: /* @__PURE__ */ jsx48(Icon, { icon: "fa-solid fa-plus" }) }),
21249
+ /* @__PURE__ */ jsx48("span", { children: "Insert..." })
21076
21250
  ]
21077
- },
21078
- btn.id
21079
- );
21080
- }),
21081
- showInsertInOverflow && /* @__PURE__ */ jsxs37(
21082
- "button",
21083
- {
21084
- className: `squisq-toolbar-overflow-item${insertMenuAnchor ? " squisq-toolbar-overflow-item--active" : ""}`,
21085
- onClick: (event) => {
21086
- if (insertMenuAnchor) {
21087
- closeInsertMenu();
21088
- } else {
21089
- openInsertMenu(event.currentTarget);
21090
- }
21091
- setShowOverflow(false);
21092
- },
21093
- "aria-haspopup": "menu",
21094
- "aria-expanded": insertMenuAnchor !== null,
21095
- children: [
21096
- /* @__PURE__ */ jsx48("span", { className: "squisq-toolbar-overflow-icon", children: /* @__PURE__ */ jsx48(Icon, { icon: "fa-solid fa-plus" }) }),
21097
- /* @__PURE__ */ jsx48("span", { children: "Insert..." })
21098
- ]
21099
- }
21100
- ),
21101
- collapsedChrome.length > 0 && (collapsedFormatButtons.length > 0 || showInsertInOverflow) && /* @__PURE__ */ jsx48(
21102
- "div",
21103
- {
21104
- className: "squisq-toolbar-separator",
21105
- style: { margin: "4px 0", width: "100%", height: 1 }
21106
- }
21107
- ),
21108
- collapsedChrome.includes("layouts") && /* @__PURE__ */ jsxs37(
21109
- "button",
21110
- {
21111
- className: "squisq-toolbar-overflow-item",
21112
- onClick: () => {
21113
- setShowLayoutManager(true);
21114
- setShowOverflow(false);
21115
- },
21116
- children: [
21117
- /* @__PURE__ */ jsx48("span", { className: "squisq-toolbar-overflow-icon", children: /* @__PURE__ */ jsx48(Icon, { icon: "fa-solid fa-shapes" }) }),
21118
- /* @__PURE__ */ jsx48("span", { children: "Custom layouts" })
21119
- ]
21120
- }
21121
- ),
21122
- collapsedChrome.includes("docSettings") && /* @__PURE__ */ jsxs37(
21123
- "button",
21124
- {
21125
- className: "squisq-toolbar-overflow-item",
21126
- onClick: () => {
21127
- setShowDocSettings(true);
21128
- setShowOverflow(false);
21129
- },
21130
- children: [
21131
- /* @__PURE__ */ jsx48("span", { className: "squisq-toolbar-overflow-icon", children: /* @__PURE__ */ jsx48(Icon, { icon: "fa-solid fa-file-lines" }) }),
21132
- /* @__PURE__ */ jsx48("span", { children: "Document settings" })
21133
- ]
21134
- }
21135
- ),
21136
- collapsedChrome.includes("files") && onToggleFiles && /* @__PURE__ */ jsxs37(
21137
- "button",
21138
- {
21139
- className: `squisq-toolbar-overflow-item${showFiles ? " squisq-toolbar-overflow-item--active" : ""}`,
21140
- "aria-pressed": showFiles,
21141
- onClick: () => {
21142
- onToggleFiles();
21143
- setShowOverflow(false);
21144
- },
21145
- children: [
21146
- /* @__PURE__ */ jsx48("span", { className: "squisq-toolbar-overflow-icon", children: /* @__PURE__ */ jsx48(Icon, { icon: "fa-solid fa-paperclip" }) }),
21147
- /* @__PURE__ */ jsxs37("span", { children: [
21148
- showFiles ? "Hide" : "Show",
21149
- " Files panel",
21150
- resolvedFileCount > 0 ? ` (${fileCountLabel(resolvedFileCount)})` : ""
21151
- ] })
21152
- ]
21153
- }
21154
- ),
21155
- showBlockSectionInOverflow && /* @__PURE__ */ jsxs37(Fragment17, { children: [
21156
- /* @__PURE__ */ jsx48(
21157
- "div",
21158
- {
21159
- className: "squisq-toolbar-separator",
21160
- style: { margin: "4px 0", width: "100%", height: 1 }
21161
21251
  }
21162
21252
  ),
21163
- /* @__PURE__ */ jsxs37("div", { className: "squisq-toolbar-overflow-heading", children: [
21164
- overflowBlockLabel,
21165
- " Block:"
21166
- ] })
21167
- ] }),
21168
- showTemplateInOverflow && /* @__PURE__ */ jsx48("div", { className: "squisq-toolbar-overflow-item squisq-toolbar-overflow-template", children: /* @__PURE__ */ jsx48(
21169
- TemplatePicker,
21170
- {
21171
- value: currentTemplate,
21172
- onChange: (v2) => {
21173
- handleTemplatePick(v2);
21174
- setShowOverflow(false);
21175
- },
21176
- colorScheme,
21177
- recommended: recommendedTemplates,
21178
- previewSource: templatePreviewSource
21179
- }
21180
- ) }),
21181
- showTransitionInOverflow && /* @__PURE__ */ jsx48("div", { className: "squisq-toolbar-overflow-item squisq-toolbar-overflow-template", children: /* @__PURE__ */ jsx48(
21182
- TransitionPicker,
21183
- {
21184
- value: currentTransition,
21185
- onChange: handleTransitionPick,
21186
- colorScheme,
21187
- accentColor: previewSettings?.activeTheme.colors.primary
21188
- }
21189
- ) }),
21190
- showFormattingControls && isInTable && clippedContextual.has("table") && /* @__PURE__ */ jsxs37(Fragment17, { children: [
21191
- /* @__PURE__ */ jsx48(
21253
+ collapsedChrome.length > 0 && (collapsedFormatButtons.length > 0 || showInsertInOverflow) && /* @__PURE__ */ jsx48(
21192
21254
  "div",
21193
21255
  {
21194
21256
  className: "squisq-toolbar-separator",
21195
21257
  style: { margin: "4px 0", width: "100%", height: 1 }
21196
21258
  }
21197
21259
  ),
21198
- [
21199
- {
21200
- label: "Add column before",
21201
- action: () => tiptapEditor.chain().focus().addColumnBefore().run()
21202
- },
21203
- {
21204
- label: "Add column after",
21205
- action: () => tiptapEditor.chain().focus().addColumnAfter().run()
21206
- },
21207
- {
21208
- label: "Delete column",
21209
- action: () => tiptapEditor.chain().focus().deleteColumn().run()
21210
- },
21211
- {
21212
- label: "Add row above",
21213
- action: () => tiptapEditor.chain().focus().addRowBefore().run()
21214
- },
21215
- {
21216
- label: "Add row below",
21217
- action: () => tiptapEditor.chain().focus().addRowAfter().run()
21218
- },
21260
+ collapsedChrome.includes("layouts") && /* @__PURE__ */ jsxs37(
21261
+ "button",
21219
21262
  {
21220
- label: "Delete row",
21221
- action: () => tiptapEditor.chain().focus().deleteRow().run()
21222
- },
21263
+ className: "squisq-toolbar-overflow-item",
21264
+ onClick: () => {
21265
+ setShowLayoutManager(true);
21266
+ setShowOverflow(false);
21267
+ },
21268
+ children: [
21269
+ /* @__PURE__ */ jsx48("span", { className: "squisq-toolbar-overflow-icon", children: /* @__PURE__ */ jsx48(Icon, { icon: "fa-solid fa-shapes" }) }),
21270
+ /* @__PURE__ */ jsx48("span", { children: "Custom layouts" })
21271
+ ]
21272
+ }
21273
+ ),
21274
+ collapsedChrome.includes("docSettings") && /* @__PURE__ */ jsxs37(
21275
+ "button",
21223
21276
  {
21224
- label: "Delete table",
21225
- action: () => tiptapEditor.chain().focus().deleteTable().run()
21277
+ className: "squisq-toolbar-overflow-item",
21278
+ onClick: () => {
21279
+ setShowDocSettings(true);
21280
+ setShowOverflow(false);
21281
+ },
21282
+ children: [
21283
+ /* @__PURE__ */ jsx48("span", { className: "squisq-toolbar-overflow-icon", children: /* @__PURE__ */ jsx48(Icon, { icon: "fa-solid fa-file-lines" }) }),
21284
+ /* @__PURE__ */ jsx48("span", { children: "Document settings" })
21285
+ ]
21226
21286
  }
21227
- ].map((item) => /* @__PURE__ */ jsx48(
21287
+ ),
21288
+ collapsedChrome.includes("files") && onToggleFiles && /* @__PURE__ */ jsxs37(
21228
21289
  "button",
21229
21290
  {
21230
- className: `squisq-toolbar-overflow-item${item.label.startsWith("Delete") ? " squisq-toolbar-overflow-item--danger" : ""}`,
21291
+ className: `squisq-toolbar-overflow-item${showFiles ? " squisq-toolbar-overflow-item--active" : ""}`,
21292
+ "aria-pressed": showFiles,
21231
21293
  onClick: () => {
21232
- item.action();
21294
+ onToggleFiles();
21233
21295
  setShowOverflow(false);
21234
21296
  },
21235
- children: /* @__PURE__ */ jsx48("span", { children: item.label })
21236
- },
21237
- item.label
21238
- ))
21239
- ] })
21240
- ]
21241
- }
21297
+ children: [
21298
+ /* @__PURE__ */ jsx48("span", { className: "squisq-toolbar-overflow-icon", children: /* @__PURE__ */ jsx48(Icon, { icon: "fa-solid fa-paperclip" }) }),
21299
+ /* @__PURE__ */ jsxs37("span", { children: [
21300
+ showFiles ? "Hide" : "Show",
21301
+ " Files panel",
21302
+ resolvedFileCount > 0 ? ` (${fileCountLabel(resolvedFileCount)})` : ""
21303
+ ] })
21304
+ ]
21305
+ }
21306
+ ),
21307
+ showBlockSectionInOverflow && /* @__PURE__ */ jsxs37(Fragment17, { children: [
21308
+ /* @__PURE__ */ jsx48(
21309
+ "div",
21310
+ {
21311
+ className: "squisq-toolbar-separator",
21312
+ style: { margin: "4px 0", width: "100%", height: 1 }
21313
+ }
21314
+ ),
21315
+ /* @__PURE__ */ jsxs37("div", { className: "squisq-toolbar-overflow-heading", children: [
21316
+ overflowBlockLabel,
21317
+ " Block:"
21318
+ ] })
21319
+ ] }),
21320
+ showTemplateInOverflow && /* @__PURE__ */ jsx48("div", { className: "squisq-toolbar-overflow-item squisq-toolbar-overflow-template", children: /* @__PURE__ */ jsx48(
21321
+ TemplatePicker,
21322
+ {
21323
+ value: currentTemplate,
21324
+ onChange: (v2) => {
21325
+ handleTemplatePick(v2);
21326
+ setShowOverflow(false);
21327
+ },
21328
+ colorScheme,
21329
+ recommended: recommendedTemplates,
21330
+ previewSource: templatePreviewSource
21331
+ }
21332
+ ) }),
21333
+ showTransitionInOverflow && /* @__PURE__ */ jsx48("div", { className: "squisq-toolbar-overflow-item squisq-toolbar-overflow-template", children: /* @__PURE__ */ jsx48(
21334
+ TransitionPicker,
21335
+ {
21336
+ value: currentTransition,
21337
+ onChange: handleTransitionPick,
21338
+ colorScheme,
21339
+ accentColor: previewSettings?.activeTheme.colors.primary
21340
+ }
21341
+ ) }),
21342
+ showFormattingControls && isInTable && clippedContextual.has("table") && /* @__PURE__ */ jsxs37(Fragment17, { children: [
21343
+ /* @__PURE__ */ jsx48(
21344
+ "div",
21345
+ {
21346
+ className: "squisq-toolbar-separator",
21347
+ style: { margin: "4px 0", width: "100%", height: 1 }
21348
+ }
21349
+ ),
21350
+ [
21351
+ {
21352
+ label: "Add column before",
21353
+ action: () => tiptapEditor.chain().focus().addColumnBefore().run()
21354
+ },
21355
+ {
21356
+ label: "Add column after",
21357
+ action: () => tiptapEditor.chain().focus().addColumnAfter().run()
21358
+ },
21359
+ {
21360
+ label: "Delete column",
21361
+ action: () => tiptapEditor.chain().focus().deleteColumn().run()
21362
+ },
21363
+ {
21364
+ label: "Add row above",
21365
+ action: () => tiptapEditor.chain().focus().addRowBefore().run()
21366
+ },
21367
+ {
21368
+ label: "Add row below",
21369
+ action: () => tiptapEditor.chain().focus().addRowAfter().run()
21370
+ },
21371
+ {
21372
+ label: "Delete row",
21373
+ action: () => tiptapEditor.chain().focus().deleteRow().run()
21374
+ },
21375
+ {
21376
+ label: "Delete table",
21377
+ action: () => tiptapEditor.chain().focus().deleteTable().run()
21378
+ }
21379
+ ].map((item) => /* @__PURE__ */ jsx48(
21380
+ "button",
21381
+ {
21382
+ className: `squisq-toolbar-overflow-item${item.label.startsWith("Delete") ? " squisq-toolbar-overflow-item--danger" : ""}`,
21383
+ onClick: () => {
21384
+ item.action();
21385
+ setShowOverflow(false);
21386
+ },
21387
+ children: /* @__PURE__ */ jsx48("span", { children: item.label })
21388
+ },
21389
+ item.label
21390
+ ))
21391
+ ] })
21392
+ ]
21393
+ }
21394
+ ),
21395
+ overflowTriggerRef.current?.closest('[role="dialog"][aria-modal="true"]') ?? document.body
21242
21396
  )
21243
21397
  ] }),
21244
21398
  !findMode && slotAfterActions,
@@ -21326,7 +21480,7 @@ ${TASK_LIST_MARKDOWN}
21326
21480
  }
21327
21481
  ),
21328
21482
  videoEmbedDialog,
21329
- insertMenuAnchor && createPortal11(
21483
+ insertMenuAnchor && createPortal12(
21330
21484
  /* @__PURE__ */ jsxs37(
21331
21485
  "div",
21332
21486
  {
@@ -21472,7 +21626,7 @@ ${TASK_LIST_MARKDOWN}
21472
21626
  ),
21473
21627
  document.body
21474
21628
  ),
21475
- mermaidTypeMenuAnchor && createPortal11(
21629
+ mermaidTypeMenuAnchor && createPortal12(
21476
21630
  /* @__PURE__ */ jsxs37(
21477
21631
  "div",
21478
21632
  {
@@ -21522,7 +21676,7 @@ ${TASK_LIST_MARKDOWN}
21522
21676
  ),
21523
21677
  document.body
21524
21678
  ),
21525
- chartTypeMenuAnchor && createPortal11(
21679
+ chartTypeMenuAnchor && createPortal12(
21526
21680
  /* @__PURE__ */ jsxs37(
21527
21681
  "div",
21528
21682
  {
@@ -21565,7 +21719,7 @@ ${TASK_LIST_MARKDOWN}
21565
21719
  ),
21566
21720
  document.body
21567
21721
  ),
21568
- codeSnippetMenuAnchor && createPortal11(
21722
+ codeSnippetMenuAnchor && createPortal12(
21569
21723
  /* @__PURE__ */ jsxs37(
21570
21724
  "div",
21571
21725
  {
@@ -21617,7 +21771,7 @@ ${TASK_LIST_MARKDOWN}
21617
21771
  ),
21618
21772
  document.body
21619
21773
  ),
21620
- emojiPickerAnchor && createPortal11(
21774
+ emojiPickerAnchor && createPortal12(
21621
21775
  /* @__PURE__ */ jsx48(
21622
21776
  EmojiPicker,
21623
21777
  {
@@ -21641,7 +21795,7 @@ ${TASK_LIST_MARKDOWN}
21641
21795
  }
21642
21796
 
21643
21797
  // src/StatusBar.tsx
21644
- import { useEffect as useEffect29, useMemo as useMemo25, useState as useState37 } from "react";
21798
+ import { useEffect as useEffect30, useMemo as useMemo25, useState as useState39 } from "react";
21645
21799
  import { countBlocks } from "@bendyline/squisq/doc";
21646
21800
  import { jsx as jsx49, jsxs as jsxs38 } from "react/jsx-runtime";
21647
21801
  var STATS_DEBOUNCE_MS = 150;
@@ -21651,8 +21805,8 @@ function countLabel(count, noun) {
21651
21805
  function StatusBar({ className, slotRight }) {
21652
21806
  const { markdownSource, doc, parseError } = useEditorContext();
21653
21807
  const proofingState = useProofingState();
21654
- const [statsSource, setStatsSource] = useState37(markdownSource);
21655
- useEffect29(() => {
21808
+ const [statsSource, setStatsSource] = useState39(markdownSource);
21809
+ useEffect30(() => {
21656
21810
  if (statsSource === markdownSource) return;
21657
21811
  const timeout = setTimeout(() => setStatsSource(markdownSource), STATS_DEBOUNCE_MS);
21658
21812
  return () => clearTimeout(timeout);
@@ -21699,12 +21853,12 @@ import {
21699
21853
  createContext as createContext5,
21700
21854
  useCallback as useCallback32,
21701
21855
  useContext as useContext5,
21702
- useEffect as useEffect30,
21856
+ useEffect as useEffect31,
21703
21857
  useMemo as useMemo26,
21704
21858
  useRef as useRef34,
21705
- useState as useState38
21859
+ useState as useState40
21706
21860
  } from "react";
21707
- import { createPortal as createPortal12 } from "react-dom";
21861
+ import { createPortal as createPortal13 } from "react-dom";
21708
21862
  import { CellSelection } from "@tiptap/pm/tables";
21709
21863
  import { jsx as jsx50, jsxs as jsxs39 } from "react/jsx-runtime";
21710
21864
  var EditorContextMenuRegistry = createContext5(null);
@@ -21720,7 +21874,7 @@ function useEditorContextMenuItems(items) {
21720
21874
  if (!registry) {
21721
21875
  throw new Error("useEditorContextMenuItems must be used within an <EditorShell>");
21722
21876
  }
21723
- useEffect30(() => registry.register(() => itemsRef.current), [registry]);
21877
+ useEffect31(() => registry.register(() => itemsRef.current), [registry]);
21724
21878
  }
21725
21879
  function selectedTextFromBrowser(content) {
21726
21880
  const selection = window.getSelection();
@@ -21890,8 +22044,8 @@ function EditorContextMenuProvider({
21890
22044
  const { activeView, editorMode, colorScheme, monacoEditor, tiptapEditor } = useEditorContext();
21891
22045
  const itemGettersRef = useRef34(/* @__PURE__ */ new Set());
21892
22046
  const menuRef = useRef34(null);
21893
- const [menu, setMenu] = useState38(null);
21894
- const [menuStyle2, setMenuStyle] = useState38({});
22047
+ const [menu, setMenu] = useState40(null);
22048
+ const [menuStyle2, setMenuStyle] = useState40({});
21895
22049
  const register = useCallback32((getItems) => {
21896
22050
  itemGettersRef.current.add(getItems);
21897
22051
  return () => itemGettersRef.current.delete(getItems);
@@ -22046,7 +22200,7 @@ function EditorContextMenuProvider({
22046
22200
  },
22047
22201
  [buildInteraction, tiptapEditor]
22048
22202
  );
22049
- useEffect30(() => {
22203
+ useEffect31(() => {
22050
22204
  const root = rootRef.current;
22051
22205
  if (!root) return;
22052
22206
  const onContextMenu = (event) => {
@@ -22071,7 +22225,7 @@ function EditorContextMenuProvider({
22071
22225
  root.removeEventListener("keydown", onKeyDown);
22072
22226
  };
22073
22227
  }, [openAt, rootRef]);
22074
- useEffect30(() => {
22228
+ useEffect31(() => {
22075
22229
  if (!menu) return;
22076
22230
  const frame = requestAnimationFrame(() => {
22077
22231
  setMenuStyle(computeMenuStyle(menu, menuRef.current));
@@ -22133,7 +22287,7 @@ function EditorContextMenuProvider({
22133
22287
  }, []);
22134
22288
  return /* @__PURE__ */ jsxs39(EditorContextMenuRegistry.Provider, { value: registry, children: [
22135
22289
  children,
22136
- menu && createPortal12(
22290
+ menu && createPortal13(
22137
22291
  /* @__PURE__ */ jsxs39(
22138
22292
  "div",
22139
22293
  {
@@ -22178,7 +22332,7 @@ function EditorContextMenuProvider({
22178
22332
  }
22179
22333
 
22180
22334
  // src/RawEditor.tsx
22181
- import { useRef as useRef35, useCallback as useCallback33, useEffect as useEffect31, useState as useState39 } from "react";
22335
+ import { useRef as useRef35, useCallback as useCallback33, useEffect as useEffect32, useState as useState41 } from "react";
22182
22336
  import { getAvailableTemplates } from "@bendyline/squisq/doc";
22183
22337
  import { suggestIcons, resolveIcon, iconGlyph } from "@bendyline/squisq/icons";
22184
22338
  import { BLOCK_META_KEY_DESCRIPTORS, tokenizeAttrTokens as tokenizeAttrTokens3 } from "@bendyline/squisq/markdown";
@@ -22215,10 +22369,10 @@ var SQUISQ_THEMES = {
22215
22369
  "vs-dark": "squisq-dark"
22216
22370
  };
22217
22371
  function useDocumentMonacoLanguages(language, source) {
22218
- const [requested, setRequested] = useState39(
22372
+ const [requested, setRequested] = useState41(
22219
22373
  () => monacoLanguagesForDocument(language, source)
22220
22374
  );
22221
- useEffect31(() => {
22375
+ useEffect32(() => {
22222
22376
  const delay = normalizeMonacoLanguage(language) === "markdown" ? 250 : 0;
22223
22377
  const timer = window.setTimeout(() => {
22224
22378
  setRequested(monacoLanguagesForDocument(language, source));
@@ -22228,6 +22382,7 @@ function useDocumentMonacoLanguages(language, source) {
22228
22382
  return requested;
22229
22383
  }
22230
22384
  function RawEditor({
22385
+ ariaLabel = "Document source",
22231
22386
  monacoTheme = "vs",
22232
22387
  minimap = false,
22233
22388
  fontSize = 14,
@@ -22255,14 +22410,14 @@ function RawEditor({
22255
22410
  const keyDisposable = useRef35(null);
22256
22411
  const submitOnEnterRef = useRef35(submitOnEnter);
22257
22412
  const readOnlyRef = useRef35(readOnly);
22258
- useEffect31(() => {
22413
+ useEffect32(() => {
22259
22414
  submitOnEnterRef.current = submitOnEnter;
22260
22415
  }, [submitOnEnter]);
22261
- useEffect31(() => {
22416
+ useEffect32(() => {
22262
22417
  readOnlyRef.current = readOnly;
22263
22418
  }, [readOnly]);
22264
22419
  const mentionProviderRef = useRef35(mentionProvider);
22265
- useEffect31(() => {
22420
+ useEffect32(() => {
22266
22421
  mentionProviderRef.current = mentionProvider;
22267
22422
  }, [mentionProvider]);
22268
22423
  const docCustomTemplates = doc?.customTemplates;
@@ -22273,7 +22428,7 @@ function RawEditor({
22273
22428
  detail: "Block template"
22274
22429
  }));
22275
22430
  }
22276
- useEffect31(() => {
22431
+ useEffect32(() => {
22277
22432
  const builtIns = getAvailableTemplates().map((name) => ({
22278
22433
  name,
22279
22434
  detail: "Block template"
@@ -22559,7 +22714,6 @@ function RawEditor({
22559
22714
  }
22560
22715
  keyDisposable.current?.dispose();
22561
22716
  keyDisposable.current = editor.onKeyDown((e2) => {
22562
- void preloadMonacoSuggestions().catch(() => void 0);
22563
22717
  if (e2.keyCode !== monaco.KeyCode.Enter) return;
22564
22718
  if (!submitOnEnterRef.current) return;
22565
22719
  if (e2.metaKey || e2.ctrlKey || e2.shiftKey || e2.altKey) return;
@@ -22615,7 +22769,7 @@ function RawEditor({
22615
22769
  },
22616
22770
  [setMonacoEditor, language]
22617
22771
  );
22618
- useEffect31(() => {
22772
+ useEffect32(() => {
22619
22773
  return () => {
22620
22774
  setMonacoEditor(null);
22621
22775
  completionDisposable.current?.dispose();
@@ -22643,7 +22797,7 @@ function RawEditor({
22643
22797
  },
22644
22798
  [setEditorSource]
22645
22799
  );
22646
- useEffect31(() => {
22800
+ useEffect32(() => {
22647
22801
  const editor = editorRef.current;
22648
22802
  if (editor) {
22649
22803
  const currentValue = editor.getValue();
@@ -22654,7 +22808,7 @@ function RawEditor({
22654
22808
  }
22655
22809
  }
22656
22810
  }, [editorSource]);
22657
- useEffect31(() => {
22811
+ useEffect32(() => {
22658
22812
  const editor = editorRef.current;
22659
22813
  if (!editor || !monacoNs) return;
22660
22814
  if (language !== "markdown") return;
@@ -22698,7 +22852,7 @@ function RawEditor({
22698
22852
  "textarea",
22699
22853
  {
22700
22854
  className,
22701
- "aria-label": "Document source",
22855
+ "aria-label": ariaLabel,
22702
22856
  "aria-busy": "true",
22703
22857
  autoFocus: true,
22704
22858
  readOnly,
@@ -22751,6 +22905,7 @@ function RawEditor({
22751
22905
  onMount: handleMount,
22752
22906
  onChange: handleChange,
22753
22907
  options: {
22908
+ ariaLabel,
22754
22909
  fontSize,
22755
22910
  wordWrap,
22756
22911
  minimap: { enabled: minimap },
@@ -23004,7 +23159,7 @@ var Subscript = Mark.create({
23004
23159
  });
23005
23160
 
23006
23161
  // src/diagram/DiagramCanvas.tsx
23007
- import { useCallback as useCallback34, useMemo as useMemo27, useRef as useRef36, useState as useState40 } from "react";
23162
+ import { useCallback as useCallback34, useMemo as useMemo27, useRef as useRef36, useState as useState42 } from "react";
23008
23163
 
23009
23164
  // src/diagram/diagramConstants.ts
23010
23165
  var DIAGRAM_VIEWPORT = { width: 1600, height: 900 };
@@ -23029,7 +23184,7 @@ function DiagramCanvas({
23029
23184
  () => buildDiagramScene(incomingNodes, incomingEdges),
23030
23185
  [incomingNodes, incomingEdges]
23031
23186
  );
23032
- const [internalToolId, setInternalToolId] = useState40("select");
23187
+ const [internalToolId, setInternalToolId] = useState42("select");
23033
23188
  const activeToolId = controlledToolId ?? internalToolId;
23034
23189
  const setActiveToolId = onActiveToolIdChange ?? setInternalToolId;
23035
23190
  const handleSceneCommand = useCallback34(
@@ -23317,7 +23472,7 @@ function removeNodeOp(diagram, nodeId) {
23317
23472
  }
23318
23473
 
23319
23474
  // src/asciiDiagram/asciiDiagramData.ts
23320
- import { useEffect as useEffect32, useMemo as useMemo29, useState as useState42 } from "react";
23475
+ import { useEffect as useEffect33, useMemo as useMemo29, useState as useState44 } from "react";
23321
23476
  import {
23322
23477
  asciiCellToCanvas,
23323
23478
  asciiDiagramToTemplateData,
@@ -23339,7 +23494,7 @@ import {
23339
23494
  } from "@bendyline/squisq/doc";
23340
23495
 
23341
23496
  // src/asciiDiagram/AsciiDiagramWidget.tsx
23342
- import { useCallback as useCallback35, useMemo as useMemo28, useRef as useRef37, useState as useState41 } from "react";
23497
+ import { useCallback as useCallback35, useMemo as useMemo28, useRef as useRef37, useState as useState43 } from "react";
23343
23498
 
23344
23499
  // src/asciiDiagram/asciiDiagramCommands.ts
23345
23500
  import {
@@ -23587,11 +23742,11 @@ function AsciiDiagramWidget({
23587
23742
  textChannel
23588
23743
  }) {
23589
23744
  const view = useAsciiDiagramData(editor, blockId);
23590
- const [maximized, setMaximized] = useState41(false);
23591
- const [height, setHeight] = useState41(null);
23592
- const [dragHeight, setDragHeight] = useState41(null);
23745
+ const [maximized, setMaximized] = useState43(false);
23746
+ const [height, setHeight] = useState43(null);
23747
+ const [dragHeight, setDragHeight] = useState43(null);
23593
23748
  const canvasOffsetRef = useRef37(null);
23594
- const [canvasOffsetVersion, setCanvasOffsetVersion] = useState41(0);
23749
+ const [canvasOffsetVersion, setCanvasOffsetVersion] = useState43(0);
23595
23750
  const inlineRef = useRef37(null);
23596
23751
  const effectiveHeight = dragHeight ?? height;
23597
23752
  if (view && canvasOffsetRef.current === null) {
@@ -23644,8 +23799,8 @@ function AsciiDiagramWidget({
23644
23799
  setDragHeight(null);
23645
23800
  setHeight(null);
23646
23801
  }, []);
23647
- const [activeToolId, setActiveToolId] = useState41("select");
23648
- const [selectedIds, setSelectedIds] = useState41(() => /* @__PURE__ */ new Set());
23802
+ const [activeToolId, setActiveToolId] = useState43("select");
23803
+ const [selectedIds, setSelectedIds] = useState43(() => /* @__PURE__ */ new Set());
23649
23804
  const selectedNodeIds = useMemo28(
23650
23805
  () => [...selectedIds].map((id) => nodeIdFromCardLayerId(id)).filter((id) => id != null),
23651
23806
  [selectedIds]
@@ -24017,8 +24172,8 @@ function asciiDiagramToCanvas(diagram) {
24017
24172
  return { nodes, edges };
24018
24173
  }
24019
24174
  function useAsciiDiagramData(editor, blockId) {
24020
- const [version, setVersion] = useState42(0);
24021
- useEffect32(() => {
24175
+ const [version, setVersion] = useState44(0);
24176
+ useEffect33(() => {
24022
24177
  const onUpdate = () => setVersion((v2) => v2 + 1);
24023
24178
  editor.on("transaction", onUpdate);
24024
24179
  return () => {
@@ -25861,7 +26016,7 @@ function mermaidErrorMessage(error) {
25861
26016
  }
25862
26017
 
25863
26018
  // src/mermaid/mermaidSurfaceTheme.ts
25864
- import { useEffect as useEffect33, useMemo as useMemo30, useState as useState43 } from "react";
26019
+ import { useEffect as useEffect34, useMemo as useMemo30, useState as useState45 } from "react";
25865
26020
  import { relativeLuminance } from "@bendyline/squisq/schemas";
25866
26021
  var EDITOR_SURFACE = {
25867
26022
  light: {
@@ -25897,8 +26052,8 @@ function resolveMermaidSurfaceTheme(host, theme) {
25897
26052
  return applyHostSurface(readHostSurface(host), theme);
25898
26053
  }
25899
26054
  function useMermaidSurfaceTheme(host, theme) {
25900
- const [surface, setSurface] = useState43(() => readHostSurface(host));
25901
- useEffect33(() => {
26055
+ const [surface, setSurface] = useState45(() => readHostSurface(host));
26056
+ useEffect34(() => {
25902
26057
  const sync = () => setSurface((current) => {
25903
26058
  const next = readHostSurface(host);
25904
26059
  return current.scheme === next.scheme && current.inheritsThemeColors === next.inheritsThemeColors ? current : next;
@@ -25924,7 +26079,7 @@ function useMermaidSurfaceTheme(host, theme) {
25924
26079
  }
25925
26080
 
25926
26081
  // src/mermaid/MermaidDiagramCanvas.tsx
25927
- import { useCallback as useCallback36, useEffect as useEffect34, useId as useId13, useLayoutEffect as useLayoutEffect7, useRef as useRef38, useState as useState44 } from "react";
26082
+ import { useCallback as useCallback36, useEffect as useEffect35, useId as useId12, useLayoutEffect as useLayoutEffect10, useRef as useRef38, useState as useState46 } from "react";
25928
26083
  import { jsx as jsx54, jsxs as jsxs42 } from "react/jsx-runtime";
25929
26084
  var renderSequence = 0;
25930
26085
  function excludesCanvasPan(target, viewport) {
@@ -25987,21 +26142,21 @@ function MermaidDiagramCanvas({
25987
26142
  const scrollRef = useRef38(null);
25988
26143
  const renameInputRef = useRef38(null);
25989
26144
  const panDragRef = useRef38(null);
25990
- const renameHintId = useId13();
25991
- const [svg, setSvg] = useState44("");
25992
- const [model2, setModel] = useState44(null);
25993
- const [diagramType, setDiagramType] = useState44("mermaid");
25994
- const [error, setError] = useState44("");
25995
- const [rendering, setRendering] = useState44(true);
25996
- const [zoom, setZoom] = useState44(1);
25997
- const [viewMode, setViewMode] = useState44("fit");
25998
- const [contentSize, setContentSize] = useState44(null);
25999
- const [canvasSize, setCanvasSize] = useState44(null);
26000
- const [pan, setPan] = useState44({ x: 0, y: 0 });
26001
- const [panning, setPanning] = useState44(false);
26002
- const [selectionAnchor, setSelectionAnchor] = useState44(null);
26003
- const [renameValue, setRenameValue] = useState44("");
26004
- useEffect34(() => {
26145
+ const renameHintId = useId12();
26146
+ const [svg, setSvg] = useState46("");
26147
+ const [model2, setModel] = useState46(null);
26148
+ const [diagramType, setDiagramType] = useState46("mermaid");
26149
+ const [error, setError] = useState46("");
26150
+ const [rendering, setRendering] = useState46(true);
26151
+ const [zoom, setZoom] = useState46(1);
26152
+ const [viewMode, setViewMode] = useState46("fit");
26153
+ const [contentSize, setContentSize] = useState46(null);
26154
+ const [canvasSize, setCanvasSize] = useState46(null);
26155
+ const [pan, setPan] = useState46({ x: 0, y: 0 });
26156
+ const [panning, setPanning] = useState46(false);
26157
+ const [selectionAnchor, setSelectionAnchor] = useState46(null);
26158
+ const [renameValue, setRenameValue] = useState46("");
26159
+ useEffect35(() => {
26005
26160
  if (!panning) return;
26006
26161
  const finish = () => {
26007
26162
  panDragRef.current = null;
@@ -26029,7 +26184,7 @@ function MermaidDiagramCanvas({
26029
26184
  window.removeEventListener("blur", finish);
26030
26185
  };
26031
26186
  }, [panning]);
26032
- useEffect34(() => {
26187
+ useEffect35(() => {
26033
26188
  let current = true;
26034
26189
  const id = `squisq-mermaid-svg-${++renderSequence}`;
26035
26190
  setRendering(true);
@@ -26054,7 +26209,7 @@ function MermaidDiagramCanvas({
26054
26209
  current = false;
26055
26210
  };
26056
26211
  }, [source, onModelChange, theme]);
26057
- useLayoutEffect7(() => {
26212
+ useLayoutEffect10(() => {
26058
26213
  const scroll = scrollRef.current;
26059
26214
  if (!scroll) return;
26060
26215
  const measure = () => {
@@ -26075,7 +26230,7 @@ function MermaidDiagramCanvas({
26075
26230
  observer.observe(scroll);
26076
26231
  return () => observer.disconnect();
26077
26232
  }, []);
26078
- useLayoutEffect7(() => {
26233
+ useLayoutEffect10(() => {
26079
26234
  setContentSize(readSvgViewBox(svgRootRef.current));
26080
26235
  }, [svg]);
26081
26236
  const fitZoom = contentSize && canvasSize ? calculateFitScale(contentSize, canvasSize) : 1;
@@ -26084,7 +26239,7 @@ function MermaidDiagramCanvas({
26084
26239
  setZoom(fitZoom);
26085
26240
  setPan({ x: 0, y: 0 });
26086
26241
  }, [fitZoom]);
26087
- useLayoutEffect7(() => {
26242
+ useLayoutEffect10(() => {
26088
26243
  if (viewMode !== "fit") return;
26089
26244
  setZoom(fitZoom);
26090
26245
  setPan({ x: 0, y: 0 });
@@ -26151,7 +26306,7 @@ function MermaidDiagramCanvas({
26151
26306
  selectedNodeId,
26152
26307
  selectedTextId
26153
26308
  ]);
26154
- useLayoutEffect7(() => {
26309
+ useLayoutEffect10(() => {
26155
26310
  const node2 = renamingNodeId ? model2?.nodes.find((candidate) => candidate.id === renamingNodeId) : null;
26156
26311
  const edge2 = renamingEdgeId ? model2?.edges.find((candidate) => candidate.id === renamingEdgeId) : null;
26157
26312
  const text = renamingTextId ? model2 && mermaidEditableTexts(model2).find((candidate) => candidate.id === renamingTextId) : null;
@@ -26164,7 +26319,7 @@ function MermaidDiagramCanvas({
26164
26319
  });
26165
26320
  return () => window.cancelAnimationFrame(frame);
26166
26321
  }, [model2, renamingEdgeId, renamingNodeId, renamingTextId]);
26167
- useLayoutEffect7(() => {
26322
+ useLayoutEffect10(() => {
26168
26323
  const root = svgRootRef.current;
26169
26324
  if (!root || !model2) {
26170
26325
  setSelectionAnchor(null);
@@ -26300,7 +26455,7 @@ function MermaidDiagramCanvas({
26300
26455
  updateSelectionAnchor,
26301
26456
  zoom
26302
26457
  ]);
26303
- useEffect34(() => {
26458
+ useEffect35(() => {
26304
26459
  const scroll = scrollRef.current;
26305
26460
  if (!scroll) return;
26306
26461
  const update = () => updateSelectionAnchor();
@@ -26705,7 +26860,7 @@ function CanvasAction({
26705
26860
  }
26706
26861
 
26707
26862
  // src/mermaid/MermaidShapePalette.tsx
26708
- import { useEffect as useEffect35, useLayoutEffect as useLayoutEffect8, useMemo as useMemo31, useRef as useRef39, useState as useState45 } from "react";
26863
+ import { useEffect as useEffect36, useLayoutEffect as useLayoutEffect11, useMemo as useMemo31, useRef as useRef39, useState as useState47 } from "react";
26709
26864
  import { jsx as jsx55, jsxs as jsxs43 } from "react/jsx-runtime";
26710
26865
  var CATEGORIES = ["Basic", "Process", "Data", "Documents", "Symbols"];
26711
26866
  var PALETTE_WIDTH = 360;
@@ -26713,10 +26868,10 @@ var PALETTE_MAX_HEIGHT = 520;
26713
26868
  var PALETTE_GAP = 6;
26714
26869
  var VIEWPORT_GUTTER = 8;
26715
26870
  function MermaidShapePalette({ selected, onPick, onClose }) {
26716
- const [query, setQuery] = useState45("");
26717
- const [position, setPosition] = useState45(null);
26871
+ const [query, setQuery] = useState47("");
26872
+ const [position, setPosition] = useState47(null);
26718
26873
  const ref = useRef39(null);
26719
- useEffect35(() => {
26874
+ useEffect36(() => {
26720
26875
  const onPointerDown = (event) => {
26721
26876
  const target = event.target;
26722
26877
  if (target?.closest(".squisq-scene-block-toolbar")) return;
@@ -26741,7 +26896,7 @@ function MermaidShapePalette({ selected, onPick, onClose }) {
26741
26896
  )
26742
26897
  })).filter((section) => section.shapes.length > 0);
26743
26898
  }, [query]);
26744
- useLayoutEffect8(() => {
26899
+ useLayoutEffect11(() => {
26745
26900
  const palette = ref.current;
26746
26901
  const anchor = palette?.parentElement;
26747
26902
  if (!palette || !anchor) return;
@@ -26887,7 +27042,7 @@ function MermaidShapeThumb({ shape }) {
26887
27042
  }
26888
27043
 
26889
27044
  // src/mermaid/mermaidData.ts
26890
- import { useEffect as useEffect37, useMemo as useMemo32, useState as useState47 } from "react";
27045
+ import { useEffect as useEffect38, useMemo as useMemo32, useState as useState49 } from "react";
26891
27046
 
26892
27047
  // src/mermaid/MermaidDiagramExtension.ts
26893
27048
  import { Extension as Extension6 } from "@tiptap/core";
@@ -26899,10 +27054,10 @@ import { createRoot as createRoot3 } from "react-dom/client";
26899
27054
  // src/mermaid/MermaidDiagramWidget.tsx
26900
27055
  import {
26901
27056
  useCallback as useCallback37,
26902
- useEffect as useEffect36,
26903
- useLayoutEffect as useLayoutEffect9,
27057
+ useEffect as useEffect37,
27058
+ useLayoutEffect as useLayoutEffect12,
26904
27059
  useRef as useRef40,
26905
- useState as useState46,
27060
+ useState as useState48,
26906
27061
  useSyncExternalStore as useSyncExternalStore2
26907
27062
  } from "react";
26908
27063
 
@@ -27271,16 +27426,16 @@ function MermaidDiagramWidget({
27271
27426
  themeStore?.getSnapshot ?? getDefaultTheme
27272
27427
  );
27273
27428
  const theme = useMermaidSurfaceTheme(host, docTheme);
27274
- const [model2, setModel] = useState46(null);
27275
- const [selection, setSelection] = useState46(null);
27276
- const [renaming, setRenaming] = useState46(null);
27277
- const [connecting, setConnecting] = useState46(false);
27278
- const [connectSourceId, setConnectSourceId] = useState46(null);
27279
- const [openPopover, setOpenPopover] = useState46(null);
27280
- const [editNotice, setEditNotice] = useState46("");
27281
- const [maximized, setMaximized] = useState46(false);
27282
- const [height, setHeight] = useState46(null);
27283
- const [dragHeight, setDragHeight] = useState46(null);
27429
+ const [model2, setModel] = useState48(null);
27430
+ const [selection, setSelection] = useState48(null);
27431
+ const [renaming, setRenaming] = useState48(null);
27432
+ const [connecting, setConnecting] = useState48(false);
27433
+ const [connectSourceId, setConnectSourceId] = useState48(null);
27434
+ const [openPopover, setOpenPopover] = useState48(null);
27435
+ const [editNotice, setEditNotice] = useState48("");
27436
+ const [maximized, setMaximized] = useState48(false);
27437
+ const [height, setHeight] = useState48(null);
27438
+ const [dragHeight, setDragHeight] = useState48(null);
27284
27439
  const inlineRef = useRef40(null);
27285
27440
  const effectiveHeight = dragHeight ?? height;
27286
27441
  const onModelChange = useCallback37((next) => {
@@ -27539,7 +27694,7 @@ function MermaidDiagramWidget({
27539
27694
  },
27540
27695
  [effectiveHeight]
27541
27696
  );
27542
- useEffect36(() => {
27697
+ useEffect37(() => {
27543
27698
  if (!editNotice) return;
27544
27699
  const timeout = window.setTimeout(() => setEditNotice(""), 7e3);
27545
27700
  return () => window.clearTimeout(timeout);
@@ -27776,7 +27931,7 @@ function MermaidDiagramWidget({
27776
27931
  ] });
27777
27932
  }
27778
27933
  function useDismissibleMermaidPopover(ref, onClose) {
27779
- useEffect36(() => {
27934
+ useEffect37(() => {
27780
27935
  const onPointerDown = (event) => {
27781
27936
  const target = event.target;
27782
27937
  if (target?.closest(".squisq-scene-block-toolbar")) return;
@@ -27794,8 +27949,8 @@ function useDismissibleMermaidPopover(ref, onClose) {
27794
27949
  }, [onClose, ref]);
27795
27950
  }
27796
27951
  function useClampedMermaidPopoverPosition(ref, preferredWidth, preferredMaxHeight) {
27797
- const [position, setPosition] = useState46(null);
27798
- useLayoutEffect9(() => {
27952
+ const [position, setPosition] = useState48(null);
27953
+ useLayoutEffect12(() => {
27799
27954
  const picker = ref.current;
27800
27955
  const anchor = picker?.parentElement;
27801
27956
  if (!picker || !anchor) return;
@@ -27860,7 +28015,7 @@ function MermaidPropertiesPalette({
27860
28015
  onApply,
27861
28016
  onClose
27862
28017
  }) {
27863
- const [values, setValues] = useState46(
28018
+ const [values, setValues] = useState48(
27864
28019
  () => Object.fromEntries(properties.map((property) => [property.id, property.value]))
27865
28020
  );
27866
28021
  const ref = useRef40(null);
@@ -28154,8 +28309,8 @@ var MermaidDiagramExtension = Extension6.create({
28154
28309
 
28155
28310
  // src/mermaid/mermaidData.ts
28156
28311
  function useMermaidDiagramData(editor, blockId) {
28157
- const [version, setVersion] = useState47(0);
28158
- useEffect37(() => {
28312
+ const [version, setVersion] = useState49(0);
28313
+ useEffect38(() => {
28159
28314
  const onTransaction = () => setVersion((value) => value + 1);
28160
28315
  editor.on("transaction", onTransaction);
28161
28316
  return () => {
@@ -28179,13 +28334,13 @@ import { createElement as createElement10 } from "react";
28179
28334
  import { createRoot as createRoot4 } from "react-dom/client";
28180
28335
 
28181
28336
  // src/codeSnippet/CodeSnippetWidget.tsx
28182
- import { useCallback as useCallback38, useEffect as useEffect39, useRef as useRef41, useState as useState49 } from "react";
28337
+ import { useCallback as useCallback38, useEffect as useEffect40, useRef as useRef41, useState as useState51 } from "react";
28183
28338
 
28184
28339
  // src/codeSnippet/codeSnippetData.ts
28185
- import { useEffect as useEffect38, useMemo as useMemo33, useState as useState48 } from "react";
28340
+ import { useEffect as useEffect39, useMemo as useMemo33, useState as useState50 } from "react";
28186
28341
  function useCodeSnippetData(editor, blockId) {
28187
- const [version, setVersion] = useState48(0);
28188
- useEffect38(() => {
28342
+ const [version, setVersion] = useState50(0);
28343
+ useEffect39(() => {
28189
28344
  const onTransaction = () => setVersion((value) => value + 1);
28190
28345
  editor.on("transaction", onTransaction);
28191
28346
  return () => {
@@ -28229,10 +28384,10 @@ function schemeFromHost(host) {
28229
28384
  return host?.closest("[data-theme]")?.dataset.theme === "dark" ? "dark" : "light";
28230
28385
  }
28231
28386
  function useHostColorScheme(host) {
28232
- const [scheme, setScheme] = useState49(
28387
+ const [scheme, setScheme] = useState51(
28233
28388
  () => host != null && !host.isConnected ? null : schemeFromHost(host)
28234
28389
  );
28235
- useEffect39(() => {
28390
+ useEffect40(() => {
28236
28391
  if (host != null && !host.isConnected) {
28237
28392
  setScheme(null);
28238
28393
  const raf = requestAnimationFrame(() => {
@@ -28270,8 +28425,8 @@ async function writeSnippetToClipboard(source, language, handler) {
28270
28425
  await navigator.clipboard.writeText(source);
28271
28426
  }
28272
28427
  function useEditorEditable(editor) {
28273
- const [editable, setEditable] = useState49(editor.isEditable);
28274
- useEffect39(() => {
28428
+ const [editable, setEditable] = useState51(editor.isEditable);
28429
+ useEffect40(() => {
28275
28430
  const sync = () => setEditable(editor.isEditable);
28276
28431
  editor.on("update", sync);
28277
28432
  editor.on("transaction", sync);
@@ -28293,14 +28448,14 @@ function CodeSnippetWidget({
28293
28448
  const { ready } = useMonacoLoader(data?.monacoLanguage);
28294
28449
  const colorScheme = useHostColorScheme(host);
28295
28450
  const editable = useEditorEditable(editor);
28296
- const [modelInstanceId] = useState49(allocateCodeSnippetModelInstanceId);
28297
- const [copyStatus, setCopyStatus] = useState49("idle");
28451
+ const [modelInstanceId] = useState51(allocateCodeSnippetModelInstanceId);
28452
+ const [copyStatus, setCopyStatus] = useState51("idle");
28298
28453
  const copyResetTimer = useRef41();
28299
28454
  const sourceRef = useRef41("");
28300
28455
  sourceRef.current = data?.source ?? "";
28301
28456
  const languageRef = useRef41("");
28302
28457
  languageRef.current = data?.fenceLanguage ?? "";
28303
- useEffect39(
28458
+ useEffect40(
28304
28459
  () => () => {
28305
28460
  if (copyResetTimer.current !== void 0) clearTimeout(copyResetTimer.current);
28306
28461
  },
@@ -28558,7 +28713,7 @@ import { createRoot as createRoot5 } from "react-dom/client";
28558
28713
  import { createElement as createElement11 } from "react";
28559
28714
 
28560
28715
  // src/fenceWidgets/HostFenceWidget.tsx
28561
- import { Component, useEffect as useEffect40, useMemo as useMemo34, useState as useState50 } from "react";
28716
+ import { Component, useEffect as useEffect41, useMemo as useMemo34, useState as useState52 } from "react";
28562
28717
  import { jsx as jsx58 } from "react/jsx-runtime";
28563
28718
  var HostFenceErrorBoundary = class extends Component {
28564
28719
  constructor() {
@@ -28573,8 +28728,8 @@ var HostFenceErrorBoundary = class extends Component {
28573
28728
  }
28574
28729
  };
28575
28730
  function HostFenceWidget({ editor, blockId, getRenderers, getTheme }) {
28576
- const [version, setVersion] = useState50(0);
28577
- useEffect40(() => {
28731
+ const [version, setVersion] = useState52(0);
28732
+ useEffect41(() => {
28578
28733
  const onUpdate = () => setVersion((v2) => v2 + 1);
28579
28734
  editor.on("transaction", onUpdate);
28580
28735
  return () => {
@@ -29047,7 +29202,7 @@ import { createElement as createElement12 } from "react";
29047
29202
  import { isDataFilePath } from "@bendyline/squisq/doc";
29048
29203
 
29049
29204
  // src/dataCard/DataCardWidget.tsx
29050
- import { useCallback as useCallback39, useEffect as useEffect41, useMemo as useMemo35, useRef as useRef42, useState as useState51 } from "react";
29205
+ import { useCallback as useCallback39, useEffect as useEffect42, useMemo as useMemo35, useRef as useRef42, useState as useState53 } from "react";
29051
29206
  import { EMPTY_TABLE_VIEW_STATE } from "@bendyline/squisq/table";
29052
29207
 
29053
29208
  // src/dataCard/gridSave.ts
@@ -29450,8 +29605,8 @@ import { jsx as jsx59, jsxs as jsxs46 } from "react/jsx-runtime";
29450
29605
  var XLSX_SESSION_LOCKED_REASON = "Date cells and shared-formula masters stay locked; other formulas are editable";
29451
29606
  var pendingFormulas = /* @__PURE__ */ new WeakMap();
29452
29607
  function useCardLink(editor, blockId) {
29453
- const [version, setVersion] = useState51(0);
29454
- useEffect41(() => {
29608
+ const [version, setVersion] = useState53(0);
29609
+ useEffect42(() => {
29455
29610
  const bump = () => setVersion((v2) => v2 + 1);
29456
29611
  editor.on("transaction", bump);
29457
29612
  return () => {
@@ -29470,8 +29625,8 @@ function useCardLink(editor, blockId) {
29470
29625
  }, [editor, blockId, version]);
29471
29626
  }
29472
29627
  function useMediaRevision(getMediaRevision) {
29473
- const [revision, setRevision] = useState51(() => getMediaRevision());
29474
- useEffect41(() => {
29628
+ const [revision, setRevision] = useState53(() => getMediaRevision());
29629
+ useEffect42(() => {
29475
29630
  const timer = window.setInterval(() => {
29476
29631
  const next = getMediaRevision();
29477
29632
  setRevision((prev) => prev === next ? prev : next);
@@ -29497,13 +29652,13 @@ function DataCardWidget({
29497
29652
  }) {
29498
29653
  const link = useCardLink(editor, blockId);
29499
29654
  const revision = useMediaRevision(getMediaRevision);
29500
- const [state, setState3] = useState51({ kind: "loading" });
29501
- const [view, setView] = useState51(EMPTY_TABLE_VIEW_STATE);
29502
- const [viewPersisted, setViewPersisted] = useState51(false);
29503
- const [saving, setSaving] = useState51(false);
29655
+ const [state, setState3] = useState53({ kind: "loading" });
29656
+ const [view, setView] = useState53(EMPTY_TABLE_VIEW_STATE);
29657
+ const [viewPersisted, setViewPersisted] = useState53(false);
29658
+ const [saving, setSaving] = useState53(false);
29504
29659
  const savingRef = useRef42(false);
29505
- const [saveNotice, setSaveNotice] = useState51(null);
29506
- const [formulaDirty, setFormulaDirty] = useState51(0);
29660
+ const [saveNotice, setSaveNotice] = useState53(null);
29661
+ const [formulaDirty, setFormulaDirty] = useState53(0);
29507
29662
  const gridRef = useRef42(null);
29508
29663
  const href = link?.href ?? null;
29509
29664
  const cardPos = link?.pos ?? null;
@@ -29515,7 +29670,7 @@ function DataCardWidget({
29515
29670
  regionParams.anchor,
29516
29671
  regionParams.headerRow
29517
29672
  ]);
29518
- useEffect41(() => {
29673
+ useEffect42(() => {
29519
29674
  if (!href || cardPos === null) return;
29520
29675
  const provider = activeProvider;
29521
29676
  if (!provider) {
@@ -29677,7 +29832,7 @@ function DataCardWidget({
29677
29832
  cancelled = true;
29678
29833
  };
29679
29834
  }, [href, revision, activeProvider, activeContainer, regionIdentity, editor]);
29680
- useEffect41(
29835
+ useEffect42(
29681
29836
  () => () => {
29682
29837
  gridRef.current?.formulaSession?.dispose();
29683
29838
  gridRef.current?.provider.dispose();
@@ -30193,7 +30348,7 @@ function pasteVideoEmbedCode(view, text) {
30193
30348
  }
30194
30349
 
30195
30350
  // src/treeview/treeViewData.ts
30196
- import { useEffect as useEffect42, useMemo as useMemo36, useState as useState53 } from "react";
30351
+ import { useEffect as useEffect43, useMemo as useMemo36, useState as useState55 } from "react";
30197
30352
 
30198
30353
  // src/treeview/TreeViewExtension.ts
30199
30354
  import { Extension as Extension12 } from "@tiptap/core";
@@ -30210,7 +30365,7 @@ import {
30210
30365
  } from "@bendyline/squisq/doc";
30211
30366
 
30212
30367
  // src/treeview/TreeOutlineWidget.tsx
30213
- import { useCallback as useCallback40, useRef as useRef43, useState as useState52 } from "react";
30368
+ import { useCallback as useCallback40, useRef as useRef43, useState as useState54 } from "react";
30214
30369
 
30215
30370
  // src/treeview/treeViewCommands.ts
30216
30371
  import { parseTree, renderTree } from "@bendyline/squisq/doc";
@@ -30447,10 +30602,10 @@ function dropPositionForPointer(event) {
30447
30602
  }
30448
30603
  function TreeOutlineWidget({ editor, blockId }) {
30449
30604
  const view = useTreeViewData(editor, blockId);
30450
- const [collapsed, setCollapsed] = useState52(() => /* @__PURE__ */ new Set());
30605
+ const [collapsed, setCollapsed] = useState54(() => /* @__PURE__ */ new Set());
30451
30606
  const activeDragRef = useRef43(null);
30452
- const [draggedId, setDraggedId] = useState52(null);
30453
- const [dropTarget, setDropTarget] = useState52(null);
30607
+ const [draggedId, setDraggedId] = useState54(null);
30608
+ const [dropTarget, setDropTarget] = useState54(null);
30454
30609
  const dispatch = useCallback40(
30455
30610
  (cmd) => applyTreeCommand(editor, blockId, cmd),
30456
30611
  [editor, blockId]
@@ -30597,7 +30752,7 @@ function TreeRowView({
30597
30752
  const hasChildren = node2.children.length > 0;
30598
30753
  const isCollapsed = collapsed.has(node2.id);
30599
30754
  const isDir = node2.isDir || hasChildren;
30600
- const [draft, setDraft] = useState52(node2.label);
30755
+ const [draft, setDraft] = useState54(node2.label);
30601
30756
  const dropPosition = dropTarget?.id === node2.id ? dropTarget.position : null;
30602
30757
  const itemClassName = [
30603
30758
  "squisq-tree-item",
@@ -30901,8 +31056,8 @@ var TreeViewExtension = Extension12.create({
30901
31056
 
30902
31057
  // src/treeview/treeViewData.ts
30903
31058
  function useTreeViewData(editor, blockId) {
30904
- const [version, setVersion] = useState53(0);
30905
- useEffect42(() => {
31059
+ const [version, setVersion] = useState55(0);
31060
+ useEffect43(() => {
30906
31061
  const onUpdate = () => setVersion((v2) => v2 + 1);
30907
31062
  editor.on("transaction", onUpdate);
30908
31063
  return () => {
@@ -30928,7 +31083,7 @@ function shouldPasteAsTreeFence(text) {
30928
31083
  }
30929
31084
 
30930
31085
  // src/timeline/timelineData.ts
30931
- import { useEffect as useEffect44, useMemo as useMemo38, useRef as useRef45, useState as useState55 } from "react";
31086
+ import { useEffect as useEffect45, useMemo as useMemo38, useRef as useRef45, useState as useState57 } from "react";
30932
31087
 
30933
31088
  // src/timeline/TimelineViewExtension.ts
30934
31089
  import { Extension as Extension13 } from "@tiptap/core";
@@ -30943,7 +31098,7 @@ import {
30943
31098
  } from "@bendyline/squisq/doc";
30944
31099
 
30945
31100
  // src/timeline/TimelineEditorWidget.tsx
30946
- import { useCallback as useCallback41, useEffect as useEffect43, useMemo as useMemo37, useRef as useRef44, useState as useState54 } from "react";
31101
+ import { useCallback as useCallback41, useEffect as useEffect44, useMemo as useMemo37, useRef as useRef44, useState as useState56 } from "react";
30947
31102
  import {
30948
31103
  asciiTimelineToTemplateData
30949
31104
  } from "@bendyline/squisq/doc";
@@ -31427,13 +31582,13 @@ import { Fragment as Fragment19, jsx as jsx61, jsxs as jsxs48 } from "react/jsx-
31427
31582
  var clamp01 = (value) => Math.max(0, Math.min(1, value));
31428
31583
  function TimelineEditorWidget({ editor, blockId }) {
31429
31584
  const view = useTimelineData(editor, blockId);
31430
- const [selectedEventId, setSelectedEventId] = useState54(null);
31431
- const [addingTrackId, setAddingTrackId] = useState54(null);
31432
- const [editingTrackId, setEditingTrackId] = useState54(null);
31433
- const [hover, setHover] = useState54(null);
31434
- const [dragged, setDragged] = useState54(null);
31585
+ const [selectedEventId, setSelectedEventId] = useState56(null);
31586
+ const [addingTrackId, setAddingTrackId] = useState56(null);
31587
+ const [editingTrackId, setEditingTrackId] = useState56(null);
31588
+ const [hover, setHover] = useState56(null);
31589
+ const [dragged, setDragged] = useState56(null);
31435
31590
  const suppressClickEventId = useRef44(null);
31436
- const [announcement, setAnnouncement] = useState54("");
31591
+ const [announcement, setAnnouncement] = useState56("");
31437
31592
  const dispatch = useCallback41(
31438
31593
  (command) => {
31439
31594
  const result = applyTimelineCommand(editor, blockId, command);
@@ -31494,7 +31649,7 @@ function TimelineEditorWidget({ editor, blockId }) {
31494
31649
  }
31495
31650
  return null;
31496
31651
  }, [selectedEventId, view]);
31497
- useEffect43(() => {
31652
+ useEffect44(() => {
31498
31653
  if (!view) return;
31499
31654
  const ids = new Set(
31500
31655
  view.timeline.tracks.flatMap((track) => track.events.map((event) => event.id))
@@ -31502,13 +31657,13 @@ function TimelineEditorWidget({ editor, blockId }) {
31502
31657
  if (selectedEventId && ids.has(selectedEventId)) return;
31503
31658
  setSelectedEventId(view.timeline.tracks[0]?.events[0]?.id ?? null);
31504
31659
  }, [selectedEventId, view]);
31505
- useEffect43(() => {
31660
+ useEffect44(() => {
31506
31661
  if (editable) return;
31507
31662
  setAddingTrackId(null);
31508
31663
  setEditingTrackId(null);
31509
31664
  setHover(null);
31510
31665
  }, [editable]);
31511
- useEffect43(() => {
31666
+ useEffect44(() => {
31512
31667
  if (!editingTrackId || view?.timeline.tracks.some((track) => track.id === editingTrackId)) {
31513
31668
  return;
31514
31669
  }
@@ -31914,8 +32069,8 @@ function InlineTrackLabel({
31914
32069
  onStart,
31915
32070
  onFinish
31916
32071
  }) {
31917
- const [draft, setDraft] = useState54(label);
31918
- useEffect43(() => {
32072
+ const [draft, setDraft] = useState56(label);
32073
+ useEffect44(() => {
31919
32074
  if (editing) setDraft(label);
31920
32075
  }, [editing, label]);
31921
32076
  const commitLabel = () => {
@@ -31972,10 +32127,10 @@ function EventInspector({
31972
32127
  onDelete
31973
32128
  }) {
31974
32129
  const { event } = selected;
31975
- const [label, setLabel] = useState54(event.label);
31976
- const [description, setDescription] = useState54(event.description ?? "");
31977
- useEffect43(() => setLabel(event.label), [event.label]);
31978
- useEffect43(() => setDescription(event.description ?? ""), [event.description]);
32130
+ const [label, setLabel] = useState56(event.label);
32131
+ const [description, setDescription] = useState56(event.description ?? "");
32132
+ useEffect44(() => setLabel(event.label), [event.label]);
32133
+ useEffect44(() => setDescription(event.description ?? ""), [event.description]);
31979
32134
  const update = (patch) => dispatch(patch);
31980
32135
  const commitLabel = () => {
31981
32136
  const next = label.trim();
@@ -32280,9 +32435,9 @@ var TimelineViewExtension = Extension13.create({
32280
32435
 
32281
32436
  // src/timeline/timelineData.ts
32282
32437
  function useTimelineData(editor, blockId) {
32283
- const [version, setVersion] = useState55(0);
32438
+ const [version, setVersion] = useState57(0);
32284
32439
  const dataCache = useRef45(null);
32285
- useEffect44(() => {
32440
+ useEffect45(() => {
32286
32441
  const onEditorChange = () => setVersion((value) => value + 1);
32287
32442
  editor.on("transaction", onEditorChange);
32288
32443
  editor.on("update", onEditorChange);
@@ -32317,8 +32472,8 @@ function shouldPasteAsTimelineFence(text) {
32317
32472
  }
32318
32473
 
32319
32474
  // src/BlockPropertiesPopover.tsx
32320
- import { useEffect as useEffect45, useId as useId14, useRef as useRef46, useState as useState56 } from "react";
32321
- import { createPortal as createPortal13 } from "react-dom";
32475
+ import { useEffect as useEffect46, useId as useId13, useRef as useRef46, useState as useState58 } from "react";
32476
+ import { createPortal as createPortal14 } from "react-dom";
32322
32477
  import { jsx as jsx62, jsxs as jsxs49 } from "react/jsx-runtime";
32323
32478
  var TRANSITION_FLYOUT = ".squisq-transition-flyout";
32324
32479
  function BlockPropertiesPopover({
@@ -32332,14 +32487,14 @@ function BlockPropertiesPopover({
32332
32487
  onClose
32333
32488
  }) {
32334
32489
  const panelRef = useRef46(null);
32335
- const panelId = `squisq-block-props-portal-${useId14().replace(/:/g, "")}`;
32336
- const [inner, setInner] = useState56(blockAttrs);
32337
- const [templateInner, setTemplateInner] = useState56(templateParams);
32338
- const [style, setStyle] = useState56(() => computeStyle3(anchorRect));
32339
- useEffect45(() => {
32490
+ const panelId = `squisq-block-props-portal-${useId13().replace(/:/g, "")}`;
32491
+ const [inner, setInner] = useState58(blockAttrs);
32492
+ const [templateInner, setTemplateInner] = useState58(templateParams);
32493
+ const [style, setStyle] = useState58(() => computeStyle3(anchorRect));
32494
+ useEffect46(() => {
32340
32495
  requestAnimationFrame(() => setStyle(computeStyle3(anchorRect, panelRef.current)));
32341
32496
  }, [anchorRect]);
32342
- useEffect45(() => {
32497
+ useEffect46(() => {
32343
32498
  const onKey = (e2) => {
32344
32499
  if (e2.key === "Escape") onClose();
32345
32500
  };
@@ -32372,7 +32527,7 @@ function BlockPropertiesPopover({
32372
32527
  };
32373
32528
  const onDuration = (v2) => apply(setBlockAttrsValue(inner, "duration", v2));
32374
32529
  const onStartTime = (v2) => apply(setBlockAttrsValue(inner, "startTime", v2));
32375
- return createPortal13(
32530
+ return createPortal14(
32376
32531
  /* @__PURE__ */ jsxs49(
32377
32532
  "div",
32378
32533
  {
@@ -32501,7 +32656,7 @@ function persistFromWrite(bodyMd, state) {
32501
32656
  }
32502
32657
 
32503
32658
  // src/WysiwygEditor.tsx
32504
- import { useCallback as useCallback42, useEffect as useEffect49, useMemo as useMemo40, useRef as useRef48, useState as useState60 } from "react";
32659
+ import { useCallback as useCallback42, useEffect as useEffect50, useMemo as useMemo40, useRef as useRef48, useState as useState62 } from "react";
32505
32660
  import { useEditor as useEditor2, EditorContent as EditorContent2 } from "@tiptap/react";
32506
32661
  import { Selection } from "@tiptap/pm/state";
32507
32662
  import { Extension as Extension14 } from "@tiptap/core";
@@ -32590,7 +32745,7 @@ var InlineIcon = Node2.create({
32590
32745
  });
32591
32746
 
32592
32747
  // src/ImageNodeView.tsx
32593
- import { useEffect as useEffect46, useRef as useRef47, useState as useState57 } from "react";
32748
+ import { useEffect as useEffect47, useRef as useRef47, useState as useState59 } from "react";
32594
32749
  import { NodeViewWrapper, ReactNodeViewRenderer } from "@tiptap/react";
32595
32750
  import Image from "@tiptap/extension-image";
32596
32751
  import { mergeAttributes as mergeAttributes3 } from "@tiptap/core";
@@ -32614,12 +32769,12 @@ import { Fragment as Fragment20, jsx as jsx63, jsxs as jsxs50 } from "react/jsx-
32614
32769
  function ImageComponent({ node: node2, selected, editor, updateAttributes }) {
32615
32770
  const { src, alt, title, width } = node2.attrs;
32616
32771
  const { mediaProvider, imageDisplayMode, openImageEdit, mediaRevision } = useEditorContext();
32617
- const [resolution, setResolution] = useState57(null);
32618
- const [imageLoad, setImageLoad] = useState57(null);
32772
+ const [resolution, setResolution] = useState59(null);
32773
+ const [imageLoad, setImageLoad] = useState59(null);
32619
32774
  const isUploading = title?.startsWith("squisq-upload:") ?? false;
32620
- const [hovered, setHovered] = useState57(false);
32775
+ const [hovered, setHovered] = useState59(false);
32621
32776
  const imgRef = useRef47(null);
32622
- const [previewWidth, setPreviewWidth] = useState57(null);
32777
+ const [previewWidth, setPreviewWidth] = useState59(null);
32623
32778
  const isThumbnail = imageDisplayMode === "thumbnail";
32624
32779
  const isEditable = editor?.isEditable ?? true;
32625
32780
  const normalizedRelativePath = normalizeMalformedAssetUrl(src);
@@ -32629,7 +32784,7 @@ function ImageComponent({ node: node2, selected, editor, updateAttributes }) {
32629
32784
  const currentResolution = resolution?.src === src && resolution.provider === mediaProvider && resolution.revision === mediaRevision ? resolution : null;
32630
32785
  const resolvedSrc = isUploading ? "" : needsResolution ? currentResolution?.url ?? "" : src;
32631
32786
  const resolutionFailed = needsResolution && currentResolution?.url === null;
32632
- useEffect46(() => {
32787
+ useEffect47(() => {
32633
32788
  if (isUploading || !mediaProvider || !resolveAs) return;
32634
32789
  setImageLoad(null);
32635
32790
  let cancelled = false;
@@ -32959,15 +33114,15 @@ function MediaEditButton({ src, kind, fx, className }) {
32959
33114
 
32960
33115
  // src/tiptap/TiptapVideo.tsx
32961
33116
  import { NodeViewWrapper as NodeViewWrapper2, ReactNodeViewRenderer as ReactNodeViewRenderer2 } from "@tiptap/react";
32962
- import { useEffect as useEffect48, useState as useState59 } from "react";
33117
+ import { useEffect as useEffect49, useState as useState61 } from "react";
32963
33118
 
32964
33119
  // src/tiptap/useResolvedMediaSrc.ts
32965
- import { useEffect as useEffect47, useState as useState58 } from "react";
33120
+ import { useEffect as useEffect48, useState as useState60 } from "react";
32966
33121
  function useResolvedMediaSrc(src) {
32967
33122
  const { mediaProvider, mediaRevision } = useEditorContext();
32968
33123
  const isRelative = !!src && !src.startsWith("blob:") && !src.startsWith("http:") && !src.startsWith("https:") && !src.startsWith("data:") && !src.startsWith("/");
32969
- const [resolved, setResolved] = useState58(isRelative && mediaProvider ? "" : src);
32970
- useEffect47(() => {
33124
+ const [resolved, setResolved] = useState60(isRelative && mediaProvider ? "" : src);
33125
+ useEffect48(() => {
32971
33126
  if (!mediaProvider || !isRelative) {
32972
33127
  setResolved(src);
32973
33128
  return;
@@ -33019,9 +33174,9 @@ function VideoNodeView({ node: node2, updateAttributes, selected }) {
33019
33174
  const placement = normalizeVideoPlacement(rawPlacement);
33020
33175
  const lockToBlock = normalizeLockToBlock(rawLockToBlock);
33021
33176
  const resolvedSrc = useResolvedMediaSrc(src ?? "");
33022
- const [audioOnly, setAudioOnly] = useState59(false);
33177
+ const [audioOnly, setAudioOnly] = useState61(false);
33023
33178
  const resolvedPoster = useResolvedMediaSrc(poster ?? "");
33024
- useEffect48(() => {
33179
+ useEffect49(() => {
33025
33180
  setAudioOnly(false);
33026
33181
  }, [resolvedSrc]);
33027
33182
  const handleLoadedMetadata = (event) => {
@@ -33780,6 +33935,7 @@ var SourceFrontmatter = Extension14.create({
33780
33935
  }
33781
33936
  });
33782
33937
  function WysiwygEditor({
33938
+ ariaLabel = "Document editor",
33783
33939
  placeholder,
33784
33940
  className,
33785
33941
  submitOnEnter,
@@ -33819,11 +33975,11 @@ function WysiwygEditor({
33819
33975
  mermaidThemeStoreRef.current = createMermaidThemeStore(activeTheme ?? DEFAULT_THEME4);
33820
33976
  }
33821
33977
  const mermaidThemeStore = mermaidThemeStoreRef.current;
33822
- useEffect49(() => {
33978
+ useEffect50(() => {
33823
33979
  mermaidThemeStore.setTheme(activeTheme ?? DEFAULT_THEME4);
33824
33980
  }, [activeTheme, mermaidThemeStore]);
33825
33981
  const { docTemplates, onDocTemplatesChange } = useDocCustomTemplates();
33826
- const [designerState, setDesignerState] = useState60(
33982
+ const [designerState, setDesignerState] = useState62(
33827
33983
  null
33828
33984
  );
33829
33985
  const handleDesignerSave = useCallback42(
@@ -33839,19 +33995,19 @@ function WysiwygEditor({
33839
33995
  [docTemplates, onDocTemplatesChange]
33840
33996
  );
33841
33997
  const mentionProviderRef = useRef48(mentionProvider);
33842
- useEffect49(() => {
33998
+ useEffect50(() => {
33843
33999
  mentionProviderRef.current = mentionProvider;
33844
34000
  }, [mentionProvider]);
33845
34001
  const fenceRenderersRef = useRef48(fenceRenderers);
33846
- useEffect49(() => {
34002
+ useEffect50(() => {
33847
34003
  fenceRenderersRef.current = fenceRenderers;
33848
34004
  }, [fenceRenderers]);
33849
34005
  const onCopyCodeRef = useRef48(onCopyCode);
33850
- useEffect49(() => {
34006
+ useEffect50(() => {
33851
34007
  onCopyCodeRef.current = onCopyCode;
33852
34008
  }, [onCopyCode]);
33853
34009
  const activeThemeRef = useRef48(activeTheme);
33854
- useEffect49(() => {
34010
+ useEffect50(() => {
33855
34011
  activeThemeRef.current = activeTheme;
33856
34012
  }, [activeTheme]);
33857
34013
  const resolvedPlaceholder = useMemo40(() => placeholder ?? pickEmptyPrompt(), [placeholder]);
@@ -33861,30 +34017,30 @@ function WysiwygEditor({
33861
34017
  const pendingLocalSourcesRef = useRef48([]);
33862
34018
  const mediaProviderRef = useRef48(mediaProvider);
33863
34019
  const mediaRevisionRef = useRef48(mediaRevision);
33864
- useEffect49(() => {
34020
+ useEffect50(() => {
33865
34021
  mediaRevisionRef.current = mediaRevision;
33866
34022
  }, [mediaRevision]);
33867
34023
  const onOpenFilesPanelRef = useRef48(onOpenFilesPanel);
33868
- useEffect49(() => {
34024
+ useEffect50(() => {
33869
34025
  onOpenFilesPanelRef.current = onOpenFilesPanel;
33870
34026
  }, [onOpenFilesPanel]);
33871
34027
  const calcEngineFactoryRef = useRef48(calcEngineFactory);
33872
- useEffect49(() => {
34028
+ useEffect50(() => {
33873
34029
  calcEngineFactoryRef.current = calcEngineFactory;
33874
34030
  }, [calcEngineFactory]);
33875
34031
  const workspaceContainerRef = useRef48(workspaceContainer);
33876
- useEffect49(() => {
34032
+ useEffect50(() => {
33877
34033
  workspaceContainerRef.current = workspaceContainer;
33878
34034
  }, [workspaceContainer]);
33879
34035
  const bumpMediaRevisionRef = useRef48(bumpMediaRevision);
33880
- useEffect49(() => {
34036
+ useEffect50(() => {
33881
34037
  bumpMediaRevisionRef.current = bumpMediaRevision;
33882
34038
  }, [bumpMediaRevision]);
33883
- useEffect49(() => {
34039
+ useEffect50(() => {
33884
34040
  mediaProviderRef.current = mediaProvider;
33885
34041
  }, [mediaProvider]);
33886
- const [accessoryPaths, setAccessoryPaths] = useState60(() => /* @__PURE__ */ new Set());
33887
- useEffect49(() => {
34042
+ const [accessoryPaths, setAccessoryPaths] = useState62(() => /* @__PURE__ */ new Set());
34043
+ useEffect50(() => {
33888
34044
  if (!mediaProvider) {
33889
34045
  setAccessoryPaths(/* @__PURE__ */ new Set());
33890
34046
  return;
@@ -33916,7 +34072,7 @@ function WysiwygEditor({
33916
34072
  }
33917
34073
  }
33918
34074
  const submitOnEnterRef = useRef48(submitOnEnter);
33919
- useEffect49(() => {
34075
+ useEffect50(() => {
33920
34076
  submitOnEnterRef.current = submitOnEnter;
33921
34077
  }, [submitOnEnter]);
33922
34078
  const editor = useEditor2({
@@ -34000,7 +34156,11 @@ function WysiwygEditor({
34000
34156
  editorProps: {
34001
34157
  attributes: {
34002
34158
  class: "squisq-wysiwyg-editor",
34003
- "data-testid": "wysiwyg-editor"
34159
+ "data-testid": "wysiwyg-editor",
34160
+ role: "textbox",
34161
+ "aria-label": ariaLabel,
34162
+ "aria-multiline": "true",
34163
+ "aria-readonly": String(readOnly)
34004
34164
  },
34005
34165
  // Chat-composer mode: Enter commits via submitOnEnter(), Cmd/Ctrl+Enter
34006
34166
  // inserts a soft break. When no callback is set, fall through to Tiptap's
@@ -34133,13 +34293,13 @@ function WysiwygEditor({
34133
34293
  }
34134
34294
  }
34135
34295
  });
34136
- useEffect49(() => {
34296
+ useEffect50(() => {
34137
34297
  if (editor) {
34138
34298
  setTiptapEditor(editor);
34139
34299
  }
34140
34300
  return () => setTiptapEditor(null);
34141
34301
  }, [editor, setTiptapEditor]);
34142
- useEffect49(() => {
34302
+ useEffect50(() => {
34143
34303
  if (!editor) return;
34144
34304
  const syncPlaceholders = () => {
34145
34305
  syncAccessoryFileLinkPlaceholders(editor.view.dom, accessoryPaths);
@@ -34150,19 +34310,19 @@ function WysiwygEditor({
34150
34310
  editor.off("update", syncPlaceholders);
34151
34311
  };
34152
34312
  }, [accessoryPaths, editor]);
34153
- useEffect49(() => {
34313
+ useEffect50(() => {
34154
34314
  if (editor) editor.setEditable(!readOnly);
34155
34315
  }, [editor, readOnly]);
34156
34316
  const containerRef = useRef48(null);
34157
- const [badgeMenu, setBadgeMenu] = useState60(null);
34158
- const [propsMenu, setPropsMenu] = useState60(null);
34317
+ const [badgeMenu, setBadgeMenu] = useState62(null);
34318
+ const [propsMenu, setPropsMenu] = useState62(null);
34159
34319
  const closeBadgeMenu = useCallback42(() => {
34160
34320
  setBadgeMenu(null);
34161
34321
  requestAnimationFrame(() => {
34162
34322
  if (editor && !editor.isDestroyed) editor.commands.focus();
34163
34323
  });
34164
34324
  }, [editor]);
34165
- useEffect49(() => {
34325
+ useEffect50(() => {
34166
34326
  if (!editor) return;
34167
34327
  const root = containerRef.current;
34168
34328
  if (!root) return;
@@ -34218,7 +34378,7 @@ function WysiwygEditor({
34218
34378
  root.addEventListener("mousedown", onClick);
34219
34379
  return () => root.removeEventListener("mousedown", onClick);
34220
34380
  }, [editor]);
34221
- useEffect49(() => {
34381
+ useEffect50(() => {
34222
34382
  if (!editor) return;
34223
34383
  const layoutChanged = sourceLayoutRef.current !== layoutMode;
34224
34384
  sourceLayoutRef.current = layoutMode;
@@ -34484,7 +34644,7 @@ function moveSelectionToDropPoint(view, event) {
34484
34644
  }
34485
34645
 
34486
34646
  // src/InlinePreviewGutter.tsx
34487
- import { useLayoutEffect as useLayoutEffect10, useMemo as useMemo42, useRef as useRef49, useState as useState63 } from "react";
34647
+ import { useLayoutEffect as useLayoutEffect13, useMemo as useMemo42, useRef as useRef49, useState as useState65 } from "react";
34488
34648
  import { VIEWPORT_PRESETS as VIEWPORT_PRESETS5 } from "@bendyline/squisq/schemas";
34489
34649
  import {
34490
34650
  flattenBlocks as flattenBlocks4,
@@ -34496,14 +34656,14 @@ import { extractPlainText as extractPlainText3, getChildren } from "@bendyline/s
34496
34656
  import { BlockRenderer as BlockRenderer3, MediaContext as MediaContext4 } from "@bendyline/squisq-react";
34497
34657
 
34498
34658
  // src/useHeadingLayout.ts
34499
- import { useCallback as useCallback43, useEffect as useEffect50, useMemo as useMemo41, useState as useState61 } from "react";
34659
+ import { useCallback as useCallback43, useEffect as useEffect51, useMemo as useMemo41, useState as useState63 } from "react";
34500
34660
  import { flattenBlocks as flattenBlocks3, hasTemplate } from "@bendyline/squisq/doc";
34501
34661
  function useHeadingLayout(refInsideWrapper) {
34502
34662
  const { doc, activeView, monacoEditor, tiptapEditor } = useEditorContext();
34503
34663
  const flatBlocks = useMemo41(() => doc ? flattenBlocks3(doc.blocks) : [], [doc]);
34504
- const [entries, setEntries] = useState61([]);
34505
- const [pageEdges, setPageEdges] = useState61(null);
34506
- useEffect50(() => {
34664
+ const [entries, setEntries] = useState63([]);
34665
+ const [pageEdges, setPageEdges] = useState63(null);
34666
+ useEffect51(() => {
34507
34667
  if (activeView !== "wysiwyg") return;
34508
34668
  const node2 = refInsideWrapper.current;
34509
34669
  if (!node2) return;
@@ -34571,7 +34731,7 @@ function useHeadingLayout(refInsideWrapper) {
34571
34731
  window.removeEventListener("resize", recompute);
34572
34732
  };
34573
34733
  }, [activeView, flatBlocks, refInsideWrapper]);
34574
- useEffect50(() => {
34734
+ useEffect51(() => {
34575
34735
  if (activeView !== "raw") return;
34576
34736
  if (!monacoEditor) return;
34577
34737
  const node2 = refInsideWrapper.current;
@@ -34632,7 +34792,7 @@ function useHeadingLayout(refInsideWrapper) {
34632
34792
  window.removeEventListener("resize", recompute);
34633
34793
  };
34634
34794
  }, [activeView, monacoEditor, flatBlocks, refInsideWrapper]);
34635
- useEffect50(() => {
34795
+ useEffect51(() => {
34636
34796
  setEntries([]);
34637
34797
  setPageEdges(null);
34638
34798
  }, [activeView]);
@@ -34694,7 +34854,7 @@ function sameEntries(a, b) {
34694
34854
  }
34695
34855
 
34696
34856
  // src/usePreviewProjection.ts
34697
- import { useEffect as useEffect51, useState as useState62 } from "react";
34857
+ import { useEffect as useEffect52, useState as useState64 } from "react";
34698
34858
  import {
34699
34859
  resolveAudioMapping,
34700
34860
  resolveDataReferences
@@ -34740,8 +34900,8 @@ function preserveEquivalentAudio(previous, next) {
34740
34900
  };
34741
34901
  }
34742
34902
  function usePreviewProjection(doc, transformStyle, workspaceContainer, documentTitle2, mediaRevision) {
34743
- const [projection, setProjection] = useState62(null);
34744
- useEffect51(() => {
34903
+ const [projection, setProjection] = useState64(null);
34904
+ useEffect52(() => {
34745
34905
  if (!doc || !doc.blocks.length) {
34746
34906
  setProjection(null);
34747
34907
  return;
@@ -35022,8 +35182,8 @@ function InlinePreviewGutter({
35022
35182
  headingEntries.forEach((e2) => m.set(e2.block.id, e2.top));
35023
35183
  return m;
35024
35184
  }, [headingEntries]);
35025
- const [positions, setPositions] = useState63(/* @__PURE__ */ new Map());
35026
- useLayoutEffect10(() => {
35185
+ const [positions, setPositions] = useState65(/* @__PURE__ */ new Map());
35186
+ useLayoutEffect13(() => {
35027
35187
  if (items.length === 0) {
35028
35188
  setPositions((prev) => prev.size === 0 ? prev : /* @__PURE__ */ new Map());
35029
35189
  return;
@@ -35207,10 +35367,10 @@ function InlinePreviewGutter({
35207
35367
  import {
35208
35368
  memo,
35209
35369
  useCallback as useCallback44,
35210
- useEffect as useEffect52,
35370
+ useEffect as useEffect53,
35211
35371
  useMemo as useMemo43,
35212
35372
  useRef as useRef50,
35213
- useState as useState64
35373
+ useState as useState66
35214
35374
  } from "react";
35215
35375
  import { flattenBlocks as flattenBlocks5, hasTemplate as hasTemplate2 } from "@bendyline/squisq/doc";
35216
35376
  import { extractPlainText as extractPlainText4 } from "@bendyline/squisq/markdown";
@@ -35332,8 +35492,8 @@ function OutlinePanel({ width, className, readOnly = false }) {
35332
35492
  const paneRef = useRef50(null);
35333
35493
  const cursorActiveId = useActiveOutlineBlockId();
35334
35494
  const activeDragRef = useRef50(null);
35335
- const [draggedBlockId, setDraggedBlockId] = useState64(null);
35336
- const [dropTarget, setDropTarget] = useState64(null);
35495
+ const [draggedBlockId, setDraggedBlockId] = useState66(null);
35496
+ const [dropTarget, setDropTarget] = useState66(null);
35337
35497
  const nextOutlineBlocks = doc?.blocks ?? EMPTY_BLOCKS;
35338
35498
  const outlineBlocksRef = useRef50(nextOutlineBlocks);
35339
35499
  if (!sameOutlineStructure(outlineBlocksRef.current, nextOutlineBlocks)) {
@@ -35666,11 +35826,11 @@ function useActiveOutlineBlockId() {
35666
35826
  const flatBlocksRef = useRef50(flatBlocks);
35667
35827
  flatBlocksRef.current = flatBlocks;
35668
35828
  const headingLocations = flatBlocks.map((block) => `${block.id}:${block.sourceHeading?.position?.start.line ?? ""}`).join("\0");
35669
- const [activeId, setActiveId] = useState64(null);
35670
- useEffect52(() => {
35829
+ const [activeId, setActiveId] = useState66(null);
35830
+ useEffect53(() => {
35671
35831
  setActiveId(null);
35672
35832
  }, [activeView]);
35673
- useEffect52(() => {
35833
+ useEffect53(() => {
35674
35834
  if (activeView !== "wysiwyg" || !tiptapEditor) return;
35675
35835
  const update = () => {
35676
35836
  const { from } = tiptapEditor.state.selection;
@@ -35692,7 +35852,7 @@ function useActiveOutlineBlockId() {
35692
35852
  tiptapEditor.off("update", update);
35693
35853
  };
35694
35854
  }, [activeView, tiptapEditor, headingLocations]);
35695
- useEffect52(() => {
35855
+ useEffect53(() => {
35696
35856
  if (activeView !== "raw" || !monacoEditor) return;
35697
35857
  const update = () => {
35698
35858
  const line = monacoEditor.getPosition()?.lineNumber;
@@ -35779,8 +35939,8 @@ function bumpHeadingLevelInSource(source, line, delta) {
35779
35939
  }
35780
35940
 
35781
35941
  // src/codeContext/CodeContextZones.tsx
35782
- import { useCallback as useCallback46, useEffect as useEffect54, useMemo as useMemo45, useRef as useRef52, useState as useState65 } from "react";
35783
- import { createPortal as createPortal14 } from "react-dom";
35942
+ import { useCallback as useCallback46, useEffect as useEffect55, useMemo as useMemo45, useRef as useRef52, useState as useState67 } from "react";
35943
+ import { createPortal as createPortal15 } from "react-dom";
35784
35944
 
35785
35945
  // src/codeContext/diffContextSections.ts
35786
35946
  function diffContextSections(prev, next) {
@@ -35903,7 +36063,7 @@ function setOrdinal(zone, ordinal) {
35903
36063
  // src/codeContext/CodeContextSectionView.tsx
35904
36064
  import { parseMarkdown as parseMarkdown7 } from "@bendyline/squisq/markdown";
35905
36065
  import { MarkdownRenderer } from "@bendyline/squisq-react";
35906
- import { useCallback as useCallback45, useEffect as useEffect53, useMemo as useMemo44, useRef as useRef51 } from "react";
36066
+ import { useCallback as useCallback45, useEffect as useEffect54, useMemo as useMemo44, useRef as useRef51 } from "react";
35907
36067
  import { jsx as jsx70, jsxs as jsxs57 } from "react/jsx-runtime";
35908
36068
  function CodeContextSectionView({
35909
36069
  section,
@@ -35923,7 +36083,7 @@ function CodeContextSectionView({
35923
36083
  () => expanded && section.markdown ? parseMarkdown7(section.markdown).children : null,
35924
36084
  [expanded, section.markdown]
35925
36085
  );
35926
- useEffect53(() => {
36086
+ useEffect54(() => {
35927
36087
  const el = rootRef.current;
35928
36088
  if (!el || typeof ResizeObserver === "undefined") return;
35929
36089
  const report = () => {
@@ -35995,11 +36155,11 @@ function CodeContextSectionView({
35995
36155
  import { Fragment as Fragment23, jsx as jsx71 } from "react/jsx-runtime";
35996
36156
  function CodeContextZones({ options }) {
35997
36157
  const { monacoEditor } = useEditorContext();
35998
- const [manager, setManager] = useState65(null);
35999
- const [, setZonesVersion] = useState65(0);
36000
- const [expandedById, setExpandedById] = useState65({});
36158
+ const [manager, setManager] = useState67(null);
36159
+ const [, setZonesVersion] = useState67(0);
36160
+ const [expandedById, setExpandedById] = useState67({});
36001
36161
  const seenIds = useRef52(/* @__PURE__ */ new Set());
36002
- useEffect54(() => {
36162
+ useEffect55(() => {
36003
36163
  if (!monacoEditor) return;
36004
36164
  const mgr = new CodeContextZoneManager(monacoEditor);
36005
36165
  const off = mgr.onDidChangeZones(() => setZonesVersion((v2) => v2 + 1));
@@ -36022,7 +36182,7 @@ function CodeContextZones({ options }) {
36022
36182
  });
36023
36183
  return out;
36024
36184
  }, [fileTop, sections]);
36025
- useEffect54(() => {
36185
+ useEffect55(() => {
36026
36186
  if (!manager) return;
36027
36187
  manager.sync(resolved.map((r) => r.spec));
36028
36188
  setExpandedById((prev) => {
@@ -36064,7 +36224,7 @@ function CodeContextZones({ options }) {
36064
36224
  return /* @__PURE__ */ jsx71(Fragment23, { children: resolved.map(({ section }) => {
36065
36225
  const domNode = manager.getDomNode(section.id);
36066
36226
  if (!domNode) return null;
36067
- return createPortal14(
36227
+ return createPortal15(
36068
36228
  /* @__PURE__ */ jsx71(
36069
36229
  CodeContextSectionView,
36070
36230
  {
@@ -36488,7 +36648,7 @@ function placeClipInBlock(source, fromLine, targetHeadingLine, spec, startAt) {
36488
36648
  }
36489
36649
 
36490
36650
  // src/TimelineTrack.tsx
36491
- import { useCallback as useCallback48, useEffect as useEffect57, useMemo as useMemo46, useRef as useRef55, useState as useState68 } from "react";
36651
+ import { useCallback as useCallback48, useEffect as useEffect58, useMemo as useMemo46, useRef as useRef55, useState as useState70 } from "react";
36492
36652
  import {
36493
36653
  resolveMediaSchedule as resolveMediaSchedule2,
36494
36654
  getDocPlaybackDuration,
@@ -36500,7 +36660,7 @@ import { useProcessedAudio as useProcessedAudio2 } from "@bendyline/squisq-video
36500
36660
  import { MediaClipLayer, MediaContext as MediaContext5 } from "@bendyline/squisq-react";
36501
36661
 
36502
36662
  // src/useTimelineClock.ts
36503
- import { useCallback as useCallback47, useEffect as useEffect55, useRef as useRef53, useState as useState66 } from "react";
36663
+ import { useCallback as useCallback47, useEffect as useEffect56, useRef as useRef53, useState as useState68 } from "react";
36504
36664
  function advanceTime(prev, dt, total) {
36505
36665
  if (total <= 0) return 0;
36506
36666
  return Math.min(total, Math.max(0, prev + dt));
@@ -36520,8 +36680,8 @@ function playTimelineMediaAt(root, time) {
36520
36680
  });
36521
36681
  }
36522
36682
  function useTimelineClock(total) {
36523
- const [currentTime, setCurrentTime] = useState66(0);
36524
- const [isPlaying, setIsPlaying] = useState66(false);
36683
+ const [currentTime, setCurrentTime] = useState68(0);
36684
+ const [isPlaying, setIsPlaying] = useState68(false);
36525
36685
  const rafRef = useRef53(null);
36526
36686
  const lastRef = useRef53(0);
36527
36687
  const currentTimeRef = useRef53(0);
@@ -36529,10 +36689,10 @@ function useTimelineClock(total) {
36529
36689
  const mediaHostRef = useRef53(null);
36530
36690
  currentTimeRef.current = currentTime;
36531
36691
  isPlayingRef.current = isPlaying;
36532
- useEffect55(() => {
36692
+ useEffect56(() => {
36533
36693
  setCurrentTime((t) => Math.min(t, Math.max(0, total)));
36534
36694
  }, [total]);
36535
- useEffect55(() => {
36695
+ useEffect56(() => {
36536
36696
  if (!isPlaying) return;
36537
36697
  lastRef.current = performance.now();
36538
36698
  const tick = (now) => {
@@ -36630,8 +36790,8 @@ function timelineBars(clips) {
36630
36790
  }
36631
36791
 
36632
36792
  // src/TimelineItemMenu.tsx
36633
- import { useEffect as useEffect56, useLayoutEffect as useLayoutEffect11, useRef as useRef54, useState as useState67 } from "react";
36634
- import { createPortal as createPortal15 } from "react-dom";
36793
+ import { useEffect as useEffect57, useLayoutEffect as useLayoutEffect14, useRef as useRef54, useState as useState69 } from "react";
36794
+ import { createPortal as createPortal16 } from "react-dom";
36635
36795
  import { Fragment as Fragment24, jsx as jsx73, jsxs as jsxs59 } from "react/jsx-runtime";
36636
36796
  function TimelineItemMenu({
36637
36797
  anchor,
@@ -36646,8 +36806,8 @@ function TimelineItemMenu({
36646
36806
  onClose
36647
36807
  }) {
36648
36808
  const panelRef = useRef54(null);
36649
- const [style, setStyle] = useState67(() => menuStyle(anchor));
36650
- useLayoutEffect11(() => {
36809
+ const [style, setStyle] = useState69(() => menuStyle(anchor));
36810
+ useLayoutEffect14(() => {
36651
36811
  const panel = panelRef.current;
36652
36812
  if (!panel) return;
36653
36813
  const updatePosition = () => setStyle(menuStyle(anchor, panel));
@@ -36660,7 +36820,7 @@ function TimelineItemMenu({
36660
36820
  resizeObserver?.disconnect();
36661
36821
  };
36662
36822
  }, [anchor]);
36663
- useEffect56(() => {
36823
+ useEffect57(() => {
36664
36824
  const onKeyDown = (event) => {
36665
36825
  if (event.key !== "Escape") return;
36666
36826
  event.preventDefault();
@@ -36680,7 +36840,7 @@ function TimelineItemMenu({
36680
36840
  document.removeEventListener("mousedown", onMouseDown);
36681
36841
  };
36682
36842
  }, [onClose]);
36683
- return createPortal15(
36843
+ return createPortal16(
36684
36844
  /* @__PURE__ */ jsxs59(
36685
36845
  "div",
36686
36846
  {
@@ -36734,12 +36894,12 @@ function BlockMenu({
36734
36894
  onStartTime,
36735
36895
  onTransition
36736
36896
  }) {
36737
- const [explicitDuration, setExplicitDuration] = useState67(target.explicitDuration);
36738
- const [duration, setDuration] = useState67(formatNumber(target.duration));
36739
- const [startTime, setStartTime] = useState67(
36897
+ const [explicitDuration, setExplicitDuration] = useState69(target.explicitDuration);
36898
+ const [duration, setDuration] = useState69(formatNumber(target.duration));
36899
+ const [startTime, setStartTime] = useState69(
36740
36900
  target.startTime == null ? "" : formatNumber(target.startTime)
36741
36901
  );
36742
- const [transition, setTransition] = useState67(target.transition);
36902
+ const [transition, setTransition] = useState69(target.transition);
36743
36903
  const toggleAutotime = (autotimed) => {
36744
36904
  setExplicitDuration(!autotimed);
36745
36905
  if (autotimed) {
@@ -36811,11 +36971,11 @@ function VideoMenu({
36811
36971
  target,
36812
36972
  onPatch
36813
36973
  }) {
36814
- const [placement, setPlacement] = useState67(target.placement);
36815
- const [locked, setLocked] = useState67(target.lockToBlock);
36816
- const [pipSize, setPipSize] = useState67(target.pipSize ?? "");
36817
- const [pipShape, setPipShape] = useState67(target.pipShape ?? "");
36818
- const [pipPosition, setPipPosition] = useState67(target.pipPosition ?? "");
36974
+ const [placement, setPlacement] = useState69(target.placement);
36975
+ const [locked, setLocked] = useState69(target.lockToBlock);
36976
+ const [pipSize, setPipSize] = useState69(target.pipSize ?? "");
36977
+ const [pipShape, setPipShape] = useState69(target.pipShape ?? "");
36978
+ const [pipPosition, setPipPosition] = useState69(target.pipPosition ?? "");
36819
36979
  const placed = placement === "picture-in-picture" || placement === "overlay";
36820
36980
  const placementOptions = [
36821
36981
  target.canUseContentPlacement ? { value: "content", label: "In layout" } : { value: "default", label: "Default" },
@@ -37088,9 +37248,9 @@ function TimelineTrack({
37088
37248
  } = useEditorContext();
37089
37249
  const processedAudio = useProcessedAudio2(mediaEditRenders);
37090
37250
  const doc = docProp ?? contextDoc;
37091
- const [drag, setDrag] = useState68(null);
37092
- const [itemMenu, setItemMenu] = useState68(null);
37093
- const [pxPerSecond, setPxPerSecond] = useState68(DEFAULT_PX_PER_SECOND);
37251
+ const [drag, setDrag] = useState70(null);
37252
+ const [itemMenu, setItemMenu] = useState70(null);
37253
+ const [pxPerSecond, setPxPerSecond] = useState70(DEFAULT_PX_PER_SECOND);
37094
37254
  const scrollRef = useRef55(null);
37095
37255
  const blocks = useMemo46(() => doc ? flattenBlocks6(doc.blocks) : [], [doc]);
37096
37256
  const previewSettings = usePreviewSettingsOptional();
@@ -37123,8 +37283,8 @@ function TimelineTrack({
37123
37283
  setDrag(null);
37124
37284
  play();
37125
37285
  }, [play]);
37126
- const [scrubbing, setScrubbing] = useState68(false);
37127
- useEffect57(() => {
37286
+ const [scrubbing, setScrubbing] = useState70(false);
37287
+ useEffect58(() => {
37128
37288
  if (!scrubbing) return;
37129
37289
  const onMove = (e2) => {
37130
37290
  const scroll = scrollRef.current;
@@ -37162,7 +37322,7 @@ function TimelineTrack({
37162
37322
  [blocks]
37163
37323
  );
37164
37324
  const followedBlockRef = useRef55(null);
37165
- useEffect57(() => {
37325
+ useEffect58(() => {
37166
37326
  if (!isPlaying) {
37167
37327
  followedBlockRef.current = null;
37168
37328
  return;
@@ -37173,7 +37333,7 @@ function TimelineTrack({
37173
37333
  const line = headingLine(block);
37174
37334
  if (line != null) goToBlockByLine(line);
37175
37335
  }, [isPlaying, currentTime, blockAtTime, goToBlockByLine]);
37176
- useEffect57(() => {
37336
+ useEffect58(() => {
37177
37337
  if (!isPlaying) return;
37178
37338
  const scroll = scrollRef.current;
37179
37339
  if (!scroll) return;
@@ -37221,8 +37381,8 @@ function TimelineTrack({
37221
37381
  );
37222
37382
  const zoomIn = useCallback48(() => setPxPerSecond((s) => Math.min(ZOOM_MAX, s * ZOOM_FACTOR)), []);
37223
37383
  const zoomOut = useCallback48(() => setPxPerSecond((s) => Math.max(ZOOM_MIN, s / ZOOM_FACTOR)), []);
37224
- const [viewportWidth, setViewportWidth] = useState68(0);
37225
- useEffect57(() => {
37384
+ const [viewportWidth, setViewportWidth] = useState70(0);
37385
+ useEffect58(() => {
37226
37386
  const el = scrollRef.current;
37227
37387
  if (!el || typeof ResizeObserver === "undefined") return;
37228
37388
  const update = () => setViewportWidth(el.clientWidth);
@@ -37236,7 +37396,7 @@ function TimelineTrack({
37236
37396
  const dragRef = useRef55(null);
37237
37397
  dragRef.current = drag;
37238
37398
  const isDragging = drag != null && !drag.committed;
37239
- useEffect57(() => {
37399
+ useEffect58(() => {
37240
37400
  if (!isDragging) return;
37241
37401
  const onMove = (e2) => {
37242
37402
  const d = dragRef.current;
@@ -37267,7 +37427,7 @@ function TimelineTrack({
37267
37427
  window.removeEventListener("pointerup", onUp);
37268
37428
  };
37269
37429
  }, [isDragging]);
37270
- useEffect57(() => {
37430
+ useEffect58(() => {
37271
37431
  if (dragRef.current?.committed) setDrag(null);
37272
37432
  }, [doc]);
37273
37433
  const beginDrag = useCallback48(
@@ -38121,7 +38281,7 @@ function TimelineToolbar({
38121
38281
  }
38122
38282
 
38123
38283
  // src/PlainHtmlPreview.tsx
38124
- import { useCallback as useCallback49, useEffect as useEffect58, useMemo as useMemo49, useRef as useRef56, useState as useState69 } from "react";
38284
+ import { useCallback as useCallback49, useEffect as useEffect59, useMemo as useMemo49, useRef as useRef56, useState as useState71 } from "react";
38125
38285
  import { parseMarkdown as parseMarkdown8 } from "@bendyline/squisq/markdown";
38126
38286
 
38127
38287
  // src/utils/collectInlineFontAwesomeCss.ts
@@ -38202,8 +38362,8 @@ function PlainHtmlPreview({
38202
38362
  [onFrameChange]
38203
38363
  );
38204
38364
  const mdDoc = useMemo49(() => parseMarkdown8(markdown), [markdown]);
38205
- const [resolvedImages, setResolvedImages] = useState69(null);
38206
- useEffect58(() => {
38365
+ const [resolvedImages, setResolvedImages] = useState71(null);
38366
+ useEffect59(() => {
38207
38367
  if (!mediaProvider) {
38208
38368
  setResolvedImages(null);
38209
38369
  return;
@@ -38239,8 +38399,8 @@ function PlainHtmlPreview({
38239
38399
  return merged;
38240
38400
  }, [resolvedImages, images]);
38241
38401
  const iconsCss = useMemo49(() => collectInlineFontAwesomeCss(), []);
38242
- const [renderFn, setRenderFn] = useState69(() => cachedRender);
38243
- useEffect58(() => {
38402
+ const [renderFn, setRenderFn] = useState71(() => cachedRender);
38403
+ useEffect59(() => {
38244
38404
  if (renderFn) return;
38245
38405
  let cancelled = false;
38246
38406
  loadRenderFn().then((fn) => {
@@ -38277,7 +38437,7 @@ function PlainHtmlPreview({
38277
38437
  frameDocument.addEventListener("click", handleClick, true);
38278
38438
  removeFrameLinkHandlerRef.current = () => frameDocument.removeEventListener("click", handleClick, true);
38279
38439
  }, [onLinkClick]);
38280
- useEffect58(() => {
38440
+ useEffect59(() => {
38281
38441
  installFrameLinkHandler();
38282
38442
  return () => removeFrameLinkHandlerRef.current();
38283
38443
  }, [html, installFrameLinkHandler]);
@@ -38373,11 +38533,11 @@ function PlainHtmlPreview({
38373
38533
  style2.remove();
38374
38534
  };
38375
38535
  }, [onCopyCode, showCodeCopyButton]);
38376
- useEffect58(() => {
38536
+ useEffect59(() => {
38377
38537
  installFrameCodeCopyControls();
38378
38538
  return () => removeFrameCodeCopyControlsRef.current();
38379
38539
  }, [html, installFrameCodeCopyControls]);
38380
- useEffect58(() => {
38540
+ useEffect59(() => {
38381
38541
  if (!globalKeyboardShortcuts) return;
38382
38542
  const handleKeyDown = (event) => {
38383
38543
  if (event.defaultPrevented || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey || event.key !== "ArrowDown" && event.key !== "ArrowUp") {
@@ -38456,8 +38616,8 @@ function collectImageRefs(doc) {
38456
38616
  }
38457
38617
 
38458
38618
  // src/PreviewPanel.tsx
38459
- import { useState as useState73, useEffect as useEffect63, useMemo as useMemo54, useCallback as useCallback53, useRef as useRef60 } from "react";
38460
- import { createPortal as createPortal17 } from "react-dom";
38619
+ import { useState as useState75, useEffect as useEffect64, useMemo as useMemo54, useCallback as useCallback53, useRef as useRef60 } from "react";
38620
+ import { createPortal as createPortal18 } from "react-dom";
38461
38621
  import {
38462
38622
  DashboardView,
38463
38623
  DocPlayer as DocPlayer2,
@@ -38601,14 +38761,14 @@ import {
38601
38761
  createContext as createContext6,
38602
38762
  useCallback as useCallback50,
38603
38763
  useContext as useContext6,
38604
- useEffect as useEffect59,
38605
- useId as useId15,
38606
- useLayoutEffect as useLayoutEffect12,
38764
+ useEffect as useEffect60,
38765
+ useId as useId14,
38766
+ useLayoutEffect as useLayoutEffect15,
38607
38767
  useMemo as useMemo50,
38608
38768
  useRef as useRef57,
38609
- useState as useState70
38769
+ useState as useState72
38610
38770
  } from "react";
38611
- import { createPortal as createPortal16 } from "react-dom";
38771
+ import { createPortal as createPortal17 } from "react-dom";
38612
38772
  import { jsx as jsx79, jsxs as jsxs64 } from "react/jsx-runtime";
38613
38773
  var PresentationModeContext = createContext6(null);
38614
38774
  function usePresentationMode() {
@@ -38707,12 +38867,12 @@ function PresentationModeProvider({
38707
38867
  }) {
38708
38868
  const { activeView, colorScheme, doc } = useEditorContext();
38709
38869
  const { activeTheme } = usePreviewSettings();
38710
- const popupNameId = useId15().replace(/[^a-zA-Z0-9_-]/g, "");
38711
- const [selectedTarget, setSelectedTarget] = useState70("control");
38712
- const [activeTarget, setActiveTarget] = useState70(null);
38713
- const [popupRoot, setPopupRoot] = useState70(null);
38714
- const [error, setError] = useState70(null);
38715
- const [fullscreenExitStyle, setFullscreenExitStyle] = useState70(null);
38870
+ const popupNameId = useId14().replace(/[^a-zA-Z0-9_-]/g, "");
38871
+ const [selectedTarget, setSelectedTarget] = useState72("control");
38872
+ const [activeTarget, setActiveTarget] = useState72(null);
38873
+ const [popupRoot, setPopupRoot] = useState72(null);
38874
+ const [error, setError] = useState72(null);
38875
+ const [fullscreenExitStyle, setFullscreenExitStyle] = useState72(null);
38716
38876
  const activeTargetRef = useRef57(activeTarget);
38717
38877
  activeTargetRef.current = activeTarget;
38718
38878
  const previousActiveTargetRef = useRef57(null);
@@ -38860,12 +39020,12 @@ function PresentationModeProvider({
38860
39020
  },
38861
39021
  [availableTargets, selectedTarget, stop]
38862
39022
  );
38863
- useEffect59(() => {
39023
+ useEffect60(() => {
38864
39024
  if (availableTargets.includes(selectedTarget)) return;
38865
39025
  setSelectedTarget("control");
38866
39026
  if (activeTargetRef.current !== null) void stop();
38867
39027
  }, [availableTargets, selectedTarget, stop]);
38868
- useEffect59(() => {
39028
+ useEffect60(() => {
38869
39029
  const root = rootRef.current;
38870
39030
  const ownerDocument = root?.ownerDocument;
38871
39031
  if (!root || !ownerDocument) return;
@@ -38877,7 +39037,7 @@ function PresentationModeProvider({
38877
39037
  ownerDocument.addEventListener("fullscreenchange", handleFullscreenChange);
38878
39038
  return () => ownerDocument.removeEventListener("fullscreenchange", handleFullscreenChange);
38879
39039
  }, [rootRef]);
38880
- useEffect59(() => {
39040
+ useEffect60(() => {
38881
39041
  const root = rootRef.current;
38882
39042
  if (!root) return;
38883
39043
  if (activeTarget) root.dataset.presentationMode = activeTarget;
@@ -38886,10 +39046,10 @@ function PresentationModeProvider({
38886
39046
  delete root.dataset.presentationMode;
38887
39047
  };
38888
39048
  }, [activeTarget, rootRef]);
38889
- useEffect59(() => {
39049
+ useEffect60(() => {
38890
39050
  if (activeView !== "preview" && activeTargetRef.current !== null) void stop();
38891
39051
  }, [activeView, stop]);
38892
- useEffect59(() => {
39052
+ useEffect60(() => {
38893
39053
  const previous = previousActiveTargetRef.current;
38894
39054
  previousActiveTargetRef.current = activeTarget;
38895
39055
  if (previous === null || activeTarget !== null) return;
@@ -38897,7 +39057,7 @@ function PresentationModeProvider({
38897
39057
  returnFocusRef.current = null;
38898
39058
  if (target?.isConnected) target.focus();
38899
39059
  }, [activeTarget]);
38900
- useEffect59(() => {
39060
+ useEffect60(() => {
38901
39061
  if (activeTarget !== "control") return;
38902
39062
  const ownerDocument = rootRef.current?.ownerDocument;
38903
39063
  if (!ownerDocument) return;
@@ -38909,12 +39069,12 @@ function PresentationModeProvider({
38909
39069
  ownerDocument.addEventListener("keydown", handleKeyDown);
38910
39070
  return () => ownerDocument.removeEventListener("keydown", handleKeyDown);
38911
39071
  }, [activeTarget, rootRef, stop]);
38912
- useEffect59(() => {
39072
+ useEffect60(() => {
38913
39073
  if (!error) return;
38914
39074
  const timer = window.setTimeout(() => setError(null), 6e3);
38915
39075
  return () => window.clearTimeout(timer);
38916
39076
  }, [error]);
38917
- useLayoutEffect12(() => {
39077
+ useLayoutEffect15(() => {
38918
39078
  if (activeTarget !== "fullscreen") {
38919
39079
  setFullscreenExitStyle(null);
38920
39080
  return;
@@ -38944,7 +39104,7 @@ function PresentationModeProvider({
38944
39104
  window.removeEventListener("resize", updatePosition);
38945
39105
  };
38946
39106
  }, [activeTarget, rootRef]);
38947
- useEffect59(
39107
+ useEffect60(
38948
39108
  () => () => {
38949
39109
  popupCleanupRef.current?.();
38950
39110
  const popup = popupRef.current;
@@ -39004,8 +39164,8 @@ function PresentationModeProvider({
39004
39164
  return /* @__PURE__ */ jsxs64(PresentationModeContext.Provider, { value, children: [
39005
39165
  children,
39006
39166
  (activeTarget === "control" || activeTarget === "fullscreen") && exitButton,
39007
- activeTarget === "window" && popupRoot && exitButton ? createPortal16(exitButton, popupRoot) : null,
39008
- error && typeof document !== "undefined" ? createPortal16(
39167
+ activeTarget === "window" && popupRoot && exitButton ? createPortal17(exitButton, popupRoot) : null,
39168
+ error && typeof document !== "undefined" ? createPortal17(
39009
39169
  /* @__PURE__ */ jsx79("div", { className: "squisq-presentation-error", "data-theme": colorScheme, role: "alert", children: error }),
39010
39170
  document.body
39011
39171
  ) : null
@@ -39047,8 +39207,8 @@ function PresentationModeControl() {
39047
39207
  const { colorScheme } = useEditorContext();
39048
39208
  const triggerRef = useRef57(null);
39049
39209
  const menuRef = useRef57(null);
39050
- const [open, setOpen] = useState70(false);
39051
- const [anchor, setAnchor] = useState70(null);
39210
+ const [open, setOpen] = useState72(false);
39211
+ const [anchor, setAnchor] = useState72(null);
39052
39212
  const options = PRESENTATION_OPTIONS.filter((option) => availableTargets.includes(option.target));
39053
39213
  const selected = options.find((option) => option.target === selectedTarget) ?? PRESENTATION_OPTIONS[0];
39054
39214
  const updatePosition = useCallback50(() => {
@@ -39073,7 +39233,7 @@ function PresentationModeControl() {
39073
39233
  updatePosition();
39074
39234
  setOpen(true);
39075
39235
  }, [updatePosition]);
39076
- useEffect59(() => {
39236
+ useEffect60(() => {
39077
39237
  if (!open) return;
39078
39238
  const handlePointerDown = (event) => {
39079
39239
  const target = event.target;
@@ -39096,7 +39256,7 @@ function PresentationModeControl() {
39096
39256
  window.removeEventListener("scroll", updatePosition, true);
39097
39257
  };
39098
39258
  }, [closeMenu, open, updatePosition]);
39099
- useLayoutEffect12(() => {
39259
+ useLayoutEffect15(() => {
39100
39260
  if (!open || !anchor) return;
39101
39261
  const checked = menuRef.current?.querySelector('[aria-checked="true"]');
39102
39262
  const first = menuRef.current?.querySelector('[role="menuitemradio"]');
@@ -39134,7 +39294,7 @@ function PresentationModeControl() {
39134
39294
  children: /* @__PURE__ */ jsx79("svg", { width: "10", height: "10", viewBox: "0 0 10 10", "aria-hidden": "true", children: /* @__PURE__ */ jsx79("path", { d: "M2 3.5 5 6.5 8 3.5", fill: "none", stroke: "currentColor", strokeWidth: "1.4" }) })
39135
39295
  }
39136
39296
  ),
39137
- open && anchor ? createPortal16(
39297
+ open && anchor ? createPortal17(
39138
39298
  /* @__PURE__ */ jsx79(
39139
39299
  "div",
39140
39300
  {
@@ -39216,10 +39376,10 @@ import {
39216
39376
  createContext as createContext7,
39217
39377
  useCallback as useCallback51,
39218
39378
  useContext as useContext7,
39219
- useEffect as useEffect60,
39379
+ useEffect as useEffect61,
39220
39380
  useMemo as useMemo51,
39221
39381
  useRef as useRef58,
39222
- useState as useState71
39382
+ useState as useState73
39223
39383
  } from "react";
39224
39384
  import { jsx as jsx80, jsxs as jsxs65 } from "react/jsx-runtime";
39225
39385
  var PrintModeContext = createContext7(null);
@@ -39234,8 +39394,8 @@ function usePrintModeOptional() {
39234
39394
  function PrintModeProvider({ rootRef, children }) {
39235
39395
  const { activeView } = useEditorContext();
39236
39396
  const { activeTarget: presentationTarget, stop: stopPresentation } = usePresentationMode();
39237
- const [active, setActive] = useState71(false);
39238
- const [slidesPerPage, setSlidesPerPage] = useState71(1);
39397
+ const [active, setActive] = useState73(false);
39398
+ const [slidesPerPage, setSlidesPerPage] = useState73(1);
39239
39399
  const customPrintHandlerRef = useRef58(null);
39240
39400
  const printAncestorsRef = useRef58([]);
39241
39401
  const unmarkPrinting = useCallback51(() => {
@@ -39286,7 +39446,7 @@ function PrintModeProvider({ rootRef, children }) {
39286
39446
  markPrinting();
39287
39447
  ownerWindow.print();
39288
39448
  }, [markPrinting, rootRef]);
39289
- useEffect60(() => {
39449
+ useEffect61(() => {
39290
39450
  const root = rootRef.current;
39291
39451
  if (!root) return;
39292
39452
  if (active) root.dataset.printPreview = "true";
@@ -39295,10 +39455,10 @@ function PrintModeProvider({ rootRef, children }) {
39295
39455
  delete root.dataset.printPreview;
39296
39456
  };
39297
39457
  }, [active, rootRef]);
39298
- useEffect60(() => {
39458
+ useEffect61(() => {
39299
39459
  if (activeView !== "preview" && active) close();
39300
39460
  }, [active, activeView, close]);
39301
- useEffect60(() => {
39461
+ useEffect61(() => {
39302
39462
  if (!active) return;
39303
39463
  const ownerWindow = rootRef.current?.ownerDocument.defaultView;
39304
39464
  const ownerDocument = rootRef.current?.ownerDocument;
@@ -39389,7 +39549,7 @@ function PrintPreviewToolbar() {
39389
39549
  }
39390
39550
 
39391
39551
  // src/print/PrintPreview.tsx
39392
- import { useCallback as useCallback52, useEffect as useEffect61, useMemo as useMemo52, useRef as useRef59 } from "react";
39552
+ import { useCallback as useCallback52, useEffect as useEffect62, useMemo as useMemo52, useRef as useRef59 } from "react";
39393
39553
  import {
39394
39554
  BlockRenderer as BlockRenderer4,
39395
39555
  FlashcardFaceView,
@@ -39445,7 +39605,7 @@ function PrintPreview({
39445
39605
  [contentDoc]
39446
39606
  );
39447
39607
  const isTextDocument = displayMode === "page" || displayMode === "narrate";
39448
- useEffect61(() => {
39608
+ useEffect62(() => {
39449
39609
  if (!isTextDocument) return registerPrintHandler(null);
39450
39610
  return registerPrintHandler(() => {
39451
39611
  const frameWindow = documentFrameRef.current?.contentWindow;
@@ -39583,9 +39743,9 @@ function PrintPreview({
39583
39743
  import {
39584
39744
  createContext as createContext8,
39585
39745
  useContext as useContext8,
39586
- useEffect as useEffect62,
39746
+ useEffect as useEffect63,
39587
39747
  useMemo as useMemo53,
39588
- useState as useState72
39748
+ useState as useState74
39589
39749
  } from "react";
39590
39750
  import { parseTableViewState as parseTableViewState2 } from "@bendyline/squisq/table";
39591
39751
 
@@ -39688,9 +39848,9 @@ function SlideshowDataGridRenderer({
39688
39848
  const { container, mediaRevision, sources } = useContext8(SlideshowDataGridContext);
39689
39849
  const source = sourceForBlock(sources, block);
39690
39850
  const activeSourceKey = sourceKey(source);
39691
- const [remote, setRemote] = useState72({ key: "", status: "idle" });
39692
- const [gridModule, setGridModule] = useState72(null);
39693
- useEffect62(() => {
39851
+ const [remote, setRemote] = useState74({ key: "", status: "idle" });
39852
+ const [gridModule, setGridModule] = useState74(null);
39853
+ useEffect63(() => {
39694
39854
  let active = true;
39695
39855
  void loadGridModule().then((module) => {
39696
39856
  if (active) setGridModule(module);
@@ -39699,7 +39859,7 @@ function SlideshowDataGridRenderer({
39699
39859
  active = false;
39700
39860
  };
39701
39861
  }, []);
39702
- useEffect62(() => {
39862
+ useEffect63(() => {
39703
39863
  if (!container || !source || !gridModule) {
39704
39864
  setRemote({ key: activeSourceKey, status: "idle" });
39705
39865
  return;
@@ -39750,13 +39910,13 @@ function SlideshowDataGridRenderer({
39750
39910
  () => useLocalGrid && gridModule ? new gridModule.TableStoreClient({ headers: previewHeaders, cells: previewRows }) : null,
39751
39911
  [previewHeaders, previewRows, useLocalGrid, gridModule]
39752
39912
  );
39753
- useEffect62(() => () => localProvider?.dispose(), [localProvider]);
39913
+ useEffect63(() => () => localProvider?.dispose(), [localProvider]);
39754
39914
  const ready = currentRemote?.status === "ready" ? currentRemote : void 0;
39755
39915
  const provider = ready?.provider ?? localProvider;
39756
39916
  const ingest = ready?.ingest ?? (localProvider ? { headers: previewHeaders, cells: previewRows } : void 0);
39757
39917
  const initialView = ready?.initialView ?? EMPTY_VIEW;
39758
- const [view, setView] = useState72(initialView);
39759
- useEffect62(() => setView(initialView), [initialView, provider]);
39918
+ const [view, setView] = useState74(initialView);
39919
+ useEffect63(() => setView(initialView), [initialView, provider]);
39760
39920
  if (!provider || !ingest || !gridModule) return /* @__PURE__ */ jsx82(Fragment25, { children: fallback });
39761
39921
  const { style } = layer.content;
39762
39922
  const rowHeight = Math.max(32, style.fontSize * 2.1);
@@ -39851,7 +40011,7 @@ function PreviewPanel({
39851
40011
  } = usePreviewSettings();
39852
40012
  const mainSurfaceRef = useRef60(null);
39853
40013
  const popupSurfaceRef = useRef60(null);
39854
- const [playbackState, setPlaybackState] = useState73(null);
40014
+ const [playbackState, setPlaybackState] = useState75(null);
39855
40015
  const handlePlaybackStateChange = useCallback53((next) => {
39856
40016
  setPlaybackState(next);
39857
40017
  }, []);
@@ -39892,11 +40052,11 @@ function PreviewPanel({
39892
40052
  const isNarrateMode = activeDisplayMode === "narrate";
39893
40053
  const isDashboardMode = activeDisplayMode === "dashboard";
39894
40054
  const isFlashcardsMode = activeDisplayMode === "flashcards";
39895
- useEffect63(() => {
40055
+ useEffect64(() => {
39896
40056
  if (presentation?.activeTarget === "window") return;
39897
40057
  setPlaybackState(null);
39898
40058
  }, [presentation?.activeTarget]);
39899
- useEffect63(() => {
40059
+ useEffect64(() => {
39900
40060
  if (presentation?.activeTarget !== "window" || !presentation.popupRoot) return;
39901
40061
  const mainRoot = mainSurfaceRef.current;
39902
40062
  const followerRoot = popupSurfaceRef.current;
@@ -40144,7 +40304,7 @@ function PreviewPanel({
40144
40304
  children: /* @__PURE__ */ jsx83("div", { ref: mainSurfaceRef, className: "squisq-preview-player", style: surfaceStyle, children: renderSurface(false) })
40145
40305
  }
40146
40306
  ),
40147
- audienceWindowOpen && presentation?.popupRoot && !isNarrateMode ? createPortal17(
40307
+ audienceWindowOpen && presentation?.popupRoot && !isNarrateMode ? createPortal18(
40148
40308
  /* @__PURE__ */ jsx83(
40149
40309
  "div",
40150
40310
  {
@@ -40170,7 +40330,7 @@ function PreviewPanel({
40170
40330
  }
40171
40331
 
40172
40332
  // src/MediaBin.tsx
40173
- import { useState as useState74, useEffect as useEffect64, useRef as useRef61, useCallback as useCallback54 } from "react";
40333
+ import { useState as useState76, useEffect as useEffect65, useRef as useRef61, useCallback as useCallback54 } from "react";
40174
40334
  import { jsx as jsx84, jsxs as jsxs68 } from "react/jsx-runtime";
40175
40335
  function formatSize(bytes) {
40176
40336
  if (bytes < 1024) return `${bytes} B`;
@@ -40239,20 +40399,20 @@ function MediaBin({
40239
40399
  allowBinaryDownloads = true,
40240
40400
  highlightPath = null
40241
40401
  }) {
40242
- const [entries, setEntries] = useState74([]);
40402
+ const [entries, setEntries] = useState76([]);
40243
40403
  const listRef = useRef61(null);
40244
- useEffect64(() => {
40404
+ useEffect65(() => {
40245
40405
  if (!highlightPath || !listRef.current) return;
40246
40406
  const item = listRef.current.querySelector(`[data-media-path="${CSS.escape(highlightPath)}"]`);
40247
40407
  if (item instanceof HTMLElement) {
40248
40408
  item.scrollIntoView({ block: "nearest" });
40249
40409
  }
40250
40410
  }, [highlightPath, entries]);
40251
- const [thumbUrls, setThumbUrls] = useState74({});
40252
- const [loading, setLoading] = useState74(false);
40253
- const [isDropActive, setIsDropActive] = useState74(false);
40254
- const [downloadingPath, setDownloadingPath] = useState74(null);
40255
- const [contextMenu, setContextMenu] = useState74(null);
40411
+ const [thumbUrls, setThumbUrls] = useState76({});
40412
+ const [loading, setLoading] = useState76(false);
40413
+ const [isDropActive, setIsDropActive] = useState76(false);
40414
+ const [downloadingPath, setDownloadingPath] = useState76(null);
40415
+ const [contextMenu, setContextMenu] = useState76(null);
40256
40416
  const fileInputRef = useRef61(null);
40257
40417
  const contextMenuRef = useRef61(null);
40258
40418
  const dropDepthRef = useRef61(0);
@@ -40274,7 +40434,7 @@ function MediaBin({
40274
40434
  },
40275
40435
  [onCountChange]
40276
40436
  );
40277
- useEffect64(() => {
40437
+ useEffect65(() => {
40278
40438
  if (!contextMenu) return;
40279
40439
  const handlePointerDown = (event) => {
40280
40440
  if (contextMenuRef.current?.contains(event.target)) return;
@@ -40295,7 +40455,7 @@ function MediaBin({
40295
40455
  window.removeEventListener("resize", close);
40296
40456
  };
40297
40457
  }, [contextMenu]);
40298
- useEffect64(() => {
40458
+ useEffect65(() => {
40299
40459
  if (!mediaProvider) {
40300
40460
  setEntries([]);
40301
40461
  setThumbUrls({});
@@ -40639,7 +40799,7 @@ ${formatSize(entry.size)}`,
40639
40799
  }
40640
40800
 
40641
40801
  // src/DropZoneOverlay.tsx
40642
- import { useState as useState75 } from "react";
40802
+ import { useState as useState77 } from "react";
40643
40803
  import { Fragment as Fragment26, jsx as jsx85, jsxs as jsxs69 } from "react/jsx-runtime";
40644
40804
  function DropZoneOverlay({
40645
40805
  dragContentType,
@@ -40696,7 +40856,7 @@ function DropZone({
40696
40856
  disabled,
40697
40857
  variant
40698
40858
  }) {
40699
- const [isHovering, setIsHovering] = useState75(false);
40859
+ const [isHovering, setIsHovering] = useState77(false);
40700
40860
  const props = zoneProps(target);
40701
40861
  return /* @__PURE__ */ jsxs69(
40702
40862
  "div",
@@ -40740,8 +40900,8 @@ function DropZone({
40740
40900
  }
40741
40901
 
40742
40902
  // src/Tooltip.tsx
40743
- import { useEffect as useEffect65, useLayoutEffect as useLayoutEffect13, useRef as useRef62, useState as useState76 } from "react";
40744
- import { createPortal as createPortal18 } from "react-dom";
40903
+ import { useEffect as useEffect66, useLayoutEffect as useLayoutEffect16, useRef as useRef62, useState as useState78 } from "react";
40904
+ import { createPortal as createPortal19 } from "react-dom";
40745
40905
 
40746
40906
  // src/tooltipPlacement.ts
40747
40907
  var EDGE_PADDING_PX = 8;
@@ -40756,14 +40916,14 @@ function clampTooltipLeft(anchorX, tooltipWidth, viewportWidth, edgePadding = ED
40756
40916
  import { jsx as jsx86 } from "react/jsx-runtime";
40757
40917
  var SHOW_DELAY_MS = 180;
40758
40918
  function TooltipLayer() {
40759
- const [state, setState3] = useState76(null);
40919
+ const [state, setState3] = useState78(null);
40760
40920
  const tooltipRef = useRef62(null);
40761
40921
  const timerRef = useRef62(null);
40762
40922
  const currentTargetRef = useRef62(null);
40763
40923
  const visibleRef = useRef62(false);
40764
40924
  const pressedTargetRef = useRef62(null);
40765
40925
  const lastPointerWasTouchRef = useRef62(false);
40766
- useLayoutEffect13(() => {
40926
+ useLayoutEffect16(() => {
40767
40927
  if (!state) return;
40768
40928
  const node2 = tooltipRef.current;
40769
40929
  if (!node2) return;
@@ -40774,7 +40934,7 @@ function TooltipLayer() {
40774
40934
  node2.style.left = `${left}px`;
40775
40935
  node2.style.visibility = "visible";
40776
40936
  }, [state]);
40777
- useEffect65(() => {
40937
+ useEffect66(() => {
40778
40938
  const clearTimer = () => {
40779
40939
  if (timerRef.current) {
40780
40940
  clearTimeout(timerRef.current);
@@ -40855,7 +41015,7 @@ function TooltipLayer() {
40855
41015
  };
40856
41016
  }, []);
40857
41017
  if (!state) return null;
40858
- return createPortal18(
41018
+ return createPortal19(
40859
41019
  /* @__PURE__ */ jsx86(
40860
41020
  "div",
40861
41021
  {
@@ -40876,7 +41036,7 @@ function TooltipLayer() {
40876
41036
  }
40877
41037
 
40878
41038
  // src/EditorShell.tsx
40879
- import { useEffect as useEffect69, useRef as useRef67, useState as useState81, useCallback as useCallback59, useMemo as useMemo58 } from "react";
41039
+ import { useEffect as useEffect70, useRef as useRef67, useState as useState83, useCallback as useCallback59, useMemo as useMemo58 } from "react";
40880
41040
 
40881
41041
  // src/BlockPreviewPanel.tsx
40882
41042
  import { useMemo as useMemo55 } from "react";
@@ -41046,18 +41206,18 @@ function MediaEditContextMenuItems() {
41046
41206
  // src/mediaEdit/MediaEditModal.tsx
41047
41207
  import {
41048
41208
  useCallback as useCallback58,
41049
- useEffect as useEffect68,
41050
- useId as useId16,
41209
+ useEffect as useEffect69,
41210
+ useId as useId15,
41051
41211
  useMemo as useMemo57,
41052
41212
  useRef as useRef66,
41053
- useState as useState80
41213
+ useState as useState82
41054
41214
  } from "react";
41055
41215
  import {
41056
41216
  useMediaEditStatus as useMediaEditStatus2
41057
41217
  } from "@bendyline/squisq-video-react/media-edit";
41058
41218
 
41059
41219
  // src/mediaEdit/MediaEditAudioSection.tsx
41060
- import { useCallback as useCallback55, useEffect as useEffect66, useRef as useRef63, useState as useState77 } from "react";
41220
+ import { useCallback as useCallback55, useEffect as useEffect67, useRef as useRef63, useState as useState79 } from "react";
41061
41221
  import { MEDIA_FX_SPECS as MEDIA_FX_SPECS2, serializeMediaFx } from "@bendyline/squisq/mediaEdit";
41062
41222
 
41063
41223
  // src/mediaEdit/mediaEditDraft.ts
@@ -41210,8 +41370,8 @@ var LOUDNESS_PRESETS = [
41210
41370
  ];
41211
41371
  var PREVIEW_SECONDS = 10;
41212
41372
  function useMediaDuration(url) {
41213
- const [duration, setDuration] = useState77(null);
41214
- useEffect66(() => {
41373
+ const [duration, setDuration] = useState79(null);
41374
+ useEffect67(() => {
41215
41375
  setDuration(null);
41216
41376
  if (!url || typeof Audio === "undefined") return;
41217
41377
  const probe = new Audio();
@@ -41231,9 +41391,9 @@ function usePreviewPlayer(preview) {
41231
41391
  const ctxRef = useRef63(null);
41232
41392
  const sourceRef = useRef63(null);
41233
41393
  const startedRef = useRef63(null);
41234
- const [playing, setPlaying] = useState77(null);
41394
+ const [playing, setPlaying] = useState79(null);
41235
41395
  const cueRef = useRef63(0);
41236
- const [position, setPosition] = useState77(0);
41396
+ const [position, setPosition] = useState79(0);
41237
41397
  const frames = preview?.original[0]?.length ?? 0;
41238
41398
  const duration = preview && frames > 0 ? frames / preview.sampleRate : 0;
41239
41399
  const currentOffset = useCallback55(() => {
@@ -41251,8 +41411,8 @@ function usePreviewPlayer(preview) {
41251
41411
  setPosition(0);
41252
41412
  setPlaying(null);
41253
41413
  }, []);
41254
- useEffect66(() => stop, [preview, stop]);
41255
- useEffect66(
41414
+ useEffect67(() => stop, [preview, stop]);
41415
+ useEffect67(
41256
41416
  () => () => {
41257
41417
  void ctxRef.current?.close();
41258
41418
  ctxRef.current = null;
@@ -41291,7 +41451,7 @@ function usePreviewPlayer(preview) {
41291
41451
  },
41292
41452
  [duration, playing, play]
41293
41453
  );
41294
- useEffect66(() => {
41454
+ useEffect67(() => {
41295
41455
  if (!playing) return;
41296
41456
  let frame = requestAnimationFrame(function tick() {
41297
41457
  setPosition(currentOffset());
@@ -41339,14 +41499,14 @@ function MediaEditAudioSection({
41339
41499
  const duration = useMediaDuration(resolvedSrc);
41340
41500
  const windowMin = item.clipStart ?? 0;
41341
41501
  const windowMax = Math.max(windowMin, (item.clipEnd ?? duration ?? windowMin) - 1);
41342
- const [previewFrom, setPreviewFrom] = useState77(windowMin);
41343
- const [preview, setPreview] = useState77(null);
41344
- const [previewedFx, setPreviewedFx] = useState77(null);
41345
- const [previewing, setPreviewing] = useState77(false);
41346
- const [previewError, setPreviewError] = useState77(null);
41502
+ const [previewFrom, setPreviewFrom] = useState79(windowMin);
41503
+ const [preview, setPreview] = useState79(null);
41504
+ const [previewedFx, setPreviewedFx] = useState79(null);
41505
+ const [previewing, setPreviewing] = useState79(false);
41506
+ const [previewError, setPreviewError] = useState79(null);
41347
41507
  const previewAbort = useRef63(null);
41348
41508
  const player = usePreviewPlayer(preview);
41349
- useEffect66(() => () => previewAbort.current?.abort(), []);
41509
+ useEffect67(() => () => previewAbort.current?.abort(), []);
41350
41510
  const runPreview = useCallback55(async () => {
41351
41511
  if (draftFx.ops.length === 0) return;
41352
41512
  previewAbort.current?.abort();
@@ -41526,7 +41686,7 @@ function MediaEditAudioSection({
41526
41686
  }
41527
41687
 
41528
41688
  // src/mediaEdit/MediaEditTimingSection.tsx
41529
- import { useCallback as useCallback56, useEffect as useEffect67, useRef as useRef64, useState as useState78 } from "react";
41689
+ import { useCallback as useCallback56, useEffect as useEffect68, useRef as useRef64, useState as useState80 } from "react";
41530
41690
  import { jsx as jsx90, jsxs as jsxs72 } from "react/jsx-runtime";
41531
41691
  var DEFAULT_MAX_PAUSE = 0.8;
41532
41692
  function formatDb(value) {
@@ -41540,11 +41700,11 @@ function MediaEditTimingSection({
41540
41700
  manager,
41541
41701
  idPrefix
41542
41702
  }) {
41543
- const [maxPause, setMaxPause] = useState78(DEFAULT_MAX_PAUSE);
41544
- const [finding, setFinding] = useState78(false);
41545
- const [error, setError] = useState78(null);
41703
+ const [maxPause, setMaxPause] = useState80(DEFAULT_MAX_PAUSE);
41704
+ const [finding, setFinding] = useState80(false);
41705
+ const [error, setError] = useState80(null);
41546
41706
  const abortRef = useRef64(null);
41547
- useEffect67(() => () => abortRef.current?.abort(), []);
41707
+ useEffect68(() => () => abortRef.current?.abort(), []);
41548
41708
  const findPauses = useCallback56(async () => {
41549
41709
  abortRef.current?.abort();
41550
41710
  const controller = new AbortController();
@@ -41644,7 +41804,7 @@ function MediaEditTimingSection({
41644
41804
  import {
41645
41805
  useCallback as useCallback57,
41646
41806
  useRef as useRef65,
41647
- useState as useState79
41807
+ useState as useState81
41648
41808
  } from "react";
41649
41809
  import { normalizeMediaCrop } from "@bendyline/squisq/mediaEdit";
41650
41810
  import { jsx as jsx91, jsxs as jsxs73 } from "react/jsx-runtime";
@@ -41670,8 +41830,8 @@ function clampCrop(crop) {
41670
41830
  }
41671
41831
  function MediaEditFrameSection({ item, draft, onChange }) {
41672
41832
  const src = useResolvedMediaSrc(item.src);
41673
- const [frame, setFrame] = useState79(null);
41674
- const [aspect, setAspect] = useState79(null);
41833
+ const [frame, setFrame] = useState81(null);
41834
+ const [aspect, setAspect] = useState81(null);
41675
41835
  const stageRef = useRef65(null);
41676
41836
  const crop = draft.crop ?? FULL;
41677
41837
  const setCrop = useCallback57(
@@ -41865,21 +42025,21 @@ function MediaEditModal({ target, onClose }) {
41865
42025
  const { doc, markdownSource, setMarkdownSource, mediaEditRenders } = useEditorContext();
41866
42026
  const modalRef = useRef66(null);
41867
42027
  const surfaceRef = useRef66(null);
41868
- const titleId = useId16();
42028
+ const titleId = useId15();
41869
42029
  useModalDialog({ rootRef: modalRef, dialogRef: surfaceRef, onClose });
41870
42030
  const item = useMemo57(() => doc ? findEditableMedia(doc, target) : null, [doc, target]);
41871
42031
  const companions = useMemo57(() => doc && item ? groupCompanions(doc, item) : [], [doc, item]);
41872
42032
  const renderStatus = useRenderStatus(item, mediaEditRenders);
41873
- const [draft, setDraft] = useState80(() => draftFromEdits(item?.edits));
42033
+ const [draft, setDraft] = useState82(() => draftFromEdits(item?.edits));
41874
42034
  const seedKey = item ? `${item.sourceLine}|${editsSignature(item.edits)}` : null;
41875
42035
  const seededRef = useRef66(null);
41876
- useEffect68(() => {
42036
+ useEffect69(() => {
41877
42037
  if (seedKey === null || seededRef.current === seedKey) return;
41878
42038
  seededRef.current = seedKey;
41879
42039
  setDraft(draftFromEdits(item?.edits));
41880
42040
  }, [seedKey]);
41881
42041
  const tabs = TABS.filter((t) => t.id !== "frame" || item?.kind === "video");
41882
- const [activeTab, setActiveTab] = useState80("audio");
42042
+ const [activeTab, setActiveTab] = useState82("audio");
41883
42043
  const tabRefs = useRef66(/* @__PURE__ */ new Map());
41884
42044
  const onTabKeyDown = (event, index2) => {
41885
42045
  const next = event.key === "ArrowRight" ? (index2 + 1) % tabs.length : event.key === "ArrowLeft" ? (index2 - 1 + tabs.length) % tabs.length : event.key === "Home" ? 0 : event.key === "End" ? tabs.length - 1 : null;
@@ -42306,6 +42466,7 @@ import {
42306
42466
  } from "@bendyline/squisq-video-react/media-edit";
42307
42467
  import { Fragment as Fragment29, jsx as jsx93, jsxs as jsxs75 } from "react/jsx-runtime";
42308
42468
  function EditorShell({
42469
+ ariaLabel,
42309
42470
  initialMarkdown = "",
42310
42471
  initialView = "wysiwyg",
42311
42472
  hostMode = "document",
@@ -42405,7 +42566,7 @@ function EditorShell({
42405
42566
  () => mediaEditRenders === void 0 && effectiveMediaProvider ? createMediaEditRenderManager({ mediaProvider: effectiveMediaProvider }) : null,
42406
42567
  [mediaEditRenders, effectiveMediaProvider]
42407
42568
  );
42408
- useEffect69(() => () => ownedMediaEditRenders?.dispose(), [ownedMediaEditRenders]);
42569
+ useEffect70(() => () => ownedMediaEditRenders?.dispose(), [ownedMediaEditRenders]);
42409
42570
  const effectiveMediaEditRenders = mediaEditRenders === void 0 ? ownedMediaEditRenders : mediaEditRenders;
42410
42571
  const filesToggleEnabled = showFilesToggle ?? effectiveMediaProvider !== void 0;
42411
42572
  const effectiveInitialView = hostMode === "chat" || !showPlayTab && initialView === "preview" ? "wysiwyg" : initialView;
@@ -42457,6 +42618,7 @@ function EditorShell({
42457
42618
  children: /* @__PURE__ */ jsx93(ProofingRoot, { children: /* @__PURE__ */ jsx93(ReviewRoot, { providers: reviewProviders, children: /* @__PURE__ */ jsx93(
42458
42619
  EditorShellInner,
42459
42620
  {
42621
+ ariaLabel: ariaLabel ?? (hostMode === "chat" ? "Message" : fileName ? `Edit ${fileName}` : "Document editor"),
42460
42622
  basePath,
42461
42623
  defaultViewportPreset,
42462
42624
  onChange,
@@ -42541,6 +42703,7 @@ function UseModeProviders({
42541
42703
  );
42542
42704
  }
42543
42705
  function EditorShellInner({
42706
+ ariaLabel,
42544
42707
  basePath,
42545
42708
  defaultViewportPreset,
42546
42709
  onChange,
@@ -42624,7 +42787,7 @@ function EditorShellInner({
42624
42787
  const processedAudio = useProcessedAudio4(mediaEditRenders);
42625
42788
  const { docThemes, onDocThemesChange } = useDocCustomThemes();
42626
42789
  const lastEditingView = useRef67(activeView === "raw" ? "raw" : "wysiwyg");
42627
- useEffect69(() => {
42790
+ useEffect70(() => {
42628
42791
  if (activeView !== "preview") lastEditingView.current = activeView;
42629
42792
  }, [activeView]);
42630
42793
  const editingView = activeView === "preview" ? lastEditingView.current : activeView;
@@ -42671,14 +42834,14 @@ function EditorShellInner({
42671
42834
  );
42672
42835
  const timelineClock = useTimelineClock(isTimelineMode ? timelineDuration : 0);
42673
42836
  const hasTimelineVideo = timelineVideoSchedule.length > 0;
42674
- const [timelineVideoVisible, setTimelineVideoVisible] = useState81(false);
42675
- const [timelineCompositionVisible, setTimelineCompositionVisible] = useState81(false);
42837
+ const [timelineVideoVisible, setTimelineVideoVisible] = useState83(false);
42838
+ const [timelineCompositionVisible, setTimelineCompositionVisible] = useState83(false);
42676
42839
  const timelinePreviewCount = Number(timelineVideoVisible) + Number(timelineCompositionVisible);
42677
- const [showFiles, setShowFiles] = useState81(false);
42678
- const [filesFocusPath, setFilesFocusPath] = useState81(null);
42679
- const [mediaRefreshKey, setMediaRefreshKey] = useState81(0);
42680
- const [mediaCount, setMediaCount] = useState81(0);
42681
- const [mediaBinRecorderOpen, setMediaBinRecorderOpen] = useState81(false);
42840
+ const [showFiles, setShowFiles] = useState83(false);
42841
+ const [filesFocusPath, setFilesFocusPath] = useState83(null);
42842
+ const [mediaRefreshKey, setMediaRefreshKey] = useState83(0);
42843
+ const [mediaCount, setMediaCount] = useState83(0);
42844
+ const [mediaBinRecorderOpen, setMediaBinRecorderOpen] = useState83(false);
42682
42845
  const mediaListRefreshKey = mediaRefreshKey + mediaRevision;
42683
42846
  const usedMediaPaths = useMemo58(
42684
42847
  () => collectMediaReferencesFromMarkdown(markdownSource),
@@ -42690,13 +42853,13 @@ function EditorShellInner({
42690
42853
  }
42691
42854
  const imageEditFallbackContainer = imageEditFallbackContainerRef.current;
42692
42855
  const isDark = colorScheme === "dark";
42693
- useEffect69(() => {
42856
+ useEffect70(() => {
42694
42857
  if (!isTimelineMode || !hasTimelineVideo) setTimelineVideoVisible(false);
42695
42858
  }, [isTimelineMode, hasTimelineVideo]);
42696
- useEffect69(() => {
42859
+ useEffect70(() => {
42697
42860
  if (!isTimelineMode || !doc?.blocks.length) setTimelineCompositionVisible(false);
42698
42861
  }, [isTimelineMode, doc]);
42699
- useEffect69(() => {
42862
+ useEffect70(() => {
42700
42863
  if (!mediaProvider) {
42701
42864
  setMediaCount(0);
42702
42865
  return;
@@ -42720,7 +42883,7 @@ function EditorShellInner({
42720
42883
  cancelled = true;
42721
42884
  };
42722
42885
  }, [mediaProvider, mediaListRefreshKey]);
42723
- useEffect69(() => {
42886
+ useEffect70(() => {
42724
42887
  if (showFilesWhenNotEmpty && mediaCount > 0) setShowFiles(true);
42725
42888
  }, [mediaCount, showFilesWhenNotEmpty]);
42726
42889
  const handleToggleFiles = useCallback59(() => {
@@ -42740,7 +42903,7 @@ function EditorShellInner({
42740
42903
  [insertionTarget]
42741
42904
  );
42742
42905
  const docBasenameRef = useRef67("document");
42743
- useEffect69(() => {
42906
+ useEffect70(() => {
42744
42907
  let cancelled = false;
42745
42908
  docBasenameRef.current = "document";
42746
42909
  void resolveDocBasename(workspaceContainer).then((base) => {
@@ -42823,7 +42986,7 @@ function EditorShellInner({
42823
42986
  onDrop: handleFileDrop,
42824
42987
  enabled: !readOnly
42825
42988
  });
42826
- useEffect69(() => {
42989
+ useEffect70(() => {
42827
42990
  onChange?.(markdownSource);
42828
42991
  }, [markdownSource, onChange]);
42829
42992
  const handleShellKeyDown = useCallback59((e2) => {
@@ -43017,6 +43180,7 @@ function EditorShellInner({
43017
43180
  children: /* @__PURE__ */ jsx93("div", { className: "squisq-raw-editor-container", children: /* @__PURE__ */ jsx93(
43018
43181
  RawEditor,
43019
43182
  {
43183
+ ariaLabel: `${ariaLabel} \u2014 source`,
43020
43184
  monacoTheme: colorScheme === "dark" ? "vs-dark" : "vs",
43021
43185
  submitOnEnter,
43022
43186
  readOnly
@@ -43060,6 +43224,7 @@ function EditorShellInner({
43060
43224
  children: /* @__PURE__ */ jsx93(
43061
43225
  WysiwygEditor,
43062
43226
  {
43227
+ ariaLabel,
43063
43228
  submitOnEnter,
43064
43229
  placeholder,
43065
43230
  readOnly,
@@ -43238,9 +43403,9 @@ function ImageEditModal({
43238
43403
  const parent = container ?? new MemoryContentContainer();
43239
43404
  return scopeContainer(parent, `.imageEdits/${scopedName}`);
43240
43405
  }, [container, relativePath]);
43241
- const [initialSrc, setInitialSrc] = useState81(null);
43242
- const [resolveError, setResolveError] = useState81(null);
43243
- useEffect69(() => {
43406
+ const [initialSrc, setInitialSrc] = useState83(null);
43407
+ const [resolveError, setResolveError] = useState83(null);
43408
+ useEffect70(() => {
43244
43409
  let cancelled = false;
43245
43410
  setInitialSrc(null);
43246
43411
  setResolveError(null);
@@ -43382,6 +43547,7 @@ export {
43382
43547
  processTextFiles,
43383
43548
  useDocCustomTemplates,
43384
43549
  platformShortcut,
43550
+ navigateViewTabs,
43385
43551
  videoEmbedOfParagraph,
43386
43552
  videoEmbedParagraphJson,
43387
43553
  videoEmbedMarkdown,