@bendyline/squisq-editor-react 2.11.2 → 2.11.4

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.
@@ -6,7 +6,7 @@ import {
6
6
  import {
7
7
  markdownToTiptap,
8
8
  tiptapToMarkdown
9
- } from "./chunk-A2W4GYPG.js";
9
+ } from "./chunk-ES6CPRCW.js";
10
10
  import {
11
11
  ImageEditor,
12
12
  ImageViewer,
@@ -19,13 +19,13 @@ import {
19
19
  documentTitleFromFileName,
20
20
  resolveBlockVisual,
21
21
  useModalDialog
22
- } from "./chunk-7RRYZULY.js";
22
+ } from "./chunk-BJ3TXAIQ.js";
23
23
  import {
24
24
  Icon
25
25
  } from "./chunk-GS7QWYFT.js";
26
26
  import {
27
27
  TeleprompterView
28
- } from "./chunk-UNOKKSAC.js";
28
+ } from "./chunk-ENDRPV6T.js";
29
29
 
30
30
  // src/fileKind.ts
31
31
  var DATA_MODE_EXTENSIONS = /* @__PURE__ */ new Set(["csv", "tsv", "parquet"]);
@@ -28535,61 +28535,18 @@ import {
28535
28535
  } from "@bendyline/squisq/markdown";
28536
28536
  import { parseTableViewState, serializeTableViewState } from "@bendyline/squisq/table";
28537
28537
  import { TABLE_FED_TEMPLATES, resolveTemplateName as resolveTemplateName2 } from "@bendyline/squisq/doc";
28538
- function paramsOf(inner) {
28539
- const params = {};
28540
- if (!inner) return params;
28541
- for (const token of tokenizeAttrTokens4(inner)) {
28542
- const pair = splitKeyValueToken3(token);
28543
- if (pair) params[pair.key] = unquoteAttrValue(pair.value);
28544
- }
28545
- return params;
28546
- }
28547
- function readHeadingViewBinding(editor, cardPos, href) {
28548
- const headingPos = findOwningHeadingPosition(editor.state.doc, cardPos);
28549
- if (headingPos === null) {
28550
- return { headingPos: null, persisted: false, params: {} };
28551
- }
28552
- const node2 = editor.state.doc.nodeAt(headingPos);
28553
- if (!node2 || node2.type.name !== "heading") {
28554
- return { headingPos: null, persisted: false, params: {} };
28555
- }
28556
- const attrs = node2.attrs;
28557
- const params = paramsOf(attrs.dataTemplateParams);
28558
- const template = attrs.dataTemplate ? resolveTemplateName2(attrs.dataTemplate) : null;
28559
- const persisted = template !== null && TABLE_FED_TEMPLATES.has(template) && params.src === href;
28560
- return {
28561
- headingPos,
28562
- persisted,
28563
- params,
28564
- ...params.sort !== void 0 ? { sortRaw: params.sort } : {},
28565
- ...params.filter !== void 0 ? { filterRaw: params.filter } : {}
28566
- };
28567
- }
28568
- function serializeParams3(params) {
28569
- return Object.entries(params).map(([key, value]) => `${key}=${needsQuoting(value) ? quoteAttrValue5(value) : value}`).join(" ");
28570
- }
28571
- function writeHeadingViewState(editor, cardPos, href, view) {
28572
- if (!editor.isEditable) return false;
28573
- const binding = readHeadingViewBinding(editor, cardPos, href);
28574
- if (binding.headingPos === null || !binding.persisted) return false;
28575
- const raw = serializeTableViewState(view);
28576
- const params = { ...binding.params };
28577
- if (raw.sort !== void 0) params.sort = raw.sort;
28578
- else delete params.sort;
28579
- if (raw.filter !== void 0) params.filter = raw.filter;
28580
- else delete params.filter;
28581
- const serialized = serializeParams3(params);
28582
- const pos = binding.headingPos;
28583
- return editor.chain().command(({ tr }) => {
28584
- const node2 = tr.doc.nodeAt(pos);
28585
- if (!node2 || node2.type.name !== "heading") return false;
28586
- tr.setNodeAttribute(pos, "dataTemplateParams", serialized.length > 0 ? serialized : null);
28587
- return true;
28588
- }).run();
28589
- }
28590
- function viewStateFromBinding(binding, headers) {
28591
- return parseTableViewState(binding.sortRaw, binding.filterRaw, headers).view;
28592
- }
28538
+
28539
+ // src/dataCard/DataCardExtension.ts
28540
+ import { Extension as Extension10 } from "@tiptap/core";
28541
+ import { Plugin as Plugin10, PluginKey as PluginKey10 } from "@tiptap/pm/state";
28542
+ import { Decoration as Decoration10, DecorationSet as DecorationSet10 } from "@tiptap/pm/view";
28543
+ import { createRoot as createRoot6 } from "react-dom/client";
28544
+ import { createElement as createElement12 } from "react";
28545
+ import { isDataFilePath } from "@bendyline/squisq/doc";
28546
+
28547
+ // src/dataCard/DataCardWidget.tsx
28548
+ import { useCallback as useCallback38, useEffect as useEffect39, useMemo as useMemo36, useRef as useRef40, useState as useState49 } from "react";
28549
+ import { EMPTY_TABLE_VIEW_STATE } from "@bendyline/squisq/table";
28593
28550
 
28594
28551
  // src/dataCard/gridSave.ts
28595
28552
  import { DATA_BACKUP_PREFIX, buildDataBackupPath } from "@bendyline/squisq/versions";
@@ -28886,134 +28843,6 @@ async function createXlsxFormulaSession(meta, options = {}) {
28886
28843
  };
28887
28844
  }
28888
28845
 
28889
- // src/dataCard/DataCardWidget.tsx
28890
- import { useCallback as useCallback38, useEffect as useEffect39, useMemo as useMemo36, useRef as useRef40, useState as useState49 } from "react";
28891
- import { EMPTY_TABLE_VIEW_STATE } from "@bendyline/squisq/table";
28892
-
28893
- // src/dataCard/DataCardExtension.ts
28894
- import { Extension as Extension10 } from "@tiptap/core";
28895
- import { Plugin as Plugin10, PluginKey as PluginKey10 } from "@tiptap/pm/state";
28896
- import { Decoration as Decoration10, DecorationSet as DecorationSet10 } from "@tiptap/pm/view";
28897
- import { createRoot as createRoot6 } from "react-dom/client";
28898
- import { createElement as createElement12 } from "react";
28899
- import { isDataFilePath } from "@bendyline/squisq/doc";
28900
- var DATA_CARD_KEY = new PluginKey10("squisq-data-card");
28901
- function dataLinkHrefOf(node2) {
28902
- if (node2.type.name !== "paragraph" || node2.childCount === 0) return null;
28903
- let href = null;
28904
- for (let i = 0; i < node2.childCount; i++) {
28905
- const child = node2.child(i);
28906
- if (!child.isText || !child.text || !child.text.trim()) return null;
28907
- const link = child.marks.find((mark) => mark.type.name === "link");
28908
- const childHref = link?.attrs?.href;
28909
- if (typeof childHref !== "string") return null;
28910
- if (href === null) href = childHref;
28911
- else if (href !== childHref) return null;
28912
- }
28913
- return href !== null && isDataFilePath(href) ? href : null;
28914
- }
28915
- function findDataCardBlockPos(editor, blockId) {
28916
- return DATA_CARD_KEY.getState(editor.state)?.entries.find((e2) => e2.id === blockId)?.pos ?? null;
28917
- }
28918
- function buildDecorations8(doc, entries, editor, options) {
28919
- const decos = [];
28920
- for (const entry of entries) {
28921
- const node2 = doc.nodeAt(entry.pos);
28922
- if (!node2 || node2.type.name !== "paragraph") continue;
28923
- decos.push(
28924
- Decoration10.node(entry.pos, entry.pos + node2.nodeSize, {
28925
- class: "squisq-data-card-hidden"
28926
- })
28927
- );
28928
- const blockId = entry.id;
28929
- decos.push(
28930
- Decoration10.widget(
28931
- entry.pos + node2.nodeSize,
28932
- () => {
28933
- const container = document.createElement("div");
28934
- container.className = "squisq-data-card-host squisq-block-fill-available";
28935
- container.contentEditable = "false";
28936
- containFenceWidgetEvents(container);
28937
- const root = createRoot6(container);
28938
- root.render(
28939
- createElement12(DataCardWidget, {
28940
- editor,
28941
- blockId,
28942
- getMediaProvider: () => options.mediaProvider?.(),
28943
- getMediaRevision: () => options.mediaRevision?.() ?? 0,
28944
- getContainer: () => options.container?.(),
28945
- onOpenFiles: options.onOpenFiles,
28946
- onMediaSaved: options.onMediaSaved,
28947
- getCalcEngineFactory: () => options.calcEngineFactory?.()
28948
- })
28949
- );
28950
- container.__squisqDataCardRoot = { root };
28951
- return container;
28952
- },
28953
- {
28954
- destroy: (dom) => {
28955
- const ref = dom.__squisqDataCardRoot;
28956
- if (ref) setTimeout(() => ref.root.unmount(), 0);
28957
- },
28958
- side: 1,
28959
- ignoreSelection: true,
28960
- key: `squisq-data-card-${entry.id}`
28961
- }
28962
- )
28963
- );
28964
- }
28965
- return DecorationSet10.create(doc, decos);
28966
- }
28967
- function collectEntries(doc, mapped, seqStart) {
28968
- let seq = seqStart;
28969
- const entries = [];
28970
- doc.descendants((node2, pos) => {
28971
- if (node2.type.name !== "paragraph") return;
28972
- if (!dataLinkHrefOf(node2)) return false;
28973
- entries.push({ id: mapped?.get(pos) ?? `data-card-${++seq}`, pos });
28974
- return false;
28975
- });
28976
- return { entries, seq };
28977
- }
28978
- function applyState6(tr, prev, editor, doc, options) {
28979
- if (!tr.docChanged) return prev;
28980
- const mapped = mapFenceEntries(tr, prev.entries, doc, "paragraph");
28981
- const { entries, seq } = collectEntries(doc, mapped, prev.seq);
28982
- return { entries, seq, decorations: buildDecorations8(doc, entries, editor, options) };
28983
- }
28984
- var DataCardExtension = Extension10.create({
28985
- name: "squisqDataCard",
28986
- addOptions() {
28987
- return { enabled: true };
28988
- },
28989
- addProseMirrorPlugins() {
28990
- const editor = this.editor;
28991
- const options = this.options;
28992
- if (options.enabled === false) return [];
28993
- return [
28994
- new Plugin10({
28995
- key: DATA_CARD_KEY,
28996
- state: {
28997
- init: (_config, state) => {
28998
- const { entries, seq } = collectEntries(state.doc, null, 0);
28999
- return {
29000
- entries,
29001
- seq,
29002
- decorations: buildDecorations8(state.doc, entries, editor, options)
29003
- };
29004
- },
29005
- apply: (tr, prev, _oldState, newState) => applyState6(tr, prev, editor, newState.doc, options)
29006
- },
29007
- props: {
29008
- decorations(state) {
29009
- return this.getState(state)?.decorations ?? DecorationSet10.empty;
29010
- }
29011
- }
29012
- })
29013
- ];
29014
- }
29015
- });
29016
-
29017
28846
  // src/dataCard/DataCardWidget.tsx
29018
28847
  import { jsx as jsx55, jsxs as jsxs43 } from "react/jsx-runtime";
29019
28848
  var XLSX_SESSION_LOCKED_REASON = "Date cells and shared-formula masters stay locked; other formulas are editable";
@@ -29324,6 +29153,198 @@ function DataCardWidget({
29324
29153
  );
29325
29154
  }
29326
29155
 
29156
+ // src/dataCard/DataCardExtension.ts
29157
+ function normalizeDataLinkPath(value) {
29158
+ let normalized = "";
29159
+ for (let index2 = 0; index2 < value.length; index2++) {
29160
+ const char = value[index2];
29161
+ const next = value[index2 + 1];
29162
+ const code = next?.charCodeAt(0) ?? -1;
29163
+ const escapable = code >= 33 && code <= 47 || code >= 58 && code <= 64 || code >= 91 && code <= 96 || code >= 123 && code <= 126;
29164
+ if (char === "\\" && next !== void 0 && escapable) {
29165
+ normalized += next;
29166
+ index2++;
29167
+ } else {
29168
+ normalized += char;
29169
+ }
29170
+ }
29171
+ return normalized;
29172
+ }
29173
+ var DATA_CARD_KEY = new PluginKey10("squisq-data-card");
29174
+ function dataLinkHrefOf(node2) {
29175
+ if (node2.type.name !== "paragraph" || node2.childCount === 0) return null;
29176
+ let href = null;
29177
+ for (let i = 0; i < node2.childCount; i++) {
29178
+ const child = node2.child(i);
29179
+ if (!child.isText || !child.text || !child.text.trim()) return null;
29180
+ const link = child.marks.find((mark) => mark.type.name === "link");
29181
+ const childHref = link?.attrs?.href;
29182
+ if (typeof childHref !== "string") return null;
29183
+ const normalizedHref = normalizeDataLinkPath(childHref);
29184
+ if (href === null) href = normalizedHref;
29185
+ else if (href !== normalizedHref) return null;
29186
+ }
29187
+ return href !== null && isDataFilePath(href) ? href : null;
29188
+ }
29189
+ function findDataCardBlockPos(editor, blockId) {
29190
+ return DATA_CARD_KEY.getState(editor.state)?.entries.find((e2) => e2.id === blockId)?.pos ?? null;
29191
+ }
29192
+ function buildDecorations8(doc, entries, editor, options) {
29193
+ const decos = [];
29194
+ for (const entry of entries) {
29195
+ const node2 = doc.nodeAt(entry.pos);
29196
+ if (!node2 || node2.type.name !== "paragraph") continue;
29197
+ decos.push(
29198
+ Decoration10.node(entry.pos, entry.pos + node2.nodeSize, {
29199
+ class: "squisq-data-card-hidden"
29200
+ })
29201
+ );
29202
+ const blockId = entry.id;
29203
+ decos.push(
29204
+ Decoration10.widget(
29205
+ entry.pos + node2.nodeSize,
29206
+ () => {
29207
+ const container = document.createElement("div");
29208
+ container.className = "squisq-data-card-host squisq-block-fill-available";
29209
+ container.contentEditable = "false";
29210
+ containFenceWidgetEvents(container);
29211
+ const root = createRoot6(container);
29212
+ root.render(
29213
+ createElement12(DataCardWidget, {
29214
+ editor,
29215
+ blockId,
29216
+ getMediaProvider: () => options.mediaProvider?.(),
29217
+ getMediaRevision: () => options.mediaRevision?.() ?? 0,
29218
+ getContainer: () => options.container?.(),
29219
+ onOpenFiles: options.onOpenFiles,
29220
+ onMediaSaved: options.onMediaSaved,
29221
+ getCalcEngineFactory: () => options.calcEngineFactory?.()
29222
+ })
29223
+ );
29224
+ container.__squisqDataCardRoot = { root };
29225
+ return container;
29226
+ },
29227
+ {
29228
+ destroy: (dom) => {
29229
+ const ref = dom.__squisqDataCardRoot;
29230
+ if (ref) setTimeout(() => ref.root.unmount(), 0);
29231
+ },
29232
+ side: 1,
29233
+ ignoreSelection: true,
29234
+ key: `squisq-data-card-${entry.id}`
29235
+ }
29236
+ )
29237
+ );
29238
+ }
29239
+ return DecorationSet10.create(doc, decos);
29240
+ }
29241
+ function collectEntries(doc, mapped, seqStart) {
29242
+ let seq = seqStart;
29243
+ const entries = [];
29244
+ doc.descendants((node2, pos) => {
29245
+ if (node2.type.name !== "paragraph") return;
29246
+ if (!dataLinkHrefOf(node2)) return false;
29247
+ entries.push({ id: mapped?.get(pos) ?? `data-card-${++seq}`, pos });
29248
+ return false;
29249
+ });
29250
+ return { entries, seq };
29251
+ }
29252
+ function applyState6(tr, prev, editor, doc, options) {
29253
+ if (!tr.docChanged) return prev;
29254
+ const mapped = mapFenceEntries(tr, prev.entries, doc, "paragraph");
29255
+ const { entries, seq } = collectEntries(doc, mapped, prev.seq);
29256
+ return { entries, seq, decorations: buildDecorations8(doc, entries, editor, options) };
29257
+ }
29258
+ var DataCardExtension = Extension10.create({
29259
+ name: "squisqDataCard",
29260
+ addOptions() {
29261
+ return { enabled: true };
29262
+ },
29263
+ addProseMirrorPlugins() {
29264
+ const editor = this.editor;
29265
+ const options = this.options;
29266
+ if (options.enabled === false) return [];
29267
+ return [
29268
+ new Plugin10({
29269
+ key: DATA_CARD_KEY,
29270
+ state: {
29271
+ init: (_config, state) => {
29272
+ const { entries, seq } = collectEntries(state.doc, null, 0);
29273
+ return {
29274
+ entries,
29275
+ seq,
29276
+ decorations: buildDecorations8(state.doc, entries, editor, options)
29277
+ };
29278
+ },
29279
+ apply: (tr, prev, _oldState, newState) => applyState6(tr, prev, editor, newState.doc, options)
29280
+ },
29281
+ props: {
29282
+ decorations(state) {
29283
+ return this.getState(state)?.decorations ?? DecorationSet10.empty;
29284
+ }
29285
+ }
29286
+ })
29287
+ ];
29288
+ }
29289
+ });
29290
+
29291
+ // src/dataCard/viewStateBinding.ts
29292
+ function paramsOf(inner) {
29293
+ const params = {};
29294
+ if (!inner) return params;
29295
+ for (const token of tokenizeAttrTokens4(inner)) {
29296
+ const pair = splitKeyValueToken3(token);
29297
+ if (pair) params[pair.key] = unquoteAttrValue(pair.value);
29298
+ }
29299
+ return params;
29300
+ }
29301
+ function readHeadingViewBinding(editor, cardPos, href) {
29302
+ const headingPos = findOwningHeadingPosition(editor.state.doc, cardPos);
29303
+ if (headingPos === null) {
29304
+ return { headingPos: null, persisted: false, params: {} };
29305
+ }
29306
+ const node2 = editor.state.doc.nodeAt(headingPos);
29307
+ if (!node2 || node2.type.name !== "heading") {
29308
+ return { headingPos: null, persisted: false, params: {} };
29309
+ }
29310
+ const attrs = node2.attrs;
29311
+ const params = paramsOf(attrs.dataTemplateParams);
29312
+ const template = attrs.dataTemplate ? resolveTemplateName2(attrs.dataTemplate) : null;
29313
+ const persisted = template !== null && TABLE_FED_TEMPLATES.has(template) && params.src !== void 0 && normalizeDataLinkPath(params.src) === href;
29314
+ return {
29315
+ headingPos,
29316
+ persisted,
29317
+ params,
29318
+ ...params.sort !== void 0 ? { sortRaw: params.sort } : {},
29319
+ ...params.filter !== void 0 ? { filterRaw: params.filter } : {}
29320
+ };
29321
+ }
29322
+ function serializeParams3(params) {
29323
+ return Object.entries(params).map(([key, value]) => `${key}=${needsQuoting(value) ? quoteAttrValue5(value) : value}`).join(" ");
29324
+ }
29325
+ function writeHeadingViewState(editor, cardPos, href, view) {
29326
+ if (!editor.isEditable) return false;
29327
+ const binding = readHeadingViewBinding(editor, cardPos, href);
29328
+ if (binding.headingPos === null || !binding.persisted) return false;
29329
+ const raw = serializeTableViewState(view);
29330
+ const params = { ...binding.params };
29331
+ if (raw.sort !== void 0) params.sort = raw.sort;
29332
+ else delete params.sort;
29333
+ if (raw.filter !== void 0) params.filter = raw.filter;
29334
+ else delete params.filter;
29335
+ const serialized = serializeParams3(params);
29336
+ const pos = binding.headingPos;
29337
+ return editor.chain().command(({ tr }) => {
29338
+ const node2 = tr.doc.nodeAt(pos);
29339
+ if (!node2 || node2.type.name !== "heading") return false;
29340
+ tr.setNodeAttribute(pos, "dataTemplateParams", serialized.length > 0 ? serialized : null);
29341
+ return true;
29342
+ }).run();
29343
+ }
29344
+ function viewStateFromBinding(binding, headers) {
29345
+ return parseTableViewState(binding.sortRaw, binding.filterRaw, headers).view;
29346
+ }
29347
+
29327
29348
  // src/treeview/treeViewData.ts
29328
29349
  import { useEffect as useEffect40, useMemo as useMemo37, useState as useState51 } from "react";
29329
29350
 
@@ -33311,7 +33332,7 @@ function moveSelectionToDropPoint(view, event) {
33311
33332
  }
33312
33333
 
33313
33334
  // src/InlinePreviewGutter.tsx
33314
- import { useLayoutEffect as useLayoutEffect9, useMemo as useMemo42, useRef as useRef47, useState as useState60 } from "react";
33335
+ import { useLayoutEffect as useLayoutEffect9, useMemo as useMemo42, useRef as useRef47, useState as useState61 } from "react";
33315
33336
  import { VIEWPORT_PRESETS as VIEWPORT_PRESETS5 } from "@bendyline/squisq/schemas";
33316
33337
  import {
33317
33338
  flattenBlocks as flattenBlocks4,
@@ -33520,6 +33541,96 @@ function sameEntries(a, b) {
33520
33541
  return true;
33521
33542
  }
33522
33543
 
33544
+ // src/usePreviewProjection.ts
33545
+ import { useEffect as useEffect49, useState as useState60 } from "react";
33546
+ import {
33547
+ resolveAudioMapping,
33548
+ resolveDataReferences
33549
+ } from "@bendyline/squisq/doc";
33550
+ import { applyTransform } from "@bendyline/squisq/transform";
33551
+ var DATA_PREVIEW_ROWS = 50;
33552
+ var dataTableCaches = /* @__PURE__ */ new WeakMap();
33553
+ function dataTableCacheFor(container, revision) {
33554
+ let entry = dataTableCaches.get(container);
33555
+ if (!entry || entry.revision !== revision) {
33556
+ entry = { revision, cache: /* @__PURE__ */ new Map() };
33557
+ dataTableCaches.set(container, entry);
33558
+ }
33559
+ return entry.cache;
33560
+ }
33561
+ async function resolveDataPreviews(doc, container, mediaRevision) {
33562
+ try {
33563
+ const { defaultDataReaders } = await import("@bendyline/squisq-formats/data");
33564
+ const resolved = await resolveDataReferences(doc, container, {
33565
+ readers: defaultDataReaders(),
33566
+ maxPreviewRows: DATA_PREVIEW_ROWS,
33567
+ tableCache: dataTableCacheFor(container, mediaRevision)
33568
+ });
33569
+ return resolved.doc;
33570
+ } catch {
33571
+ return doc;
33572
+ }
33573
+ }
33574
+ function hasEquivalentAudio(left, right) {
33575
+ if (left === right) return true;
33576
+ if (left.segments.length !== right.segments.length) return false;
33577
+ return left.segments.every((segment, index2) => {
33578
+ const other = right.segments[index2];
33579
+ return segment.src === other.src && segment.name === other.name && segment.duration === other.duration && segment.startTime === other.startTime;
33580
+ });
33581
+ }
33582
+ function preserveEquivalentAudio(previous, next) {
33583
+ const previousAudio = previous?.playerDoc.audio;
33584
+ if (!previousAudio || !hasEquivalentAudio(previousAudio, next.playerDoc.audio)) return next;
33585
+ return {
33586
+ ...next,
33587
+ playerDoc: { ...next.playerDoc, audio: previousAudio }
33588
+ };
33589
+ }
33590
+ function usePreviewProjection(doc, transformStyle, workspaceContainer, documentTitle2, mediaRevision) {
33591
+ const [projection, setProjection] = useState60(null);
33592
+ useEffect49(() => {
33593
+ if (!doc || !doc.blocks.length) {
33594
+ setProjection(null);
33595
+ return;
33596
+ }
33597
+ const build = (sourceDoc) => {
33598
+ const contentDoc = transformStyle ? applyTransform(sourceDoc, transformStyle).doc : sourceDoc;
33599
+ const narrationOwnsTimeline = (contentDoc.documentMedia ?? []).some(
33600
+ (clip) => clip.anchor === "document"
33601
+ );
33602
+ return {
33603
+ contentDoc,
33604
+ playerDoc: buildPreviewDoc(contentDoc, {
33605
+ documentTitle: documentTitle2,
33606
+ interleaveImages: !narrationOwnsTimeline
33607
+ })
33608
+ };
33609
+ };
33610
+ const commit = (next) => {
33611
+ setProjection((previous) => preserveEquivalentAudio(previous, next));
33612
+ };
33613
+ if (workspaceContainer) {
33614
+ let cancelled = false;
33615
+ const immediate = build(doc);
33616
+ resolveAudioMapping(doc, workspaceContainer).then((audioDoc) => resolveDataPreviews(audioDoc, workspaceContainer, mediaRevision ?? 0)).then(
33617
+ (resolvedDoc) => {
33618
+ if (!cancelled) commit(build(resolvedDoc));
33619
+ },
33620
+ () => {
33621
+ if (!cancelled) commit(immediate);
33622
+ }
33623
+ );
33624
+ setProjection((previous) => previous ?? immediate);
33625
+ return () => {
33626
+ cancelled = true;
33627
+ };
33628
+ }
33629
+ commit(build(doc));
33630
+ }, [doc, transformStyle, workspaceContainer, documentTitle2, mediaRevision]);
33631
+ return projection;
33632
+ }
33633
+
33523
33634
  // src/InlinePreviewGutter.tsx
33524
33635
  import { Fragment as Fragment18, jsx as jsx63, jsxs as jsxs50 } from "react/jsx-runtime";
33525
33636
  function isAnnotated(block) {
@@ -33686,14 +33797,16 @@ function InlinePreviewGutter({
33686
33797
  connectorWidth = 24,
33687
33798
  mediaProvider = null
33688
33799
  }) {
33689
- const { doc } = useEditorContext();
33800
+ const { doc, workspaceContainer, fileName, mediaRevision } = useEditorContext();
33801
+ const projection = usePreviewProjection(doc, "", workspaceContainer, fileName, mediaRevision);
33802
+ const previewDoc = projection?.contentDoc ?? doc;
33690
33803
  const gutterRef = useRef47(null);
33691
33804
  const { entries: headingEntries, scrollToBlock } = useHeadingLayout(gutterRef);
33692
33805
  const previewSettings = usePreviewSettingsOptional();
33693
33806
  const activeTheme = previewSettings?.activeTheme ?? DEFAULT_THEME5;
33694
33807
  const items = useMemo42(() => {
33695
- if (!doc || !doc.blocks.length) return [];
33696
- const flat = flattenBlocks4(doc.blocks);
33808
+ if (!previewDoc || !previewDoc.blocks.length) return [];
33809
+ const flat = flattenBlocks4(previewDoc.blocks);
33697
33810
  const totalBlocks = flat.length;
33698
33811
  const result = [];
33699
33812
  flat.forEach((block, index2) => {
@@ -33718,6 +33831,10 @@ function InlinePreviewGutter({
33718
33831
  block.contents,
33719
33832
  collectImagesDeep(block)
33720
33833
  ),
33834
+ // Async sidecar resolution stores its bounded table window here.
33835
+ // Forward it before authored params/overrides so document-mode cards
33836
+ // render the same CSV/XLSX data as block and full-preview modes.
33837
+ ...block.templateData,
33721
33838
  ...annotation.params,
33722
33839
  ...block.templateOverrides
33723
33840
  };
@@ -33726,7 +33843,7 @@ function InlinePreviewGutter({
33726
33843
  totalBlocks,
33727
33844
  theme: activeTheme,
33728
33845
  viewport,
33729
- customTemplates: doc.customTemplates
33846
+ customTemplates: previewDoc.customTemplates
33730
33847
  };
33731
33848
  try {
33732
33849
  const { layers } = materializeBlockLayers2(templateBlock, ctx);
@@ -33747,13 +33864,13 @@ function InlinePreviewGutter({
33747
33864
  }
33748
33865
  });
33749
33866
  return result;
33750
- }, [doc, viewport, activeTheme]);
33867
+ }, [previewDoc, viewport, activeTheme]);
33751
33868
  const connectorTops = useMemo42(() => {
33752
33869
  const m = /* @__PURE__ */ new Map();
33753
33870
  headingEntries.forEach((e2) => m.set(e2.block.id, e2.top));
33754
33871
  return m;
33755
33872
  }, [headingEntries]);
33756
- const [positions, setPositions] = useState60(/* @__PURE__ */ new Map());
33873
+ const [positions, setPositions] = useState61(/* @__PURE__ */ new Map());
33757
33874
  useLayoutEffect9(() => {
33758
33875
  if (items.length === 0) {
33759
33876
  setPositions((prev) => prev.size === 0 ? prev : /* @__PURE__ */ new Map());
@@ -33938,10 +34055,10 @@ function InlinePreviewGutter({
33938
34055
  import {
33939
34056
  memo,
33940
34057
  useCallback as useCallback43,
33941
- useEffect as useEffect49,
34058
+ useEffect as useEffect50,
33942
34059
  useMemo as useMemo43,
33943
34060
  useRef as useRef48,
33944
- useState as useState61
34061
+ useState as useState62
33945
34062
  } from "react";
33946
34063
  import { flattenBlocks as flattenBlocks5, hasTemplate as hasTemplate2 } from "@bendyline/squisq/doc";
33947
34064
  import { extractPlainText as extractPlainText4 } from "@bendyline/squisq/markdown";
@@ -34063,8 +34180,8 @@ function OutlinePanel({ width, className, readOnly = false }) {
34063
34180
  const paneRef = useRef48(null);
34064
34181
  const cursorActiveId = useActiveOutlineBlockId();
34065
34182
  const activeDragRef = useRef48(null);
34066
- const [draggedBlockId, setDraggedBlockId] = useState61(null);
34067
- const [dropTarget, setDropTarget] = useState61(null);
34183
+ const [draggedBlockId, setDraggedBlockId] = useState62(null);
34184
+ const [dropTarget, setDropTarget] = useState62(null);
34068
34185
  const nextOutlineBlocks = doc?.blocks ?? EMPTY_BLOCKS;
34069
34186
  const outlineBlocksRef = useRef48(nextOutlineBlocks);
34070
34187
  if (!sameOutlineStructure(outlineBlocksRef.current, nextOutlineBlocks)) {
@@ -34397,11 +34514,11 @@ function useActiveOutlineBlockId() {
34397
34514
  const flatBlocksRef = useRef48(flatBlocks);
34398
34515
  flatBlocksRef.current = flatBlocks;
34399
34516
  const headingLocations = flatBlocks.map((block) => `${block.id}:${block.sourceHeading?.position?.start.line ?? ""}`).join("\0");
34400
- const [activeId, setActiveId] = useState61(null);
34401
- useEffect49(() => {
34517
+ const [activeId, setActiveId] = useState62(null);
34518
+ useEffect50(() => {
34402
34519
  setActiveId(null);
34403
34520
  }, [activeView]);
34404
- useEffect49(() => {
34521
+ useEffect50(() => {
34405
34522
  if (activeView !== "wysiwyg" || !tiptapEditor) return;
34406
34523
  const update = () => {
34407
34524
  const { from } = tiptapEditor.state.selection;
@@ -34423,7 +34540,7 @@ function useActiveOutlineBlockId() {
34423
34540
  tiptapEditor.off("update", update);
34424
34541
  };
34425
34542
  }, [activeView, tiptapEditor, headingLocations]);
34426
- useEffect49(() => {
34543
+ useEffect50(() => {
34427
34544
  if (activeView !== "raw" || !monacoEditor) return;
34428
34545
  const update = () => {
34429
34546
  const line = monacoEditor.getPosition()?.lineNumber;
@@ -34510,7 +34627,7 @@ function bumpHeadingLevelInSource(source, line, delta) {
34510
34627
  }
34511
34628
 
34512
34629
  // src/codeContext/CodeContextZones.tsx
34513
- import { useCallback as useCallback45, useEffect as useEffect51, useMemo as useMemo45, useRef as useRef50, useState as useState62 } from "react";
34630
+ import { useCallback as useCallback45, useEffect as useEffect52, useMemo as useMemo45, useRef as useRef50, useState as useState63 } from "react";
34514
34631
  import { createPortal as createPortal13 } from "react-dom";
34515
34632
 
34516
34633
  // src/codeContext/diffContextSections.ts
@@ -34634,7 +34751,7 @@ function setOrdinal(zone, ordinal) {
34634
34751
  // src/codeContext/CodeContextSectionView.tsx
34635
34752
  import { parseMarkdown as parseMarkdown8 } from "@bendyline/squisq/markdown";
34636
34753
  import { MarkdownRenderer } from "@bendyline/squisq-react";
34637
- import { useCallback as useCallback44, useEffect as useEffect50, useMemo as useMemo44, useRef as useRef49 } from "react";
34754
+ import { useCallback as useCallback44, useEffect as useEffect51, useMemo as useMemo44, useRef as useRef49 } from "react";
34638
34755
  import { jsx as jsx65, jsxs as jsxs52 } from "react/jsx-runtime";
34639
34756
  function CodeContextSectionView({
34640
34757
  section,
@@ -34654,7 +34771,7 @@ function CodeContextSectionView({
34654
34771
  () => expanded && section.markdown ? parseMarkdown8(section.markdown).children : null,
34655
34772
  [expanded, section.markdown]
34656
34773
  );
34657
- useEffect50(() => {
34774
+ useEffect51(() => {
34658
34775
  const el = rootRef.current;
34659
34776
  if (!el || typeof ResizeObserver === "undefined") return;
34660
34777
  const report = () => {
@@ -34726,11 +34843,11 @@ function CodeContextSectionView({
34726
34843
  import { Fragment as Fragment19, jsx as jsx66 } from "react/jsx-runtime";
34727
34844
  function CodeContextZones({ options }) {
34728
34845
  const { monacoEditor } = useEditorContext();
34729
- const [manager, setManager] = useState62(null);
34730
- const [, setZonesVersion] = useState62(0);
34731
- const [expandedById, setExpandedById] = useState62({});
34846
+ const [manager, setManager] = useState63(null);
34847
+ const [, setZonesVersion] = useState63(0);
34848
+ const [expandedById, setExpandedById] = useState63({});
34732
34849
  const seenIds = useRef50(/* @__PURE__ */ new Set());
34733
- useEffect51(() => {
34850
+ useEffect52(() => {
34734
34851
  if (!monacoEditor) return;
34735
34852
  const mgr = new CodeContextZoneManager(monacoEditor);
34736
34853
  const off = mgr.onDidChangeZones(() => setZonesVersion((v2) => v2 + 1));
@@ -34753,7 +34870,7 @@ function CodeContextZones({ options }) {
34753
34870
  });
34754
34871
  return out;
34755
34872
  }, [fileTop, sections]);
34756
- useEffect51(() => {
34873
+ useEffect52(() => {
34757
34874
  if (!manager) return;
34758
34875
  manager.sync(resolved.map((r) => r.spec));
34759
34876
  setExpandedById((prev) => {
@@ -35189,7 +35306,7 @@ function placeClipInBlock(source, fromLine, targetHeadingLine, spec, startAt) {
35189
35306
  }
35190
35307
 
35191
35308
  // src/TimelineTrack.tsx
35192
- import { useCallback as useCallback47, useEffect as useEffect54, useMemo as useMemo46, useRef as useRef53, useState as useState65 } from "react";
35309
+ import { useCallback as useCallback47, useEffect as useEffect55, useMemo as useMemo46, useRef as useRef53, useState as useState66 } from "react";
35193
35310
  import {
35194
35311
  resolveMediaSchedule as resolveMediaSchedule2,
35195
35312
  getDocPlaybackDuration,
@@ -35314,7 +35431,7 @@ function collectTimelinePlaybackSchedule(doc, scheduled) {
35314
35431
  }
35315
35432
 
35316
35433
  // src/useTimelineClock.ts
35317
- import { useCallback as useCallback46, useEffect as useEffect52, useRef as useRef51, useState as useState63 } from "react";
35434
+ import { useCallback as useCallback46, useEffect as useEffect53, useRef as useRef51, useState as useState64 } from "react";
35318
35435
  function advanceTime(prev, dt, total) {
35319
35436
  if (total <= 0) return 0;
35320
35437
  return Math.min(total, Math.max(0, prev + dt));
@@ -35334,8 +35451,8 @@ function playTimelineMediaAt(root, time) {
35334
35451
  });
35335
35452
  }
35336
35453
  function useTimelineClock(total) {
35337
- const [currentTime, setCurrentTime] = useState63(0);
35338
- const [isPlaying, setIsPlaying] = useState63(false);
35454
+ const [currentTime, setCurrentTime] = useState64(0);
35455
+ const [isPlaying, setIsPlaying] = useState64(false);
35339
35456
  const rafRef = useRef51(null);
35340
35457
  const lastRef = useRef51(0);
35341
35458
  const currentTimeRef = useRef51(0);
@@ -35343,10 +35460,10 @@ function useTimelineClock(total) {
35343
35460
  const mediaHostRef = useRef51(null);
35344
35461
  currentTimeRef.current = currentTime;
35345
35462
  isPlayingRef.current = isPlaying;
35346
- useEffect52(() => {
35463
+ useEffect53(() => {
35347
35464
  setCurrentTime((t) => Math.min(t, Math.max(0, total)));
35348
35465
  }, [total]);
35349
- useEffect52(() => {
35466
+ useEffect53(() => {
35350
35467
  if (!isPlaying) return;
35351
35468
  lastRef.current = performance.now();
35352
35469
  const tick = (now) => {
@@ -35408,7 +35525,7 @@ function timelineMediaLabel(src, kind) {
35408
35525
  }
35409
35526
 
35410
35527
  // src/TimelineItemMenu.tsx
35411
- import { useEffect as useEffect53, useLayoutEffect as useLayoutEffect10, useRef as useRef52, useState as useState64 } from "react";
35528
+ import { useEffect as useEffect54, useLayoutEffect as useLayoutEffect10, useRef as useRef52, useState as useState65 } from "react";
35412
35529
  import { createPortal as createPortal14 } from "react-dom";
35413
35530
  import { Fragment as Fragment20, jsx as jsx68, jsxs as jsxs54 } from "react/jsx-runtime";
35414
35531
  function TimelineItemMenu({
@@ -35423,7 +35540,7 @@ function TimelineItemMenu({
35423
35540
  onClose
35424
35541
  }) {
35425
35542
  const panelRef = useRef52(null);
35426
- const [style, setStyle] = useState64(() => menuStyle(anchor));
35543
+ const [style, setStyle] = useState65(() => menuStyle(anchor));
35427
35544
  useLayoutEffect10(() => {
35428
35545
  const panel = panelRef.current;
35429
35546
  if (!panel) return;
@@ -35437,7 +35554,7 @@ function TimelineItemMenu({
35437
35554
  resizeObserver?.disconnect();
35438
35555
  };
35439
35556
  }, [anchor]);
35440
- useEffect53(() => {
35557
+ useEffect54(() => {
35441
35558
  const onKeyDown = (event) => {
35442
35559
  if (event.key !== "Escape") return;
35443
35560
  event.preventDefault();
@@ -35497,12 +35614,12 @@ function BlockMenu({
35497
35614
  onStartTime,
35498
35615
  onTransition
35499
35616
  }) {
35500
- const [explicitDuration, setExplicitDuration] = useState64(target.explicitDuration);
35501
- const [duration, setDuration] = useState64(formatNumber(target.duration));
35502
- const [startTime, setStartTime] = useState64(
35617
+ const [explicitDuration, setExplicitDuration] = useState65(target.explicitDuration);
35618
+ const [duration, setDuration] = useState65(formatNumber(target.duration));
35619
+ const [startTime, setStartTime] = useState65(
35503
35620
  target.startTime == null ? "" : formatNumber(target.startTime)
35504
35621
  );
35505
- const [transition, setTransition] = useState64(target.transition);
35622
+ const [transition, setTransition] = useState65(target.transition);
35506
35623
  const toggleAutotime = (autotimed) => {
35507
35624
  setExplicitDuration(!autotimed);
35508
35625
  if (autotimed) {
@@ -35574,11 +35691,11 @@ function VideoMenu({
35574
35691
  target,
35575
35692
  onPatch
35576
35693
  }) {
35577
- const [placement, setPlacement] = useState64(target.placement);
35578
- const [locked, setLocked] = useState64(target.lockToBlock);
35579
- const [pipSize, setPipSize] = useState64(target.pipSize ?? "");
35580
- const [pipShape, setPipShape] = useState64(target.pipShape ?? "");
35581
- const [pipPosition, setPipPosition] = useState64(target.pipPosition ?? "");
35694
+ const [placement, setPlacement] = useState65(target.placement);
35695
+ const [locked, setLocked] = useState65(target.lockToBlock);
35696
+ const [pipSize, setPipSize] = useState65(target.pipSize ?? "");
35697
+ const [pipShape, setPipShape] = useState65(target.pipShape ?? "");
35698
+ const [pipPosition, setPipPosition] = useState65(target.pipPosition ?? "");
35582
35699
  const placed = placement === "picture-in-picture" || placement === "overlay";
35583
35700
  const placementOptions = [
35584
35701
  target.canUseContentPlacement ? { value: "content", label: "In layout" } : { value: "default", label: "Default" },
@@ -35848,9 +35965,9 @@ function TimelineTrack({
35848
35965
  colorScheme
35849
35966
  } = useEditorContext();
35850
35967
  const doc = docProp ?? contextDoc;
35851
- const [drag, setDrag] = useState65(null);
35852
- const [itemMenu, setItemMenu] = useState65(null);
35853
- const [pxPerSecond, setPxPerSecond] = useState65(DEFAULT_PX_PER_SECOND);
35968
+ const [drag, setDrag] = useState66(null);
35969
+ const [itemMenu, setItemMenu] = useState66(null);
35970
+ const [pxPerSecond, setPxPerSecond] = useState66(DEFAULT_PX_PER_SECOND);
35854
35971
  const scrollRef = useRef53(null);
35855
35972
  const blocks = useMemo46(() => doc ? flattenBlocks6(doc.blocks) : [], [doc]);
35856
35973
  const previewSettings = usePreviewSettingsOptional();
@@ -35883,8 +36000,8 @@ function TimelineTrack({
35883
36000
  setDrag(null);
35884
36001
  play();
35885
36002
  }, [play]);
35886
- const [scrubbing, setScrubbing] = useState65(false);
35887
- useEffect54(() => {
36003
+ const [scrubbing, setScrubbing] = useState66(false);
36004
+ useEffect55(() => {
35888
36005
  if (!scrubbing) return;
35889
36006
  const onMove = (e2) => {
35890
36007
  const scroll = scrollRef.current;
@@ -35922,7 +36039,7 @@ function TimelineTrack({
35922
36039
  [blocks]
35923
36040
  );
35924
36041
  const followedBlockRef = useRef53(null);
35925
- useEffect54(() => {
36042
+ useEffect55(() => {
35926
36043
  if (!isPlaying) {
35927
36044
  followedBlockRef.current = null;
35928
36045
  return;
@@ -35933,7 +36050,7 @@ function TimelineTrack({
35933
36050
  const line = headingLine(block);
35934
36051
  if (line != null) goToBlockByLine(line);
35935
36052
  }, [isPlaying, currentTime, blockAtTime, goToBlockByLine]);
35936
- useEffect54(() => {
36053
+ useEffect55(() => {
35937
36054
  if (!isPlaying) return;
35938
36055
  const scroll = scrollRef.current;
35939
36056
  if (!scroll) return;
@@ -35981,8 +36098,8 @@ function TimelineTrack({
35981
36098
  );
35982
36099
  const zoomIn = useCallback47(() => setPxPerSecond((s) => Math.min(ZOOM_MAX, s * ZOOM_FACTOR)), []);
35983
36100
  const zoomOut = useCallback47(() => setPxPerSecond((s) => Math.max(ZOOM_MIN, s / ZOOM_FACTOR)), []);
35984
- const [viewportWidth, setViewportWidth] = useState65(0);
35985
- useEffect54(() => {
36101
+ const [viewportWidth, setViewportWidth] = useState66(0);
36102
+ useEffect55(() => {
35986
36103
  const el = scrollRef.current;
35987
36104
  if (!el || typeof ResizeObserver === "undefined") return;
35988
36105
  const update = () => setViewportWidth(el.clientWidth);
@@ -35996,7 +36113,7 @@ function TimelineTrack({
35996
36113
  const dragRef = useRef53(null);
35997
36114
  dragRef.current = drag;
35998
36115
  const isDragging = drag != null && !drag.committed;
35999
- useEffect54(() => {
36116
+ useEffect55(() => {
36000
36117
  if (!isDragging) return;
36001
36118
  const onMove = (e2) => {
36002
36119
  const d = dragRef.current;
@@ -36027,7 +36144,7 @@ function TimelineTrack({
36027
36144
  window.removeEventListener("pointerup", onUp);
36028
36145
  };
36029
36146
  }, [isDragging]);
36030
- useEffect54(() => {
36147
+ useEffect55(() => {
36031
36148
  if (dragRef.current?.committed) setDrag(null);
36032
36149
  }, [doc]);
36033
36150
  const beginDrag = useCallback47(
@@ -36630,98 +36747,6 @@ function formatClock3(seconds) {
36630
36747
  import { useMemo as useMemo48 } from "react";
36631
36748
  import { getDocPlaybackDuration as getDocPlaybackDuration2, resolveMediaSchedule as resolveMediaSchedule3 } from "@bendyline/squisq/schemas";
36632
36749
  import { DocPlayer } from "@bendyline/squisq-react";
36633
-
36634
- // src/usePreviewProjection.ts
36635
- import { useEffect as useEffect55, useState as useState66 } from "react";
36636
- import {
36637
- resolveAudioMapping,
36638
- resolveDataReferences
36639
- } from "@bendyline/squisq/doc";
36640
- import { applyTransform } from "@bendyline/squisq/transform";
36641
- var DATA_PREVIEW_ROWS = 50;
36642
- var dataTableCaches = /* @__PURE__ */ new WeakMap();
36643
- function dataTableCacheFor(container, revision) {
36644
- let entry = dataTableCaches.get(container);
36645
- if (!entry || entry.revision !== revision) {
36646
- entry = { revision, cache: /* @__PURE__ */ new Map() };
36647
- dataTableCaches.set(container, entry);
36648
- }
36649
- return entry.cache;
36650
- }
36651
- async function resolveDataPreviews(doc, container, mediaRevision) {
36652
- try {
36653
- const { defaultDataReaders } = await import("@bendyline/squisq-formats/data");
36654
- const resolved = await resolveDataReferences(doc, container, {
36655
- readers: defaultDataReaders(),
36656
- maxPreviewRows: DATA_PREVIEW_ROWS,
36657
- tableCache: dataTableCacheFor(container, mediaRevision)
36658
- });
36659
- return resolved.doc;
36660
- } catch {
36661
- return doc;
36662
- }
36663
- }
36664
- function hasEquivalentAudio(left, right) {
36665
- if (left === right) return true;
36666
- if (left.segments.length !== right.segments.length) return false;
36667
- return left.segments.every((segment, index2) => {
36668
- const other = right.segments[index2];
36669
- return segment.src === other.src && segment.name === other.name && segment.duration === other.duration && segment.startTime === other.startTime;
36670
- });
36671
- }
36672
- function preserveEquivalentAudio(previous, next) {
36673
- const previousAudio = previous?.playerDoc.audio;
36674
- if (!previousAudio || !hasEquivalentAudio(previousAudio, next.playerDoc.audio)) return next;
36675
- return {
36676
- ...next,
36677
- playerDoc: { ...next.playerDoc, audio: previousAudio }
36678
- };
36679
- }
36680
- function usePreviewProjection(doc, transformStyle, workspaceContainer, documentTitle2, mediaRevision) {
36681
- const [projection, setProjection] = useState66(null);
36682
- useEffect55(() => {
36683
- if (!doc || !doc.blocks.length) {
36684
- setProjection(null);
36685
- return;
36686
- }
36687
- const build = (sourceDoc) => {
36688
- const contentDoc = transformStyle ? applyTransform(sourceDoc, transformStyle).doc : sourceDoc;
36689
- const narrationOwnsTimeline = (contentDoc.documentMedia ?? []).some(
36690
- (clip) => clip.anchor === "document"
36691
- );
36692
- return {
36693
- contentDoc,
36694
- playerDoc: buildPreviewDoc(contentDoc, {
36695
- documentTitle: documentTitle2,
36696
- interleaveImages: !narrationOwnsTimeline
36697
- })
36698
- };
36699
- };
36700
- const commit = (next) => {
36701
- setProjection((previous) => preserveEquivalentAudio(previous, next));
36702
- };
36703
- if (workspaceContainer) {
36704
- let cancelled = false;
36705
- const immediate = build(doc);
36706
- resolveAudioMapping(doc, workspaceContainer).then((audioDoc) => resolveDataPreviews(audioDoc, workspaceContainer, mediaRevision ?? 0)).then(
36707
- (resolvedDoc) => {
36708
- if (!cancelled) commit(build(resolvedDoc));
36709
- },
36710
- () => {
36711
- if (!cancelled) commit(immediate);
36712
- }
36713
- );
36714
- setProjection((previous) => previous ?? immediate);
36715
- return () => {
36716
- cancelled = true;
36717
- };
36718
- }
36719
- commit(build(doc));
36720
- }, [doc, transformStyle, workspaceContainer, documentTitle2, mediaRevision]);
36721
- return projection;
36722
- }
36723
-
36724
- // src/TimelineCompositionPanel.tsx
36725
36750
  import { jsx as jsx71, jsxs as jsxs57 } from "react/jsx-runtime";
36726
36751
  function TimelineCompositionPanel({
36727
36752
  doc,
@@ -37280,7 +37305,7 @@ function collectImageRefs(doc) {
37280
37305
  }
37281
37306
 
37282
37307
  // src/PreviewPanel.tsx
37283
- import { useState as useState70, useEffect as useEffect60, useMemo as useMemo53, useCallback as useCallback52, useRef as useRef58 } from "react";
37308
+ import { useState as useState71, useEffect as useEffect61, useMemo as useMemo54, useCallback as useCallback52, useRef as useRef58 } from "react";
37284
37309
  import { createPortal as createPortal16 } from "react-dom";
37285
37310
  import {
37286
37311
  DashboardView,
@@ -38403,8 +38428,219 @@ function PrintPreview({
38403
38428
  );
38404
38429
  }
38405
38430
 
38431
+ // src/slideshow/SlideshowDataGrid.tsx
38432
+ import {
38433
+ createContext as createContext9,
38434
+ useContext as useContext9,
38435
+ useEffect as useEffect60,
38436
+ useMemo as useMemo53,
38437
+ useState as useState70
38438
+ } from "react";
38439
+ import { parseTableViewState as parseTableViewState2 } from "@bendyline/squisq/table";
38440
+ import { DataGrid, TableStoreClient } from "@bendyline/squisq-grid-react";
38441
+
38442
+ // src/slideshow/slideshowDataSources.ts
38443
+ import { isDataFilePath as isDataFilePath2, resolveTemplateName as resolveTemplateName3 } from "@bendyline/squisq/doc";
38444
+ function extensionOf2(path) {
38445
+ const base = path.split("/").pop() ?? path;
38446
+ const dot = base.lastIndexOf(".");
38447
+ return dot > 0 ? base.slice(dot + 1).toLowerCase() : "";
38448
+ }
38449
+ function blockHasAuthoredRows(block) {
38450
+ const owns = (record, key) => !!record && Object.prototype.hasOwnProperty.call(record, key);
38451
+ return owns(block.templateData, "headers") || owns(block.templateData, "rows") || owns(block.templateOverrides, "headers") || owns(block.templateOverrides, "rows");
38452
+ }
38453
+ function collectSlideshowDataSources(doc) {
38454
+ const sources = /* @__PURE__ */ new Map();
38455
+ if (!doc) return sources;
38456
+ const visit = (blocks) => {
38457
+ for (const block of blocks) {
38458
+ const overrides = block.templateOverrides;
38459
+ const src = overrides?.src;
38460
+ if (typeof src === "string" && isDataFilePath2(src) && resolveTemplateName3(block.template ?? "") === "dataTable" && !blockHasAuthoredRows(block)) {
38461
+ sources.set(block.id, {
38462
+ blockId: block.id,
38463
+ src,
38464
+ ext: extensionOf2(src),
38465
+ ...overrides?.sheet ? { sheet: overrides.sheet } : {},
38466
+ ...overrides?.anchor ? { anchor: overrides.anchor } : {},
38467
+ ...overrides?.headerRow !== void 0 ? { headerRow: overrides.headerRow !== "false" } : {},
38468
+ ...overrides?.sort ? { sort: overrides.sort } : {},
38469
+ ...overrides?.filter ? { filter: overrides.filter } : {}
38470
+ });
38471
+ }
38472
+ if (block.children?.length) visit(block.children);
38473
+ }
38474
+ };
38475
+ visit(doc.blocks);
38476
+ return sources;
38477
+ }
38478
+
38479
+ // src/slideshow/SlideshowDataGrid.tsx
38480
+ import { Fragment as Fragment21, jsx as jsx77 } from "react/jsx-runtime";
38481
+ var EMPTY_CONTEXT = {
38482
+ container: null,
38483
+ mediaRevision: 0,
38484
+ sources: /* @__PURE__ */ new Map()
38485
+ };
38486
+ var SlideshowDataGridContext = createContext9(EMPTY_CONTEXT);
38487
+ function SlideshowDataGridProvider({
38488
+ doc,
38489
+ container,
38490
+ mediaRevision,
38491
+ children
38492
+ }) {
38493
+ const sources = useMemo53(() => collectSlideshowDataSources(doc), [doc]);
38494
+ const value = useMemo53(
38495
+ () => ({ container: container ?? null, mediaRevision, sources }),
38496
+ [container, mediaRevision, sources]
38497
+ );
38498
+ return /* @__PURE__ */ jsx77(SlideshowDataGridContext.Provider, { value, children });
38499
+ }
38500
+ var EMPTY_VIEW = { sort: [], filter: [] };
38501
+ function sourceKey(source) {
38502
+ if (!source) return "";
38503
+ return [
38504
+ source.blockId,
38505
+ source.src,
38506
+ source.sheet ?? "",
38507
+ source.anchor ?? "",
38508
+ String(source.headerRow ?? ""),
38509
+ source.sort ?? "",
38510
+ source.filter ?? ""
38511
+ ].join("\0");
38512
+ }
38513
+ function columnWidthsFor(ingest, availableWidth, fontSize) {
38514
+ if (ingest.headers.length === 0) return [];
38515
+ const widths = ingest.headers.map((header, col) => {
38516
+ let chars = header.length;
38517
+ for (const row of ingest.cells.slice(0, 100)) {
38518
+ chars = Math.max(chars, String(row[col] ?? "").length);
38519
+ }
38520
+ return Math.max(fontSize * 4.5, Math.min(chars, 38) * fontSize * 0.58 + fontSize * 1.5);
38521
+ });
38522
+ const total = widths.reduce((sum, value) => sum + value, 0);
38523
+ if (total >= availableWidth) return widths;
38524
+ const bonus = (availableWidth - total) / widths.length;
38525
+ return widths.map((value) => value + bonus);
38526
+ }
38527
+ function sourceForBlock(sources, block) {
38528
+ const sourceBlockId = block.sourceBlockId;
38529
+ return sources.get(block.id) ?? (sourceBlockId ? sources.get(sourceBlockId) : void 0);
38530
+ }
38531
+ function SlideshowDataGridRenderer({
38532
+ block,
38533
+ layer,
38534
+ width,
38535
+ height,
38536
+ fallback
38537
+ }) {
38538
+ const { container, mediaRevision, sources } = useContext9(SlideshowDataGridContext);
38539
+ const source = sourceForBlock(sources, block);
38540
+ const activeSourceKey = sourceKey(source);
38541
+ const [remote, setRemote] = useState70({ key: "", status: "idle" });
38542
+ useEffect60(() => {
38543
+ if (!container || !source) {
38544
+ setRemote({ key: activeSourceKey, status: "idle" });
38545
+ return;
38546
+ }
38547
+ let cancelled = false;
38548
+ let ownedProvider = null;
38549
+ setRemote({ key: activeSourceKey, status: "loading" });
38550
+ void (async () => {
38551
+ try {
38552
+ const bytes = await container.readFile(source.src);
38553
+ if (!bytes) throw new Error("data sidecar not found");
38554
+ const { ingest: ingest2 } = await ingestSidecarBytes(bytes, source.ext, {
38555
+ ...source.sheet ? { sheet: source.sheet } : {},
38556
+ ...source.anchor ? { anchor: source.anchor } : {},
38557
+ ...source.headerRow !== void 0 ? { headerRow: source.headerRow } : {}
38558
+ });
38559
+ const provider2 = new TableStoreClient(ingest2);
38560
+ ownedProvider = provider2;
38561
+ await provider2.describe();
38562
+ if (cancelled) {
38563
+ provider2.dispose();
38564
+ ownedProvider = null;
38565
+ return;
38566
+ }
38567
+ const initialView2 = parseTableViewState2(source.sort, source.filter, ingest2.headers).view;
38568
+ setRemote({ key: activeSourceKey, status: "ready", provider: provider2, ingest: ingest2, initialView: initialView2 });
38569
+ } catch {
38570
+ if (!cancelled) setRemote({ key: activeSourceKey, status: "error" });
38571
+ }
38572
+ })();
38573
+ return () => {
38574
+ cancelled = true;
38575
+ ownedProvider?.dispose();
38576
+ };
38577
+ }, [activeSourceKey, container, mediaRevision]);
38578
+ const currentRemote = remote.key === activeSourceKey ? remote : void 0;
38579
+ const previewRows = useMemo53(
38580
+ () => Array.isArray(layer.content.rows) ? layer.content.rows : [],
38581
+ [layer.content.rows]
38582
+ );
38583
+ const previewHeaders = useMemo53(
38584
+ () => Array.isArray(layer.content.headers) ? layer.content.headers : [],
38585
+ [layer.content.headers]
38586
+ );
38587
+ const useLocalGrid = (!source || currentRemote?.status === "error") && previewRows.length > (layer.content.maxVisibleRows ?? 10);
38588
+ const localProvider = useMemo53(
38589
+ () => useLocalGrid ? new TableStoreClient({ headers: previewHeaders, cells: previewRows }) : null,
38590
+ [previewHeaders, previewRows, useLocalGrid]
38591
+ );
38592
+ useEffect60(() => () => localProvider?.dispose(), [localProvider]);
38593
+ const ready = currentRemote?.status === "ready" ? currentRemote : void 0;
38594
+ const provider = ready?.provider ?? localProvider;
38595
+ const ingest = ready?.ingest ?? (localProvider ? { headers: previewHeaders, cells: previewRows } : void 0);
38596
+ const initialView = ready?.initialView ?? EMPTY_VIEW;
38597
+ const [view, setView] = useState70(initialView);
38598
+ useEffect60(() => setView(initialView), [initialView, provider]);
38599
+ if (!provider || !ingest) return /* @__PURE__ */ jsx77(Fragment21, { children: fallback });
38600
+ const { style } = layer.content;
38601
+ const rowHeight = Math.max(32, style.fontSize * 2.1);
38602
+ const footerHeight = Math.max(28, style.fontSize * 1.5);
38603
+ const scrollerHeight = Math.max(rowHeight * 2, height - footerHeight);
38604
+ const widths = columnWidthsFor(ingest, width - 2, style.fontSize);
38605
+ const gridStyle = {
38606
+ width: `${width}px`,
38607
+ height: `${height}px`,
38608
+ fontFamily: style.fontFamily ?? "system-ui, sans-serif",
38609
+ "--squisq-grid-font-size": `${style.fontSize}px`,
38610
+ "--squisq-grid-header-font-family": style.headerFontFamily ?? style.fontFamily ?? "system-ui, sans-serif",
38611
+ "--squisq-grid-footer-font-size": `${style.fontSize * 0.6}px`,
38612
+ "--squisq-grid-bg": style.cellBackground,
38613
+ "--squisq-grid-text": style.cellColor,
38614
+ "--squisq-grid-text-muted": style.cellColor,
38615
+ "--squisq-grid-text-on-accent": style.headerColor,
38616
+ "--squisq-grid-border": style.borderColor,
38617
+ "--squisq-grid-border-subtle": style.borderColor,
38618
+ "--squisq-grid-header-bg": style.headerBackground,
38619
+ "--squisq-grid-header-text": style.headerColor,
38620
+ "--squisq-grid-input-bg": style.cellBackground,
38621
+ "--squisq-grid-row-hover": `color-mix(in srgb, ${style.headerBackground} 12%, ${style.cellBackground})`,
38622
+ "--squisq-grid-selection-bg": `color-mix(in srgb, ${style.headerBackground} 22%, ${style.cellBackground})`,
38623
+ "--squisq-grid-selection-border": style.headerBackground,
38624
+ "--squisq-grid-focus-ring": style.headerBackground,
38625
+ "--squisq-grid-accent": style.headerBackground,
38626
+ "--squisq-grid-resize-handle": style.headerBackground
38627
+ };
38628
+ return /* @__PURE__ */ jsx77("div", { className: "squisq-slideshow-data-grid", style: gridStyle, children: /* @__PURE__ */ jsx77(
38629
+ DataGrid,
38630
+ {
38631
+ provider,
38632
+ view,
38633
+ onViewChange: setView,
38634
+ height: scrollerHeight,
38635
+ rowHeight,
38636
+ showFilters: false,
38637
+ defaultColumnWidths: widths
38638
+ }
38639
+ ) });
38640
+ }
38641
+
38406
38642
  // src/PreviewPanel.tsx
38407
- import { Fragment as Fragment21, jsx as jsx77, jsxs as jsxs62 } from "react/jsx-runtime";
38643
+ import { jsx as jsx78, jsxs as jsxs62 } from "react/jsx-runtime";
38408
38644
  function PreviewPanel({
38409
38645
  basePath = "/",
38410
38646
  className,
@@ -38451,7 +38687,7 @@ function PreviewPanel({
38451
38687
  } = usePreviewSettings();
38452
38688
  const mainSurfaceRef = useRef58(null);
38453
38689
  const popupSurfaceRef = useRef58(null);
38454
- const [playbackState, setPlaybackState] = useState70(null);
38690
+ const [playbackState, setPlaybackState] = useState71(null);
38455
38691
  const handlePlaybackStateChange = useCallback52((next) => {
38456
38692
  setPlaybackState(next);
38457
38693
  }, []);
@@ -38464,7 +38700,7 @@ function PreviewPanel({
38464
38700
  );
38465
38701
  const previewDoc = previewProjection?.playerDoc ?? null;
38466
38702
  const contentDoc = previewProjection?.contentDoc ?? null;
38467
- const followerAudioController = useMemo53(() => {
38703
+ const followerAudioController = useMemo54(() => {
38468
38704
  if (!playbackState || !previewDoc) return null;
38469
38705
  const noOp = () => Promise.resolve();
38470
38706
  return {
@@ -38483,7 +38719,7 @@ function PreviewPanel({
38483
38719
  restart: noOp
38484
38720
  };
38485
38721
  }, [playbackState, previewDoc]);
38486
- const documentMarkdown = useMemo53(
38722
+ const documentMarkdown = useMemo54(
38487
38723
  () => activeTransformStyle && contentDoc ? buildDocumentPreviewMarkdown(contentDoc) : markdownSource,
38488
38724
  [activeTransformStyle, contentDoc, markdownSource]
38489
38725
  );
@@ -38492,11 +38728,11 @@ function PreviewPanel({
38492
38728
  const isNarrateMode = activeDisplayMode === "narrate";
38493
38729
  const isDashboardMode = activeDisplayMode === "dashboard";
38494
38730
  const isFlashcardsMode = activeDisplayMode === "flashcards";
38495
- useEffect60(() => {
38731
+ useEffect61(() => {
38496
38732
  if (presentation?.activeTarget === "window") return;
38497
38733
  setPlaybackState(null);
38498
38734
  }, [presentation?.activeTarget]);
38499
- useEffect60(() => {
38735
+ useEffect61(() => {
38500
38736
  if (presentation?.activeTarget !== "window" || !presentation.popupRoot) return;
38501
38737
  const mainRoot = mainSurfaceRef.current;
38502
38738
  const followerRoot = popupSurfaceRef.current;
@@ -38559,22 +38795,22 @@ function PreviewPanel({
38559
38795
  presentation?.popupRoot
38560
38796
  ]);
38561
38797
  if (isParsing && !isNarrateMode && !previewDoc) {
38562
- return /* @__PURE__ */ jsx77("div", { className: `squisq-preview-status ${className || ""}`, "data-testid": "preview-panel", children: /* @__PURE__ */ jsx77("p", { children: "Parsing\u2026" }) });
38798
+ return /* @__PURE__ */ jsx78("div", { className: `squisq-preview-status ${className || ""}`, "data-testid": "preview-panel", children: /* @__PURE__ */ jsx78("p", { children: "Parsing\u2026" }) });
38563
38799
  }
38564
38800
  if (parseError && !isNarrateMode) {
38565
38801
  return /* @__PURE__ */ jsxs62("div", { className: `squisq-preview-status ${className || ""}`, "data-testid": "preview-panel", children: [
38566
- /* @__PURE__ */ jsx77("h3", { children: "Parse Error" }),
38567
- /* @__PURE__ */ jsx77("pre", { children: parseError })
38802
+ /* @__PURE__ */ jsx78("h3", { children: "Parse Error" }),
38803
+ /* @__PURE__ */ jsx78("pre", { children: parseError })
38568
38804
  ] });
38569
38805
  }
38570
38806
  if (!previewDoc && !isDocumentMode && !isNarrateMode) {
38571
- return /* @__PURE__ */ jsx77("div", { className: `squisq-preview-status ${className || ""}`, "data-testid": "preview-panel", children: /* @__PURE__ */ jsx77("p", { children: "No content to preview. Start typing in the editor." }) });
38807
+ return /* @__PURE__ */ jsx78("div", { className: `squisq-preview-status ${className || ""}`, "data-testid": "preview-panel", children: /* @__PURE__ */ jsx78("p", { children: "No content to preview. Start typing in the editor." }) });
38572
38808
  }
38573
38809
  const fillsContainer = printMode?.active || isDocumentMode || isPageMode || isNarrateMode || isFlashcardsMode ? "stretch" : "center";
38574
38810
  const audienceWindowOpen = presentation?.activeTarget === "window";
38575
38811
  const renderSurface = (audience) => {
38576
38812
  if (!audience && printMode?.active) {
38577
- return /* @__PURE__ */ jsx77(
38813
+ return /* @__PURE__ */ jsx78(
38578
38814
  PrintPreview,
38579
38815
  {
38580
38816
  displayMode: activeDisplayMode,
@@ -38591,7 +38827,7 @@ function PreviewPanel({
38591
38827
  );
38592
38828
  }
38593
38829
  if (isDocumentMode) {
38594
- return /* @__PURE__ */ jsx77(
38830
+ return /* @__PURE__ */ jsx78(
38595
38831
  PlainHtmlPreview,
38596
38832
  {
38597
38833
  markdown: documentMarkdown,
@@ -38608,7 +38844,7 @@ function PreviewPanel({
38608
38844
  }
38609
38845
  if (isNarrateMode) {
38610
38846
  if (audience) return null;
38611
- return /* @__PURE__ */ jsx77(
38847
+ return /* @__PURE__ */ jsx78(
38612
38848
  TeleprompterView,
38613
38849
  {
38614
38850
  doc,
@@ -38627,7 +38863,7 @@ function PreviewPanel({
38627
38863
  );
38628
38864
  }
38629
38865
  if (isPageMode) {
38630
- return /* @__PURE__ */ jsx77(
38866
+ return /* @__PURE__ */ jsx78(
38631
38867
  LinearDocView2,
38632
38868
  {
38633
38869
  doc: contentDoc ?? doc,
@@ -38644,7 +38880,7 @@ function PreviewPanel({
38644
38880
  );
38645
38881
  }
38646
38882
  if (isFlashcardsMode) {
38647
- return /* @__PURE__ */ jsx77(
38883
+ return /* @__PURE__ */ jsx78(
38648
38884
  FlashcardView,
38649
38885
  {
38650
38886
  doc: contentDoc ?? doc,
@@ -38659,7 +38895,7 @@ function PreviewPanel({
38659
38895
  );
38660
38896
  }
38661
38897
  if (isDashboardMode) {
38662
- return /* @__PURE__ */ jsx77("div", { className: "squisq-dashboard-fit", children: /* @__PURE__ */ jsx77(
38898
+ return /* @__PURE__ */ jsx78("div", { className: "squisq-dashboard-fit", children: /* @__PURE__ */ jsx78(
38663
38899
  DashboardView,
38664
38900
  {
38665
38901
  doc: contentDoc ?? doc,
@@ -38674,10 +38910,10 @@ function PreviewPanel({
38674
38910
  ) });
38675
38911
  }
38676
38912
  if (audience && !followerAudioController) {
38677
- return /* @__PURE__ */ jsx77("div", { className: "squisq-presentation-connecting", children: "Connecting presentation..." });
38913
+ return /* @__PURE__ */ jsx78("div", { className: "squisq-presentation-connecting", children: "Connecting presentation..." });
38678
38914
  }
38679
38915
  const audienceCaptionMode = playbackState?.captionMode;
38680
- return /* @__PURE__ */ jsx77(
38916
+ return /* @__PURE__ */ jsx78(
38681
38917
  DocPlayer2,
38682
38918
  {
38683
38919
  doc: previewDoc,
@@ -38705,7 +38941,8 @@ function PreviewPanel({
38705
38941
  globalKeyboardShortcuts: !audience,
38706
38942
  showCodeCopyButton,
38707
38943
  onCopyCode,
38708
- onPlaybackStateChange: !audience && audienceWindowOpen ? handlePlaybackStateChange : void 0
38944
+ onPlaybackStateChange: !audience && audienceWindowOpen ? handlePlaybackStateChange : void 0,
38945
+ tableContentRenderer: !audience && activeDisplayMode === "slideshow" ? SlideshowDataGridRenderer : void 0
38709
38946
  },
38710
38947
  `${audience ? "audience" : "primary"}-${activeTransformStyle || "none"}`
38711
38948
  );
@@ -38719,49 +38956,57 @@ function PreviewPanel({
38719
38956
  minHeight: 0,
38720
38957
  background: presentation?.activeTarget ? activeTheme.colors.background : void 0
38721
38958
  };
38722
- return /* @__PURE__ */ jsxs62(Fragment21, { children: [
38723
- /* @__PURE__ */ jsx77(
38724
- "div",
38725
- {
38726
- className: `squisq-preview-container ${className || ""}`,
38727
- "data-testid": "preview-panel",
38728
- style: {
38729
- width: "100%",
38730
- height: "100%",
38731
- display: "flex",
38732
- flexDirection: "column",
38733
- overflow: "hidden",
38734
- background: "var(--squisq-bg)"
38735
- },
38736
- children: /* @__PURE__ */ jsx77("div", { ref: mainSurfaceRef, className: "squisq-preview-player", style: surfaceStyle, children: renderSurface(false) })
38737
- }
38738
- ),
38739
- audienceWindowOpen && presentation?.popupRoot && !isNarrateMode ? createPortal16(
38740
- /* @__PURE__ */ jsx77(
38741
- "div",
38742
- {
38743
- className: "squisq-editor-shell squisq-presentation-window",
38744
- "data-theme": colorScheme,
38745
- children: /* @__PURE__ */ jsx77("div", { className: "squisq-preview-container squisq-presentation-window-preview", children: /* @__PURE__ */ jsx77(
38959
+ return /* @__PURE__ */ jsxs62(
38960
+ SlideshowDataGridProvider,
38961
+ {
38962
+ doc,
38963
+ container: workspaceContainer,
38964
+ mediaRevision,
38965
+ children: [
38966
+ /* @__PURE__ */ jsx78(
38967
+ "div",
38968
+ {
38969
+ className: `squisq-preview-container ${className || ""}`,
38970
+ "data-testid": "preview-panel",
38971
+ style: {
38972
+ width: "100%",
38973
+ height: "100%",
38974
+ display: "flex",
38975
+ flexDirection: "column",
38976
+ overflow: "hidden",
38977
+ background: "var(--squisq-bg)"
38978
+ },
38979
+ children: /* @__PURE__ */ jsx78("div", { ref: mainSurfaceRef, className: "squisq-preview-player", style: surfaceStyle, children: renderSurface(false) })
38980
+ }
38981
+ ),
38982
+ audienceWindowOpen && presentation?.popupRoot && !isNarrateMode ? createPortal16(
38983
+ /* @__PURE__ */ jsx78(
38746
38984
  "div",
38747
38985
  {
38748
- ref: popupSurfaceRef,
38749
- className: "squisq-preview-player squisq-presentation-window-surface",
38750
- style: surfaceStyle,
38751
- "aria-label": "Audience presentation",
38752
- children: renderSurface(true)
38986
+ className: "squisq-editor-shell squisq-presentation-window",
38987
+ "data-theme": colorScheme,
38988
+ children: /* @__PURE__ */ jsx78("div", { className: "squisq-preview-container squisq-presentation-window-preview", children: /* @__PURE__ */ jsx78(
38989
+ "div",
38990
+ {
38991
+ ref: popupSurfaceRef,
38992
+ className: "squisq-preview-player squisq-presentation-window-surface",
38993
+ style: surfaceStyle,
38994
+ "aria-label": "Audience presentation",
38995
+ children: renderSurface(true)
38996
+ }
38997
+ ) })
38753
38998
  }
38754
- ) })
38755
- }
38756
- ),
38757
- presentation.popupRoot
38758
- ) : null
38759
- ] });
38999
+ ),
39000
+ presentation.popupRoot
39001
+ ) : null
39002
+ ]
39003
+ }
39004
+ );
38760
39005
  }
38761
39006
 
38762
39007
  // src/MediaBin.tsx
38763
- import { useState as useState71, useEffect as useEffect61, useRef as useRef59, useCallback as useCallback53 } from "react";
38764
- import { jsx as jsx78, jsxs as jsxs63 } from "react/jsx-runtime";
39008
+ import { useState as useState72, useEffect as useEffect62, useRef as useRef59, useCallback as useCallback53 } from "react";
39009
+ import { jsx as jsx79, jsxs as jsxs63 } from "react/jsx-runtime";
38765
39010
  function formatSize(bytes) {
38766
39011
  if (bytes < 1024) return `${bytes} B`;
38767
39012
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
@@ -38829,20 +39074,20 @@ function MediaBin({
38829
39074
  allowBinaryDownloads = true,
38830
39075
  highlightPath = null
38831
39076
  }) {
38832
- const [entries, setEntries] = useState71([]);
39077
+ const [entries, setEntries] = useState72([]);
38833
39078
  const listRef = useRef59(null);
38834
- useEffect61(() => {
39079
+ useEffect62(() => {
38835
39080
  if (!highlightPath || !listRef.current) return;
38836
39081
  const item = listRef.current.querySelector(`[data-media-path="${CSS.escape(highlightPath)}"]`);
38837
39082
  if (item instanceof HTMLElement) {
38838
39083
  item.scrollIntoView({ block: "nearest" });
38839
39084
  }
38840
39085
  }, [highlightPath, entries]);
38841
- const [thumbUrls, setThumbUrls] = useState71({});
38842
- const [loading, setLoading] = useState71(false);
38843
- const [isDropActive, setIsDropActive] = useState71(false);
38844
- const [downloadingPath, setDownloadingPath] = useState71(null);
38845
- const [contextMenu, setContextMenu] = useState71(null);
39086
+ const [thumbUrls, setThumbUrls] = useState72({});
39087
+ const [loading, setLoading] = useState72(false);
39088
+ const [isDropActive, setIsDropActive] = useState72(false);
39089
+ const [downloadingPath, setDownloadingPath] = useState72(null);
39090
+ const [contextMenu, setContextMenu] = useState72(null);
38846
39091
  const fileInputRef = useRef59(null);
38847
39092
  const contextMenuRef = useRef59(null);
38848
39093
  const dropDepthRef = useRef59(0);
@@ -38864,7 +39109,7 @@ function MediaBin({
38864
39109
  },
38865
39110
  [onCountChange]
38866
39111
  );
38867
- useEffect61(() => {
39112
+ useEffect62(() => {
38868
39113
  if (!contextMenu) return;
38869
39114
  const handlePointerDown = (event) => {
38870
39115
  if (contextMenuRef.current?.contains(event.target)) return;
@@ -38885,7 +39130,7 @@ function MediaBin({
38885
39130
  window.removeEventListener("resize", close);
38886
39131
  };
38887
39132
  }, [contextMenu]);
38888
- useEffect61(() => {
39133
+ useEffect62(() => {
38889
39134
  if (!mediaProvider) {
38890
39135
  setEntries([]);
38891
39136
  setThumbUrls({});
@@ -39091,12 +39336,12 @@ function MediaBin({
39091
39336
  "aria-haspopup": "dialog",
39092
39337
  "aria-expanded": isRecorderOpen,
39093
39338
  children: [
39094
- /* @__PURE__ */ jsx78("span", { className: "squisq-media-bin-record-dot", "aria-hidden": "true" }),
39339
+ /* @__PURE__ */ jsx79("span", { className: "squisq-media-bin-record-dot", "aria-hidden": "true" }),
39095
39340
  "Record"
39096
39341
  ]
39097
39342
  }
39098
39343
  ),
39099
- /* @__PURE__ */ jsx78(
39344
+ /* @__PURE__ */ jsx79(
39100
39345
  "button",
39101
39346
  {
39102
39347
  type: "button",
@@ -39112,10 +39357,10 @@ function MediaBin({
39112
39357
  /* @__PURE__ */ jsxs63("div", { className: "squisq-media-bin-list", ref: listRef, children: [
39113
39358
  !mediaProvider && /* @__PURE__ */ jsxs63("div", { className: "squisq-media-bin-empty", children: [
39114
39359
  "No media context.",
39115
- /* @__PURE__ */ jsx78("br", {}),
39360
+ /* @__PURE__ */ jsx79("br", {}),
39116
39361
  "Load a content zip or select a storage slot."
39117
39362
  ] }),
39118
- mediaProvider && entries.length === 0 && !loading && /* @__PURE__ */ jsx78("div", { className: "squisq-media-bin-empty", children: "No files yet." }),
39363
+ mediaProvider && entries.length === 0 && !loading && /* @__PURE__ */ jsx79("div", { className: "squisq-media-bin-empty", children: "No files yet." }),
39119
39364
  entries.map((entry) => {
39120
39365
  const thumb = thumbUrls[entry.name];
39121
39366
  const basename = basenameForPath(entry.name);
@@ -39148,7 +39393,7 @@ ${formatSize(entry.size)}`,
39148
39393
  onDragStart: handleDragStart,
39149
39394
  onKeyDown: (e2) => handleItemKeyDown(entry, e2),
39150
39395
  children: [
39151
- thumb ? /* @__PURE__ */ jsx78(
39396
+ thumb ? /* @__PURE__ */ jsx79(
39152
39397
  "img",
39153
39398
  {
39154
39399
  src: thumb,
@@ -39156,15 +39401,15 @@ ${formatSize(entry.size)}`,
39156
39401
  className: "squisq-media-bin-thumb",
39157
39402
  draggable: false
39158
39403
  }
39159
- ) : /* @__PURE__ */ jsx78("span", { className: "squisq-media-bin-icon", children: iconForMime(entry.mimeType) }),
39404
+ ) : /* @__PURE__ */ jsx79("span", { className: "squisq-media-bin-icon", children: iconForMime(entry.mimeType) }),
39160
39405
  /* @__PURE__ */ jsxs63("div", { className: "squisq-media-bin-meta", children: [
39161
- /* @__PURE__ */ jsx78("div", { className: "squisq-media-bin-name", children: basename }),
39406
+ /* @__PURE__ */ jsx79("div", { className: "squisq-media-bin-name", children: basename }),
39162
39407
  /* @__PURE__ */ jsxs63("div", { className: "squisq-media-bin-detail-row", children: [
39163
- /* @__PURE__ */ jsx78("span", { className: "squisq-media-bin-size", children: formatSize(entry.size) }),
39164
- isUnused && /* @__PURE__ */ jsx78("span", { className: "squisq-media-bin-unused-badge", title: "Not used in document", children: "Unused" })
39408
+ /* @__PURE__ */ jsx79("span", { className: "squisq-media-bin-size", children: formatSize(entry.size) }),
39409
+ isUnused && /* @__PURE__ */ jsx79("span", { className: "squisq-media-bin-unused-badge", title: "Not used in document", children: "Unused" })
39165
39410
  ] })
39166
39411
  ] }),
39167
- allowBinaryDownloads && /* @__PURE__ */ jsx78(
39412
+ allowBinaryDownloads && /* @__PURE__ */ jsx79(
39168
39413
  "button",
39169
39414
  {
39170
39415
  type: "button",
@@ -39178,7 +39423,7 @@ ${formatSize(entry.size)}`,
39178
39423
  void handleDownloadEntry(entry);
39179
39424
  },
39180
39425
  onDragStart: (event) => event.preventDefault(),
39181
- children: /* @__PURE__ */ jsx78("span", { "aria-hidden": "true", children: downloadingPath === entry.name ? "\u2026" : "\u2193" })
39426
+ children: /* @__PURE__ */ jsx79("span", { "aria-hidden": "true", children: downloadingPath === entry.name ? "\u2026" : "\u2193" })
39182
39427
  }
39183
39428
  )
39184
39429
  ]
@@ -39188,11 +39433,11 @@ ${formatSize(entry.size)}`,
39188
39433
  })
39189
39434
  ] }),
39190
39435
  isDropActive && /* @__PURE__ */ jsxs63("div", { className: "squisq-media-bin-drop-target", "aria-hidden": "true", children: [
39191
- /* @__PURE__ */ jsx78("span", { className: "squisq-media-bin-drop-target-icon", children: "+" }),
39192
- /* @__PURE__ */ jsx78("strong", { children: "Drop images here" }),
39193
- /* @__PURE__ */ jsx78("span", { children: "Add to Files" })
39436
+ /* @__PURE__ */ jsx79("span", { className: "squisq-media-bin-drop-target-icon", children: "+" }),
39437
+ /* @__PURE__ */ jsx79("strong", { children: "Drop images here" }),
39438
+ /* @__PURE__ */ jsx79("span", { children: "Add to Files" })
39194
39439
  ] }),
39195
- contextMenu && /* @__PURE__ */ jsx78(
39440
+ contextMenu && /* @__PURE__ */ jsx79(
39196
39441
  "div",
39197
39442
  {
39198
39443
  ref: contextMenuRef,
@@ -39200,7 +39445,7 @@ ${formatSize(entry.size)}`,
39200
39445
  role: "menu",
39201
39446
  "aria-label": `${contextMenu.entry.name} actions`,
39202
39447
  style: contextMenuStyle,
39203
- children: /* @__PURE__ */ jsx78(
39448
+ children: /* @__PURE__ */ jsx79(
39204
39449
  "button",
39205
39450
  {
39206
39451
  type: "button",
@@ -39213,7 +39458,7 @@ ${formatSize(entry.size)}`,
39213
39458
  )
39214
39459
  }
39215
39460
  ),
39216
- /* @__PURE__ */ jsx78(
39461
+ /* @__PURE__ */ jsx79(
39217
39462
  "input",
39218
39463
  {
39219
39464
  ref: fileInputRef,
@@ -39229,8 +39474,8 @@ ${formatSize(entry.size)}`,
39229
39474
  }
39230
39475
 
39231
39476
  // src/DropZoneOverlay.tsx
39232
- import { useState as useState72 } from "react";
39233
- import { Fragment as Fragment22, jsx as jsx79, jsxs as jsxs64 } from "react/jsx-runtime";
39477
+ import { useState as useState73 } from "react";
39478
+ import { Fragment as Fragment22, jsx as jsx80, jsxs as jsxs64 } from "react/jsx-runtime";
39234
39479
  function DropZoneOverlay({
39235
39480
  dragContentType,
39236
39481
  zoneProps,
@@ -39238,8 +39483,8 @@ function DropZoneOverlay({
39238
39483
  }) {
39239
39484
  const showMedia = dragContentType === "media" || dragContentType === "mixed";
39240
39485
  const showText = dragContentType === "text" || dragContentType === "mixed";
39241
- return /* @__PURE__ */ jsx79("div", { className: "squisq-drop-overlay", children: /* @__PURE__ */ jsxs64("div", { className: "squisq-drop-overlay-inner", children: [
39242
- showMedia && /* @__PURE__ */ jsx79(
39486
+ return /* @__PURE__ */ jsx80("div", { className: "squisq-drop-overlay", children: /* @__PURE__ */ jsxs64("div", { className: "squisq-drop-overlay-inner", children: [
39487
+ showMedia && /* @__PURE__ */ jsx80(
39243
39488
  DropZone,
39244
39489
  {
39245
39490
  target: "media",
@@ -39252,7 +39497,7 @@ function DropZoneOverlay({
39252
39497
  }
39253
39498
  ),
39254
39499
  showText && /* @__PURE__ */ jsxs64(Fragment22, { children: [
39255
- /* @__PURE__ */ jsx79(
39500
+ /* @__PURE__ */ jsx80(
39256
39501
  DropZone,
39257
39502
  {
39258
39503
  target: "insert",
@@ -39263,7 +39508,7 @@ function DropZoneOverlay({
39263
39508
  variant: "insert"
39264
39509
  }
39265
39510
  ),
39266
- /* @__PURE__ */ jsx79(
39511
+ /* @__PURE__ */ jsx80(
39267
39512
  DropZone,
39268
39513
  {
39269
39514
  target: "replace",
@@ -39286,7 +39531,7 @@ function DropZone({
39286
39531
  disabled,
39287
39532
  variant
39288
39533
  }) {
39289
- const [isHovering, setIsHovering] = useState72(false);
39534
+ const [isHovering, setIsHovering] = useState73(false);
39290
39535
  const props = zoneProps(target);
39291
39536
  return /* @__PURE__ */ jsxs64(
39292
39537
  "div",
@@ -39321,16 +39566,16 @@ function DropZone({
39321
39566
  props.onDrop(e2);
39322
39567
  },
39323
39568
  children: [
39324
- /* @__PURE__ */ jsx79("span", { className: "squisq-drop-zone-icon", children: icon }),
39325
- /* @__PURE__ */ jsx79("span", { className: "squisq-drop-zone-label", children: label }),
39326
- /* @__PURE__ */ jsx79("span", { className: "squisq-drop-zone-desc", children: description })
39569
+ /* @__PURE__ */ jsx80("span", { className: "squisq-drop-zone-icon", children: icon }),
39570
+ /* @__PURE__ */ jsx80("span", { className: "squisq-drop-zone-label", children: label }),
39571
+ /* @__PURE__ */ jsx80("span", { className: "squisq-drop-zone-desc", children: description })
39327
39572
  ]
39328
39573
  }
39329
39574
  );
39330
39575
  }
39331
39576
 
39332
39577
  // src/Tooltip.tsx
39333
- import { useEffect as useEffect62, useLayoutEffect as useLayoutEffect12, useRef as useRef60, useState as useState73 } from "react";
39578
+ import { useEffect as useEffect63, useLayoutEffect as useLayoutEffect12, useRef as useRef60, useState as useState74 } from "react";
39334
39579
  import { createPortal as createPortal17 } from "react-dom";
39335
39580
 
39336
39581
  // src/tooltipPlacement.ts
@@ -39343,10 +39588,10 @@ function clampTooltipLeft(anchorX, tooltipWidth, viewportWidth, edgePadding = ED
39343
39588
  }
39344
39589
 
39345
39590
  // src/Tooltip.tsx
39346
- import { jsx as jsx80 } from "react/jsx-runtime";
39591
+ import { jsx as jsx81 } from "react/jsx-runtime";
39347
39592
  var SHOW_DELAY_MS = 180;
39348
39593
  function TooltipLayer() {
39349
- const [state, setState3] = useState73(null);
39594
+ const [state, setState3] = useState74(null);
39350
39595
  const tooltipRef = useRef60(null);
39351
39596
  const timerRef = useRef60(null);
39352
39597
  const currentTargetRef = useRef60(null);
@@ -39362,7 +39607,7 @@ function TooltipLayer() {
39362
39607
  node2.style.left = `${left}px`;
39363
39608
  node2.style.visibility = "visible";
39364
39609
  }, [state]);
39365
- useEffect62(() => {
39610
+ useEffect63(() => {
39366
39611
  const clearTimer = () => {
39367
39612
  if (timerRef.current) {
39368
39613
  clearTimeout(timerRef.current);
@@ -39428,7 +39673,7 @@ function TooltipLayer() {
39428
39673
  }, []);
39429
39674
  if (!state) return null;
39430
39675
  return createPortal17(
39431
- /* @__PURE__ */ jsx80(
39676
+ /* @__PURE__ */ jsx81(
39432
39677
  "div",
39433
39678
  {
39434
39679
  role: "tooltip",
@@ -39448,35 +39693,37 @@ function TooltipLayer() {
39448
39693
  }
39449
39694
 
39450
39695
  // src/EditorShell.tsx
39451
- import { useEffect as useEffect63, useRef as useRef61, useState as useState74, useCallback as useCallback54, useMemo as useMemo55 } from "react";
39696
+ import { useEffect as useEffect64, useRef as useRef61, useState as useState75, useCallback as useCallback54, useMemo as useMemo56 } from "react";
39452
39697
 
39453
39698
  // src/BlockPreviewPanel.tsx
39454
- import { useMemo as useMemo54 } from "react";
39699
+ import { useMemo as useMemo55 } from "react";
39455
39700
  import { VIEWPORT_PRESETS as VIEWPORT_PRESETS7 } from "@bendyline/squisq/schemas";
39456
39701
  import { flattenBlocks as flattenBlocks7, DEFAULT_THEME as DEFAULT_THEME7 } from "@bendyline/squisq/doc";
39457
- import { jsx as jsx81 } from "react/jsx-runtime";
39702
+ import { jsx as jsx82 } from "react/jsx-runtime";
39458
39703
  function BlockPreviewPanel({ basePath = "/" }) {
39459
- const { doc, activeBlockStartLine, mediaProvider } = useEditorContext();
39704
+ const { doc, activeBlockStartLine, mediaProvider, workspaceContainer, fileName, mediaRevision } = useEditorContext();
39460
39705
  const previewSettings = usePreviewSettingsOptional();
39461
39706
  const theme = previewSettings?.activeTheme ?? DEFAULT_THEME7;
39462
39707
  const viewport = previewSettings?.activeViewport ?? VIEWPORT_PRESETS7.landscape;
39463
- const block = useMemo54(() => {
39464
- if (!doc) return null;
39465
- const blocks = flattenBlocks7(doc.blocks);
39708
+ const projection = usePreviewProjection(doc, "", workspaceContainer, fileName, mediaRevision);
39709
+ const previewDoc = projection?.contentDoc ?? doc;
39710
+ const block = useMemo55(() => {
39711
+ if (!previewDoc) return null;
39712
+ const blocks = flattenBlocks7(previewDoc.blocks);
39466
39713
  if (blocks.length === 0) return null;
39467
39714
  return blocks.find((b) => b.sourceHeading?.position?.start.line === activeBlockStartLine) ?? blocks[0];
39468
- }, [doc, activeBlockStartLine]);
39469
- const visual = useMemo54(
39470
- () => doc && block ? resolveBlockVisual(doc, block, theme, viewport) : null,
39471
- [doc, block, theme, viewport]
39715
+ }, [previewDoc, activeBlockStartLine]);
39716
+ const visual = useMemo55(
39717
+ () => previewDoc && block ? resolveBlockVisual(previewDoc, block, theme, viewport) : null,
39718
+ [previewDoc, block, theme, viewport]
39472
39719
  );
39473
39720
  if (!visual) return null;
39474
- return /* @__PURE__ */ jsx81("div", { className: "squisq-block-preview-panel", "data-testid": "block-preview-panel", "aria-hidden": true, children: /* @__PURE__ */ jsx81(
39721
+ return /* @__PURE__ */ jsx82("div", { className: "squisq-block-preview-panel", "data-testid": "block-preview-panel", "aria-hidden": true, children: /* @__PURE__ */ jsx82(
39475
39722
  "div",
39476
39723
  {
39477
39724
  className: "squisq-block-preview-frame",
39478
39725
  style: { aspectRatio: `${viewport.width} / ${viewport.height}` },
39479
- children: /* @__PURE__ */ jsx81(
39726
+ children: /* @__PURE__ */ jsx82(
39480
39727
  BlockThumbnail,
39481
39728
  {
39482
39729
  visual,
@@ -39490,7 +39737,7 @@ function BlockPreviewPanel({ basePath = "/" }) {
39490
39737
  }
39491
39738
 
39492
39739
  // src/proofing/ProofingPanel.tsx
39493
- import { jsx as jsx82, jsxs as jsxs65 } from "react/jsx-runtime";
39740
+ import { jsx as jsx83, jsxs as jsxs65 } from "react/jsx-runtime";
39494
39741
  var CATEGORY_LABELS = {
39495
39742
  spelling: "Spelling",
39496
39743
  grammar: "Grammar",
@@ -39504,10 +39751,10 @@ function ProofingPanel() {
39504
39751
  /* @__PURE__ */ jsxs65("div", { className: "squisq-proof-panel-header", children: [
39505
39752
  /* @__PURE__ */ jsxs65("span", { className: "squisq-proof-panel-title", children: [
39506
39753
  "Proofing",
39507
- /* @__PURE__ */ jsx82("span", { className: "squisq-proof-panel-count", children: findings.length })
39754
+ /* @__PURE__ */ jsx83("span", { className: "squisq-proof-panel-count", children: findings.length })
39508
39755
  ] }),
39509
39756
  /* @__PURE__ */ jsxs65("span", { className: "squisq-proof-panel-actions", children: [
39510
- /* @__PURE__ */ jsx82(
39757
+ /* @__PURE__ */ jsx83(
39511
39758
  "button",
39512
39759
  {
39513
39760
  type: "button",
@@ -39519,7 +39766,7 @@ function ProofingPanel() {
39519
39766
  children: "\u2191"
39520
39767
  }
39521
39768
  ),
39522
- /* @__PURE__ */ jsx82(
39769
+ /* @__PURE__ */ jsx83(
39523
39770
  "button",
39524
39771
  {
39525
39772
  type: "button",
@@ -39531,7 +39778,7 @@ function ProofingPanel() {
39531
39778
  children: "\u2193"
39532
39779
  }
39533
39780
  ),
39534
- /* @__PURE__ */ jsx82(
39781
+ /* @__PURE__ */ jsx83(
39535
39782
  "button",
39536
39783
  {
39537
39784
  type: "button",
@@ -39544,20 +39791,20 @@ function ProofingPanel() {
39544
39791
  )
39545
39792
  ] })
39546
39793
  ] }),
39547
- state.status === "loading" && /* @__PURE__ */ jsx82("div", { className: "squisq-proof-panel-empty", children: "Loading proofing engine\u2026" }),
39794
+ state.status === "loading" && /* @__PURE__ */ jsx83("div", { className: "squisq-proof-panel-empty", children: "Loading proofing engine\u2026" }),
39548
39795
  state.status === "error" && /* @__PURE__ */ jsxs65("div", { className: "squisq-proof-panel-empty", children: [
39549
39796
  "Proofing failed to load.",
39550
- /* @__PURE__ */ jsx82("button", { type: "button", className: "squisq-proof-panel-retry", onClick: state.retrySetup, children: "Retry" })
39797
+ /* @__PURE__ */ jsx83("button", { type: "button", className: "squisq-proof-panel-retry", onClick: state.retrySetup, children: "Retry" })
39551
39798
  ] }),
39552
- state.status === "ready" && findings.length === 0 && /* @__PURE__ */ jsx82("div", { className: "squisq-proof-panel-empty", children: "No issues found." }),
39553
- /* @__PURE__ */ jsx82("ul", { className: "squisq-proof-panel-list", children: findings.map((finding) => /* @__PURE__ */ jsx82("li", { children: /* @__PURE__ */ jsxs65(
39799
+ state.status === "ready" && findings.length === 0 && /* @__PURE__ */ jsx83("div", { className: "squisq-proof-panel-empty", children: "No issues found." }),
39800
+ /* @__PURE__ */ jsx83("ul", { className: "squisq-proof-panel-list", children: findings.map((finding) => /* @__PURE__ */ jsx83("li", { children: /* @__PURE__ */ jsxs65(
39554
39801
  "button",
39555
39802
  {
39556
39803
  type: "button",
39557
39804
  className: finding.id === activeFindingId ? "squisq-proof-panel-row squisq-proof-panel-row--active" : "squisq-proof-panel-row",
39558
39805
  onClick: () => state.selectFinding(finding.id),
39559
39806
  children: [
39560
- /* @__PURE__ */ jsx82(
39807
+ /* @__PURE__ */ jsx83(
39561
39808
  "span",
39562
39809
  {
39563
39810
  className: `squisq-proof-dot squisq-proof-dot--${finding.category}`,
@@ -39566,8 +39813,8 @@ function ProofingPanel() {
39566
39813
  }
39567
39814
  ),
39568
39815
  /* @__PURE__ */ jsxs65("span", { className: "squisq-proof-panel-row-body", children: [
39569
- /* @__PURE__ */ jsx82("span", { className: "squisq-proof-panel-excerpt", children: finding.originalText }),
39570
- /* @__PURE__ */ jsx82("span", { className: "squisq-proof-panel-message", children: finding.message })
39816
+ /* @__PURE__ */ jsx83("span", { className: "squisq-proof-panel-excerpt", children: finding.originalText }),
39817
+ /* @__PURE__ */ jsx83("span", { className: "squisq-proof-panel-message", children: finding.message })
39571
39818
  ] })
39572
39819
  ]
39573
39820
  }
@@ -39820,7 +40067,7 @@ import {
39820
40067
  createMediaProviderFromContainer
39821
40068
  } from "@bendyline/squisq/storage";
39822
40069
  import { MediaContext as MediaContext6, useMediaClipDurations } from "@bendyline/squisq-react";
39823
- import { Fragment as Fragment23, jsx as jsx83, jsxs as jsxs66 } from "react/jsx-runtime";
40070
+ import { Fragment as Fragment23, jsx as jsx84, jsxs as jsxs66 } from "react/jsx-runtime";
39824
40071
  function EditorShell({
39825
40072
  initialMarkdown = "",
39826
40073
  initialView = "wysiwyg",
@@ -39903,14 +40150,14 @@ function EditorShell({
39903
40150
  themeOverride = null
39904
40151
  }) {
39905
40152
  const effectiveContainer = workspaceContainer ?? null;
39906
- const effectiveMediaProvider = useMemo55(() => {
40153
+ const effectiveMediaProvider = useMemo56(() => {
39907
40154
  if (mediaProvider !== void 0) return mediaProvider;
39908
40155
  if (effectiveContainer) return createMediaProviderFromContainer(effectiveContainer);
39909
40156
  return void 0;
39910
40157
  }, [mediaProvider, effectiveContainer]);
39911
40158
  const filesToggleEnabled = showFilesToggle ?? effectiveMediaProvider !== void 0;
39912
40159
  const effectiveInitialView = hostMode === "chat" || !showPlayTab && initialView === "preview" ? "wysiwyg" : initialView;
39913
- return /* @__PURE__ */ jsx83(MediaContext6.Provider, { value: effectiveMediaProvider ?? null, children: /* @__PURE__ */ jsx83(
40160
+ return /* @__PURE__ */ jsx84(MediaContext6.Provider, { value: effectiveMediaProvider ?? null, children: /* @__PURE__ */ jsx84(
39914
40161
  EditorProvider,
39915
40162
  {
39916
40163
  initialMarkdown,
@@ -39952,7 +40199,7 @@ function EditorShell({
39952
40199
  themeInheritance,
39953
40200
  viewPreferences,
39954
40201
  onViewPreferencesChange,
39955
- children: /* @__PURE__ */ jsx83(ProofingRoot, { children: /* @__PURE__ */ jsx83(
40202
+ children: /* @__PURE__ */ jsx84(ProofingRoot, { children: /* @__PURE__ */ jsx84(
39956
40203
  EditorShellInner,
39957
40204
  {
39958
40205
  basePath,
@@ -40007,11 +40254,11 @@ function EditorShell({
40007
40254
  }
40008
40255
  function UseModeToolbarControls({ allowPrint }) {
40009
40256
  const printMode = usePrintMode();
40010
- if (printMode.active) return /* @__PURE__ */ jsx83(PrintPreviewToolbar, {});
40257
+ if (printMode.active) return /* @__PURE__ */ jsx84(PrintPreviewToolbar, {});
40011
40258
  return /* @__PURE__ */ jsxs66(Fragment23, { children: [
40012
- /* @__PURE__ */ jsx83(PreviewToolbarControls, {}),
40013
- /* @__PURE__ */ jsx83(PresentationModeControl, {}),
40014
- allowPrint && /* @__PURE__ */ jsx83(PrintModeControl, {})
40259
+ /* @__PURE__ */ jsx84(PreviewToolbarControls, {}),
40260
+ /* @__PURE__ */ jsx84(PresentationModeControl, {}),
40261
+ allowPrint && /* @__PURE__ */ jsx84(PrintModeControl, {})
40015
40262
  ] });
40016
40263
  }
40017
40264
  function UseModeProviders({
@@ -40020,13 +40267,13 @@ function UseModeProviders({
40020
40267
  allowPresentationWindow,
40021
40268
  allowPresentationFullscreen
40022
40269
  }) {
40023
- return /* @__PURE__ */ jsx83(
40270
+ return /* @__PURE__ */ jsx84(
40024
40271
  PresentationModeProvider,
40025
40272
  {
40026
40273
  rootRef,
40027
40274
  allowWindow: allowPresentationWindow,
40028
40275
  allowFullscreen: allowPresentationFullscreen,
40029
- children: /* @__PURE__ */ jsx83(PrintModeProvider, { rootRef, children })
40276
+ children: /* @__PURE__ */ jsx84(PrintModeProvider, { rootRef, children })
40030
40277
  }
40031
40278
  );
40032
40279
  }
@@ -40117,7 +40364,7 @@ function EditorShellInner({
40117
40364
  workspaceContainer
40118
40365
  );
40119
40366
  const timelineDoc = timelineProjection?.contentDoc ?? doc;
40120
- const timelineRawSchedule = useMemo55(
40367
+ const timelineRawSchedule = useMemo56(
40121
40368
  () => timelineDoc ? resolveMediaSchedule4(timelineDoc) : [],
40122
40369
  [timelineDoc]
40123
40370
  );
@@ -40126,19 +40373,19 @@ function EditorShellInner({
40126
40373
  basePath,
40127
40374
  mediaProvider ?? null
40128
40375
  );
40129
- const timelineDuration = useMemo55(
40376
+ const timelineDuration = useMemo56(
40130
40377
  () => timelineDoc ? getDocPlaybackDuration3(timelineDoc, {
40131
40378
  intrinsicDuration: (clip) => timelineClipDurations.get(clip.src)
40132
40379
  }) : 0,
40133
40380
  [timelineDoc, timelineClipDurations]
40134
40381
  );
40135
- const timelineSchedule = useMemo55(
40382
+ const timelineSchedule = useMemo56(
40136
40383
  () => timelineDoc ? resolveMediaSchedule4(timelineDoc, {
40137
40384
  intrinsicDuration: (clip) => timelineClipDurations.get(clip.src)
40138
40385
  }) : [],
40139
40386
  [timelineDoc, timelineClipDurations]
40140
40387
  );
40141
- const timelineVideoSchedule = useMemo55(
40388
+ const timelineVideoSchedule = useMemo56(
40142
40389
  () => timelineDoc ? [
40143
40390
  ...timelineSchedule.filter((clip) => clip.kind === "video"),
40144
40391
  ...collectEmbeddedVideoSchedule(timelineDoc)
@@ -40147,16 +40394,16 @@ function EditorShellInner({
40147
40394
  );
40148
40395
  const timelineClock = useTimelineClock(isTimelineMode ? timelineDuration : 0);
40149
40396
  const hasTimelineVideo = timelineVideoSchedule.length > 0;
40150
- const [timelineVideoVisible, setTimelineVideoVisible] = useState74(false);
40151
- const [timelineCompositionVisible, setTimelineCompositionVisible] = useState74(false);
40397
+ const [timelineVideoVisible, setTimelineVideoVisible] = useState75(false);
40398
+ const [timelineCompositionVisible, setTimelineCompositionVisible] = useState75(false);
40152
40399
  const timelinePreviewCount = Number(timelineVideoVisible) + Number(timelineCompositionVisible);
40153
- const [showFiles, setShowFiles] = useState74(false);
40154
- const [filesFocusPath, setFilesFocusPath] = useState74(null);
40155
- const [mediaRefreshKey, setMediaRefreshKey] = useState74(0);
40156
- const [mediaCount, setMediaCount] = useState74(0);
40157
- const [mediaBinRecorderOpen, setMediaBinRecorderOpen] = useState74(false);
40400
+ const [showFiles, setShowFiles] = useState75(false);
40401
+ const [filesFocusPath, setFilesFocusPath] = useState75(null);
40402
+ const [mediaRefreshKey, setMediaRefreshKey] = useState75(0);
40403
+ const [mediaCount, setMediaCount] = useState75(0);
40404
+ const [mediaBinRecorderOpen, setMediaBinRecorderOpen] = useState75(false);
40158
40405
  const mediaListRefreshKey = mediaRefreshKey + mediaRevision;
40159
- const usedMediaPaths = useMemo55(
40406
+ const usedMediaPaths = useMemo56(
40160
40407
  () => collectMediaReferencesFromMarkdown(markdownSource),
40161
40408
  [markdownSource]
40162
40409
  );
@@ -40166,13 +40413,13 @@ function EditorShellInner({
40166
40413
  }
40167
40414
  const imageEditFallbackContainer = imageEditFallbackContainerRef.current;
40168
40415
  const isDark = colorScheme === "dark";
40169
- useEffect63(() => {
40416
+ useEffect64(() => {
40170
40417
  if (!isTimelineMode || !hasTimelineVideo) setTimelineVideoVisible(false);
40171
40418
  }, [isTimelineMode, hasTimelineVideo]);
40172
- useEffect63(() => {
40419
+ useEffect64(() => {
40173
40420
  if (!isTimelineMode || !doc?.blocks.length) setTimelineCompositionVisible(false);
40174
40421
  }, [isTimelineMode, doc]);
40175
- useEffect63(() => {
40422
+ useEffect64(() => {
40176
40423
  if (!mediaProvider) {
40177
40424
  setMediaCount(0);
40178
40425
  return;
@@ -40196,7 +40443,7 @@ function EditorShellInner({
40196
40443
  cancelled = true;
40197
40444
  };
40198
40445
  }, [mediaProvider, mediaListRefreshKey]);
40199
- useEffect63(() => {
40446
+ useEffect64(() => {
40200
40447
  if (showFilesWhenNotEmpty && mediaCount > 0) setShowFiles(true);
40201
40448
  }, [mediaCount, showFilesWhenNotEmpty]);
40202
40449
  const handleToggleFiles = useCallback54(() => {
@@ -40235,7 +40482,7 @@ ${snippet}` : snippet);
40235
40482
  [activeView, tiptapEditor, monacoEditor, insertAtCursor, markdownSource, setMarkdownSource]
40236
40483
  );
40237
40484
  const docBasenameRef = useRef61("document");
40238
- useEffect63(() => {
40485
+ useEffect64(() => {
40239
40486
  let cancelled = false;
40240
40487
  docBasenameRef.current = "document";
40241
40488
  if (!workspaceContainer) return;
@@ -40356,7 +40603,7 @@ ${snippet}` : snippet);
40356
40603
  onDrop: handleFileDrop,
40357
40604
  enabled: !readOnly
40358
40605
  });
40359
- useEffect63(() => {
40606
+ useEffect64(() => {
40360
40607
  onChange?.(markdownSource);
40361
40608
  }, [markdownSource, onChange]);
40362
40609
  const handleShellKeyDown = useCallback54(
@@ -40444,7 +40691,7 @@ ${snippet}` : snippet);
40444
40691
  },
40445
40692
  ...containerProps,
40446
40693
  children: [
40447
- /* @__PURE__ */ jsx83(CustomThemeProvider, { docThemes, onDocThemesChange, children: /* @__PURE__ */ jsx83(
40694
+ /* @__PURE__ */ jsx84(CustomThemeProvider, { docThemes, onDocThemesChange, children: /* @__PURE__ */ jsx84(
40448
40695
  PreviewSettingsProvider,
40449
40696
  {
40450
40697
  doc,
@@ -40459,16 +40706,16 @@ ${snippet}` : snippet);
40459
40706
  children: [
40460
40707
  isImageMode ? (toolbarSlotLeft || toolbarSlotRight) && /* @__PURE__ */ jsxs66("div", { className: "squisq-editor-header squisq-editor-header--image", children: [
40461
40708
  toolbarSlotLeft,
40462
- /* @__PURE__ */ jsx83("div", { style: { flex: 1 } }),
40709
+ /* @__PURE__ */ jsx84("div", { style: { flex: 1 } }),
40463
40710
  toolbarSlotRight
40464
- ] }) : /* @__PURE__ */ jsx83("div", { className: "squisq-editor-header", children: /* @__PURE__ */ jsx83(
40711
+ ] }) : /* @__PURE__ */ jsx84("div", { className: "squisq-editor-header", children: /* @__PURE__ */ jsx84(
40465
40712
  Toolbar,
40466
40713
  {
40467
40714
  showFiles,
40468
40715
  fileCount: mediaCount,
40469
40716
  onToggleFiles: !isCodeMode && filesToggleEnabled ? handleToggleFiles : void 0,
40470
40717
  slotLeft: toolbarSlotLeft,
40471
- slotAfterTabs: !isCodeMode && isPreview && /* @__PURE__ */ jsx83(UseModeToolbarControls, { allowPrint }),
40718
+ slotAfterTabs: !isCodeMode && isPreview && /* @__PURE__ */ jsx84(UseModeToolbarControls, { allowPrint }),
40472
40719
  slotAfterActions: toolbarSlotAfterActions,
40473
40720
  slotRight: toolbarSlotRight,
40474
40721
  showPlayTab,
@@ -40502,7 +40749,7 @@ ${snippet}` : snippet);
40502
40749
  position: "relative"
40503
40750
  },
40504
40751
  children: [
40505
- isImageMode && imageSrc && (imageMode === "edit" && imageEditorContainer ? /* @__PURE__ */ jsx83(
40752
+ isImageMode && imageSrc && (imageMode === "edit" && imageEditorContainer ? /* @__PURE__ */ jsx84(
40506
40753
  ImageEditor,
40507
40754
  {
40508
40755
  filesContainer: imageEditorContainer,
@@ -40512,10 +40759,10 @@ ${snippet}` : snippet);
40512
40759
  onExport: onImageExport,
40513
40760
  surface: colorScheme === "dark" ? DARK_SURFACE : LIGHT_SURFACE
40514
40761
  }
40515
- ) : /* @__PURE__ */ jsx83(ImageViewer, { src: imageSrc, alt: imageAlt, theme: colorScheme })),
40762
+ ) : /* @__PURE__ */ jsx84(ImageViewer, { src: imageSrc, alt: imageAlt, theme: colorScheme })),
40516
40763
  !isImageMode && activeView === "raw" && /* @__PURE__ */ jsxs66("div", { className: "squisq-editor-with-gutter", children: [
40517
- isMarkdownMode && outlineVisible && /* @__PURE__ */ jsx83(OutlinePanel, { width: outlineWidth, readOnly }, "outline"),
40518
- /* @__PURE__ */ jsx83(
40764
+ isMarkdownMode && outlineVisible && /* @__PURE__ */ jsx84(OutlinePanel, { width: outlineWidth, readOnly }, "outline"),
40765
+ /* @__PURE__ */ jsx84(
40519
40766
  BlockCardView,
40520
40767
  {
40521
40768
  active: isCardMode,
@@ -40524,7 +40771,7 @@ ${snippet}` : snippet);
40524
40771
  onPrev: prevBlock,
40525
40772
  onNext: nextBlock,
40526
40773
  onAdd: addBlock,
40527
- children: /* @__PURE__ */ jsx83("div", { className: "squisq-raw-editor-container", children: /* @__PURE__ */ jsx83(
40774
+ children: /* @__PURE__ */ jsx84("div", { className: "squisq-raw-editor-container", children: /* @__PURE__ */ jsx84(
40528
40775
  RawEditor,
40529
40776
  {
40530
40777
  monacoTheme: colorScheme === "dark" ? "vs-dark" : "vs",
@@ -40535,9 +40782,9 @@ ${snippet}` : snippet);
40535
40782
  },
40536
40783
  "raw-frame"
40537
40784
  ),
40538
- isCodeMode && codeContext && /* @__PURE__ */ jsx83(CodeContextZones, { options: codeContext }, "code-context"),
40539
- isMarkdownMode && isCardMode && inlinePreviewVisible && /* @__PURE__ */ jsx83(BlockPreviewPanel, { basePath }, "block-preview"),
40540
- isMarkdownMode && !isCardMode && inlinePreviewVisible && /* @__PURE__ */ jsx83(
40785
+ isCodeMode && codeContext && /* @__PURE__ */ jsx84(CodeContextZones, { options: codeContext }, "code-context"),
40786
+ isMarkdownMode && isCardMode && inlinePreviewVisible && /* @__PURE__ */ jsx84(BlockPreviewPanel, { basePath }, "block-preview"),
40787
+ isMarkdownMode && !isCardMode && inlinePreviewVisible && /* @__PURE__ */ jsx84(
40541
40788
  InlinePreviewGutter,
40542
40789
  {
40543
40790
  width: inlinePreviewWidth,
@@ -40548,8 +40795,8 @@ ${snippet}` : snippet);
40548
40795
  )
40549
40796
  ] }, "raw-shell"),
40550
40797
  isMarkdownMode && activeView === "wysiwyg" && /* @__PURE__ */ jsxs66("div", { className: "squisq-editor-with-gutter", children: [
40551
- outlineVisible && /* @__PURE__ */ jsx83(OutlinePanel, { width: outlineWidth, readOnly }, "outline"),
40552
- /* @__PURE__ */ jsx83(
40798
+ outlineVisible && /* @__PURE__ */ jsx84(OutlinePanel, { width: outlineWidth, readOnly }, "outline"),
40799
+ /* @__PURE__ */ jsx84(
40553
40800
  BlockCardView,
40554
40801
  {
40555
40802
  active: isCardMode,
@@ -40558,7 +40805,7 @@ ${snippet}` : snippet);
40558
40805
  onPrev: prevBlock,
40559
40806
  onNext: nextBlock,
40560
40807
  onAdd: addBlock,
40561
- children: /* @__PURE__ */ jsx83(
40808
+ children: /* @__PURE__ */ jsx84(
40562
40809
  WysiwygEditor,
40563
40810
  {
40564
40811
  submitOnEnter,
@@ -40575,8 +40822,8 @@ ${snippet}` : snippet);
40575
40822
  },
40576
40823
  "wysiwyg-frame"
40577
40824
  ),
40578
- isCardMode && inlinePreviewVisible && /* @__PURE__ */ jsx83(BlockPreviewPanel, { basePath }, "block-preview"),
40579
- !isCardMode && inlinePreviewVisible && /* @__PURE__ */ jsx83(
40825
+ isCardMode && inlinePreviewVisible && /* @__PURE__ */ jsx84(BlockPreviewPanel, { basePath }, "block-preview"),
40826
+ !isCardMode && inlinePreviewVisible && /* @__PURE__ */ jsx84(
40580
40827
  InlinePreviewGutter,
40581
40828
  {
40582
40829
  width: inlinePreviewWidth,
@@ -40586,7 +40833,7 @@ ${snippet}` : snippet);
40586
40833
  "inline"
40587
40834
  )
40588
40835
  ] }, "wysiwyg-shell"),
40589
- isMarkdownMode && isPreview && /* @__PURE__ */ jsx83(
40836
+ isMarkdownMode && isPreview && /* @__PURE__ */ jsx84(
40590
40837
  PreviewPanel,
40591
40838
  {
40592
40839
  basePath,
@@ -40599,7 +40846,7 @@ ${snippet}` : snippet);
40599
40846
  ]
40600
40847
  }
40601
40848
  ),
40602
- isTimelineMode && timelineVideoVisible && /* @__PURE__ */ jsx83(
40849
+ isTimelineMode && timelineVideoVisible && /* @__PURE__ */ jsx84(
40603
40850
  TimelineVideoPanel,
40604
40851
  {
40605
40852
  schedule: timelineVideoSchedule,
@@ -40609,7 +40856,7 @@ ${snippet}` : snippet);
40609
40856
  onClose: () => setTimelineVideoVisible(false)
40610
40857
  }
40611
40858
  ),
40612
- isTimelineMode && timelineCompositionVisible && /* @__PURE__ */ jsx83(
40859
+ isTimelineMode && timelineCompositionVisible && /* @__PURE__ */ jsx84(
40613
40860
  TimelineCompositionPanel,
40614
40861
  {
40615
40862
  doc,
@@ -40619,7 +40866,7 @@ ${snippet}` : snippet);
40619
40866
  onClose: () => setTimelineCompositionVisible(false)
40620
40867
  }
40621
40868
  ),
40622
- isMarkdownMode && showFiles && /* @__PURE__ */ jsx83(
40869
+ isMarkdownMode && showFiles && /* @__PURE__ */ jsx84(
40623
40870
  MediaBin,
40624
40871
  {
40625
40872
  mediaProvider,
@@ -40635,9 +40882,9 @@ ${snippet}` : snippet);
40635
40882
  highlightPath: filesFocusPath
40636
40883
  }
40637
40884
  ),
40638
- isMarkdownMode && /* @__PURE__ */ jsx83(ProofingPanel, {}),
40639
- isMarkdownMode && /* @__PURE__ */ jsx83(ThemeDesignerDock, {}),
40640
- isMarkdownMode && isDragging && !(activeView === "wysiwyg" && dragContentType === "media") && /* @__PURE__ */ jsx83(
40885
+ isMarkdownMode && /* @__PURE__ */ jsx84(ProofingPanel, {}),
40886
+ isMarkdownMode && /* @__PURE__ */ jsx84(ThemeDesignerDock, {}),
40887
+ isMarkdownMode && isDragging && !(activeView === "wysiwyg" && dragContentType === "media") && /* @__PURE__ */ jsx84(
40641
40888
  DropZoneOverlay,
40642
40889
  {
40643
40890
  dragContentType,
@@ -40648,7 +40895,7 @@ ${snippet}` : snippet);
40648
40895
  ]
40649
40896
  }
40650
40897
  ),
40651
- isTimelineMode && /* @__PURE__ */ jsx83(
40898
+ isTimelineMode && /* @__PURE__ */ jsx84(
40652
40899
  TimelineToolbar,
40653
40900
  {
40654
40901
  literalVideoVisible: timelineVideoVisible,
@@ -40659,7 +40906,7 @@ ${snippet}` : snippet);
40659
40906
  onToggleComposition: () => setTimelineCompositionVisible((visible) => !visible)
40660
40907
  }
40661
40908
  ),
40662
- isTimelineMode && /* @__PURE__ */ jsx83(
40909
+ isTimelineMode && /* @__PURE__ */ jsx84(
40663
40910
  TimelineTrack,
40664
40911
  {
40665
40912
  doc: timelineDoc,
@@ -40668,8 +40915,8 @@ ${snippet}` : snippet);
40668
40915
  basePath
40669
40916
  }
40670
40917
  ),
40671
- statusBarVisible && !isImageMode && /* @__PURE__ */ jsx83(StatusBar, { slotRight: statusBarSlotRight }),
40672
- isMarkdownMode && allowRecording && mediaProvider && /* @__PURE__ */ jsx83(
40918
+ statusBarVisible && !isImageMode && /* @__PURE__ */ jsx84(StatusBar, { slotRight: statusBarSlotRight }),
40919
+ isMarkdownMode && allowRecording && mediaProvider && /* @__PURE__ */ jsx84(
40673
40920
  RecorderEntry,
40674
40921
  {
40675
40922
  open: mediaBinRecorderOpen,
@@ -40682,8 +40929,8 @@ ${snippet}` : snippet);
40682
40929
  )
40683
40930
  }
40684
40931
  ) }),
40685
- /* @__PURE__ */ jsx83(TooltipLayer, {}),
40686
- imageEditTarget !== null && mediaProvider && /* @__PURE__ */ jsx83(
40932
+ /* @__PURE__ */ jsx84(TooltipLayer, {}),
40933
+ imageEditTarget !== null && mediaProvider && /* @__PURE__ */ jsx84(
40687
40934
  ImageEditModal,
40688
40935
  {
40689
40936
  relativePath: imageEditTarget,
@@ -40702,7 +40949,7 @@ ${snippet}` : snippet);
40702
40949
  ]
40703
40950
  }
40704
40951
  );
40705
- return /* @__PURE__ */ jsx83(EditorContextMenuProvider, { rootRef: shellRef, readOnly, children: shell });
40952
+ return /* @__PURE__ */ jsx84(EditorContextMenuProvider, { rootRef: shellRef, readOnly, children: shell });
40706
40953
  }
40707
40954
  function ImageEditModal({
40708
40955
  relativePath,
@@ -40719,7 +40966,7 @@ function ImageEditModal({
40719
40966
  useModalDialog({ rootRef: modalRef, dialogRef: surfaceRef, onClose });
40720
40967
  const extension = relativePath.split(/[?#]/, 1)[0]?.split(".").pop()?.toLowerCase();
40721
40968
  const saveFormat = extension === "png" ? "png" : extension === "jpg" || extension === "jpeg" ? "jpeg" : extension === "webp" ? "webp" : null;
40722
- const sidecar = useMemo55(() => {
40969
+ const sidecar = useMemo56(() => {
40723
40970
  const sanitized = relativePath.replace(/[^a-zA-Z0-9._-]+/g, "_");
40724
40971
  let hash = 2166136261;
40725
40972
  for (let i = 0; i < relativePath.length; i++) {
@@ -40730,9 +40977,9 @@ function ImageEditModal({
40730
40977
  const parent = container ?? new MemoryContentContainer();
40731
40978
  return scopeContainer(parent, `.imageEdits/${scopedName}`);
40732
40979
  }, [container, relativePath]);
40733
- const [initialSrc, setInitialSrc] = useState74(null);
40734
- const [resolveError, setResolveError] = useState74(null);
40735
- useEffect63(() => {
40980
+ const [initialSrc, setInitialSrc] = useState75(null);
40981
+ const [resolveError, setResolveError] = useState75(null);
40982
+ useEffect64(() => {
40736
40983
  let cancelled = false;
40737
40984
  setInitialSrc(null);
40738
40985
  setResolveError(null);
@@ -40762,7 +41009,7 @@ function ImageEditModal({
40762
41009
  },
40763
41010
  [mediaProvider, relativePath, onSaved]
40764
41011
  );
40765
- return /* @__PURE__ */ jsx83(
41012
+ return /* @__PURE__ */ jsx84(
40766
41013
  "div",
40767
41014
  {
40768
41015
  ref: modalRef,
@@ -40776,9 +41023,9 @@ function ImageEditModal({
40776
41023
  },
40777
41024
  children: /* @__PURE__ */ jsxs66("div", { ref: surfaceRef, className: "squisq-image-edit-modal__surface", children: [
40778
41025
  /* @__PURE__ */ jsxs66("header", { className: "squisq-image-edit-modal__header", children: [
40779
- /* @__PURE__ */ jsx83("span", { className: "squisq-image-edit-modal__title", children: "Edit image" }),
40780
- /* @__PURE__ */ jsx83("span", { className: "squisq-image-edit-modal__path", children: relativePath }),
40781
- /* @__PURE__ */ jsx83(
41026
+ /* @__PURE__ */ jsx84("span", { className: "squisq-image-edit-modal__title", children: "Edit image" }),
41027
+ /* @__PURE__ */ jsx84("span", { className: "squisq-image-edit-modal__path", children: relativePath }),
41028
+ /* @__PURE__ */ jsx84(
40782
41029
  "button",
40783
41030
  {
40784
41031
  type: "button",
@@ -40790,10 +41037,10 @@ function ImageEditModal({
40790
41037
  }
40791
41038
  )
40792
41039
  ] }),
40793
- /* @__PURE__ */ jsx83("div", { className: "squisq-image-edit-modal__body", children: resolveError ? /* @__PURE__ */ jsxs66("div", { className: "squisq-image-edit-modal__error", children: [
41040
+ /* @__PURE__ */ jsx84("div", { className: "squisq-image-edit-modal__body", children: resolveError ? /* @__PURE__ */ jsxs66("div", { className: "squisq-image-edit-modal__error", children: [
40794
41041
  "Failed to load image: ",
40795
41042
  resolveError
40796
- ] }) : !saveFormat ? /* @__PURE__ */ jsx83("div", { className: "squisq-image-edit-modal__error", children: "Editing supports PNG, JPEG, and WebP images without changing the asset type." }) : !initialSrc ? /* @__PURE__ */ jsx83("div", { className: "squisq-image-edit-modal__loading", children: "Loading image\u2026" }) : /* @__PURE__ */ jsx83(
41043
+ ] }) : !saveFormat ? /* @__PURE__ */ jsx84("div", { className: "squisq-image-edit-modal__error", children: "Editing supports PNG, JPEG, and WebP images without changing the asset type." }) : !initialSrc ? /* @__PURE__ */ jsx84("div", { className: "squisq-image-edit-modal__loading", children: "Loading image\u2026" }) : /* @__PURE__ */ jsx84(
40797
41044
  ImageEditor,
40798
41045
  {
40799
41046
  filesContainer: sidecar,