@bendyline/squisq-editor-react 2.11.1 → 2.11.3

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.
@@ -27716,10 +27716,9 @@ var CODE_SNIPPET_HEADER_HEIGHT = 34;
27716
27716
  var CODE_SNIPPET_LINE_HEIGHT = 20;
27717
27717
  var CODE_SNIPPET_VERTICAL_PADDING = 20;
27718
27718
  var CODE_SNIPPET_SHELL_BORDER = 2;
27719
- var CODE_SNIPPET_EXTRA_LINES = 1;
27720
27719
  function codeSnippetAutoHeight(source) {
27721
27720
  const sourceLineCount = source.split("\n").length;
27722
- return CODE_SNIPPET_SHELL_BORDER + CODE_SNIPPET_HEADER_HEIGHT + CODE_SNIPPET_VERTICAL_PADDING + (sourceLineCount + CODE_SNIPPET_EXTRA_LINES) * CODE_SNIPPET_LINE_HEIGHT;
27721
+ return CODE_SNIPPET_SHELL_BORDER + CODE_SNIPPET_HEADER_HEIGHT + CODE_SNIPPET_VERTICAL_PADDING + sourceLineCount * CODE_SNIPPET_LINE_HEIGHT;
27723
27722
  }
27724
27723
 
27725
27724
  // src/codeSnippet/CodeSnippetWidget.tsx
@@ -28536,61 +28535,18 @@ import {
28536
28535
  } from "@bendyline/squisq/markdown";
28537
28536
  import { parseTableViewState, serializeTableViewState } from "@bendyline/squisq/table";
28538
28537
  import { TABLE_FED_TEMPLATES, resolveTemplateName as resolveTemplateName2 } from "@bendyline/squisq/doc";
28539
- function paramsOf(inner) {
28540
- const params = {};
28541
- if (!inner) return params;
28542
- for (const token of tokenizeAttrTokens4(inner)) {
28543
- const pair = splitKeyValueToken3(token);
28544
- if (pair) params[pair.key] = unquoteAttrValue(pair.value);
28545
- }
28546
- return params;
28547
- }
28548
- function readHeadingViewBinding(editor, cardPos, href) {
28549
- const headingPos = findOwningHeadingPosition(editor.state.doc, cardPos);
28550
- if (headingPos === null) {
28551
- return { headingPos: null, persisted: false, params: {} };
28552
- }
28553
- const node2 = editor.state.doc.nodeAt(headingPos);
28554
- if (!node2 || node2.type.name !== "heading") {
28555
- return { headingPos: null, persisted: false, params: {} };
28556
- }
28557
- const attrs = node2.attrs;
28558
- const params = paramsOf(attrs.dataTemplateParams);
28559
- const template = attrs.dataTemplate ? resolveTemplateName2(attrs.dataTemplate) : null;
28560
- const persisted = template !== null && TABLE_FED_TEMPLATES.has(template) && params.src === href;
28561
- return {
28562
- headingPos,
28563
- persisted,
28564
- params,
28565
- ...params.sort !== void 0 ? { sortRaw: params.sort } : {},
28566
- ...params.filter !== void 0 ? { filterRaw: params.filter } : {}
28567
- };
28568
- }
28569
- function serializeParams3(params) {
28570
- return Object.entries(params).map(([key, value]) => `${key}=${needsQuoting(value) ? quoteAttrValue5(value) : value}`).join(" ");
28571
- }
28572
- function writeHeadingViewState(editor, cardPos, href, view) {
28573
- if (!editor.isEditable) return false;
28574
- const binding = readHeadingViewBinding(editor, cardPos, href);
28575
- if (binding.headingPos === null || !binding.persisted) return false;
28576
- const raw = serializeTableViewState(view);
28577
- const params = { ...binding.params };
28578
- if (raw.sort !== void 0) params.sort = raw.sort;
28579
- else delete params.sort;
28580
- if (raw.filter !== void 0) params.filter = raw.filter;
28581
- else delete params.filter;
28582
- const serialized = serializeParams3(params);
28583
- const pos = binding.headingPos;
28584
- return editor.chain().command(({ tr }) => {
28585
- const node2 = tr.doc.nodeAt(pos);
28586
- if (!node2 || node2.type.name !== "heading") return false;
28587
- tr.setNodeAttribute(pos, "dataTemplateParams", serialized.length > 0 ? serialized : null);
28588
- return true;
28589
- }).run();
28590
- }
28591
- function viewStateFromBinding(binding, headers) {
28592
- return parseTableViewState(binding.sortRaw, binding.filterRaw, headers).view;
28593
- }
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";
28594
28550
 
28595
28551
  // src/dataCard/gridSave.ts
28596
28552
  import { DATA_BACKUP_PREFIX, buildDataBackupPath } from "@bendyline/squisq/versions";
@@ -28887,134 +28843,6 @@ async function createXlsxFormulaSession(meta, options = {}) {
28887
28843
  };
28888
28844
  }
28889
28845
 
28890
- // src/dataCard/DataCardWidget.tsx
28891
- import { useCallback as useCallback38, useEffect as useEffect39, useMemo as useMemo36, useRef as useRef40, useState as useState49 } from "react";
28892
- import { EMPTY_TABLE_VIEW_STATE } from "@bendyline/squisq/table";
28893
-
28894
- // src/dataCard/DataCardExtension.ts
28895
- import { Extension as Extension10 } from "@tiptap/core";
28896
- import { Plugin as Plugin10, PluginKey as PluginKey10 } from "@tiptap/pm/state";
28897
- import { Decoration as Decoration10, DecorationSet as DecorationSet10 } from "@tiptap/pm/view";
28898
- import { createRoot as createRoot6 } from "react-dom/client";
28899
- import { createElement as createElement12 } from "react";
28900
- import { isDataFilePath } from "@bendyline/squisq/doc";
28901
- var DATA_CARD_KEY = new PluginKey10("squisq-data-card");
28902
- function dataLinkHrefOf(node2) {
28903
- if (node2.type.name !== "paragraph" || node2.childCount === 0) return null;
28904
- let href = null;
28905
- for (let i = 0; i < node2.childCount; i++) {
28906
- const child = node2.child(i);
28907
- if (!child.isText || !child.text || !child.text.trim()) return null;
28908
- const link = child.marks.find((mark) => mark.type.name === "link");
28909
- const childHref = link?.attrs?.href;
28910
- if (typeof childHref !== "string") return null;
28911
- if (href === null) href = childHref;
28912
- else if (href !== childHref) return null;
28913
- }
28914
- return href !== null && isDataFilePath(href) ? href : null;
28915
- }
28916
- function findDataCardBlockPos(editor, blockId) {
28917
- return DATA_CARD_KEY.getState(editor.state)?.entries.find((e2) => e2.id === blockId)?.pos ?? null;
28918
- }
28919
- function buildDecorations8(doc, entries, editor, options) {
28920
- const decos = [];
28921
- for (const entry of entries) {
28922
- const node2 = doc.nodeAt(entry.pos);
28923
- if (!node2 || node2.type.name !== "paragraph") continue;
28924
- decos.push(
28925
- Decoration10.node(entry.pos, entry.pos + node2.nodeSize, {
28926
- class: "squisq-data-card-hidden"
28927
- })
28928
- );
28929
- const blockId = entry.id;
28930
- decos.push(
28931
- Decoration10.widget(
28932
- entry.pos + node2.nodeSize,
28933
- () => {
28934
- const container = document.createElement("div");
28935
- container.className = "squisq-data-card-host squisq-block-fill-available";
28936
- container.contentEditable = "false";
28937
- containFenceWidgetEvents(container);
28938
- const root = createRoot6(container);
28939
- root.render(
28940
- createElement12(DataCardWidget, {
28941
- editor,
28942
- blockId,
28943
- getMediaProvider: () => options.mediaProvider?.(),
28944
- getMediaRevision: () => options.mediaRevision?.() ?? 0,
28945
- getContainer: () => options.container?.(),
28946
- onOpenFiles: options.onOpenFiles,
28947
- onMediaSaved: options.onMediaSaved,
28948
- getCalcEngineFactory: () => options.calcEngineFactory?.()
28949
- })
28950
- );
28951
- container.__squisqDataCardRoot = { root };
28952
- return container;
28953
- },
28954
- {
28955
- destroy: (dom) => {
28956
- const ref = dom.__squisqDataCardRoot;
28957
- if (ref) setTimeout(() => ref.root.unmount(), 0);
28958
- },
28959
- side: 1,
28960
- ignoreSelection: true,
28961
- key: `squisq-data-card-${entry.id}`
28962
- }
28963
- )
28964
- );
28965
- }
28966
- return DecorationSet10.create(doc, decos);
28967
- }
28968
- function collectEntries(doc, mapped, seqStart) {
28969
- let seq = seqStart;
28970
- const entries = [];
28971
- doc.descendants((node2, pos) => {
28972
- if (node2.type.name !== "paragraph") return;
28973
- if (!dataLinkHrefOf(node2)) return false;
28974
- entries.push({ id: mapped?.get(pos) ?? `data-card-${++seq}`, pos });
28975
- return false;
28976
- });
28977
- return { entries, seq };
28978
- }
28979
- function applyState6(tr, prev, editor, doc, options) {
28980
- if (!tr.docChanged) return prev;
28981
- const mapped = mapFenceEntries(tr, prev.entries, doc, "paragraph");
28982
- const { entries, seq } = collectEntries(doc, mapped, prev.seq);
28983
- return { entries, seq, decorations: buildDecorations8(doc, entries, editor, options) };
28984
- }
28985
- var DataCardExtension = Extension10.create({
28986
- name: "squisqDataCard",
28987
- addOptions() {
28988
- return { enabled: true };
28989
- },
28990
- addProseMirrorPlugins() {
28991
- const editor = this.editor;
28992
- const options = this.options;
28993
- if (options.enabled === false) return [];
28994
- return [
28995
- new Plugin10({
28996
- key: DATA_CARD_KEY,
28997
- state: {
28998
- init: (_config, state) => {
28999
- const { entries, seq } = collectEntries(state.doc, null, 0);
29000
- return {
29001
- entries,
29002
- seq,
29003
- decorations: buildDecorations8(state.doc, entries, editor, options)
29004
- };
29005
- },
29006
- apply: (tr, prev, _oldState, newState) => applyState6(tr, prev, editor, newState.doc, options)
29007
- },
29008
- props: {
29009
- decorations(state) {
29010
- return this.getState(state)?.decorations ?? DecorationSet10.empty;
29011
- }
29012
- }
29013
- })
29014
- ];
29015
- }
29016
- });
29017
-
29018
28846
  // src/dataCard/DataCardWidget.tsx
29019
28847
  import { jsx as jsx55, jsxs as jsxs43 } from "react/jsx-runtime";
29020
28848
  var XLSX_SESSION_LOCKED_REASON = "Date cells and shared-formula masters stay locked; other formulas are editable";
@@ -29325,6 +29153,198 @@ function DataCardWidget({
29325
29153
  );
29326
29154
  }
29327
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
+
29328
29348
  // src/treeview/treeViewData.ts
29329
29349
  import { useEffect as useEffect40, useMemo as useMemo37, useState as useState51 } from "react";
29330
29350
 
@@ -33312,7 +33332,7 @@ function moveSelectionToDropPoint(view, event) {
33312
33332
  }
33313
33333
 
33314
33334
  // src/InlinePreviewGutter.tsx
33315
- 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";
33316
33336
  import { VIEWPORT_PRESETS as VIEWPORT_PRESETS5 } from "@bendyline/squisq/schemas";
33317
33337
  import {
33318
33338
  flattenBlocks as flattenBlocks4,
@@ -33521,6 +33541,96 @@ function sameEntries(a, b) {
33521
33541
  return true;
33522
33542
  }
33523
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
+
33524
33634
  // src/InlinePreviewGutter.tsx
33525
33635
  import { Fragment as Fragment18, jsx as jsx63, jsxs as jsxs50 } from "react/jsx-runtime";
33526
33636
  function isAnnotated(block) {
@@ -33687,14 +33797,16 @@ function InlinePreviewGutter({
33687
33797
  connectorWidth = 24,
33688
33798
  mediaProvider = null
33689
33799
  }) {
33690
- const { doc } = useEditorContext();
33800
+ const { doc, workspaceContainer, fileName, mediaRevision } = useEditorContext();
33801
+ const projection = usePreviewProjection(doc, "", workspaceContainer, fileName, mediaRevision);
33802
+ const previewDoc = projection?.contentDoc ?? doc;
33691
33803
  const gutterRef = useRef47(null);
33692
33804
  const { entries: headingEntries, scrollToBlock } = useHeadingLayout(gutterRef);
33693
33805
  const previewSettings = usePreviewSettingsOptional();
33694
33806
  const activeTheme = previewSettings?.activeTheme ?? DEFAULT_THEME5;
33695
33807
  const items = useMemo42(() => {
33696
- if (!doc || !doc.blocks.length) return [];
33697
- const flat = flattenBlocks4(doc.blocks);
33808
+ if (!previewDoc || !previewDoc.blocks.length) return [];
33809
+ const flat = flattenBlocks4(previewDoc.blocks);
33698
33810
  const totalBlocks = flat.length;
33699
33811
  const result = [];
33700
33812
  flat.forEach((block, index2) => {
@@ -33719,6 +33831,10 @@ function InlinePreviewGutter({
33719
33831
  block.contents,
33720
33832
  collectImagesDeep(block)
33721
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,
33722
33838
  ...annotation.params,
33723
33839
  ...block.templateOverrides
33724
33840
  };
@@ -33727,7 +33843,7 @@ function InlinePreviewGutter({
33727
33843
  totalBlocks,
33728
33844
  theme: activeTheme,
33729
33845
  viewport,
33730
- customTemplates: doc.customTemplates
33846
+ customTemplates: previewDoc.customTemplates
33731
33847
  };
33732
33848
  try {
33733
33849
  const { layers } = materializeBlockLayers2(templateBlock, ctx);
@@ -33748,13 +33864,13 @@ function InlinePreviewGutter({
33748
33864
  }
33749
33865
  });
33750
33866
  return result;
33751
- }, [doc, viewport, activeTheme]);
33867
+ }, [previewDoc, viewport, activeTheme]);
33752
33868
  const connectorTops = useMemo42(() => {
33753
33869
  const m = /* @__PURE__ */ new Map();
33754
33870
  headingEntries.forEach((e2) => m.set(e2.block.id, e2.top));
33755
33871
  return m;
33756
33872
  }, [headingEntries]);
33757
- const [positions, setPositions] = useState60(/* @__PURE__ */ new Map());
33873
+ const [positions, setPositions] = useState61(/* @__PURE__ */ new Map());
33758
33874
  useLayoutEffect9(() => {
33759
33875
  if (items.length === 0) {
33760
33876
  setPositions((prev) => prev.size === 0 ? prev : /* @__PURE__ */ new Map());
@@ -33939,10 +34055,10 @@ function InlinePreviewGutter({
33939
34055
  import {
33940
34056
  memo,
33941
34057
  useCallback as useCallback43,
33942
- useEffect as useEffect49,
34058
+ useEffect as useEffect50,
33943
34059
  useMemo as useMemo43,
33944
34060
  useRef as useRef48,
33945
- useState as useState61
34061
+ useState as useState62
33946
34062
  } from "react";
33947
34063
  import { flattenBlocks as flattenBlocks5, hasTemplate as hasTemplate2 } from "@bendyline/squisq/doc";
33948
34064
  import { extractPlainText as extractPlainText4 } from "@bendyline/squisq/markdown";
@@ -34064,8 +34180,8 @@ function OutlinePanel({ width, className, readOnly = false }) {
34064
34180
  const paneRef = useRef48(null);
34065
34181
  const cursorActiveId = useActiveOutlineBlockId();
34066
34182
  const activeDragRef = useRef48(null);
34067
- const [draggedBlockId, setDraggedBlockId] = useState61(null);
34068
- const [dropTarget, setDropTarget] = useState61(null);
34183
+ const [draggedBlockId, setDraggedBlockId] = useState62(null);
34184
+ const [dropTarget, setDropTarget] = useState62(null);
34069
34185
  const nextOutlineBlocks = doc?.blocks ?? EMPTY_BLOCKS;
34070
34186
  const outlineBlocksRef = useRef48(nextOutlineBlocks);
34071
34187
  if (!sameOutlineStructure(outlineBlocksRef.current, nextOutlineBlocks)) {
@@ -34398,11 +34514,11 @@ function useActiveOutlineBlockId() {
34398
34514
  const flatBlocksRef = useRef48(flatBlocks);
34399
34515
  flatBlocksRef.current = flatBlocks;
34400
34516
  const headingLocations = flatBlocks.map((block) => `${block.id}:${block.sourceHeading?.position?.start.line ?? ""}`).join("\0");
34401
- const [activeId, setActiveId] = useState61(null);
34402
- useEffect49(() => {
34517
+ const [activeId, setActiveId] = useState62(null);
34518
+ useEffect50(() => {
34403
34519
  setActiveId(null);
34404
34520
  }, [activeView]);
34405
- useEffect49(() => {
34521
+ useEffect50(() => {
34406
34522
  if (activeView !== "wysiwyg" || !tiptapEditor) return;
34407
34523
  const update = () => {
34408
34524
  const { from } = tiptapEditor.state.selection;
@@ -34424,7 +34540,7 @@ function useActiveOutlineBlockId() {
34424
34540
  tiptapEditor.off("update", update);
34425
34541
  };
34426
34542
  }, [activeView, tiptapEditor, headingLocations]);
34427
- useEffect49(() => {
34543
+ useEffect50(() => {
34428
34544
  if (activeView !== "raw" || !monacoEditor) return;
34429
34545
  const update = () => {
34430
34546
  const line = monacoEditor.getPosition()?.lineNumber;
@@ -34511,7 +34627,7 @@ function bumpHeadingLevelInSource(source, line, delta) {
34511
34627
  }
34512
34628
 
34513
34629
  // src/codeContext/CodeContextZones.tsx
34514
- 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";
34515
34631
  import { createPortal as createPortal13 } from "react-dom";
34516
34632
 
34517
34633
  // src/codeContext/diffContextSections.ts
@@ -34635,7 +34751,7 @@ function setOrdinal(zone, ordinal) {
34635
34751
  // src/codeContext/CodeContextSectionView.tsx
34636
34752
  import { parseMarkdown as parseMarkdown8 } from "@bendyline/squisq/markdown";
34637
34753
  import { MarkdownRenderer } from "@bendyline/squisq-react";
34638
- 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";
34639
34755
  import { jsx as jsx65, jsxs as jsxs52 } from "react/jsx-runtime";
34640
34756
  function CodeContextSectionView({
34641
34757
  section,
@@ -34655,7 +34771,7 @@ function CodeContextSectionView({
34655
34771
  () => expanded && section.markdown ? parseMarkdown8(section.markdown).children : null,
34656
34772
  [expanded, section.markdown]
34657
34773
  );
34658
- useEffect50(() => {
34774
+ useEffect51(() => {
34659
34775
  const el = rootRef.current;
34660
34776
  if (!el || typeof ResizeObserver === "undefined") return;
34661
34777
  const report = () => {
@@ -34727,11 +34843,11 @@ function CodeContextSectionView({
34727
34843
  import { Fragment as Fragment19, jsx as jsx66 } from "react/jsx-runtime";
34728
34844
  function CodeContextZones({ options }) {
34729
34845
  const { monacoEditor } = useEditorContext();
34730
- const [manager, setManager] = useState62(null);
34731
- const [, setZonesVersion] = useState62(0);
34732
- const [expandedById, setExpandedById] = useState62({});
34846
+ const [manager, setManager] = useState63(null);
34847
+ const [, setZonesVersion] = useState63(0);
34848
+ const [expandedById, setExpandedById] = useState63({});
34733
34849
  const seenIds = useRef50(/* @__PURE__ */ new Set());
34734
- useEffect51(() => {
34850
+ useEffect52(() => {
34735
34851
  if (!monacoEditor) return;
34736
34852
  const mgr = new CodeContextZoneManager(monacoEditor);
34737
34853
  const off = mgr.onDidChangeZones(() => setZonesVersion((v2) => v2 + 1));
@@ -34754,7 +34870,7 @@ function CodeContextZones({ options }) {
34754
34870
  });
34755
34871
  return out;
34756
34872
  }, [fileTop, sections]);
34757
- useEffect51(() => {
34873
+ useEffect52(() => {
34758
34874
  if (!manager) return;
34759
34875
  manager.sync(resolved.map((r) => r.spec));
34760
34876
  setExpandedById((prev) => {
@@ -35190,7 +35306,7 @@ function placeClipInBlock(source, fromLine, targetHeadingLine, spec, startAt) {
35190
35306
  }
35191
35307
 
35192
35308
  // src/TimelineTrack.tsx
35193
- 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";
35194
35310
  import {
35195
35311
  resolveMediaSchedule as resolveMediaSchedule2,
35196
35312
  getDocPlaybackDuration,
@@ -35315,7 +35431,7 @@ function collectTimelinePlaybackSchedule(doc, scheduled) {
35315
35431
  }
35316
35432
 
35317
35433
  // src/useTimelineClock.ts
35318
- 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";
35319
35435
  function advanceTime(prev, dt, total) {
35320
35436
  if (total <= 0) return 0;
35321
35437
  return Math.min(total, Math.max(0, prev + dt));
@@ -35335,8 +35451,8 @@ function playTimelineMediaAt(root, time) {
35335
35451
  });
35336
35452
  }
35337
35453
  function useTimelineClock(total) {
35338
- const [currentTime, setCurrentTime] = useState63(0);
35339
- const [isPlaying, setIsPlaying] = useState63(false);
35454
+ const [currentTime, setCurrentTime] = useState64(0);
35455
+ const [isPlaying, setIsPlaying] = useState64(false);
35340
35456
  const rafRef = useRef51(null);
35341
35457
  const lastRef = useRef51(0);
35342
35458
  const currentTimeRef = useRef51(0);
@@ -35344,10 +35460,10 @@ function useTimelineClock(total) {
35344
35460
  const mediaHostRef = useRef51(null);
35345
35461
  currentTimeRef.current = currentTime;
35346
35462
  isPlayingRef.current = isPlaying;
35347
- useEffect52(() => {
35463
+ useEffect53(() => {
35348
35464
  setCurrentTime((t) => Math.min(t, Math.max(0, total)));
35349
35465
  }, [total]);
35350
- useEffect52(() => {
35466
+ useEffect53(() => {
35351
35467
  if (!isPlaying) return;
35352
35468
  lastRef.current = performance.now();
35353
35469
  const tick = (now) => {
@@ -35409,7 +35525,7 @@ function timelineMediaLabel(src, kind) {
35409
35525
  }
35410
35526
 
35411
35527
  // src/TimelineItemMenu.tsx
35412
- 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";
35413
35529
  import { createPortal as createPortal14 } from "react-dom";
35414
35530
  import { Fragment as Fragment20, jsx as jsx68, jsxs as jsxs54 } from "react/jsx-runtime";
35415
35531
  function TimelineItemMenu({
@@ -35424,7 +35540,7 @@ function TimelineItemMenu({
35424
35540
  onClose
35425
35541
  }) {
35426
35542
  const panelRef = useRef52(null);
35427
- const [style, setStyle] = useState64(() => menuStyle(anchor));
35543
+ const [style, setStyle] = useState65(() => menuStyle(anchor));
35428
35544
  useLayoutEffect10(() => {
35429
35545
  const panel = panelRef.current;
35430
35546
  if (!panel) return;
@@ -35438,7 +35554,7 @@ function TimelineItemMenu({
35438
35554
  resizeObserver?.disconnect();
35439
35555
  };
35440
35556
  }, [anchor]);
35441
- useEffect53(() => {
35557
+ useEffect54(() => {
35442
35558
  const onKeyDown = (event) => {
35443
35559
  if (event.key !== "Escape") return;
35444
35560
  event.preventDefault();
@@ -35498,12 +35614,12 @@ function BlockMenu({
35498
35614
  onStartTime,
35499
35615
  onTransition
35500
35616
  }) {
35501
- const [explicitDuration, setExplicitDuration] = useState64(target.explicitDuration);
35502
- const [duration, setDuration] = useState64(formatNumber(target.duration));
35503
- const [startTime, setStartTime] = useState64(
35617
+ const [explicitDuration, setExplicitDuration] = useState65(target.explicitDuration);
35618
+ const [duration, setDuration] = useState65(formatNumber(target.duration));
35619
+ const [startTime, setStartTime] = useState65(
35504
35620
  target.startTime == null ? "" : formatNumber(target.startTime)
35505
35621
  );
35506
- const [transition, setTransition] = useState64(target.transition);
35622
+ const [transition, setTransition] = useState65(target.transition);
35507
35623
  const toggleAutotime = (autotimed) => {
35508
35624
  setExplicitDuration(!autotimed);
35509
35625
  if (autotimed) {
@@ -35575,11 +35691,11 @@ function VideoMenu({
35575
35691
  target,
35576
35692
  onPatch
35577
35693
  }) {
35578
- const [placement, setPlacement] = useState64(target.placement);
35579
- const [locked, setLocked] = useState64(target.lockToBlock);
35580
- const [pipSize, setPipSize] = useState64(target.pipSize ?? "");
35581
- const [pipShape, setPipShape] = useState64(target.pipShape ?? "");
35582
- 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 ?? "");
35583
35699
  const placed = placement === "picture-in-picture" || placement === "overlay";
35584
35700
  const placementOptions = [
35585
35701
  target.canUseContentPlacement ? { value: "content", label: "In layout" } : { value: "default", label: "Default" },
@@ -35849,9 +35965,9 @@ function TimelineTrack({
35849
35965
  colorScheme
35850
35966
  } = useEditorContext();
35851
35967
  const doc = docProp ?? contextDoc;
35852
- const [drag, setDrag] = useState65(null);
35853
- const [itemMenu, setItemMenu] = useState65(null);
35854
- 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);
35855
35971
  const scrollRef = useRef53(null);
35856
35972
  const blocks = useMemo46(() => doc ? flattenBlocks6(doc.blocks) : [], [doc]);
35857
35973
  const previewSettings = usePreviewSettingsOptional();
@@ -35884,8 +36000,8 @@ function TimelineTrack({
35884
36000
  setDrag(null);
35885
36001
  play();
35886
36002
  }, [play]);
35887
- const [scrubbing, setScrubbing] = useState65(false);
35888
- useEffect54(() => {
36003
+ const [scrubbing, setScrubbing] = useState66(false);
36004
+ useEffect55(() => {
35889
36005
  if (!scrubbing) return;
35890
36006
  const onMove = (e2) => {
35891
36007
  const scroll = scrollRef.current;
@@ -35923,7 +36039,7 @@ function TimelineTrack({
35923
36039
  [blocks]
35924
36040
  );
35925
36041
  const followedBlockRef = useRef53(null);
35926
- useEffect54(() => {
36042
+ useEffect55(() => {
35927
36043
  if (!isPlaying) {
35928
36044
  followedBlockRef.current = null;
35929
36045
  return;
@@ -35934,7 +36050,7 @@ function TimelineTrack({
35934
36050
  const line = headingLine(block);
35935
36051
  if (line != null) goToBlockByLine(line);
35936
36052
  }, [isPlaying, currentTime, blockAtTime, goToBlockByLine]);
35937
- useEffect54(() => {
36053
+ useEffect55(() => {
35938
36054
  if (!isPlaying) return;
35939
36055
  const scroll = scrollRef.current;
35940
36056
  if (!scroll) return;
@@ -35982,8 +36098,8 @@ function TimelineTrack({
35982
36098
  );
35983
36099
  const zoomIn = useCallback47(() => setPxPerSecond((s) => Math.min(ZOOM_MAX, s * ZOOM_FACTOR)), []);
35984
36100
  const zoomOut = useCallback47(() => setPxPerSecond((s) => Math.max(ZOOM_MIN, s / ZOOM_FACTOR)), []);
35985
- const [viewportWidth, setViewportWidth] = useState65(0);
35986
- useEffect54(() => {
36101
+ const [viewportWidth, setViewportWidth] = useState66(0);
36102
+ useEffect55(() => {
35987
36103
  const el = scrollRef.current;
35988
36104
  if (!el || typeof ResizeObserver === "undefined") return;
35989
36105
  const update = () => setViewportWidth(el.clientWidth);
@@ -35997,7 +36113,7 @@ function TimelineTrack({
35997
36113
  const dragRef = useRef53(null);
35998
36114
  dragRef.current = drag;
35999
36115
  const isDragging = drag != null && !drag.committed;
36000
- useEffect54(() => {
36116
+ useEffect55(() => {
36001
36117
  if (!isDragging) return;
36002
36118
  const onMove = (e2) => {
36003
36119
  const d = dragRef.current;
@@ -36028,7 +36144,7 @@ function TimelineTrack({
36028
36144
  window.removeEventListener("pointerup", onUp);
36029
36145
  };
36030
36146
  }, [isDragging]);
36031
- useEffect54(() => {
36147
+ useEffect55(() => {
36032
36148
  if (dragRef.current?.committed) setDrag(null);
36033
36149
  }, [doc]);
36034
36150
  const beginDrag = useCallback47(
@@ -36631,98 +36747,6 @@ function formatClock3(seconds) {
36631
36747
  import { useMemo as useMemo48 } from "react";
36632
36748
  import { getDocPlaybackDuration as getDocPlaybackDuration2, resolveMediaSchedule as resolveMediaSchedule3 } from "@bendyline/squisq/schemas";
36633
36749
  import { DocPlayer } from "@bendyline/squisq-react";
36634
-
36635
- // src/usePreviewProjection.ts
36636
- import { useEffect as useEffect55, useState as useState66 } from "react";
36637
- import {
36638
- resolveAudioMapping,
36639
- resolveDataReferences
36640
- } from "@bendyline/squisq/doc";
36641
- import { applyTransform } from "@bendyline/squisq/transform";
36642
- var DATA_PREVIEW_ROWS = 50;
36643
- var dataTableCaches = /* @__PURE__ */ new WeakMap();
36644
- function dataTableCacheFor(container, revision) {
36645
- let entry = dataTableCaches.get(container);
36646
- if (!entry || entry.revision !== revision) {
36647
- entry = { revision, cache: /* @__PURE__ */ new Map() };
36648
- dataTableCaches.set(container, entry);
36649
- }
36650
- return entry.cache;
36651
- }
36652
- async function resolveDataPreviews(doc, container, mediaRevision) {
36653
- try {
36654
- const { defaultDataReaders } = await import("@bendyline/squisq-formats/data");
36655
- const resolved = await resolveDataReferences(doc, container, {
36656
- readers: defaultDataReaders(),
36657
- maxPreviewRows: DATA_PREVIEW_ROWS,
36658
- tableCache: dataTableCacheFor(container, mediaRevision)
36659
- });
36660
- return resolved.doc;
36661
- } catch {
36662
- return doc;
36663
- }
36664
- }
36665
- function hasEquivalentAudio(left, right) {
36666
- if (left === right) return true;
36667
- if (left.segments.length !== right.segments.length) return false;
36668
- return left.segments.every((segment, index2) => {
36669
- const other = right.segments[index2];
36670
- return segment.src === other.src && segment.name === other.name && segment.duration === other.duration && segment.startTime === other.startTime;
36671
- });
36672
- }
36673
- function preserveEquivalentAudio(previous, next) {
36674
- const previousAudio = previous?.playerDoc.audio;
36675
- if (!previousAudio || !hasEquivalentAudio(previousAudio, next.playerDoc.audio)) return next;
36676
- return {
36677
- ...next,
36678
- playerDoc: { ...next.playerDoc, audio: previousAudio }
36679
- };
36680
- }
36681
- function usePreviewProjection(doc, transformStyle, workspaceContainer, documentTitle2, mediaRevision) {
36682
- const [projection, setProjection] = useState66(null);
36683
- useEffect55(() => {
36684
- if (!doc || !doc.blocks.length) {
36685
- setProjection(null);
36686
- return;
36687
- }
36688
- const build = (sourceDoc) => {
36689
- const contentDoc = transformStyle ? applyTransform(sourceDoc, transformStyle).doc : sourceDoc;
36690
- const narrationOwnsTimeline = (contentDoc.documentMedia ?? []).some(
36691
- (clip) => clip.anchor === "document"
36692
- );
36693
- return {
36694
- contentDoc,
36695
- playerDoc: buildPreviewDoc(contentDoc, {
36696
- documentTitle: documentTitle2,
36697
- interleaveImages: !narrationOwnsTimeline
36698
- })
36699
- };
36700
- };
36701
- const commit = (next) => {
36702
- setProjection((previous) => preserveEquivalentAudio(previous, next));
36703
- };
36704
- if (workspaceContainer) {
36705
- let cancelled = false;
36706
- const immediate = build(doc);
36707
- resolveAudioMapping(doc, workspaceContainer).then((audioDoc) => resolveDataPreviews(audioDoc, workspaceContainer, mediaRevision ?? 0)).then(
36708
- (resolvedDoc) => {
36709
- if (!cancelled) commit(build(resolvedDoc));
36710
- },
36711
- () => {
36712
- if (!cancelled) commit(immediate);
36713
- }
36714
- );
36715
- setProjection((previous) => previous ?? immediate);
36716
- return () => {
36717
- cancelled = true;
36718
- };
36719
- }
36720
- commit(build(doc));
36721
- }, [doc, transformStyle, workspaceContainer, documentTitle2, mediaRevision]);
36722
- return projection;
36723
- }
36724
-
36725
- // src/TimelineCompositionPanel.tsx
36726
36750
  import { jsx as jsx71, jsxs as jsxs57 } from "react/jsx-runtime";
36727
36751
  function TimelineCompositionPanel({
36728
36752
  doc,
@@ -37281,7 +37305,7 @@ function collectImageRefs(doc) {
37281
37305
  }
37282
37306
 
37283
37307
  // src/PreviewPanel.tsx
37284
- 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";
37285
37309
  import { createPortal as createPortal16 } from "react-dom";
37286
37310
  import {
37287
37311
  DashboardView,
@@ -38404,8 +38428,219 @@ function PrintPreview({
38404
38428
  );
38405
38429
  }
38406
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
+
38407
38642
  // src/PreviewPanel.tsx
38408
- 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";
38409
38644
  function PreviewPanel({
38410
38645
  basePath = "/",
38411
38646
  className,
@@ -38452,7 +38687,7 @@ function PreviewPanel({
38452
38687
  } = usePreviewSettings();
38453
38688
  const mainSurfaceRef = useRef58(null);
38454
38689
  const popupSurfaceRef = useRef58(null);
38455
- const [playbackState, setPlaybackState] = useState70(null);
38690
+ const [playbackState, setPlaybackState] = useState71(null);
38456
38691
  const handlePlaybackStateChange = useCallback52((next) => {
38457
38692
  setPlaybackState(next);
38458
38693
  }, []);
@@ -38465,7 +38700,7 @@ function PreviewPanel({
38465
38700
  );
38466
38701
  const previewDoc = previewProjection?.playerDoc ?? null;
38467
38702
  const contentDoc = previewProjection?.contentDoc ?? null;
38468
- const followerAudioController = useMemo53(() => {
38703
+ const followerAudioController = useMemo54(() => {
38469
38704
  if (!playbackState || !previewDoc) return null;
38470
38705
  const noOp = () => Promise.resolve();
38471
38706
  return {
@@ -38484,7 +38719,7 @@ function PreviewPanel({
38484
38719
  restart: noOp
38485
38720
  };
38486
38721
  }, [playbackState, previewDoc]);
38487
- const documentMarkdown = useMemo53(
38722
+ const documentMarkdown = useMemo54(
38488
38723
  () => activeTransformStyle && contentDoc ? buildDocumentPreviewMarkdown(contentDoc) : markdownSource,
38489
38724
  [activeTransformStyle, contentDoc, markdownSource]
38490
38725
  );
@@ -38493,11 +38728,11 @@ function PreviewPanel({
38493
38728
  const isNarrateMode = activeDisplayMode === "narrate";
38494
38729
  const isDashboardMode = activeDisplayMode === "dashboard";
38495
38730
  const isFlashcardsMode = activeDisplayMode === "flashcards";
38496
- useEffect60(() => {
38731
+ useEffect61(() => {
38497
38732
  if (presentation?.activeTarget === "window") return;
38498
38733
  setPlaybackState(null);
38499
38734
  }, [presentation?.activeTarget]);
38500
- useEffect60(() => {
38735
+ useEffect61(() => {
38501
38736
  if (presentation?.activeTarget !== "window" || !presentation.popupRoot) return;
38502
38737
  const mainRoot = mainSurfaceRef.current;
38503
38738
  const followerRoot = popupSurfaceRef.current;
@@ -38560,22 +38795,22 @@ function PreviewPanel({
38560
38795
  presentation?.popupRoot
38561
38796
  ]);
38562
38797
  if (isParsing && !isNarrateMode && !previewDoc) {
38563
- 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" }) });
38564
38799
  }
38565
38800
  if (parseError && !isNarrateMode) {
38566
38801
  return /* @__PURE__ */ jsxs62("div", { className: `squisq-preview-status ${className || ""}`, "data-testid": "preview-panel", children: [
38567
- /* @__PURE__ */ jsx77("h3", { children: "Parse Error" }),
38568
- /* @__PURE__ */ jsx77("pre", { children: parseError })
38802
+ /* @__PURE__ */ jsx78("h3", { children: "Parse Error" }),
38803
+ /* @__PURE__ */ jsx78("pre", { children: parseError })
38569
38804
  ] });
38570
38805
  }
38571
38806
  if (!previewDoc && !isDocumentMode && !isNarrateMode) {
38572
- 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." }) });
38573
38808
  }
38574
38809
  const fillsContainer = printMode?.active || isDocumentMode || isPageMode || isNarrateMode || isFlashcardsMode ? "stretch" : "center";
38575
38810
  const audienceWindowOpen = presentation?.activeTarget === "window";
38576
38811
  const renderSurface = (audience) => {
38577
38812
  if (!audience && printMode?.active) {
38578
- return /* @__PURE__ */ jsx77(
38813
+ return /* @__PURE__ */ jsx78(
38579
38814
  PrintPreview,
38580
38815
  {
38581
38816
  displayMode: activeDisplayMode,
@@ -38592,7 +38827,7 @@ function PreviewPanel({
38592
38827
  );
38593
38828
  }
38594
38829
  if (isDocumentMode) {
38595
- return /* @__PURE__ */ jsx77(
38830
+ return /* @__PURE__ */ jsx78(
38596
38831
  PlainHtmlPreview,
38597
38832
  {
38598
38833
  markdown: documentMarkdown,
@@ -38609,7 +38844,7 @@ function PreviewPanel({
38609
38844
  }
38610
38845
  if (isNarrateMode) {
38611
38846
  if (audience) return null;
38612
- return /* @__PURE__ */ jsx77(
38847
+ return /* @__PURE__ */ jsx78(
38613
38848
  TeleprompterView,
38614
38849
  {
38615
38850
  doc,
@@ -38628,7 +38863,7 @@ function PreviewPanel({
38628
38863
  );
38629
38864
  }
38630
38865
  if (isPageMode) {
38631
- return /* @__PURE__ */ jsx77(
38866
+ return /* @__PURE__ */ jsx78(
38632
38867
  LinearDocView2,
38633
38868
  {
38634
38869
  doc: contentDoc ?? doc,
@@ -38645,7 +38880,7 @@ function PreviewPanel({
38645
38880
  );
38646
38881
  }
38647
38882
  if (isFlashcardsMode) {
38648
- return /* @__PURE__ */ jsx77(
38883
+ return /* @__PURE__ */ jsx78(
38649
38884
  FlashcardView,
38650
38885
  {
38651
38886
  doc: contentDoc ?? doc,
@@ -38660,7 +38895,7 @@ function PreviewPanel({
38660
38895
  );
38661
38896
  }
38662
38897
  if (isDashboardMode) {
38663
- return /* @__PURE__ */ jsx77("div", { className: "squisq-dashboard-fit", children: /* @__PURE__ */ jsx77(
38898
+ return /* @__PURE__ */ jsx78("div", { className: "squisq-dashboard-fit", children: /* @__PURE__ */ jsx78(
38664
38899
  DashboardView,
38665
38900
  {
38666
38901
  doc: contentDoc ?? doc,
@@ -38675,10 +38910,10 @@ function PreviewPanel({
38675
38910
  ) });
38676
38911
  }
38677
38912
  if (audience && !followerAudioController) {
38678
- return /* @__PURE__ */ jsx77("div", { className: "squisq-presentation-connecting", children: "Connecting presentation..." });
38913
+ return /* @__PURE__ */ jsx78("div", { className: "squisq-presentation-connecting", children: "Connecting presentation..." });
38679
38914
  }
38680
38915
  const audienceCaptionMode = playbackState?.captionMode;
38681
- return /* @__PURE__ */ jsx77(
38916
+ return /* @__PURE__ */ jsx78(
38682
38917
  DocPlayer2,
38683
38918
  {
38684
38919
  doc: previewDoc,
@@ -38706,7 +38941,8 @@ function PreviewPanel({
38706
38941
  globalKeyboardShortcuts: !audience,
38707
38942
  showCodeCopyButton,
38708
38943
  onCopyCode,
38709
- onPlaybackStateChange: !audience && audienceWindowOpen ? handlePlaybackStateChange : void 0
38944
+ onPlaybackStateChange: !audience && audienceWindowOpen ? handlePlaybackStateChange : void 0,
38945
+ tableContentRenderer: !audience && activeDisplayMode === "slideshow" ? SlideshowDataGridRenderer : void 0
38710
38946
  },
38711
38947
  `${audience ? "audience" : "primary"}-${activeTransformStyle || "none"}`
38712
38948
  );
@@ -38720,49 +38956,57 @@ function PreviewPanel({
38720
38956
  minHeight: 0,
38721
38957
  background: presentation?.activeTarget ? activeTheme.colors.background : void 0
38722
38958
  };
38723
- return /* @__PURE__ */ jsxs62(Fragment21, { children: [
38724
- /* @__PURE__ */ jsx77(
38725
- "div",
38726
- {
38727
- className: `squisq-preview-container ${className || ""}`,
38728
- "data-testid": "preview-panel",
38729
- style: {
38730
- width: "100%",
38731
- height: "100%",
38732
- display: "flex",
38733
- flexDirection: "column",
38734
- overflow: "hidden",
38735
- background: "var(--squisq-bg)"
38736
- },
38737
- children: /* @__PURE__ */ jsx77("div", { ref: mainSurfaceRef, className: "squisq-preview-player", style: surfaceStyle, children: renderSurface(false) })
38738
- }
38739
- ),
38740
- audienceWindowOpen && presentation?.popupRoot && !isNarrateMode ? createPortal16(
38741
- /* @__PURE__ */ jsx77(
38742
- "div",
38743
- {
38744
- className: "squisq-editor-shell squisq-presentation-window",
38745
- "data-theme": colorScheme,
38746
- 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(
38747
38984
  "div",
38748
38985
  {
38749
- ref: popupSurfaceRef,
38750
- className: "squisq-preview-player squisq-presentation-window-surface",
38751
- style: surfaceStyle,
38752
- "aria-label": "Audience presentation",
38753
- 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
+ ) })
38754
38998
  }
38755
- ) })
38756
- }
38757
- ),
38758
- presentation.popupRoot
38759
- ) : null
38760
- ] });
38999
+ ),
39000
+ presentation.popupRoot
39001
+ ) : null
39002
+ ]
39003
+ }
39004
+ );
38761
39005
  }
38762
39006
 
38763
39007
  // src/MediaBin.tsx
38764
- import { useState as useState71, useEffect as useEffect61, useRef as useRef59, useCallback as useCallback53 } from "react";
38765
- 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";
38766
39010
  function formatSize(bytes) {
38767
39011
  if (bytes < 1024) return `${bytes} B`;
38768
39012
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
@@ -38830,20 +39074,20 @@ function MediaBin({
38830
39074
  allowBinaryDownloads = true,
38831
39075
  highlightPath = null
38832
39076
  }) {
38833
- const [entries, setEntries] = useState71([]);
39077
+ const [entries, setEntries] = useState72([]);
38834
39078
  const listRef = useRef59(null);
38835
- useEffect61(() => {
39079
+ useEffect62(() => {
38836
39080
  if (!highlightPath || !listRef.current) return;
38837
39081
  const item = listRef.current.querySelector(`[data-media-path="${CSS.escape(highlightPath)}"]`);
38838
39082
  if (item instanceof HTMLElement) {
38839
39083
  item.scrollIntoView({ block: "nearest" });
38840
39084
  }
38841
39085
  }, [highlightPath, entries]);
38842
- const [thumbUrls, setThumbUrls] = useState71({});
38843
- const [loading, setLoading] = useState71(false);
38844
- const [isDropActive, setIsDropActive] = useState71(false);
38845
- const [downloadingPath, setDownloadingPath] = useState71(null);
38846
- 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);
38847
39091
  const fileInputRef = useRef59(null);
38848
39092
  const contextMenuRef = useRef59(null);
38849
39093
  const dropDepthRef = useRef59(0);
@@ -38865,7 +39109,7 @@ function MediaBin({
38865
39109
  },
38866
39110
  [onCountChange]
38867
39111
  );
38868
- useEffect61(() => {
39112
+ useEffect62(() => {
38869
39113
  if (!contextMenu) return;
38870
39114
  const handlePointerDown = (event) => {
38871
39115
  if (contextMenuRef.current?.contains(event.target)) return;
@@ -38886,7 +39130,7 @@ function MediaBin({
38886
39130
  window.removeEventListener("resize", close);
38887
39131
  };
38888
39132
  }, [contextMenu]);
38889
- useEffect61(() => {
39133
+ useEffect62(() => {
38890
39134
  if (!mediaProvider) {
38891
39135
  setEntries([]);
38892
39136
  setThumbUrls({});
@@ -39092,12 +39336,12 @@ function MediaBin({
39092
39336
  "aria-haspopup": "dialog",
39093
39337
  "aria-expanded": isRecorderOpen,
39094
39338
  children: [
39095
- /* @__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" }),
39096
39340
  "Record"
39097
39341
  ]
39098
39342
  }
39099
39343
  ),
39100
- /* @__PURE__ */ jsx78(
39344
+ /* @__PURE__ */ jsx79(
39101
39345
  "button",
39102
39346
  {
39103
39347
  type: "button",
@@ -39113,10 +39357,10 @@ function MediaBin({
39113
39357
  /* @__PURE__ */ jsxs63("div", { className: "squisq-media-bin-list", ref: listRef, children: [
39114
39358
  !mediaProvider && /* @__PURE__ */ jsxs63("div", { className: "squisq-media-bin-empty", children: [
39115
39359
  "No media context.",
39116
- /* @__PURE__ */ jsx78("br", {}),
39360
+ /* @__PURE__ */ jsx79("br", {}),
39117
39361
  "Load a content zip or select a storage slot."
39118
39362
  ] }),
39119
- 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." }),
39120
39364
  entries.map((entry) => {
39121
39365
  const thumb = thumbUrls[entry.name];
39122
39366
  const basename = basenameForPath(entry.name);
@@ -39149,7 +39393,7 @@ ${formatSize(entry.size)}`,
39149
39393
  onDragStart: handleDragStart,
39150
39394
  onKeyDown: (e2) => handleItemKeyDown(entry, e2),
39151
39395
  children: [
39152
- thumb ? /* @__PURE__ */ jsx78(
39396
+ thumb ? /* @__PURE__ */ jsx79(
39153
39397
  "img",
39154
39398
  {
39155
39399
  src: thumb,
@@ -39157,15 +39401,15 @@ ${formatSize(entry.size)}`,
39157
39401
  className: "squisq-media-bin-thumb",
39158
39402
  draggable: false
39159
39403
  }
39160
- ) : /* @__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) }),
39161
39405
  /* @__PURE__ */ jsxs63("div", { className: "squisq-media-bin-meta", children: [
39162
- /* @__PURE__ */ jsx78("div", { className: "squisq-media-bin-name", children: basename }),
39406
+ /* @__PURE__ */ jsx79("div", { className: "squisq-media-bin-name", children: basename }),
39163
39407
  /* @__PURE__ */ jsxs63("div", { className: "squisq-media-bin-detail-row", children: [
39164
- /* @__PURE__ */ jsx78("span", { className: "squisq-media-bin-size", children: formatSize(entry.size) }),
39165
- 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" })
39166
39410
  ] })
39167
39411
  ] }),
39168
- allowBinaryDownloads && /* @__PURE__ */ jsx78(
39412
+ allowBinaryDownloads && /* @__PURE__ */ jsx79(
39169
39413
  "button",
39170
39414
  {
39171
39415
  type: "button",
@@ -39179,7 +39423,7 @@ ${formatSize(entry.size)}`,
39179
39423
  void handleDownloadEntry(entry);
39180
39424
  },
39181
39425
  onDragStart: (event) => event.preventDefault(),
39182
- 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" })
39183
39427
  }
39184
39428
  )
39185
39429
  ]
@@ -39189,11 +39433,11 @@ ${formatSize(entry.size)}`,
39189
39433
  })
39190
39434
  ] }),
39191
39435
  isDropActive && /* @__PURE__ */ jsxs63("div", { className: "squisq-media-bin-drop-target", "aria-hidden": "true", children: [
39192
- /* @__PURE__ */ jsx78("span", { className: "squisq-media-bin-drop-target-icon", children: "+" }),
39193
- /* @__PURE__ */ jsx78("strong", { children: "Drop images here" }),
39194
- /* @__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" })
39195
39439
  ] }),
39196
- contextMenu && /* @__PURE__ */ jsx78(
39440
+ contextMenu && /* @__PURE__ */ jsx79(
39197
39441
  "div",
39198
39442
  {
39199
39443
  ref: contextMenuRef,
@@ -39201,7 +39445,7 @@ ${formatSize(entry.size)}`,
39201
39445
  role: "menu",
39202
39446
  "aria-label": `${contextMenu.entry.name} actions`,
39203
39447
  style: contextMenuStyle,
39204
- children: /* @__PURE__ */ jsx78(
39448
+ children: /* @__PURE__ */ jsx79(
39205
39449
  "button",
39206
39450
  {
39207
39451
  type: "button",
@@ -39214,7 +39458,7 @@ ${formatSize(entry.size)}`,
39214
39458
  )
39215
39459
  }
39216
39460
  ),
39217
- /* @__PURE__ */ jsx78(
39461
+ /* @__PURE__ */ jsx79(
39218
39462
  "input",
39219
39463
  {
39220
39464
  ref: fileInputRef,
@@ -39230,8 +39474,8 @@ ${formatSize(entry.size)}`,
39230
39474
  }
39231
39475
 
39232
39476
  // src/DropZoneOverlay.tsx
39233
- import { useState as useState72 } from "react";
39234
- 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";
39235
39479
  function DropZoneOverlay({
39236
39480
  dragContentType,
39237
39481
  zoneProps,
@@ -39239,8 +39483,8 @@ function DropZoneOverlay({
39239
39483
  }) {
39240
39484
  const showMedia = dragContentType === "media" || dragContentType === "mixed";
39241
39485
  const showText = dragContentType === "text" || dragContentType === "mixed";
39242
- return /* @__PURE__ */ jsx79("div", { className: "squisq-drop-overlay", children: /* @__PURE__ */ jsxs64("div", { className: "squisq-drop-overlay-inner", children: [
39243
- 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(
39244
39488
  DropZone,
39245
39489
  {
39246
39490
  target: "media",
@@ -39253,7 +39497,7 @@ function DropZoneOverlay({
39253
39497
  }
39254
39498
  ),
39255
39499
  showText && /* @__PURE__ */ jsxs64(Fragment22, { children: [
39256
- /* @__PURE__ */ jsx79(
39500
+ /* @__PURE__ */ jsx80(
39257
39501
  DropZone,
39258
39502
  {
39259
39503
  target: "insert",
@@ -39264,7 +39508,7 @@ function DropZoneOverlay({
39264
39508
  variant: "insert"
39265
39509
  }
39266
39510
  ),
39267
- /* @__PURE__ */ jsx79(
39511
+ /* @__PURE__ */ jsx80(
39268
39512
  DropZone,
39269
39513
  {
39270
39514
  target: "replace",
@@ -39287,7 +39531,7 @@ function DropZone({
39287
39531
  disabled,
39288
39532
  variant
39289
39533
  }) {
39290
- const [isHovering, setIsHovering] = useState72(false);
39534
+ const [isHovering, setIsHovering] = useState73(false);
39291
39535
  const props = zoneProps(target);
39292
39536
  return /* @__PURE__ */ jsxs64(
39293
39537
  "div",
@@ -39322,16 +39566,16 @@ function DropZone({
39322
39566
  props.onDrop(e2);
39323
39567
  },
39324
39568
  children: [
39325
- /* @__PURE__ */ jsx79("span", { className: "squisq-drop-zone-icon", children: icon }),
39326
- /* @__PURE__ */ jsx79("span", { className: "squisq-drop-zone-label", children: label }),
39327
- /* @__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 })
39328
39572
  ]
39329
39573
  }
39330
39574
  );
39331
39575
  }
39332
39576
 
39333
39577
  // src/Tooltip.tsx
39334
- 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";
39335
39579
  import { createPortal as createPortal17 } from "react-dom";
39336
39580
 
39337
39581
  // src/tooltipPlacement.ts
@@ -39344,10 +39588,10 @@ function clampTooltipLeft(anchorX, tooltipWidth, viewportWidth, edgePadding = ED
39344
39588
  }
39345
39589
 
39346
39590
  // src/Tooltip.tsx
39347
- import { jsx as jsx80 } from "react/jsx-runtime";
39591
+ import { jsx as jsx81 } from "react/jsx-runtime";
39348
39592
  var SHOW_DELAY_MS = 180;
39349
39593
  function TooltipLayer() {
39350
- const [state, setState3] = useState73(null);
39594
+ const [state, setState3] = useState74(null);
39351
39595
  const tooltipRef = useRef60(null);
39352
39596
  const timerRef = useRef60(null);
39353
39597
  const currentTargetRef = useRef60(null);
@@ -39363,7 +39607,7 @@ function TooltipLayer() {
39363
39607
  node2.style.left = `${left}px`;
39364
39608
  node2.style.visibility = "visible";
39365
39609
  }, [state]);
39366
- useEffect62(() => {
39610
+ useEffect63(() => {
39367
39611
  const clearTimer = () => {
39368
39612
  if (timerRef.current) {
39369
39613
  clearTimeout(timerRef.current);
@@ -39429,7 +39673,7 @@ function TooltipLayer() {
39429
39673
  }, []);
39430
39674
  if (!state) return null;
39431
39675
  return createPortal17(
39432
- /* @__PURE__ */ jsx80(
39676
+ /* @__PURE__ */ jsx81(
39433
39677
  "div",
39434
39678
  {
39435
39679
  role: "tooltip",
@@ -39449,35 +39693,37 @@ function TooltipLayer() {
39449
39693
  }
39450
39694
 
39451
39695
  // src/EditorShell.tsx
39452
- 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";
39453
39697
 
39454
39698
  // src/BlockPreviewPanel.tsx
39455
- import { useMemo as useMemo54 } from "react";
39699
+ import { useMemo as useMemo55 } from "react";
39456
39700
  import { VIEWPORT_PRESETS as VIEWPORT_PRESETS7 } from "@bendyline/squisq/schemas";
39457
39701
  import { flattenBlocks as flattenBlocks7, DEFAULT_THEME as DEFAULT_THEME7 } from "@bendyline/squisq/doc";
39458
- import { jsx as jsx81 } from "react/jsx-runtime";
39702
+ import { jsx as jsx82 } from "react/jsx-runtime";
39459
39703
  function BlockPreviewPanel({ basePath = "/" }) {
39460
- const { doc, activeBlockStartLine, mediaProvider } = useEditorContext();
39704
+ const { doc, activeBlockStartLine, mediaProvider, workspaceContainer, fileName, mediaRevision } = useEditorContext();
39461
39705
  const previewSettings = usePreviewSettingsOptional();
39462
39706
  const theme = previewSettings?.activeTheme ?? DEFAULT_THEME7;
39463
39707
  const viewport = previewSettings?.activeViewport ?? VIEWPORT_PRESETS7.landscape;
39464
- const block = useMemo54(() => {
39465
- if (!doc) return null;
39466
- 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);
39467
39713
  if (blocks.length === 0) return null;
39468
39714
  return blocks.find((b) => b.sourceHeading?.position?.start.line === activeBlockStartLine) ?? blocks[0];
39469
- }, [doc, activeBlockStartLine]);
39470
- const visual = useMemo54(
39471
- () => doc && block ? resolveBlockVisual(doc, block, theme, viewport) : null,
39472
- [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]
39473
39719
  );
39474
39720
  if (!visual) return null;
39475
- 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(
39476
39722
  "div",
39477
39723
  {
39478
39724
  className: "squisq-block-preview-frame",
39479
39725
  style: { aspectRatio: `${viewport.width} / ${viewport.height}` },
39480
- children: /* @__PURE__ */ jsx81(
39726
+ children: /* @__PURE__ */ jsx82(
39481
39727
  BlockThumbnail,
39482
39728
  {
39483
39729
  visual,
@@ -39491,7 +39737,7 @@ function BlockPreviewPanel({ basePath = "/" }) {
39491
39737
  }
39492
39738
 
39493
39739
  // src/proofing/ProofingPanel.tsx
39494
- import { jsx as jsx82, jsxs as jsxs65 } from "react/jsx-runtime";
39740
+ import { jsx as jsx83, jsxs as jsxs65 } from "react/jsx-runtime";
39495
39741
  var CATEGORY_LABELS = {
39496
39742
  spelling: "Spelling",
39497
39743
  grammar: "Grammar",
@@ -39505,10 +39751,10 @@ function ProofingPanel() {
39505
39751
  /* @__PURE__ */ jsxs65("div", { className: "squisq-proof-panel-header", children: [
39506
39752
  /* @__PURE__ */ jsxs65("span", { className: "squisq-proof-panel-title", children: [
39507
39753
  "Proofing",
39508
- /* @__PURE__ */ jsx82("span", { className: "squisq-proof-panel-count", children: findings.length })
39754
+ /* @__PURE__ */ jsx83("span", { className: "squisq-proof-panel-count", children: findings.length })
39509
39755
  ] }),
39510
39756
  /* @__PURE__ */ jsxs65("span", { className: "squisq-proof-panel-actions", children: [
39511
- /* @__PURE__ */ jsx82(
39757
+ /* @__PURE__ */ jsx83(
39512
39758
  "button",
39513
39759
  {
39514
39760
  type: "button",
@@ -39520,7 +39766,7 @@ function ProofingPanel() {
39520
39766
  children: "\u2191"
39521
39767
  }
39522
39768
  ),
39523
- /* @__PURE__ */ jsx82(
39769
+ /* @__PURE__ */ jsx83(
39524
39770
  "button",
39525
39771
  {
39526
39772
  type: "button",
@@ -39532,7 +39778,7 @@ function ProofingPanel() {
39532
39778
  children: "\u2193"
39533
39779
  }
39534
39780
  ),
39535
- /* @__PURE__ */ jsx82(
39781
+ /* @__PURE__ */ jsx83(
39536
39782
  "button",
39537
39783
  {
39538
39784
  type: "button",
@@ -39545,20 +39791,20 @@ function ProofingPanel() {
39545
39791
  )
39546
39792
  ] })
39547
39793
  ] }),
39548
- 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" }),
39549
39795
  state.status === "error" && /* @__PURE__ */ jsxs65("div", { className: "squisq-proof-panel-empty", children: [
39550
39796
  "Proofing failed to load.",
39551
- /* @__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" })
39552
39798
  ] }),
39553
- state.status === "ready" && findings.length === 0 && /* @__PURE__ */ jsx82("div", { className: "squisq-proof-panel-empty", children: "No issues found." }),
39554
- /* @__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(
39555
39801
  "button",
39556
39802
  {
39557
39803
  type: "button",
39558
39804
  className: finding.id === activeFindingId ? "squisq-proof-panel-row squisq-proof-panel-row--active" : "squisq-proof-panel-row",
39559
39805
  onClick: () => state.selectFinding(finding.id),
39560
39806
  children: [
39561
- /* @__PURE__ */ jsx82(
39807
+ /* @__PURE__ */ jsx83(
39562
39808
  "span",
39563
39809
  {
39564
39810
  className: `squisq-proof-dot squisq-proof-dot--${finding.category}`,
@@ -39567,8 +39813,8 @@ function ProofingPanel() {
39567
39813
  }
39568
39814
  ),
39569
39815
  /* @__PURE__ */ jsxs65("span", { className: "squisq-proof-panel-row-body", children: [
39570
- /* @__PURE__ */ jsx82("span", { className: "squisq-proof-panel-excerpt", children: finding.originalText }),
39571
- /* @__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 })
39572
39818
  ] })
39573
39819
  ]
39574
39820
  }
@@ -39821,7 +40067,7 @@ import {
39821
40067
  createMediaProviderFromContainer
39822
40068
  } from "@bendyline/squisq/storage";
39823
40069
  import { MediaContext as MediaContext6, useMediaClipDurations } from "@bendyline/squisq-react";
39824
- 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";
39825
40071
  function EditorShell({
39826
40072
  initialMarkdown = "",
39827
40073
  initialView = "wysiwyg",
@@ -39904,14 +40150,14 @@ function EditorShell({
39904
40150
  themeOverride = null
39905
40151
  }) {
39906
40152
  const effectiveContainer = workspaceContainer ?? null;
39907
- const effectiveMediaProvider = useMemo55(() => {
40153
+ const effectiveMediaProvider = useMemo56(() => {
39908
40154
  if (mediaProvider !== void 0) return mediaProvider;
39909
40155
  if (effectiveContainer) return createMediaProviderFromContainer(effectiveContainer);
39910
40156
  return void 0;
39911
40157
  }, [mediaProvider, effectiveContainer]);
39912
40158
  const filesToggleEnabled = showFilesToggle ?? effectiveMediaProvider !== void 0;
39913
40159
  const effectiveInitialView = hostMode === "chat" || !showPlayTab && initialView === "preview" ? "wysiwyg" : initialView;
39914
- return /* @__PURE__ */ jsx83(MediaContext6.Provider, { value: effectiveMediaProvider ?? null, children: /* @__PURE__ */ jsx83(
40160
+ return /* @__PURE__ */ jsx84(MediaContext6.Provider, { value: effectiveMediaProvider ?? null, children: /* @__PURE__ */ jsx84(
39915
40161
  EditorProvider,
39916
40162
  {
39917
40163
  initialMarkdown,
@@ -39953,7 +40199,7 @@ function EditorShell({
39953
40199
  themeInheritance,
39954
40200
  viewPreferences,
39955
40201
  onViewPreferencesChange,
39956
- children: /* @__PURE__ */ jsx83(ProofingRoot, { children: /* @__PURE__ */ jsx83(
40202
+ children: /* @__PURE__ */ jsx84(ProofingRoot, { children: /* @__PURE__ */ jsx84(
39957
40203
  EditorShellInner,
39958
40204
  {
39959
40205
  basePath,
@@ -40008,11 +40254,11 @@ function EditorShell({
40008
40254
  }
40009
40255
  function UseModeToolbarControls({ allowPrint }) {
40010
40256
  const printMode = usePrintMode();
40011
- if (printMode.active) return /* @__PURE__ */ jsx83(PrintPreviewToolbar, {});
40257
+ if (printMode.active) return /* @__PURE__ */ jsx84(PrintPreviewToolbar, {});
40012
40258
  return /* @__PURE__ */ jsxs66(Fragment23, { children: [
40013
- /* @__PURE__ */ jsx83(PreviewToolbarControls, {}),
40014
- /* @__PURE__ */ jsx83(PresentationModeControl, {}),
40015
- allowPrint && /* @__PURE__ */ jsx83(PrintModeControl, {})
40259
+ /* @__PURE__ */ jsx84(PreviewToolbarControls, {}),
40260
+ /* @__PURE__ */ jsx84(PresentationModeControl, {}),
40261
+ allowPrint && /* @__PURE__ */ jsx84(PrintModeControl, {})
40016
40262
  ] });
40017
40263
  }
40018
40264
  function UseModeProviders({
@@ -40021,13 +40267,13 @@ function UseModeProviders({
40021
40267
  allowPresentationWindow,
40022
40268
  allowPresentationFullscreen
40023
40269
  }) {
40024
- return /* @__PURE__ */ jsx83(
40270
+ return /* @__PURE__ */ jsx84(
40025
40271
  PresentationModeProvider,
40026
40272
  {
40027
40273
  rootRef,
40028
40274
  allowWindow: allowPresentationWindow,
40029
40275
  allowFullscreen: allowPresentationFullscreen,
40030
- children: /* @__PURE__ */ jsx83(PrintModeProvider, { rootRef, children })
40276
+ children: /* @__PURE__ */ jsx84(PrintModeProvider, { rootRef, children })
40031
40277
  }
40032
40278
  );
40033
40279
  }
@@ -40118,7 +40364,7 @@ function EditorShellInner({
40118
40364
  workspaceContainer
40119
40365
  );
40120
40366
  const timelineDoc = timelineProjection?.contentDoc ?? doc;
40121
- const timelineRawSchedule = useMemo55(
40367
+ const timelineRawSchedule = useMemo56(
40122
40368
  () => timelineDoc ? resolveMediaSchedule4(timelineDoc) : [],
40123
40369
  [timelineDoc]
40124
40370
  );
@@ -40127,19 +40373,19 @@ function EditorShellInner({
40127
40373
  basePath,
40128
40374
  mediaProvider ?? null
40129
40375
  );
40130
- const timelineDuration = useMemo55(
40376
+ const timelineDuration = useMemo56(
40131
40377
  () => timelineDoc ? getDocPlaybackDuration3(timelineDoc, {
40132
40378
  intrinsicDuration: (clip) => timelineClipDurations.get(clip.src)
40133
40379
  }) : 0,
40134
40380
  [timelineDoc, timelineClipDurations]
40135
40381
  );
40136
- const timelineSchedule = useMemo55(
40382
+ const timelineSchedule = useMemo56(
40137
40383
  () => timelineDoc ? resolveMediaSchedule4(timelineDoc, {
40138
40384
  intrinsicDuration: (clip) => timelineClipDurations.get(clip.src)
40139
40385
  }) : [],
40140
40386
  [timelineDoc, timelineClipDurations]
40141
40387
  );
40142
- const timelineVideoSchedule = useMemo55(
40388
+ const timelineVideoSchedule = useMemo56(
40143
40389
  () => timelineDoc ? [
40144
40390
  ...timelineSchedule.filter((clip) => clip.kind === "video"),
40145
40391
  ...collectEmbeddedVideoSchedule(timelineDoc)
@@ -40148,16 +40394,16 @@ function EditorShellInner({
40148
40394
  );
40149
40395
  const timelineClock = useTimelineClock(isTimelineMode ? timelineDuration : 0);
40150
40396
  const hasTimelineVideo = timelineVideoSchedule.length > 0;
40151
- const [timelineVideoVisible, setTimelineVideoVisible] = useState74(false);
40152
- const [timelineCompositionVisible, setTimelineCompositionVisible] = useState74(false);
40397
+ const [timelineVideoVisible, setTimelineVideoVisible] = useState75(false);
40398
+ const [timelineCompositionVisible, setTimelineCompositionVisible] = useState75(false);
40153
40399
  const timelinePreviewCount = Number(timelineVideoVisible) + Number(timelineCompositionVisible);
40154
- const [showFiles, setShowFiles] = useState74(false);
40155
- const [filesFocusPath, setFilesFocusPath] = useState74(null);
40156
- const [mediaRefreshKey, setMediaRefreshKey] = useState74(0);
40157
- const [mediaCount, setMediaCount] = useState74(0);
40158
- 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);
40159
40405
  const mediaListRefreshKey = mediaRefreshKey + mediaRevision;
40160
- const usedMediaPaths = useMemo55(
40406
+ const usedMediaPaths = useMemo56(
40161
40407
  () => collectMediaReferencesFromMarkdown(markdownSource),
40162
40408
  [markdownSource]
40163
40409
  );
@@ -40167,13 +40413,13 @@ function EditorShellInner({
40167
40413
  }
40168
40414
  const imageEditFallbackContainer = imageEditFallbackContainerRef.current;
40169
40415
  const isDark = colorScheme === "dark";
40170
- useEffect63(() => {
40416
+ useEffect64(() => {
40171
40417
  if (!isTimelineMode || !hasTimelineVideo) setTimelineVideoVisible(false);
40172
40418
  }, [isTimelineMode, hasTimelineVideo]);
40173
- useEffect63(() => {
40419
+ useEffect64(() => {
40174
40420
  if (!isTimelineMode || !doc?.blocks.length) setTimelineCompositionVisible(false);
40175
40421
  }, [isTimelineMode, doc]);
40176
- useEffect63(() => {
40422
+ useEffect64(() => {
40177
40423
  if (!mediaProvider) {
40178
40424
  setMediaCount(0);
40179
40425
  return;
@@ -40197,7 +40443,7 @@ function EditorShellInner({
40197
40443
  cancelled = true;
40198
40444
  };
40199
40445
  }, [mediaProvider, mediaListRefreshKey]);
40200
- useEffect63(() => {
40446
+ useEffect64(() => {
40201
40447
  if (showFilesWhenNotEmpty && mediaCount > 0) setShowFiles(true);
40202
40448
  }, [mediaCount, showFilesWhenNotEmpty]);
40203
40449
  const handleToggleFiles = useCallback54(() => {
@@ -40236,7 +40482,7 @@ ${snippet}` : snippet);
40236
40482
  [activeView, tiptapEditor, monacoEditor, insertAtCursor, markdownSource, setMarkdownSource]
40237
40483
  );
40238
40484
  const docBasenameRef = useRef61("document");
40239
- useEffect63(() => {
40485
+ useEffect64(() => {
40240
40486
  let cancelled = false;
40241
40487
  docBasenameRef.current = "document";
40242
40488
  if (!workspaceContainer) return;
@@ -40357,7 +40603,7 @@ ${snippet}` : snippet);
40357
40603
  onDrop: handleFileDrop,
40358
40604
  enabled: !readOnly
40359
40605
  });
40360
- useEffect63(() => {
40606
+ useEffect64(() => {
40361
40607
  onChange?.(markdownSource);
40362
40608
  }, [markdownSource, onChange]);
40363
40609
  const handleShellKeyDown = useCallback54(
@@ -40445,7 +40691,7 @@ ${snippet}` : snippet);
40445
40691
  },
40446
40692
  ...containerProps,
40447
40693
  children: [
40448
- /* @__PURE__ */ jsx83(CustomThemeProvider, { docThemes, onDocThemesChange, children: /* @__PURE__ */ jsx83(
40694
+ /* @__PURE__ */ jsx84(CustomThemeProvider, { docThemes, onDocThemesChange, children: /* @__PURE__ */ jsx84(
40449
40695
  PreviewSettingsProvider,
40450
40696
  {
40451
40697
  doc,
@@ -40460,16 +40706,16 @@ ${snippet}` : snippet);
40460
40706
  children: [
40461
40707
  isImageMode ? (toolbarSlotLeft || toolbarSlotRight) && /* @__PURE__ */ jsxs66("div", { className: "squisq-editor-header squisq-editor-header--image", children: [
40462
40708
  toolbarSlotLeft,
40463
- /* @__PURE__ */ jsx83("div", { style: { flex: 1 } }),
40709
+ /* @__PURE__ */ jsx84("div", { style: { flex: 1 } }),
40464
40710
  toolbarSlotRight
40465
- ] }) : /* @__PURE__ */ jsx83("div", { className: "squisq-editor-header", children: /* @__PURE__ */ jsx83(
40711
+ ] }) : /* @__PURE__ */ jsx84("div", { className: "squisq-editor-header", children: /* @__PURE__ */ jsx84(
40466
40712
  Toolbar,
40467
40713
  {
40468
40714
  showFiles,
40469
40715
  fileCount: mediaCount,
40470
40716
  onToggleFiles: !isCodeMode && filesToggleEnabled ? handleToggleFiles : void 0,
40471
40717
  slotLeft: toolbarSlotLeft,
40472
- slotAfterTabs: !isCodeMode && isPreview && /* @__PURE__ */ jsx83(UseModeToolbarControls, { allowPrint }),
40718
+ slotAfterTabs: !isCodeMode && isPreview && /* @__PURE__ */ jsx84(UseModeToolbarControls, { allowPrint }),
40473
40719
  slotAfterActions: toolbarSlotAfterActions,
40474
40720
  slotRight: toolbarSlotRight,
40475
40721
  showPlayTab,
@@ -40503,7 +40749,7 @@ ${snippet}` : snippet);
40503
40749
  position: "relative"
40504
40750
  },
40505
40751
  children: [
40506
- isImageMode && imageSrc && (imageMode === "edit" && imageEditorContainer ? /* @__PURE__ */ jsx83(
40752
+ isImageMode && imageSrc && (imageMode === "edit" && imageEditorContainer ? /* @__PURE__ */ jsx84(
40507
40753
  ImageEditor,
40508
40754
  {
40509
40755
  filesContainer: imageEditorContainer,
@@ -40513,10 +40759,10 @@ ${snippet}` : snippet);
40513
40759
  onExport: onImageExport,
40514
40760
  surface: colorScheme === "dark" ? DARK_SURFACE : LIGHT_SURFACE
40515
40761
  }
40516
- ) : /* @__PURE__ */ jsx83(ImageViewer, { src: imageSrc, alt: imageAlt, theme: colorScheme })),
40762
+ ) : /* @__PURE__ */ jsx84(ImageViewer, { src: imageSrc, alt: imageAlt, theme: colorScheme })),
40517
40763
  !isImageMode && activeView === "raw" && /* @__PURE__ */ jsxs66("div", { className: "squisq-editor-with-gutter", children: [
40518
- isMarkdownMode && outlineVisible && /* @__PURE__ */ jsx83(OutlinePanel, { width: outlineWidth, readOnly }, "outline"),
40519
- /* @__PURE__ */ jsx83(
40764
+ isMarkdownMode && outlineVisible && /* @__PURE__ */ jsx84(OutlinePanel, { width: outlineWidth, readOnly }, "outline"),
40765
+ /* @__PURE__ */ jsx84(
40520
40766
  BlockCardView,
40521
40767
  {
40522
40768
  active: isCardMode,
@@ -40525,7 +40771,7 @@ ${snippet}` : snippet);
40525
40771
  onPrev: prevBlock,
40526
40772
  onNext: nextBlock,
40527
40773
  onAdd: addBlock,
40528
- 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(
40529
40775
  RawEditor,
40530
40776
  {
40531
40777
  monacoTheme: colorScheme === "dark" ? "vs-dark" : "vs",
@@ -40536,9 +40782,9 @@ ${snippet}` : snippet);
40536
40782
  },
40537
40783
  "raw-frame"
40538
40784
  ),
40539
- isCodeMode && codeContext && /* @__PURE__ */ jsx83(CodeContextZones, { options: codeContext }, "code-context"),
40540
- isMarkdownMode && isCardMode && inlinePreviewVisible && /* @__PURE__ */ jsx83(BlockPreviewPanel, { basePath }, "block-preview"),
40541
- 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(
40542
40788
  InlinePreviewGutter,
40543
40789
  {
40544
40790
  width: inlinePreviewWidth,
@@ -40549,8 +40795,8 @@ ${snippet}` : snippet);
40549
40795
  )
40550
40796
  ] }, "raw-shell"),
40551
40797
  isMarkdownMode && activeView === "wysiwyg" && /* @__PURE__ */ jsxs66("div", { className: "squisq-editor-with-gutter", children: [
40552
- outlineVisible && /* @__PURE__ */ jsx83(OutlinePanel, { width: outlineWidth, readOnly }, "outline"),
40553
- /* @__PURE__ */ jsx83(
40798
+ outlineVisible && /* @__PURE__ */ jsx84(OutlinePanel, { width: outlineWidth, readOnly }, "outline"),
40799
+ /* @__PURE__ */ jsx84(
40554
40800
  BlockCardView,
40555
40801
  {
40556
40802
  active: isCardMode,
@@ -40559,7 +40805,7 @@ ${snippet}` : snippet);
40559
40805
  onPrev: prevBlock,
40560
40806
  onNext: nextBlock,
40561
40807
  onAdd: addBlock,
40562
- children: /* @__PURE__ */ jsx83(
40808
+ children: /* @__PURE__ */ jsx84(
40563
40809
  WysiwygEditor,
40564
40810
  {
40565
40811
  submitOnEnter,
@@ -40576,8 +40822,8 @@ ${snippet}` : snippet);
40576
40822
  },
40577
40823
  "wysiwyg-frame"
40578
40824
  ),
40579
- isCardMode && inlinePreviewVisible && /* @__PURE__ */ jsx83(BlockPreviewPanel, { basePath }, "block-preview"),
40580
- !isCardMode && inlinePreviewVisible && /* @__PURE__ */ jsx83(
40825
+ isCardMode && inlinePreviewVisible && /* @__PURE__ */ jsx84(BlockPreviewPanel, { basePath }, "block-preview"),
40826
+ !isCardMode && inlinePreviewVisible && /* @__PURE__ */ jsx84(
40581
40827
  InlinePreviewGutter,
40582
40828
  {
40583
40829
  width: inlinePreviewWidth,
@@ -40587,7 +40833,7 @@ ${snippet}` : snippet);
40587
40833
  "inline"
40588
40834
  )
40589
40835
  ] }, "wysiwyg-shell"),
40590
- isMarkdownMode && isPreview && /* @__PURE__ */ jsx83(
40836
+ isMarkdownMode && isPreview && /* @__PURE__ */ jsx84(
40591
40837
  PreviewPanel,
40592
40838
  {
40593
40839
  basePath,
@@ -40600,7 +40846,7 @@ ${snippet}` : snippet);
40600
40846
  ]
40601
40847
  }
40602
40848
  ),
40603
- isTimelineMode && timelineVideoVisible && /* @__PURE__ */ jsx83(
40849
+ isTimelineMode && timelineVideoVisible && /* @__PURE__ */ jsx84(
40604
40850
  TimelineVideoPanel,
40605
40851
  {
40606
40852
  schedule: timelineVideoSchedule,
@@ -40610,7 +40856,7 @@ ${snippet}` : snippet);
40610
40856
  onClose: () => setTimelineVideoVisible(false)
40611
40857
  }
40612
40858
  ),
40613
- isTimelineMode && timelineCompositionVisible && /* @__PURE__ */ jsx83(
40859
+ isTimelineMode && timelineCompositionVisible && /* @__PURE__ */ jsx84(
40614
40860
  TimelineCompositionPanel,
40615
40861
  {
40616
40862
  doc,
@@ -40620,7 +40866,7 @@ ${snippet}` : snippet);
40620
40866
  onClose: () => setTimelineCompositionVisible(false)
40621
40867
  }
40622
40868
  ),
40623
- isMarkdownMode && showFiles && /* @__PURE__ */ jsx83(
40869
+ isMarkdownMode && showFiles && /* @__PURE__ */ jsx84(
40624
40870
  MediaBin,
40625
40871
  {
40626
40872
  mediaProvider,
@@ -40636,9 +40882,9 @@ ${snippet}` : snippet);
40636
40882
  highlightPath: filesFocusPath
40637
40883
  }
40638
40884
  ),
40639
- isMarkdownMode && /* @__PURE__ */ jsx83(ProofingPanel, {}),
40640
- isMarkdownMode && /* @__PURE__ */ jsx83(ThemeDesignerDock, {}),
40641
- 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(
40642
40888
  DropZoneOverlay,
40643
40889
  {
40644
40890
  dragContentType,
@@ -40649,7 +40895,7 @@ ${snippet}` : snippet);
40649
40895
  ]
40650
40896
  }
40651
40897
  ),
40652
- isTimelineMode && /* @__PURE__ */ jsx83(
40898
+ isTimelineMode && /* @__PURE__ */ jsx84(
40653
40899
  TimelineToolbar,
40654
40900
  {
40655
40901
  literalVideoVisible: timelineVideoVisible,
@@ -40660,7 +40906,7 @@ ${snippet}` : snippet);
40660
40906
  onToggleComposition: () => setTimelineCompositionVisible((visible) => !visible)
40661
40907
  }
40662
40908
  ),
40663
- isTimelineMode && /* @__PURE__ */ jsx83(
40909
+ isTimelineMode && /* @__PURE__ */ jsx84(
40664
40910
  TimelineTrack,
40665
40911
  {
40666
40912
  doc: timelineDoc,
@@ -40669,8 +40915,8 @@ ${snippet}` : snippet);
40669
40915
  basePath
40670
40916
  }
40671
40917
  ),
40672
- statusBarVisible && !isImageMode && /* @__PURE__ */ jsx83(StatusBar, { slotRight: statusBarSlotRight }),
40673
- isMarkdownMode && allowRecording && mediaProvider && /* @__PURE__ */ jsx83(
40918
+ statusBarVisible && !isImageMode && /* @__PURE__ */ jsx84(StatusBar, { slotRight: statusBarSlotRight }),
40919
+ isMarkdownMode && allowRecording && mediaProvider && /* @__PURE__ */ jsx84(
40674
40920
  RecorderEntry,
40675
40921
  {
40676
40922
  open: mediaBinRecorderOpen,
@@ -40683,8 +40929,8 @@ ${snippet}` : snippet);
40683
40929
  )
40684
40930
  }
40685
40931
  ) }),
40686
- /* @__PURE__ */ jsx83(TooltipLayer, {}),
40687
- imageEditTarget !== null && mediaProvider && /* @__PURE__ */ jsx83(
40932
+ /* @__PURE__ */ jsx84(TooltipLayer, {}),
40933
+ imageEditTarget !== null && mediaProvider && /* @__PURE__ */ jsx84(
40688
40934
  ImageEditModal,
40689
40935
  {
40690
40936
  relativePath: imageEditTarget,
@@ -40703,7 +40949,7 @@ ${snippet}` : snippet);
40703
40949
  ]
40704
40950
  }
40705
40951
  );
40706
- return /* @__PURE__ */ jsx83(EditorContextMenuProvider, { rootRef: shellRef, readOnly, children: shell });
40952
+ return /* @__PURE__ */ jsx84(EditorContextMenuProvider, { rootRef: shellRef, readOnly, children: shell });
40707
40953
  }
40708
40954
  function ImageEditModal({
40709
40955
  relativePath,
@@ -40720,7 +40966,7 @@ function ImageEditModal({
40720
40966
  useModalDialog({ rootRef: modalRef, dialogRef: surfaceRef, onClose });
40721
40967
  const extension = relativePath.split(/[?#]/, 1)[0]?.split(".").pop()?.toLowerCase();
40722
40968
  const saveFormat = extension === "png" ? "png" : extension === "jpg" || extension === "jpeg" ? "jpeg" : extension === "webp" ? "webp" : null;
40723
- const sidecar = useMemo55(() => {
40969
+ const sidecar = useMemo56(() => {
40724
40970
  const sanitized = relativePath.replace(/[^a-zA-Z0-9._-]+/g, "_");
40725
40971
  let hash = 2166136261;
40726
40972
  for (let i = 0; i < relativePath.length; i++) {
@@ -40731,9 +40977,9 @@ function ImageEditModal({
40731
40977
  const parent = container ?? new MemoryContentContainer();
40732
40978
  return scopeContainer(parent, `.imageEdits/${scopedName}`);
40733
40979
  }, [container, relativePath]);
40734
- const [initialSrc, setInitialSrc] = useState74(null);
40735
- const [resolveError, setResolveError] = useState74(null);
40736
- useEffect63(() => {
40980
+ const [initialSrc, setInitialSrc] = useState75(null);
40981
+ const [resolveError, setResolveError] = useState75(null);
40982
+ useEffect64(() => {
40737
40983
  let cancelled = false;
40738
40984
  setInitialSrc(null);
40739
40985
  setResolveError(null);
@@ -40763,7 +41009,7 @@ function ImageEditModal({
40763
41009
  },
40764
41010
  [mediaProvider, relativePath, onSaved]
40765
41011
  );
40766
- return /* @__PURE__ */ jsx83(
41012
+ return /* @__PURE__ */ jsx84(
40767
41013
  "div",
40768
41014
  {
40769
41015
  ref: modalRef,
@@ -40777,9 +41023,9 @@ function ImageEditModal({
40777
41023
  },
40778
41024
  children: /* @__PURE__ */ jsxs66("div", { ref: surfaceRef, className: "squisq-image-edit-modal__surface", children: [
40779
41025
  /* @__PURE__ */ jsxs66("header", { className: "squisq-image-edit-modal__header", children: [
40780
- /* @__PURE__ */ jsx83("span", { className: "squisq-image-edit-modal__title", children: "Edit image" }),
40781
- /* @__PURE__ */ jsx83("span", { className: "squisq-image-edit-modal__path", children: relativePath }),
40782
- /* @__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(
40783
41029
  "button",
40784
41030
  {
40785
41031
  type: "button",
@@ -40791,10 +41037,10 @@ function ImageEditModal({
40791
41037
  }
40792
41038
  )
40793
41039
  ] }),
40794
- /* @__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: [
40795
41041
  "Failed to load image: ",
40796
41042
  resolveError
40797
- ] }) : !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(
40798
41044
  ImageEditor,
40799
41045
  {
40800
41046
  filesContainer: sidecar,