@beyondwork/docx-react-component 1.0.59 → 1.0.61
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +33 -44
- package/src/api/public-types.ts +43 -0
- package/src/core/state/editor-state.ts +2 -0
- package/src/io/docx-session.ts +167 -8
- package/src/io/export/serialize-footnotes.ts +36 -5
- package/src/io/export/serialize-headers-footers.ts +7 -0
- package/src/io/export/serialize-main-document.ts +25 -18
- package/src/io/export/serialize-paragraph-formatting.ts +6 -0
- package/src/io/export/serialize-settings.ts +130 -3
- package/src/io/normalize/normalize-text.ts +8 -4
- package/src/io/ooxml/parse-footnotes.ts +11 -0
- package/src/io/ooxml/parse-headers-footers.ts +117 -42
- package/src/io/ooxml/parse-main-document.ts +20 -8
- package/src/io/ooxml/parse-paragraph-formatting.ts +25 -1
- package/src/io/ooxml/parse-settings.ts +91 -1
- package/src/io/ooxml/workflow-payload.ts +6 -1
- package/src/model/canonical-document.ts +36 -2
- package/src/model/snapshot.ts +2 -0
- package/src/runtime/diagnostics/build-diagnostic.ts +2 -0
- package/src/runtime/diagnostics/code-metadata-table.ts +9 -0
- package/src/runtime/document-runtime.ts +770 -21
- package/src/runtime/footnote-resolver.ts +32 -8
- package/src/runtime/layout/layout-engine-version.ts +7 -1
- package/src/runtime/layout/measurement-backend-canvas.ts +1 -1
- package/src/runtime/layout/measurement-backend-empirical.ts +1 -1
- package/src/runtime/layout/paginated-layout-engine.ts +41 -8
- package/src/runtime/layout/resolved-formatting-document.ts +11 -9
- package/src/runtime/layout/resolved-formatting-state.ts +4 -0
- package/src/runtime/numbering-prefix.ts +26 -2
- package/src/runtime/query-scopes.ts +103 -2
- package/src/runtime/surface-projection.ts +75 -14
- package/src/runtime/table-schema.ts +26 -0
- package/src/ui/WordReviewEditor.tsx +25 -0
- package/src/ui/editor-runtime-boundary.ts +1 -0
- package/src/ui/editor-shell-view.tsx +8 -0
- package/src/ui-tailwind/chrome/tw-runtime-repl-dialog.tsx +514 -0
- package/src/ui-tailwind/editor-surface/pm-schema.ts +14 -0
- package/src/ui-tailwind/editor-surface/pm-state-from-snapshot.ts +55 -6
- package/src/ui-tailwind/editor-surface/surface-build-keys.ts +2 -0
- package/src/ui-tailwind/editor-surface/tw-page-block-view.tsx +4 -0
- package/src/ui-tailwind/editor-surface/tw-prosemirror-surface.tsx +9 -1
- package/src/ui-tailwind/editor-surface/tw-table-node-view.tsx +16 -0
- package/src/ui-tailwind/page-stack/floating-image-overlay-model.ts +319 -0
- package/src/ui-tailwind/page-stack/tw-floating-image-layer.tsx +248 -0
- package/src/ui-tailwind/page-stack/tw-region-block-renderer.tsx +4 -0
- package/src/ui-tailwind/tw-review-workspace.tsx +54 -3
|
@@ -32,6 +32,7 @@ import type {
|
|
|
32
32
|
BorderSpec,
|
|
33
33
|
TableBorders,
|
|
34
34
|
TableCellBorders,
|
|
35
|
+
TableCellMargins,
|
|
35
36
|
TableNode,
|
|
36
37
|
TextMark,
|
|
37
38
|
DrawingFrameNode,
|
|
@@ -491,6 +492,10 @@ function createTableBlock(
|
|
|
491
492
|
.map((region) => `band-${region}`)
|
|
492
493
|
.join(" ")
|
|
493
494
|
: null;
|
|
495
|
+
const cellPadding = resolveEffectiveCellMargins(
|
|
496
|
+
cell.margins,
|
|
497
|
+
resolvedTable.table?.cellMargins,
|
|
498
|
+
);
|
|
494
499
|
cells.push({
|
|
495
500
|
gridSpan: cell.gridSpan ?? 1,
|
|
496
501
|
verticalMerge: cell.verticalMerge ?? null,
|
|
@@ -502,6 +507,10 @@ function createTableBlock(
|
|
|
502
507
|
...(cellBorders.borderRight ? { borderRight: cellBorders.borderRight } : {}),
|
|
503
508
|
...(cellBorders.borderBottom ? { borderBottom: cellBorders.borderBottom } : {}),
|
|
504
509
|
...(cellBorders.borderLeft ? { borderLeft: cellBorders.borderLeft } : {}),
|
|
510
|
+
...(cellPadding.top !== undefined ? { paddingTop: cellPadding.top } : {}),
|
|
511
|
+
...(cellPadding.right !== undefined ? { paddingRight: cellPadding.right } : {}),
|
|
512
|
+
...(cellPadding.bottom !== undefined ? { paddingBottom: cellPadding.bottom } : {}),
|
|
513
|
+
...(cellPadding.left !== undefined ? { paddingLeft: cellPadding.left } : {}),
|
|
505
514
|
// R3.a Phase 2: per-cell text-flow direction copied from canonical
|
|
506
515
|
// TableCellNode. Node-view renders `tbRl` / `btLr` as CSS writing-mode.
|
|
507
516
|
...(cell.textDirection ? { textDirection: cell.textDirection } : {}),
|
|
@@ -626,6 +635,18 @@ function computeTableRowSpans(table: TableNode): Map<string, number> {
|
|
|
626
635
|
return rowSpans;
|
|
627
636
|
}
|
|
628
637
|
|
|
638
|
+
function resolveEffectiveCellMargins(
|
|
639
|
+
direct: TableCellMargins | undefined,
|
|
640
|
+
tableDefault: TableCellMargins | undefined,
|
|
641
|
+
): TableCellMargins {
|
|
642
|
+
return {
|
|
643
|
+
...(direct?.top !== undefined ? { top: direct.top } : tableDefault?.top !== undefined ? { top: tableDefault.top } : {}),
|
|
644
|
+
...(direct?.right !== undefined ? { right: direct.right } : tableDefault?.right !== undefined ? { right: tableDefault.right } : {}),
|
|
645
|
+
...(direct?.bottom !== undefined ? { bottom: direct.bottom } : tableDefault?.bottom !== undefined ? { bottom: tableDefault.bottom } : {}),
|
|
646
|
+
...(direct?.left !== undefined ? { left: direct.left } : tableDefault?.left !== undefined ? { left: tableDefault.left } : {}),
|
|
647
|
+
};
|
|
648
|
+
}
|
|
649
|
+
|
|
629
650
|
/**
|
|
630
651
|
* SOW gap G3 — resolve the final paintable fill for a cell `w:shd`. Precedence
|
|
631
652
|
* matches Word: a concrete `w:fill` (non-"auto") wins; otherwise the theme
|
|
@@ -660,6 +681,42 @@ function resolveCellShadingFill(
|
|
|
660
681
|
return resolved.startsWith("#") ? resolved.slice(1) : resolved;
|
|
661
682
|
}
|
|
662
683
|
|
|
684
|
+
function resolveSurfaceParagraphShading(
|
|
685
|
+
shading: ParagraphNode["shading"],
|
|
686
|
+
themeResolver: ThemeColorResolver | undefined,
|
|
687
|
+
): NonNullable<Extract<SurfaceBlockSnapshot, { kind: "paragraph" }>["shading"]> {
|
|
688
|
+
const resolvedFill = resolveCellShadingFill(shading, themeResolver);
|
|
689
|
+
return {
|
|
690
|
+
...(shading?.val ? { val: shading.val } : {}),
|
|
691
|
+
...(shading?.color ? { color: shading.color } : {}),
|
|
692
|
+
...(resolvedFill !== undefined
|
|
693
|
+
? { fill: resolvedFill }
|
|
694
|
+
: shading?.fill !== undefined
|
|
695
|
+
? { fill: shading.fill }
|
|
696
|
+
: {}),
|
|
697
|
+
};
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
function resolveSurfaceParagraphFormatting(
|
|
701
|
+
formatting: CanonicalParagraphFormatting,
|
|
702
|
+
themeResolver: ThemeColorResolver | undefined,
|
|
703
|
+
): CanonicalParagraphFormatting {
|
|
704
|
+
if (!formatting.shading) {
|
|
705
|
+
return formatting;
|
|
706
|
+
}
|
|
707
|
+
const resolvedFill = resolveCellShadingFill(formatting.shading, themeResolver);
|
|
708
|
+
if (resolvedFill === undefined && formatting.shading.fill === undefined) {
|
|
709
|
+
return formatting;
|
|
710
|
+
}
|
|
711
|
+
return {
|
|
712
|
+
...formatting,
|
|
713
|
+
shading: {
|
|
714
|
+
...formatting.shading,
|
|
715
|
+
...(resolvedFill !== undefined ? { fill: resolvedFill } : {}),
|
|
716
|
+
},
|
|
717
|
+
};
|
|
718
|
+
}
|
|
719
|
+
|
|
663
720
|
/**
|
|
664
721
|
* SOW gap G1 — derive relative column widths (percent 0–100, sum 100)
|
|
665
722
|
* from the canonical `gridColumns` (twips). Only populated when the table
|
|
@@ -842,6 +899,9 @@ function createParagraphBlock(
|
|
|
842
899
|
nextCursor: number;
|
|
843
900
|
lockedFragmentIds: string[];
|
|
844
901
|
} {
|
|
902
|
+
const themeResolver = document.subParts?.canonicalTheme
|
|
903
|
+
? new ThemeColorResolver(document.subParts.canonicalTheme)
|
|
904
|
+
: undefined;
|
|
845
905
|
// L7 Phase 2.9 — viewport bail. When the paragraph is outside the
|
|
846
906
|
// viewport, the returned block is discarded (the outer caller in
|
|
847
907
|
// `createEditorSurfaceSnapshot` replaces it with a placeholder-culled
|
|
@@ -871,6 +931,9 @@ function createParagraphBlock(
|
|
|
871
931
|
{ styleId: paragraph.styleId, direct: directParagraphFormatting },
|
|
872
932
|
stylesCatalog,
|
|
873
933
|
);
|
|
934
|
+
const surfaceResolvedParagraphFormatting = resolvedParagraphFormatting
|
|
935
|
+
? resolveSurfaceParagraphFormatting(resolvedParagraphFormatting, themeResolver)
|
|
936
|
+
: undefined;
|
|
874
937
|
|
|
875
938
|
// Task 11: compute cascaded marker run formatting (expensive).
|
|
876
939
|
const markerRunProperties =
|
|
@@ -905,8 +968,8 @@ function createParagraphBlock(
|
|
|
905
968
|
},
|
|
906
969
|
}
|
|
907
970
|
: {}),
|
|
908
|
-
...(
|
|
909
|
-
? { resolvedParagraphFormatting }
|
|
971
|
+
...(surfaceResolvedParagraphFormatting && Object.keys(surfaceResolvedParagraphFormatting).length > 0
|
|
972
|
+
? { resolvedParagraphFormatting: surfaceResolvedParagraphFormatting }
|
|
910
973
|
: {}),
|
|
911
974
|
...(paragraph.alignment ? { alignment: paragraph.alignment } : {}),
|
|
912
975
|
...(paragraph.spacing ? { spacing: paragraph.spacing } : {}),
|
|
@@ -915,28 +978,26 @@ function createParagraphBlock(
|
|
|
915
978
|
: {}),
|
|
916
979
|
...(paragraph.indentation ? { indentation: paragraph.indentation } : {}),
|
|
917
980
|
...(paragraph.borders ? { borders: paragraph.borders } : {}),
|
|
918
|
-
...(paragraph.shading
|
|
981
|
+
...(paragraph.shading
|
|
982
|
+
? { shading: resolveSurfaceParagraphShading(paragraph.shading, themeResolver) }
|
|
983
|
+
: {}),
|
|
919
984
|
...(paragraph.tabStops && paragraph.tabStops.length > 0
|
|
920
985
|
? { tabStops: paragraph.tabStops.map((tabStop) => toSurfaceTabStop(tabStop)) }
|
|
921
986
|
: {}),
|
|
922
|
-
...(paragraph.keepNext ? { keepNext:
|
|
923
|
-
...(paragraph.keepLines ? { keepLines:
|
|
924
|
-
...(paragraph.pageBreakBefore ? { pageBreakBefore:
|
|
987
|
+
...(paragraph.keepNext !== undefined ? { keepNext: paragraph.keepNext } : {}),
|
|
988
|
+
...(paragraph.keepLines !== undefined ? { keepLines: paragraph.keepLines } : {}),
|
|
989
|
+
...(paragraph.pageBreakBefore !== undefined ? { pageBreakBefore: paragraph.pageBreakBefore } : {}),
|
|
925
990
|
...(paragraph.widowControl !== undefined ? { widowControl: paragraph.widowControl } : {}),
|
|
926
991
|
...(paragraph.outlineLevel !== undefined ? { outlineLevel: paragraph.outlineLevel } : {}),
|
|
927
|
-
...(paragraph.bidi ? { bidi:
|
|
928
|
-
...(paragraph.suppressLineNumbers
|
|
992
|
+
...(paragraph.bidi !== undefined ? { bidi: paragraph.bidi } : {}),
|
|
993
|
+
...(paragraph.suppressLineNumbers !== undefined
|
|
994
|
+
? { suppressLineNumbers: paragraph.suppressLineNumbers }
|
|
995
|
+
: {}),
|
|
929
996
|
segments: [],
|
|
930
997
|
};
|
|
931
998
|
const lockedFragmentIds: string[] = [];
|
|
932
999
|
let cursor = start;
|
|
933
1000
|
const children = Array.isArray(paragraph.children) ? paragraph.children : [];
|
|
934
|
-
// Build once per paragraph block — ThemeColorResolver is a thin wrapper
|
|
935
|
-
// around CanonicalTheme that applies clrMap remapping. Constructed here so
|
|
936
|
-
// it is not recreated on every text segment (inner hot loop).
|
|
937
|
-
const themeResolver = document.subParts?.canonicalTheme
|
|
938
|
-
? new ThemeColorResolver(document.subParts.canonicalTheme)
|
|
939
|
-
: undefined;
|
|
940
1001
|
|
|
941
1002
|
for (const child of children) {
|
|
942
1003
|
const result = appendInlineSegments(
|
|
@@ -42,6 +42,10 @@ type TableCellAttrs = {
|
|
|
42
42
|
borderRight?: string | null;
|
|
43
43
|
borderBottom?: string | null;
|
|
44
44
|
borderLeft?: string | null;
|
|
45
|
+
paddingTop?: number | null;
|
|
46
|
+
paddingRight?: number | null;
|
|
47
|
+
paddingBottom?: number | null;
|
|
48
|
+
paddingLeft?: number | null;
|
|
45
49
|
/** R3.a Phase 2 — per-cell text-flow direction. */
|
|
46
50
|
textDirection?: "lrTb" | "tbRl" | "btLr" | null;
|
|
47
51
|
bandClasses?: string | null;
|
|
@@ -83,6 +87,12 @@ function getCellAttrs(dom: HTMLElement): TableCellAttrs {
|
|
|
83
87
|
const backgroundColor =
|
|
84
88
|
dom.getAttribute("data-cell-background") ?? dom.style.backgroundColor ?? null;
|
|
85
89
|
const verticalAlign = dom.getAttribute("data-vertical-align") as "top" | "center" | "bottom" | null;
|
|
90
|
+
const readPadding = (name: string): number | null => {
|
|
91
|
+
const raw = dom.getAttribute(name);
|
|
92
|
+
if (!raw) return null;
|
|
93
|
+
const parsed = Number.parseInt(raw, 10);
|
|
94
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
95
|
+
};
|
|
86
96
|
|
|
87
97
|
return {
|
|
88
98
|
colspan,
|
|
@@ -99,6 +109,10 @@ function getCellAttrs(dom: HTMLElement): TableCellAttrs {
|
|
|
99
109
|
borderRight: dom.getAttribute("data-border-right"),
|
|
100
110
|
borderBottom: dom.getAttribute("data-border-bottom"),
|
|
101
111
|
borderLeft: dom.getAttribute("data-border-left"),
|
|
112
|
+
paddingTop: readPadding("data-cell-padding-top"),
|
|
113
|
+
paddingRight: readPadding("data-cell-padding-right"),
|
|
114
|
+
paddingBottom: readPadding("data-cell-padding-bottom"),
|
|
115
|
+
paddingLeft: readPadding("data-cell-padding-left"),
|
|
102
116
|
bandClasses: dom.getAttribute("data-band-classes"),
|
|
103
117
|
};
|
|
104
118
|
}
|
|
@@ -133,6 +147,10 @@ function setCellDomAttrs(nodeAttrs: TableCellAttrs, className: string): Record<s
|
|
|
133
147
|
if (nodeAttrs.borderRight) attrs["data-border-right"] = nodeAttrs.borderRight;
|
|
134
148
|
if (nodeAttrs.borderBottom) attrs["data-border-bottom"] = nodeAttrs.borderBottom;
|
|
135
149
|
if (nodeAttrs.borderLeft) attrs["data-border-left"] = nodeAttrs.borderLeft;
|
|
150
|
+
if (typeof nodeAttrs.paddingTop === "number") attrs["data-cell-padding-top"] = String(nodeAttrs.paddingTop);
|
|
151
|
+
if (typeof nodeAttrs.paddingRight === "number") attrs["data-cell-padding-right"] = String(nodeAttrs.paddingRight);
|
|
152
|
+
if (typeof nodeAttrs.paddingBottom === "number") attrs["data-cell-padding-bottom"] = String(nodeAttrs.paddingBottom);
|
|
153
|
+
if (typeof nodeAttrs.paddingLeft === "number") attrs["data-cell-padding-left"] = String(nodeAttrs.paddingLeft);
|
|
136
154
|
if (nodeAttrs.bandClasses) {
|
|
137
155
|
attrs["data-band-classes"] = nodeAttrs.bandClasses;
|
|
138
156
|
// Concatenate band classes onto the base `class` so Tailwind's @apply resolves at parse time.
|
|
@@ -151,6 +169,10 @@ function setCellDomAttrs(nodeAttrs: TableCellAttrs, className: string): Record<s
|
|
|
151
169
|
if (bBottom) styles.push(`border-bottom: ${bBottom}`);
|
|
152
170
|
const bLeft = safeCssBorder(nodeAttrs.borderLeft);
|
|
153
171
|
if (bLeft) styles.push(`border-left: ${bLeft}`);
|
|
172
|
+
if (typeof nodeAttrs.paddingTop === "number") styles.push(`padding-top: ${nodeAttrs.paddingTop / 20}pt`);
|
|
173
|
+
if (typeof nodeAttrs.paddingRight === "number") styles.push(`padding-right: ${nodeAttrs.paddingRight / 20}pt`);
|
|
174
|
+
if (typeof nodeAttrs.paddingBottom === "number") styles.push(`padding-bottom: ${nodeAttrs.paddingBottom / 20}pt`);
|
|
175
|
+
if (typeof nodeAttrs.paddingLeft === "number") styles.push(`padding-left: ${nodeAttrs.paddingLeft / 20}pt`);
|
|
154
176
|
if (styles.length > 0) attrs.style = styles.join("; ");
|
|
155
177
|
|
|
156
178
|
return attrs;
|
|
@@ -190,6 +212,10 @@ const tableCellSpecAttrs = {
|
|
|
190
212
|
borderRight: { default: null },
|
|
191
213
|
borderBottom: { default: null },
|
|
192
214
|
borderLeft: { default: null },
|
|
215
|
+
paddingTop: { default: null },
|
|
216
|
+
paddingRight: { default: null },
|
|
217
|
+
paddingBottom: { default: null },
|
|
218
|
+
paddingLeft: { default: null },
|
|
193
219
|
/**
|
|
194
220
|
* R3.a Phase 2 — per-cell text-flow direction copied from
|
|
195
221
|
* `TableCellNode.textDirection` ("lrTb" | "tbRl" | "btLr"). Node-view maps
|
|
@@ -218,6 +218,7 @@ import {
|
|
|
218
218
|
resolveChromePreset,
|
|
219
219
|
resolveChromeVisibilityForPreset,
|
|
220
220
|
} from "../ui-tailwind/chrome/chrome-preset-model.ts";
|
|
221
|
+
import { TwRuntimeReplDialog } from "../ui-tailwind/chrome/tw-runtime-repl-dialog.tsx";
|
|
221
222
|
import { createRuntimeCollabSync } from "../runtime/collab/runtime-collab-sync.ts";
|
|
222
223
|
import {
|
|
223
224
|
clearLocalCursorState,
|
|
@@ -689,6 +690,7 @@ export function __createWordReviewEditorRefBridge(
|
|
|
689
690
|
color,
|
|
690
691
|
});
|
|
691
692
|
},
|
|
693
|
+
clearHighlight: (options) => runtime.clearHighlight(options),
|
|
692
694
|
setAlignment: (alignment) => {
|
|
693
695
|
applyRuntimeFormattingOperation(runtime, {
|
|
694
696
|
type: "set-alignment",
|
|
@@ -1237,6 +1239,7 @@ export const WordReviewEditor = forwardRef<WordReviewEditorRef, WordReviewEditor
|
|
|
1237
1239
|
const surfaceRef = useRef<TwProseMirrorSurfaceRef | null>(null);
|
|
1238
1240
|
const selectionToolbarElementRef = useRef<HTMLDivElement | null>(null);
|
|
1239
1241
|
const shellRef = useRef<HTMLDivElement | null>(null);
|
|
1242
|
+
const editorRefForRepl = useRef<WordReviewEditorRef | null>(null);
|
|
1240
1243
|
const lastSelectionToolbarKeyRef = useRef<string | null>(null);
|
|
1241
1244
|
const lastAnnouncedErrorIdRef = useRef<string | null>(null);
|
|
1242
1245
|
const scopeMetadataResolverRef = useRef<ScopeMetadataResolver | null>(null);
|
|
@@ -1817,6 +1820,7 @@ export const WordReviewEditor = forwardRef<WordReviewEditorRef, WordReviewEditor
|
|
|
1817
1820
|
color,
|
|
1818
1821
|
});
|
|
1819
1822
|
},
|
|
1823
|
+
clearHighlight: (options) => activeRuntime.clearHighlight(options),
|
|
1820
1824
|
setAlignment: (alignment) => {
|
|
1821
1825
|
applyRuntimeFormattingOperation(activeRuntime, {
|
|
1822
1826
|
type: "set-alignment",
|
|
@@ -2304,6 +2308,7 @@ export const WordReviewEditor = forwardRef<WordReviewEditorRef, WordReviewEditor
|
|
|
2304
2308
|
...projections,
|
|
2305
2309
|
}) as WordReviewEditorRef;
|
|
2306
2310
|
refHolder.current = refValue;
|
|
2311
|
+
editorRefForRepl.current = refValue;
|
|
2307
2312
|
return refValue;
|
|
2308
2313
|
},
|
|
2309
2314
|
[
|
|
@@ -3368,6 +3373,7 @@ export const WordReviewEditor = forwardRef<WordReviewEditorRef, WordReviewEditor
|
|
|
3368
3373
|
);
|
|
3369
3374
|
|
|
3370
3375
|
return (
|
|
3376
|
+
<>
|
|
3371
3377
|
<EditorShellView
|
|
3372
3378
|
shellRef={shellRef}
|
|
3373
3379
|
documentId={documentId}
|
|
@@ -3486,6 +3492,23 @@ export const WordReviewEditor = forwardRef<WordReviewEditorRef, WordReviewEditor
|
|
|
3486
3492
|
onScopeRejectSuggestionGroup={(payload) => {
|
|
3487
3493
|
applySuggestionGroupAction(activeRuntime, payload.groupId, "reject");
|
|
3488
3494
|
}}
|
|
3495
|
+
mediaPreviews={mediaPreviews}
|
|
3496
|
+
onActivateFloatingImage={(payload) => {
|
|
3497
|
+
activeRuntime.focus();
|
|
3498
|
+
applyRuntimeSelection(activeRuntime, {
|
|
3499
|
+
anchor: payload.from,
|
|
3500
|
+
head: payload.from,
|
|
3501
|
+
isCollapsed: true,
|
|
3502
|
+
activeRange: {
|
|
3503
|
+
kind: "node",
|
|
3504
|
+
at: payload.from,
|
|
3505
|
+
assoc: 1,
|
|
3506
|
+
},
|
|
3507
|
+
...(payload.storyTarget.kind === "main"
|
|
3508
|
+
? {}
|
|
3509
|
+
: { storyTarget: payload.storyTarget }),
|
|
3510
|
+
});
|
|
3511
|
+
}}
|
|
3489
3512
|
onDeselectObject={() => activeRuntime.deselectObject()}
|
|
3490
3513
|
onScopeAskAgent={(payload) => {
|
|
3491
3514
|
// Resolve the scope's anchor + story from the facet's card
|
|
@@ -3522,6 +3545,8 @@ export const WordReviewEditor = forwardRef<WordReviewEditorRef, WordReviewEditor
|
|
|
3522
3545
|
onEventRef.current?.(eventPayload);
|
|
3523
3546
|
}}
|
|
3524
3547
|
/>
|
|
3548
|
+
<TwRuntimeReplDialog runtime={activeRuntime} editorRef={editorRefForRepl} />
|
|
3549
|
+
</>
|
|
3525
3550
|
);
|
|
3526
3551
|
},
|
|
3527
3552
|
);
|
|
@@ -1071,6 +1071,7 @@ function createLoadingRuntimeBridge(input: {
|
|
|
1071
1071
|
rejectChange: () => undefined,
|
|
1072
1072
|
acceptAllChanges: () => undefined,
|
|
1073
1073
|
rejectAllChanges: () => undefined,
|
|
1074
|
+
clearHighlight: () => undefined,
|
|
1074
1075
|
openStory: () => false,
|
|
1075
1076
|
closeStory: () => undefined,
|
|
1076
1077
|
getActiveStory: () => input.snapshot.activeStory,
|
|
@@ -27,6 +27,7 @@ import type { EditorCommandBag } from "./editor-command-bag.ts";
|
|
|
27
27
|
import type { ReviewRailTab } from "../ui-tailwind/review/tw-review-rail.tsx";
|
|
28
28
|
import { TwReviewWorkspace } from "../ui-tailwind/tw-review-workspace.tsx";
|
|
29
29
|
import type { EditorViewStateSnapshot } from "../api/public-types.ts";
|
|
30
|
+
import type { MediaPreviewDescriptor } from "../ui-tailwind/editor-surface/pm-state-from-snapshot.ts";
|
|
30
31
|
|
|
31
32
|
export interface EditorShellViewProps {
|
|
32
33
|
shellRef: React.RefObject<HTMLDivElement | null>;
|
|
@@ -129,6 +130,13 @@ export interface EditorShellViewProps {
|
|
|
129
130
|
onScopeAskAgent?: (payload: { scopeId: string }) => void;
|
|
130
131
|
/** N6 — deselects the currently grabbed object; wired to runtime.deselectObject(). */
|
|
131
132
|
onDeselectObject?: () => void;
|
|
133
|
+
mediaPreviews?: Record<string, MediaPreviewDescriptor>;
|
|
134
|
+
onActivateFloatingImage?: (payload: {
|
|
135
|
+
mediaId: string;
|
|
136
|
+
from: number;
|
|
137
|
+
to: number;
|
|
138
|
+
storyTarget: import("../api/public-types.ts").EditorStoryTarget;
|
|
139
|
+
}) => void;
|
|
132
140
|
}
|
|
133
141
|
|
|
134
142
|
export function EditorShellView(props: EditorShellViewProps) {
|