@beyondwork/docx-react-component 1.0.36 → 1.0.38
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/README.md +103 -13
- package/package.json +1 -1
- package/src/api/package-version.ts +13 -0
- package/src/api/public-types.ts +402 -1
- package/src/core/commands/index.ts +18 -1
- package/src/core/commands/section-layout-commands.ts +58 -0
- package/src/core/commands/table-grid.ts +431 -0
- package/src/core/commands/table-structure-commands.ts +815 -55
- package/src/core/selection/mapping.ts +6 -0
- package/src/io/docx-session.ts +24 -9
- package/src/io/export/build-app-properties-xml.ts +88 -0
- package/src/io/export/serialize-comments.ts +6 -1
- package/src/io/export/serialize-footnotes.ts +10 -9
- package/src/io/export/serialize-headers-footers.ts +11 -10
- package/src/io/export/serialize-main-document.ts +328 -50
- package/src/io/export/serialize-numbering.ts +114 -24
- package/src/io/export/serialize-tables.ts +87 -11
- package/src/io/export/table-properties-xml.ts +174 -20
- package/src/io/export/twip.ts +66 -0
- package/src/io/normalize/normalize-text.ts +20 -0
- package/src/io/ooxml/parse-footnotes.ts +62 -1
- package/src/io/ooxml/parse-headers-footers.ts +62 -1
- package/src/io/ooxml/parse-main-document.ts +158 -1
- package/src/io/ooxml/parse-tables.ts +249 -0
- package/src/legal/bookmarks.ts +78 -0
- package/src/model/canonical-document.ts +45 -0
- package/src/review/store/scope-tag-diff.ts +130 -0
- package/src/runtime/document-layout.ts +4 -2
- package/src/runtime/document-navigation.ts +2 -306
- package/src/runtime/document-runtime.ts +287 -11
- package/src/runtime/layout/default-page-format.ts +96 -0
- package/src/runtime/layout/docx-font-loader.ts +143 -0
- package/src/runtime/layout/index.ts +233 -0
- package/src/runtime/layout/inert-layout-facet.ts +59 -0
- package/src/runtime/layout/layout-engine-instance.ts +628 -0
- package/src/runtime/layout/layout-invalidation.ts +257 -0
- package/src/runtime/layout/layout-measurement-provider.ts +175 -0
- package/src/runtime/layout/margin-preset-catalog.ts +178 -0
- package/src/runtime/layout/measurement-backend-canvas.ts +307 -0
- package/src/runtime/layout/measurement-backend-empirical.ts +208 -0
- package/src/runtime/layout/page-format-catalog.ts +233 -0
- package/src/runtime/layout/page-fragment-mapper.ts +179 -0
- package/src/runtime/layout/page-graph.ts +452 -0
- package/src/runtime/layout/page-layout-snapshot-adapter.ts +70 -0
- package/src/runtime/layout/page-story-resolver.ts +195 -0
- package/src/runtime/layout/paginated-layout-engine.ts +921 -0
- package/src/runtime/layout/project-block-fragments.ts +91 -0
- package/src/runtime/layout/public-facet.ts +1398 -0
- package/src/runtime/layout/resolved-formatting-document.ts +317 -0
- package/src/runtime/layout/resolved-formatting-state.ts +430 -0
- package/src/runtime/layout/table-render-plan.ts +229 -0
- package/src/runtime/render/block-fragment-projection.ts +35 -0
- package/src/runtime/render/decoration-resolver.ts +189 -0
- package/src/runtime/render/index.ts +57 -0
- package/src/runtime/render/pending-op-delta-reader.ts +129 -0
- package/src/runtime/render/render-frame-types.ts +317 -0
- package/src/runtime/render/render-kernel.ts +755 -0
- package/src/runtime/scope-tag-registry.ts +95 -0
- package/src/runtime/surface-projection.ts +1 -0
- package/src/runtime/text-ack-range.ts +49 -0
- package/src/runtime/view-state.ts +67 -0
- package/src/runtime/workflow-markup.ts +1 -5
- package/src/runtime/workflow-rail-segments.ts +280 -0
- package/src/ui/WordReviewEditor.tsx +99 -15
- package/src/ui/editor-runtime-boundary.ts +10 -1
- package/src/ui/editor-shell-view.tsx +6 -0
- package/src/ui/editor-surface-controller.tsx +3 -0
- package/src/ui/headless/chrome-registry.ts +501 -0
- package/src/ui/headless/scoped-chrome-policy.ts +183 -0
- package/src/ui/headless/selection-tool-context.ts +2 -0
- package/src/ui/headless/selection-tool-resolver.ts +36 -17
- package/src/ui/headless/selection-tool-types.ts +10 -0
- package/src/ui-tailwind/chrome/chrome-preset-model.ts +23 -2
- package/src/ui-tailwind/chrome/role-action-sets.ts +74 -0
- package/src/ui-tailwind/chrome/tw-detach-handle.tsx +147 -0
- package/src/ui-tailwind/chrome/tw-selection-anchor-resolver.ts +163 -0
- package/src/ui-tailwind/chrome/tw-selection-tool-host.tsx +57 -92
- package/src/ui-tailwind/chrome/tw-selection-tool-placement.ts +149 -0
- package/src/ui-tailwind/chrome/tw-selection-toolbar.tsx +15 -4
- package/src/ui-tailwind/chrome/tw-table-context-toolbar.tsx +274 -138
- package/src/ui-tailwind/chrome-overlay/chrome-overlay-projector.ts +90 -0
- package/src/ui-tailwind/chrome-overlay/index.ts +22 -0
- package/src/ui-tailwind/chrome-overlay/tw-chrome-overlay.tsx +86 -0
- package/src/ui-tailwind/chrome-overlay/tw-scope-rail-layer.tsx +178 -0
- package/src/ui-tailwind/chrome-overlay/tw-workspace-view-switcher.tsx +95 -0
- package/src/ui-tailwind/editor-surface/fast-text-edit-lane.ts +337 -0
- package/src/ui-tailwind/editor-surface/local-edit-session-state.ts +100 -0
- package/src/ui-tailwind/editor-surface/perf-probe.ts +27 -1
- package/src/ui-tailwind/editor-surface/pm-command-bridge.ts +20 -2
- package/src/ui-tailwind/editor-surface/pm-decorations.ts +93 -23
- package/src/ui-tailwind/editor-surface/predicted-position-map.ts +78 -0
- package/src/ui-tailwind/editor-surface/predicted-tag-preflight.ts +63 -0
- package/src/ui-tailwind/editor-surface/predicted-tx-gate.ts +39 -0
- package/src/ui-tailwind/editor-surface/tw-prosemirror-surface.tsx +176 -6
- package/src/ui-tailwind/index.ts +33 -0
- package/src/ui-tailwind/review/tw-comment-sidebar.tsx +2 -2
- package/src/ui-tailwind/review/tw-rail-card.tsx +150 -0
- package/src/ui-tailwind/review/tw-review-rail-footer.tsx +52 -0
- package/src/ui-tailwind/review/tw-review-rail.tsx +166 -11
- package/src/ui-tailwind/review/tw-workflow-tab.tsx +108 -0
- package/src/ui-tailwind/theme/editor-theme.css +505 -144
- package/src/ui-tailwind/toolbar/tw-role-action-region.tsx +559 -0
- package/src/ui-tailwind/toolbar/tw-scope-posture-menu.tsx +182 -0
- package/src/ui-tailwind/toolbar/tw-shell-header.tsx +162 -0
- package/src/ui-tailwind/toolbar/tw-toolbar-icon-button.tsx +2 -2
- package/src/ui-tailwind/toolbar/tw-toolbar.tsx +304 -166
- package/src/ui-tailwind/tw-review-workspace.tsx +163 -2
|
@@ -48,6 +48,8 @@ import type {
|
|
|
48
48
|
StyleCatalogSnapshot,
|
|
49
49
|
SurfaceBlockSnapshot,
|
|
50
50
|
SurfaceInlineSegment,
|
|
51
|
+
TableOp,
|
|
52
|
+
TableOpResult,
|
|
51
53
|
TrackedChangeEntrySnapshot,
|
|
52
54
|
TocRefreshResult,
|
|
53
55
|
UpdateFieldsResult,
|
|
@@ -113,6 +115,7 @@ import {
|
|
|
113
115
|
import {
|
|
114
116
|
applyTableStructureOperation,
|
|
115
117
|
getTableStructureContext,
|
|
118
|
+
type TableStructureOperation,
|
|
116
119
|
} from "../core/commands/table-structure-commands.ts";
|
|
117
120
|
import {
|
|
118
121
|
deleteSelectionOrBackward,
|
|
@@ -165,6 +168,7 @@ import {
|
|
|
165
168
|
useRuntimeValue,
|
|
166
169
|
} from "./runtime-snapshot-selectors.ts";
|
|
167
170
|
import type { MarkupDisplay } from "./headless/comment-decoration-model";
|
|
171
|
+
import { resolveScopedChromePolicy } from "./headless/scoped-chrome-policy";
|
|
168
172
|
import type {
|
|
169
173
|
SelectionToolbarAnchor,
|
|
170
174
|
SelectionToolbarModel,
|
|
@@ -577,6 +581,8 @@ export function __createWordReviewEditorRefBridge(
|
|
|
577
581
|
getRuntimeContextAnalytics: (query) => {
|
|
578
582
|
return clonePublicValue(runtime.getRuntimeContextAnalytics(query));
|
|
579
583
|
},
|
|
584
|
+
layout: runtime.layout,
|
|
585
|
+
tables: buildTablesFacet(runtime, mountedSurface ?? null),
|
|
580
586
|
goToNextReviewItem: () => {
|
|
581
587
|
return clonePublicValue(navigateReviewQueue(runtime, "next"));
|
|
582
588
|
},
|
|
@@ -1391,6 +1397,8 @@ export const WordReviewEditor = forwardRef<WordReviewEditorRef, WordReviewEditor
|
|
|
1391
1397
|
getRuntimeContextAnalytics: (query) => {
|
|
1392
1398
|
return clonePublicValue(activeRuntime.getRuntimeContextAnalytics(query));
|
|
1393
1399
|
},
|
|
1400
|
+
layout: activeRuntime.layout,
|
|
1401
|
+
tables: buildTablesFacet(activeRuntime, surfaceRef.current ?? null),
|
|
1394
1402
|
goToNextReviewItem: () => {
|
|
1395
1403
|
return clonePublicValue(navigateMountedReviewQueue("next"));
|
|
1396
1404
|
},
|
|
@@ -1670,6 +1678,14 @@ export const WordReviewEditor = forwardRef<WordReviewEditorRef, WordReviewEditor
|
|
|
1670
1678
|
snapshot.comments.activeCommentId
|
|
1671
1679
|
? snapshot.comments.threads.find((thread) => thread.commentId === snapshot.comments.activeCommentId)
|
|
1672
1680
|
: undefined;
|
|
1681
|
+
const scopedChromePolicy = resolveScopedChromePolicy({
|
|
1682
|
+
preset: effectiveChromePreset,
|
|
1683
|
+
compactMode: false,
|
|
1684
|
+
capabilities,
|
|
1685
|
+
interactionGuardSnapshot,
|
|
1686
|
+
workflowScopeSnapshot,
|
|
1687
|
+
activeListContext: viewState.activeListContext,
|
|
1688
|
+
});
|
|
1673
1689
|
const selectionToolbar = buildSelectionToolbarModel({
|
|
1674
1690
|
snapshot,
|
|
1675
1691
|
viewState,
|
|
@@ -1736,6 +1752,7 @@ export const WordReviewEditor = forwardRef<WordReviewEditorRef, WordReviewEditor
|
|
|
1736
1752
|
preferListStructureContext: viewState.workspaceMode === "page",
|
|
1737
1753
|
addCommentDisabledReason,
|
|
1738
1754
|
suppressedSuggestionRevisionId,
|
|
1755
|
+
scopedChromePolicy,
|
|
1739
1756
|
});
|
|
1740
1757
|
const selectionToolbarSelectionKey = useMemo(
|
|
1741
1758
|
() =>
|
|
@@ -2241,6 +2258,9 @@ export const WordReviewEditor = forwardRef<WordReviewEditorRef, WordReviewEditor
|
|
|
2241
2258
|
workflowMetadata={workflowMarkupSnapshot?.metadata}
|
|
2242
2259
|
onSelectionToolbarAnchorChange={handleSelectionToolbarAnchorChange}
|
|
2243
2260
|
{...editorCallbacks}
|
|
2261
|
+
dispatchRuntimeCommand={(command) =>
|
|
2262
|
+
activeRuntime.applyActiveStoryTextCommand(command as never)
|
|
2263
|
+
}
|
|
2244
2264
|
onCommentActivated={(commentId) => {
|
|
2245
2265
|
activeRuntime.openComment(commentId);
|
|
2246
2266
|
setActiveRailTab("comments");
|
|
@@ -2285,6 +2305,7 @@ export const WordReviewEditor = forwardRef<WordReviewEditorRef, WordReviewEditor
|
|
|
2285
2305
|
activeRevisionId={activeRevisionId}
|
|
2286
2306
|
showTrackedChanges={showTrackedChanges}
|
|
2287
2307
|
workflowScopeSnapshot={workflowScopeSnapshot}
|
|
2308
|
+
layoutFacet={activeRuntime.layout}
|
|
2288
2309
|
interactionGuardSnapshot={interactionGuardSnapshot}
|
|
2289
2310
|
chromePreset={effectiveChromePreset}
|
|
2290
2311
|
chromeOptions={chromeOptions}
|
|
@@ -3373,28 +3394,19 @@ function applyRuntimeImageReposition(
|
|
|
3373
3394
|
function applyRuntimeTableStructureOperation(
|
|
3374
3395
|
runtime: WordReviewEditorRuntime,
|
|
3375
3396
|
mountedSurface: TwProseMirrorSurfaceRef | null | undefined,
|
|
3376
|
-
operation:
|
|
3377
|
-
|
|
3378
|
-
| { type: "add-row-after" }
|
|
3379
|
-
| { type: "add-column-before" }
|
|
3380
|
-
| { type: "add-column-after" }
|
|
3381
|
-
| { type: "delete-row" }
|
|
3382
|
-
| { type: "delete-column" }
|
|
3383
|
-
| { type: "delete-table" }
|
|
3384
|
-
| { type: "merge-cells" }
|
|
3385
|
-
| { type: "split-cell" }
|
|
3386
|
-
| { type: "set-cell-background"; color: string },
|
|
3387
|
-
): void {
|
|
3397
|
+
operation: TableStructureOperation,
|
|
3398
|
+
): { changed: boolean; coercedReason: string | null } {
|
|
3388
3399
|
if (isSelectionSuggesting(runtime)) {
|
|
3400
|
+
const coercedReason = `Table operation "${operation.type}" is not supported in suggesting mode.`;
|
|
3389
3401
|
runtime.emitBlockedCommand(`table.${operation.type}`, [{
|
|
3390
3402
|
code: "unsupported_surface",
|
|
3391
|
-
message:
|
|
3403
|
+
message: coercedReason,
|
|
3392
3404
|
}]);
|
|
3393
|
-
return;
|
|
3405
|
+
return { changed: false, coercedReason };
|
|
3394
3406
|
}
|
|
3395
3407
|
const context = getStoryMutationContext(runtime, `table.${operation.type}`);
|
|
3396
3408
|
if (!context) {
|
|
3397
|
-
return;
|
|
3409
|
+
return { changed: false, coercedReason: "No active mutation context." };
|
|
3398
3410
|
}
|
|
3399
3411
|
|
|
3400
3412
|
const result = applyTableStructureOperation(
|
|
@@ -3404,6 +3416,78 @@ function applyRuntimeTableStructureOperation(
|
|
|
3404
3416
|
operation,
|
|
3405
3417
|
);
|
|
3406
3418
|
dispatchStoryMutationResult(runtime, context, result, context.timestamp);
|
|
3419
|
+
return {
|
|
3420
|
+
changed: result.changed,
|
|
3421
|
+
coercedReason: result.changed ? null : "Op was a no-op against the active selection.",
|
|
3422
|
+
};
|
|
3423
|
+
}
|
|
3424
|
+
|
|
3425
|
+
/**
|
|
3426
|
+
* Translate a public-API `TableOp` (kebab-case `kind` discriminator) to
|
|
3427
|
+
* the internal `TableStructureOperation` (`type` discriminator). The
|
|
3428
|
+
* shape values are identical aside from the discriminator name.
|
|
3429
|
+
*/
|
|
3430
|
+
export function __publicTableOpToInternal(op: TableOp): TableStructureOperation {
|
|
3431
|
+
return publicTableOpToInternal(op);
|
|
3432
|
+
}
|
|
3433
|
+
|
|
3434
|
+
function publicTableOpToInternal(op: TableOp): TableStructureOperation {
|
|
3435
|
+
const { kind, ...rest } = op as { kind: string } & Record<string, unknown>;
|
|
3436
|
+
if (kind === "insert") {
|
|
3437
|
+
throw new Error(
|
|
3438
|
+
"TableOp kind \"insert\" is not routed through ref.tables.apply; use ref.insertTable(...).",
|
|
3439
|
+
);
|
|
3440
|
+
}
|
|
3441
|
+
return { type: kind, ...rest } as TableStructureOperation;
|
|
3442
|
+
}
|
|
3443
|
+
|
|
3444
|
+
/**
|
|
3445
|
+
* Build the `ref.tables` facet: a typed dispatch boundary + capability
|
|
3446
|
+
* read. Delegates every op through the same `applyRuntimeTableStructureOperation`
|
|
3447
|
+
* helper the flat ref verbs use, so there is exactly one server-side path
|
|
3448
|
+
* for every table mutation.
|
|
3449
|
+
*/
|
|
3450
|
+
function buildTablesFacet(
|
|
3451
|
+
runtime: WordReviewEditorRuntime,
|
|
3452
|
+
mountedSurface: TwProseMirrorSurfaceRef | null,
|
|
3453
|
+
) {
|
|
3454
|
+
const getCapabilities = () => {
|
|
3455
|
+
const snapshot = runtime.getRenderSnapshot();
|
|
3456
|
+
const document = runtime.getSessionState().canonicalDocument;
|
|
3457
|
+
return (
|
|
3458
|
+
clonePublicValue(
|
|
3459
|
+
getTableStructureContext(
|
|
3460
|
+
document,
|
|
3461
|
+
snapshot,
|
|
3462
|
+
mountedSurface?.getTableSelection() ?? null,
|
|
3463
|
+
),
|
|
3464
|
+
) ?? null
|
|
3465
|
+
);
|
|
3466
|
+
};
|
|
3467
|
+
return {
|
|
3468
|
+
apply(op: TableOp): TableOpResult {
|
|
3469
|
+
if (op.kind === "insert") {
|
|
3470
|
+
applyRuntimeInsertTable(runtime, { rows: op.rows, columns: op.columns });
|
|
3471
|
+
return {
|
|
3472
|
+
changed: true,
|
|
3473
|
+
coercedReason: null,
|
|
3474
|
+
capabilities: getCapabilities(),
|
|
3475
|
+
};
|
|
3476
|
+
}
|
|
3477
|
+
const internal = publicTableOpToInternal(op);
|
|
3478
|
+
const outcome = applyRuntimeTableStructureOperation(
|
|
3479
|
+
runtime,
|
|
3480
|
+
mountedSurface,
|
|
3481
|
+
internal,
|
|
3482
|
+
);
|
|
3483
|
+
return {
|
|
3484
|
+
changed: outcome.changed,
|
|
3485
|
+
coercedReason: outcome.coercedReason,
|
|
3486
|
+
capabilities: getCapabilities(),
|
|
3487
|
+
};
|
|
3488
|
+
},
|
|
3489
|
+
getCapabilities,
|
|
3490
|
+
};
|
|
3407
3491
|
}
|
|
3408
3492
|
|
|
3409
3493
|
function applyRuntimeTextCommand(
|
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
type DocumentRuntimeEvent,
|
|
35
35
|
type DocumentRuntime,
|
|
36
36
|
} from "../runtime/document-runtime.ts";
|
|
37
|
+
import { createInertLayoutFacet } from "../runtime/layout/index.ts";
|
|
37
38
|
import { loadDocxEditorSession } from "../io/docx-session.ts";
|
|
38
39
|
import {
|
|
39
40
|
decodePersistedSourcePackageBytes,
|
|
@@ -738,6 +739,7 @@ function createLoadingRuntimeBridge(input: {
|
|
|
738
739
|
viewState: EditorViewStateSnapshot;
|
|
739
740
|
navigation: DocumentNavigationSnapshot;
|
|
740
741
|
}): WordReviewEditorRuntime {
|
|
742
|
+
const inertLayoutFacet = createInertLayoutFacet();
|
|
741
743
|
const emptyFieldSnapshot: FieldSnapshot = {
|
|
742
744
|
totalCount: 0,
|
|
743
745
|
supportedCount: 0,
|
|
@@ -772,7 +774,13 @@ function createLoadingRuntimeBridge(input: {
|
|
|
772
774
|
getCanonicalDocument: () => input.sessionState.canonicalDocument,
|
|
773
775
|
getSourcePackage: () => input.sessionState.sourcePackage,
|
|
774
776
|
replaceText: () => undefined,
|
|
775
|
-
applyActiveStoryTextCommand: () =>
|
|
777
|
+
applyActiveStoryTextCommand: () => ({
|
|
778
|
+
kind: "rejected",
|
|
779
|
+
newRevisionToken: "",
|
|
780
|
+
blockedReasons: [
|
|
781
|
+
{ code: "runtime_loading", message: "Document runtime is not ready yet." },
|
|
782
|
+
],
|
|
783
|
+
}),
|
|
776
784
|
dispatch: () => undefined,
|
|
777
785
|
undo: () => undefined,
|
|
778
786
|
redo: () => undefined,
|
|
@@ -801,6 +809,7 @@ function createLoadingRuntimeBridge(input: {
|
|
|
801
809
|
setZoom: () => undefined,
|
|
802
810
|
getPageLayoutSnapshot: () => null,
|
|
803
811
|
getDocumentNavigationSnapshot: () => input.navigation,
|
|
812
|
+
layout: inertLayoutFacet,
|
|
804
813
|
getCurrentLocation: () => null,
|
|
805
814
|
getLocationForSelection: () => null,
|
|
806
815
|
getLocationForAnchor: () => null,
|
|
@@ -55,6 +55,12 @@ export interface EditorShellViewProps {
|
|
|
55
55
|
activeRevisionId?: string;
|
|
56
56
|
showTrackedChanges: boolean;
|
|
57
57
|
workflowScopeSnapshot?: WorkflowScopeSnapshot | null;
|
|
58
|
+
/**
|
|
59
|
+
* Runtime-owned layout facet passed through to the workspace so the
|
|
60
|
+
* ChromeOverlay (scope rail, workflow dock, etc.) can render over the
|
|
61
|
+
* document column and the review rail's Workflow tab can read segments.
|
|
62
|
+
*/
|
|
63
|
+
layoutFacet?: import("../runtime/layout/index.ts").WordReviewEditorLayoutFacet;
|
|
58
64
|
interactionGuardSnapshot?: InteractionGuardSnapshot;
|
|
59
65
|
chromePreset?: WordReviewEditorChromePreset;
|
|
60
66
|
chromeOptions?: Partial<WordReviewEditorChromeOptions>;
|
|
@@ -60,6 +60,9 @@ export interface EditorSurfaceControllerProps {
|
|
|
60
60
|
activeWorkflowWorkItemId?: string | null;
|
|
61
61
|
activeWorkflowScopeIds?: readonly string[];
|
|
62
62
|
workflowMetadata?: readonly WorkflowMetadataMarkup[];
|
|
63
|
+
dispatchRuntimeCommand?: (
|
|
64
|
+
command: import("../ui-tailwind/editor-surface/fast-text-edit-lane.ts").LaneRuntimeCommand,
|
|
65
|
+
) => import("../api/public-types.ts").TextCommandAck;
|
|
63
66
|
}
|
|
64
67
|
|
|
65
68
|
export const EditorSurfaceController = forwardRef<
|