@beyondwork/docx-react-component 1.0.106 → 1.0.108
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 +19 -5
- package/src/api/geometry-overlay-rects.ts +5 -0
- package/src/api/package-version.ts +1 -1
- package/src/api/page-anchor-id.ts +5 -0
- package/src/api/public-types.ts +16 -9
- package/src/api/table-node-specs.ts +6 -0
- package/src/api/v3/_create.ts +2 -1
- package/src/api/v3/_page-anchor-id.ts +52 -0
- package/src/api/v3/_runtime-handle.ts +92 -1
- package/src/api/v3/ai/_audit-time.ts +5 -0
- package/src/api/v3/ai/_pe2-evidence.ts +38 -0
- package/src/api/v3/ai/attach.ts +7 -2
- package/src/api/v3/ai/replacement.ts +101 -18
- package/src/api/v3/ai/resolve.ts +2 -2
- package/src/api/v3/ai/review.ts +177 -3
- package/src/api/v3/index.ts +1 -0
- package/src/api/v3/runtime/collab.ts +462 -0
- package/src/api/v3/runtime/document.ts +503 -20
- package/src/api/v3/runtime/geometry.ts +97 -0
- package/src/api/v3/runtime/layout.ts +744 -0
- package/src/api/v3/runtime/perf-probe.ts +14 -0
- package/src/api/v3/runtime/viewport.ts +9 -8
- package/src/api/v3/ui/_types.ts +149 -55
- package/src/api/v3/ui/chrome-preset-model.ts +5 -5
- package/src/api/v3/ui/debug.ts +115 -2
- package/src/api/v3/ui/index.ts +13 -0
- package/src/api/v3/ui/overlays.ts +0 -8
- package/src/api/v3/ui/surface.ts +56 -0
- package/src/api/v3/ui/viewport.ts +22 -9
- package/src/core/commands/image-commands.ts +1 -0
- package/src/core/commands/index.ts +6 -0
- package/src/core/schema/text-schema.ts +43 -5
- package/src/core/selection/mapping.ts +8 -1
- package/src/core/selection/review-anchors.ts +5 -1
- package/src/core/state/text-transaction.ts +8 -2
- package/src/io/export/serialize-revisions.ts +149 -1
- package/src/io/normalize/normalize-text.ts +6 -0
- package/src/io/ooxml/parse-bookmark-references.ts +55 -0
- package/src/io/ooxml/parse-fields.ts +24 -2
- package/src/io/ooxml/parse-headers-footers.ts +38 -5
- package/src/io/ooxml/parse-main-document.ts +153 -9
- package/src/io/ooxml/parse-numbering.ts +20 -0
- package/src/io/ooxml/parse-revisions.ts +19 -8
- package/src/io/opc/package-reader.ts +98 -8
- package/src/model/anchor.ts +4 -3
- package/src/model/canonical-document.ts +220 -2
- package/src/model/canonical-hash.ts +221 -0
- package/src/model/canonical-layout-inputs.ts +245 -6
- package/src/model/layout/index.ts +1 -0
- package/src/model/layout/page-graph-types.ts +118 -1
- package/src/model/review/revision-types.ts +14 -3
- package/src/preservation/store.ts +20 -4
- package/src/review/README.md +1 -1
- package/src/review/store/revision-actions.ts +14 -2
- package/src/runtime/collab/event-types.ts +67 -1
- package/src/runtime/collab/runtime-collab-sync.ts +177 -5
- package/src/runtime/diagnostics/layout-guard-warning.ts +18 -0
- package/src/runtime/document-heading-outline.ts +147 -0
- package/src/runtime/document-navigation.ts +8 -243
- package/src/runtime/document-runtime.ts +240 -97
- package/src/runtime/edit-dispatch/dispatch-text-command.ts +11 -0
- package/src/runtime/formatting/layout-inputs.ts +38 -5
- package/src/runtime/formatting/numbering/geometry.ts +28 -2
- package/src/runtime/geometry/adjacent-geometry-intake.ts +835 -0
- package/src/runtime/geometry/caret-geometry.ts +5 -6
- package/src/runtime/geometry/geometry-facet.ts +60 -10
- package/src/runtime/geometry/geometry-index.ts +591 -20
- package/src/runtime/geometry/geometry-types.ts +59 -0
- package/src/runtime/geometry/hit-test.ts +11 -1
- package/src/runtime/geometry/overlay-rects.ts +5 -3
- package/src/runtime/geometry/project-anchors.ts +1 -1
- package/src/runtime/geometry/word-layout-v2-line-intake.ts +323 -0
- package/src/runtime/layout/index.ts +6 -0
- package/src/runtime/layout/layout-engine-instance.ts +6 -1
- package/src/runtime/layout/layout-engine-version.ts +181 -16
- package/src/runtime/layout/layout-facet-types.ts +6 -0
- package/src/runtime/layout/page-graph.ts +21 -4
- package/src/runtime/layout/paginated-layout-engine.ts +139 -15
- package/src/runtime/layout/project-block-fragments.ts +265 -7
- package/src/runtime/layout/public-facet.ts +78 -24
- package/src/runtime/layout/table-row-continuation-contract.ts +107 -0
- package/src/runtime/layout/table-row-split.ts +92 -35
- package/src/runtime/prerender/cache-envelope.ts +2 -2
- package/src/runtime/prerender/cache-key.ts +5 -4
- package/src/runtime/prerender/customxml-cache.ts +0 -1
- package/src/runtime/render/render-kernel.ts +1 -1
- package/src/runtime/revision-runtime.ts +112 -10
- package/src/runtime/scopes/_scope-dependencies.ts +1 -0
- package/src/runtime/scopes/action-validation.ts +22 -2
- package/src/runtime/scopes/capabilities.ts +316 -0
- package/src/runtime/scopes/compile-scope-bundle.ts +14 -0
- package/src/runtime/scopes/compiler-service.ts +108 -4
- package/src/runtime/scopes/content-control-evidence.ts +79 -0
- package/src/runtime/scopes/create-issue.ts +5 -5
- package/src/runtime/scopes/evidence.ts +91 -0
- package/src/runtime/scopes/formatting/apply.ts +2 -0
- package/src/runtime/scopes/geometry-evidence.ts +130 -0
- package/src/runtime/scopes/index.ts +54 -0
- package/src/runtime/scopes/issue-lifecycle.ts +224 -0
- package/src/runtime/scopes/layout-evidence.ts +374 -0
- package/src/runtime/scopes/multi-paragraph-refusal.ts +37 -0
- package/src/runtime/scopes/preservation-boundary.ts +7 -1
- package/src/runtime/scopes/replacement/apply.ts +97 -34
- package/src/runtime/scopes/scope-kinds/paragraph.ts +108 -12
- package/src/runtime/scopes/semantic-scope-types.ts +242 -3
- package/src/runtime/scopes/visualization.ts +28 -0
- package/src/runtime/surface-projection.ts +44 -5
- package/src/runtime/telemetry/perf-probe.ts +216 -0
- package/src/runtime/virtualized-rendering.ts +36 -1
- package/src/runtime/workflow/ai-issue-lifecycle.ts +253 -0
- package/src/runtime/workflow/coordinator.ts +39 -11
- package/src/runtime/workflow/derived-scope-resolver.ts +63 -9
- package/src/runtime/workflow/index.ts +3 -0
- package/src/runtime/workflow/overlay-lane-types.ts +58 -0
- package/src/runtime/workflow/overlay-lanes.ts +168 -10
- package/src/runtime/workflow/overlay-store.ts +2 -2
- package/src/runtime/workflow/redline-posture-calibration.ts +257 -0
- package/src/runtime/workflow/word-field-matrix-calibration.ts +231 -0
- package/src/session/_sync-legacy.ts +17 -27
- package/src/session/import/loader.ts +6 -4
- package/src/session/import/source-package-evidence.ts +186 -2
- package/src/session/index.ts +5 -6
- package/src/session/session.ts +30 -56
- package/src/session/types.ts +8 -13
- package/src/shell/session-bootstrap.ts +155 -81
- package/src/ui/WordReviewEditor.tsx +520 -12
- package/src/ui/editor-shell-view.tsx +14 -4
- package/src/ui/editor-surface-controller.tsx +5 -3
- package/src/ui/headless/selection-tool-resolver.ts +1 -2
- package/src/ui/presence-overlay-lane.ts +0 -1
- package/src/ui/ui-controller-factory.ts +7 -0
- package/src/ui-tailwind/chrome/build-context-menu-entries.ts +5 -1
- package/src/ui-tailwind/chrome/editor-action-registry.ts +105 -5
- package/src/ui-tailwind/chrome/editor-actions-to-palette.ts +7 -0
- package/src/ui-tailwind/chrome/layer-debug-contracts.ts +208 -0
- package/src/ui-tailwind/chrome/resolve-target-kind.ts +13 -0
- package/src/ui-tailwind/chrome/tw-alert-banner.tsx +11 -3
- package/src/ui-tailwind/chrome/tw-command-palette.tsx +36 -6
- package/src/ui-tailwind/chrome/tw-context-menu.tsx +6 -1
- package/src/ui-tailwind/chrome/tw-display-mode-selector.tsx +42 -109
- package/src/ui-tailwind/chrome/tw-inline-find-bar.tsx +26 -6
- package/src/ui-tailwind/chrome/tw-navigation-command-bar.tsx +328 -0
- package/src/ui-tailwind/chrome/tw-object-context-toolbar.tsx +8 -4
- package/src/ui-tailwind/chrome/tw-runtime-repl-dialog.tsx +129 -1
- package/src/ui-tailwind/chrome/tw-selection-tool-host.tsx +19 -5
- package/src/ui-tailwind/chrome/tw-selection-tool-structure.tsx +5 -1
- package/src/ui-tailwind/chrome/tw-workspace-chrome-host.tsx +28 -12
- package/src/ui-tailwind/chrome-overlay/tw-chrome-overlay.tsx +30 -3
- package/src/ui-tailwind/chrome-overlay/tw-object-selection-overlay.tsx +116 -10
- package/src/ui-tailwind/chrome-overlay/tw-page-stack-overlay-layer.tsx +223 -94
- package/src/ui-tailwind/chrome-overlay/tw-presence-overlay-lane.tsx +157 -0
- package/src/ui-tailwind/chrome-overlay/tw-review-overlay-lane-markers.tsx +259 -0
- package/src/ui-tailwind/chrome-overlay/tw-scope-card-layer.tsx +5 -2
- package/src/ui-tailwind/chrome-overlay/tw-substrate-overlay-lanes.tsx +314 -0
- package/src/ui-tailwind/debug/README.md +4 -1
- package/src/ui-tailwind/debug/layer11-consumer-readiness.ts +272 -0
- package/src/ui-tailwind/debug/layer11-word-field-matrix-evidence.ts +160 -0
- package/src/ui-tailwind/editor-surface/perf-probe.ts +14 -215
- package/src/ui-tailwind/editor-surface/pm-decorations.ts +42 -0
- package/src/ui-tailwind/editor-surface/pm-position-map.ts +38 -2
- package/src/ui-tailwind/editor-surface/pm-schema.ts +14 -4
- package/src/ui-tailwind/editor-surface/pm-state-from-snapshot.ts +34 -5
- package/src/ui-tailwind/editor-surface/runtime-decoration-plugin.ts +9 -19
- package/src/ui-tailwind/editor-surface/surface-build-keys.ts +2 -2
- package/src/ui-tailwind/editor-surface/tw-page-block-view.helpers.ts +145 -0
- package/src/ui-tailwind/editor-surface/tw-page-block-view.tsx +16 -11
- package/src/ui-tailwind/editor-surface/tw-prosemirror-surface.tsx +8 -10
- package/src/ui-tailwind/editor-surface/tw-table-node-view.tsx +3 -0
- package/src/ui-tailwind/page-stack/tw-page-chrome-entry.tsx +4 -2
- package/src/ui-tailwind/page-stack/tw-page-stack-chrome-layer.tsx +60 -20
- package/src/ui-tailwind/page-stack/tw-region-block-renderer.tsx +16 -11
- package/src/ui-tailwind/review/tw-health-panel.tsx +36 -17
- package/src/ui-tailwind/review/tw-review-rail.tsx +7 -4
- package/src/ui-tailwind/review-workspace/diagnostics-visibility.ts +44 -0
- package/src/ui-tailwind/review-workspace/page-shell-metrics.ts +11 -0
- package/src/ui-tailwind/review-workspace/tw-review-workspace-rail.tsx +16 -1
- package/src/ui-tailwind/review-workspace/types.ts +26 -12
- package/src/ui-tailwind/review-workspace/use-diagnostics-signal.ts +40 -11
- package/src/ui-tailwind/review-workspace/use-layout-facet-render-signal.ts +2 -1
- package/src/ui-tailwind/review-workspace/use-page-markers.ts +15 -26
- package/src/ui-tailwind/review-workspace/use-scope-card-state.ts +35 -18
- package/src/ui-tailwind/review-workspace/use-selection-toolbar-placement.ts +41 -32
- package/src/ui-tailwind/review-workspace/use-status-bar-page-facts.ts +2 -1
- package/src/ui-tailwind/review-workspace/use-workspace-side-effects.ts +2 -1
- package/src/ui-tailwind/status/tw-status-bar.tsx +6 -5
- package/src/ui-tailwind/toolbar/tw-role-action-region.tsx +52 -80
- package/src/ui-tailwind/toolbar/tw-shell-header.tsx +12 -48
- package/src/ui-tailwind/toolbar/tw-toolbar-icon-button.tsx +9 -4
- package/src/ui-tailwind/toolbar/tw-toolbar.tsx +328 -361
- package/src/ui-tailwind/tw-review-workspace.tsx +152 -286
|
@@ -11,6 +11,7 @@ import React, {
|
|
|
11
11
|
|
|
12
12
|
import type {
|
|
13
13
|
AutosaveState,
|
|
14
|
+
CommentSidebarThreadSnapshot,
|
|
14
15
|
CompatibilityReport,
|
|
15
16
|
DocumentNavigationSnapshot,
|
|
16
17
|
EditorAnchorProjection,
|
|
@@ -137,7 +138,13 @@ import { findTextMatchesForRuntime, searchRuntimeDocument } from "../shell/searc
|
|
|
137
138
|
import {
|
|
138
139
|
type TwProseMirrorSurfaceRef,
|
|
139
140
|
} from "../ui-tailwind/editor-surface/tw-prosemirror-surface";
|
|
140
|
-
import {
|
|
141
|
+
import {
|
|
142
|
+
TwNavigationCommandBar,
|
|
143
|
+
type NavigationCommandMode,
|
|
144
|
+
type NavigationGoToGroup,
|
|
145
|
+
type NavigationSearchScope,
|
|
146
|
+
type NavigationSearchScopeOption,
|
|
147
|
+
} from "../ui-tailwind/chrome/tw-navigation-command-bar";
|
|
141
148
|
import { PAGE_CHROME_DEFAULTS } from "../ui-tailwind/editor-surface/pm-page-break-decorations.ts";
|
|
142
149
|
import type { MediaPreviewDescriptor } from "../ui-tailwind/editor-surface/pm-state-from-snapshot";
|
|
143
150
|
import {
|
|
@@ -229,14 +236,197 @@ import type {
|
|
|
229
236
|
ChromeHostPosture,
|
|
230
237
|
ChromePosture,
|
|
231
238
|
OverlayAnchorQuery,
|
|
239
|
+
UiObjectDragCommitResult,
|
|
240
|
+
UiObjectDragSession,
|
|
241
|
+
UiObjectDragStartInput,
|
|
242
|
+
UiObjectDragUpdateInput,
|
|
232
243
|
ViewportState,
|
|
233
244
|
} from "../api/v3/ui/_types.ts";
|
|
234
245
|
|
|
235
246
|
export {
|
|
236
247
|
__createFallbackRuntime,
|
|
248
|
+
__preloadSnapshotSourceForRuntime,
|
|
237
249
|
__resolveWordReviewEditorSource,
|
|
238
250
|
} from "../shell/session-bootstrap.ts";
|
|
239
251
|
|
|
252
|
+
const EMU_PER_CSS_PX = 9525;
|
|
253
|
+
let nextObjectDragSessionId = 0;
|
|
254
|
+
|
|
255
|
+
function createMountedObjectDragSession(
|
|
256
|
+
runtime: WordReviewEditorRuntime,
|
|
257
|
+
input: UiObjectDragStartInput,
|
|
258
|
+
): UiObjectDragSession {
|
|
259
|
+
nextObjectDragSessionId += 1;
|
|
260
|
+
const sessionId = `object-drag-${nextObjectDragSessionId}`;
|
|
261
|
+
const start = findObjectDragSegment(runtime.getRenderSnapshot(), input.objectId);
|
|
262
|
+
let latestDelta = { x: 0, y: 0 };
|
|
263
|
+
let closed: "committed" | "cancelled" | null = null;
|
|
264
|
+
|
|
265
|
+
const readDelta = (update?: UiObjectDragUpdateInput) => {
|
|
266
|
+
if (!update) return latestDelta;
|
|
267
|
+
const x = update.deltaX ?? (update.clientX != null ? update.clientX - input.clientX : latestDelta.x);
|
|
268
|
+
const y = update.deltaY ?? (update.clientY != null ? update.clientY - input.clientY : latestDelta.y);
|
|
269
|
+
latestDelta = { x, y };
|
|
270
|
+
return latestDelta;
|
|
271
|
+
};
|
|
272
|
+
const snapshotFor = (
|
|
273
|
+
status: "active" | "committed" | "cancelled",
|
|
274
|
+
update?: UiObjectDragUpdateInput,
|
|
275
|
+
) => {
|
|
276
|
+
const delta = readDelta(update);
|
|
277
|
+
return {
|
|
278
|
+
objectId: input.objectId,
|
|
279
|
+
handle: input.handle,
|
|
280
|
+
status,
|
|
281
|
+
deltaPx: delta,
|
|
282
|
+
previewRect: previewObjectDragRect(input, delta),
|
|
283
|
+
};
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
return {
|
|
287
|
+
id: sessionId,
|
|
288
|
+
objectId: input.objectId,
|
|
289
|
+
handle: input.handle,
|
|
290
|
+
update(update) {
|
|
291
|
+
if (closed) return snapshotFor(closed, update);
|
|
292
|
+
return snapshotFor("active", update);
|
|
293
|
+
},
|
|
294
|
+
commit(update) {
|
|
295
|
+
if (closed) {
|
|
296
|
+
return {
|
|
297
|
+
...snapshotFor(closed, update),
|
|
298
|
+
changed: false,
|
|
299
|
+
reason: `object-drag-${closed}`,
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
const active = snapshotFor("committed", update);
|
|
303
|
+
const result = commitMountedObjectDrag(runtime, input, start, active.deltaPx);
|
|
304
|
+
closed = "committed";
|
|
305
|
+
return { ...active, ...result };
|
|
306
|
+
},
|
|
307
|
+
cancel() {
|
|
308
|
+
closed = "cancelled";
|
|
309
|
+
return {
|
|
310
|
+
...snapshotFor("cancelled"),
|
|
311
|
+
changed: false,
|
|
312
|
+
reason: "object-drag-cancelled",
|
|
313
|
+
};
|
|
314
|
+
},
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
function previewObjectDragRect(
|
|
319
|
+
input: UiObjectDragStartInput,
|
|
320
|
+
delta: { x: number; y: number },
|
|
321
|
+
) {
|
|
322
|
+
const rect = input.initialRect;
|
|
323
|
+
const next = {
|
|
324
|
+
leftPx: rect.leftPx,
|
|
325
|
+
topPx: rect.topPx,
|
|
326
|
+
widthPx: rect.widthPx,
|
|
327
|
+
heightPx: rect.heightPx,
|
|
328
|
+
space: rect.space,
|
|
329
|
+
...(rect.precision ? { precision: rect.precision } : {}),
|
|
330
|
+
};
|
|
331
|
+
if (input.handle === "move") {
|
|
332
|
+
return { ...next, leftPx: next.leftPx + delta.x, topPx: next.topPx + delta.y };
|
|
333
|
+
}
|
|
334
|
+
if (input.handle === "rotate") return next;
|
|
335
|
+
const west = input.handle.includes("w");
|
|
336
|
+
const east = input.handle.includes("e");
|
|
337
|
+
const north = input.handle.includes("n");
|
|
338
|
+
const south = input.handle.includes("s");
|
|
339
|
+
const minPx = 1;
|
|
340
|
+
return {
|
|
341
|
+
...next,
|
|
342
|
+
leftPx: west ? next.leftPx + delta.x : next.leftPx,
|
|
343
|
+
topPx: north ? next.topPx + delta.y : next.topPx,
|
|
344
|
+
widthPx: Math.max(minPx, next.widthPx + (east ? delta.x : 0) - (west ? delta.x : 0)),
|
|
345
|
+
heightPx: Math.max(minPx, next.heightPx + (south ? delta.y : 0) - (north ? delta.y : 0)),
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
function commitMountedObjectDrag(
|
|
350
|
+
runtime: WordReviewEditorRuntime,
|
|
351
|
+
input: UiObjectDragStartInput,
|
|
352
|
+
segment: ObjectDragSegment | null,
|
|
353
|
+
delta: { x: number; y: number },
|
|
354
|
+
): Pick<UiObjectDragCommitResult, "changed" | "reason"> {
|
|
355
|
+
if (!segment) return { changed: false, reason: "object-not-found" };
|
|
356
|
+
if (segment.kind !== "image") {
|
|
357
|
+
return { changed: false, reason: "object-kind-not-supported" };
|
|
358
|
+
}
|
|
359
|
+
if (input.handle === "rotate") {
|
|
360
|
+
return { changed: false, reason: "rotate-not-supported" };
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
if (input.handle === "move") {
|
|
364
|
+
if (segment.display !== "floating" && segment.anchor?.display !== "floating") {
|
|
365
|
+
return { changed: false, reason: "inline-object-move-not-supported" };
|
|
366
|
+
}
|
|
367
|
+
applyRuntimeImageReposition(runtime, input.objectId, {
|
|
368
|
+
horizontalOffsetEmu: Math.round((segment.anchor?.positionH?.offset ?? 0) + delta.x * EMU_PER_CSS_PX),
|
|
369
|
+
verticalOffsetEmu: Math.round((segment.anchor?.positionV?.offset ?? 0) + delta.y * EMU_PER_CSS_PX),
|
|
370
|
+
});
|
|
371
|
+
return { changed: true };
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
const startWidth =
|
|
375
|
+
segment.anchor?.extent?.widthEmu ??
|
|
376
|
+
Math.round(input.initialRect.widthPx * EMU_PER_CSS_PX);
|
|
377
|
+
const startHeight =
|
|
378
|
+
segment.anchor?.extent?.heightEmu ??
|
|
379
|
+
Math.round(input.initialRect.heightPx * EMU_PER_CSS_PX);
|
|
380
|
+
const west = input.handle.includes("w");
|
|
381
|
+
const east = input.handle.includes("e");
|
|
382
|
+
const north = input.handle.includes("n");
|
|
383
|
+
const south = input.handle.includes("s");
|
|
384
|
+
const minEmu = EMU_PER_CSS_PX;
|
|
385
|
+
const widthEmu = Math.max(
|
|
386
|
+
minEmu,
|
|
387
|
+
Math.round(startWidth + (east ? delta.x : 0) * EMU_PER_CSS_PX - (west ? delta.x : 0) * EMU_PER_CSS_PX),
|
|
388
|
+
);
|
|
389
|
+
const heightEmu = Math.max(
|
|
390
|
+
minEmu,
|
|
391
|
+
Math.round(startHeight + (south ? delta.y : 0) * EMU_PER_CSS_PX - (north ? delta.y : 0) * EMU_PER_CSS_PX),
|
|
392
|
+
);
|
|
393
|
+
applyRuntimeImageResize(runtime, input.objectId, { widthEmu, heightEmu });
|
|
394
|
+
return { changed: true };
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
interface ObjectDragSegment {
|
|
398
|
+
kind: string;
|
|
399
|
+
mediaId?: string;
|
|
400
|
+
from?: number;
|
|
401
|
+
to?: number;
|
|
402
|
+
display?: "inline" | "floating";
|
|
403
|
+
anchor?: {
|
|
404
|
+
display?: "inline" | "floating";
|
|
405
|
+
extent?: { widthEmu: number; heightEmu: number };
|
|
406
|
+
positionH?: { offset?: number };
|
|
407
|
+
positionV?: { offset?: number };
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
function findObjectDragSegment(
|
|
412
|
+
snapshot: RuntimeRenderSnapshot,
|
|
413
|
+
objectId: string,
|
|
414
|
+
): ObjectDragSegment | null {
|
|
415
|
+
for (const block of snapshot.surface?.blocks ?? []) {
|
|
416
|
+
if (!("segments" in block)) continue;
|
|
417
|
+
for (const segment of (block as { segments?: unknown[] }).segments ?? []) {
|
|
418
|
+
const candidate = segment as ObjectDragSegment;
|
|
419
|
+
if (
|
|
420
|
+
(candidate.kind === "image" || candidate.kind === "shape") &&
|
|
421
|
+
candidate.mediaId === objectId
|
|
422
|
+
) {
|
|
423
|
+
return candidate;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
return null;
|
|
428
|
+
}
|
|
429
|
+
|
|
240
430
|
/**
|
|
241
431
|
* Map a host-facing `markupDisplay` prop value to the narrow
|
|
242
432
|
* `ChromeMarkupDisplay` enum on `ChromeHostPosture` (`"final" | "markup"
|
|
@@ -1064,9 +1254,15 @@ export const WordReviewEditor = forwardRef<WordReviewEditorRef, WordReviewEditor
|
|
|
1064
1254
|
|
|
1065
1255
|
const [activeRailTab, setActiveRailTab] = useState<ReviewRailTab>("comments");
|
|
1066
1256
|
const [inlineFindOpen, setInlineFindOpen] = useState(false);
|
|
1257
|
+
const [navigationCommandMode, setNavigationCommandMode] =
|
|
1258
|
+
useState<NavigationCommandMode>("find");
|
|
1067
1259
|
const [inlineFindQuery, setInlineFindQuery] = useState("");
|
|
1260
|
+
const [inlineReplaceText, setInlineReplaceText] = useState("");
|
|
1261
|
+
const [inlineSearchScope, setInlineSearchScope] =
|
|
1262
|
+
useState<NavigationSearchScope>("main");
|
|
1068
1263
|
const [inlineFindResults, setInlineFindResults] = useState<readonly SearchResultSnapshot[]>([]);
|
|
1069
1264
|
const [inlineFindActiveIndex, setInlineFindActiveIndex] = useState(0);
|
|
1265
|
+
const [activeGoToGroupId, setActiveGoToGroupId] = useState("pages");
|
|
1070
1266
|
const [localMarkupDisplay, setLocalMarkupDisplay] =
|
|
1071
1267
|
useState<WorkflowMarkupMode | null>(() => suggestionsEnabled ? "all" : null);
|
|
1072
1268
|
const [activeRevisionId, setActiveRevisionId] = useState<string | undefined>();
|
|
@@ -1219,6 +1415,8 @@ export const WordReviewEditor = forwardRef<WordReviewEditorRef, WordReviewEditor
|
|
|
1219
1415
|
viewportChannelRef.current!.subscribe(listener),
|
|
1220
1416
|
subscribeOverlays: (listener) =>
|
|
1221
1417
|
overlaysChannelRef.current!.subscribe(listener),
|
|
1418
|
+
beginObjectDrag: (input) =>
|
|
1419
|
+
createMountedObjectDragSession(activeRuntime, input),
|
|
1222
1420
|
}),
|
|
1223
1421
|
}),
|
|
1224
1422
|
[activeRuntime],
|
|
@@ -2609,6 +2807,21 @@ export const WordReviewEditor = forwardRef<WordReviewEditorRef, WordReviewEditor
|
|
|
2609
2807
|
},
|
|
2610
2808
|
[activeRuntime],
|
|
2611
2809
|
);
|
|
2810
|
+
const inlineFindSearchOptions = useMemo<SearchOptions>(() => {
|
|
2811
|
+
const base: SearchOptions = { limit: 500 };
|
|
2812
|
+
if (inlineSearchScope === "story") {
|
|
2813
|
+
return { ...base, inStory: snapshot.activeStory };
|
|
2814
|
+
}
|
|
2815
|
+
if (inlineSearchScope === "scope") {
|
|
2816
|
+
const scopeId = interactionGuardSnapshot.matchedScopeId;
|
|
2817
|
+
return scopeId ? { ...base, inScope: scopeId } : base;
|
|
2818
|
+
}
|
|
2819
|
+
return base;
|
|
2820
|
+
}, [
|
|
2821
|
+
inlineSearchScope,
|
|
2822
|
+
interactionGuardSnapshot.matchedScopeId,
|
|
2823
|
+
snapshot.activeStory,
|
|
2824
|
+
]);
|
|
2612
2825
|
const refreshInlineFindResults = useCallback(
|
|
2613
2826
|
(query: string, requestedIndex = 0) => {
|
|
2614
2827
|
const normalizedQuery = query.trim();
|
|
@@ -2622,7 +2835,7 @@ export const WordReviewEditor = forwardRef<WordReviewEditorRef, WordReviewEditor
|
|
|
2622
2835
|
activeRuntime,
|
|
2623
2836
|
surfaceRef.current,
|
|
2624
2837
|
normalizedQuery,
|
|
2625
|
-
|
|
2838
|
+
inlineFindSearchOptions,
|
|
2626
2839
|
);
|
|
2627
2840
|
const nextIndex =
|
|
2628
2841
|
results.length > 0 ? wrapSearchResultIndex(requestedIndex, results.length) : 0;
|
|
@@ -2630,14 +2843,24 @@ export const WordReviewEditor = forwardRef<WordReviewEditorRef, WordReviewEditor
|
|
|
2630
2843
|
setInlineFindActiveIndex(nextIndex);
|
|
2631
2844
|
navigateInlineFindResult(results, nextIndex);
|
|
2632
2845
|
},
|
|
2633
|
-
[activeRuntime, navigateInlineFindResult],
|
|
2846
|
+
[activeRuntime, inlineFindSearchOptions, navigateInlineFindResult],
|
|
2634
2847
|
);
|
|
2635
|
-
const
|
|
2848
|
+
const openNavigationCommandBar = useCallback((mode: NavigationCommandMode) => {
|
|
2849
|
+
setNavigationCommandMode(mode);
|
|
2636
2850
|
setInlineFindOpen(true);
|
|
2637
2851
|
if (inlineFindQuery.trim()) {
|
|
2638
2852
|
refreshInlineFindResults(inlineFindQuery, inlineFindActiveIndex);
|
|
2639
2853
|
}
|
|
2640
2854
|
}, [inlineFindActiveIndex, inlineFindQuery, refreshInlineFindResults]);
|
|
2855
|
+
const handleOpenInlineFind = useCallback(() => {
|
|
2856
|
+
openNavigationCommandBar("find");
|
|
2857
|
+
}, [openNavigationCommandBar]);
|
|
2858
|
+
const handleOpenInlineReplace = useCallback(() => {
|
|
2859
|
+
openNavigationCommandBar("replace");
|
|
2860
|
+
}, [openNavigationCommandBar]);
|
|
2861
|
+
const handleOpenInlineGoTo = useCallback(() => {
|
|
2862
|
+
openNavigationCommandBar("go-to");
|
|
2863
|
+
}, [openNavigationCommandBar]);
|
|
2641
2864
|
const handleCloseInlineFind = useCallback(() => {
|
|
2642
2865
|
setInlineFindOpen(false);
|
|
2643
2866
|
surfaceRef.current?.clearSearch();
|
|
@@ -2649,6 +2872,35 @@ export const WordReviewEditor = forwardRef<WordReviewEditorRef, WordReviewEditor
|
|
|
2649
2872
|
},
|
|
2650
2873
|
[refreshInlineFindResults],
|
|
2651
2874
|
);
|
|
2875
|
+
const handleInlineSearchScopeChange = useCallback(
|
|
2876
|
+
(scope: NavigationSearchScope) => {
|
|
2877
|
+
setInlineSearchScope(scope);
|
|
2878
|
+
if (inlineFindQuery.trim()) {
|
|
2879
|
+
const options: SearchOptions =
|
|
2880
|
+
scope === "story"
|
|
2881
|
+
? { limit: 500, inStory: snapshot.activeStory }
|
|
2882
|
+
: scope === "scope" && interactionGuardSnapshot.matchedScopeId
|
|
2883
|
+
? { limit: 500, inScope: interactionGuardSnapshot.matchedScopeId }
|
|
2884
|
+
: { limit: 500 };
|
|
2885
|
+
const results = searchRuntimeDocument(
|
|
2886
|
+
activeRuntime,
|
|
2887
|
+
surfaceRef.current,
|
|
2888
|
+
inlineFindQuery.trim(),
|
|
2889
|
+
options,
|
|
2890
|
+
);
|
|
2891
|
+
setInlineFindResults(results);
|
|
2892
|
+
setInlineFindActiveIndex(0);
|
|
2893
|
+
navigateInlineFindResult(results, 0);
|
|
2894
|
+
}
|
|
2895
|
+
},
|
|
2896
|
+
[
|
|
2897
|
+
activeRuntime,
|
|
2898
|
+
inlineFindQuery,
|
|
2899
|
+
interactionGuardSnapshot.matchedScopeId,
|
|
2900
|
+
navigateInlineFindResult,
|
|
2901
|
+
snapshot.activeStory,
|
|
2902
|
+
],
|
|
2903
|
+
);
|
|
2652
2904
|
const handleInlineFindNext = useCallback(() => {
|
|
2653
2905
|
if (inlineFindResults.length === 0) {
|
|
2654
2906
|
refreshInlineFindResults(inlineFindQuery, 0);
|
|
@@ -2667,6 +2919,26 @@ export const WordReviewEditor = forwardRef<WordReviewEditorRef, WordReviewEditor
|
|
|
2667
2919
|
navigateInlineFindResult,
|
|
2668
2920
|
refreshInlineFindResults,
|
|
2669
2921
|
]);
|
|
2922
|
+
const handleInlineReplaceCurrent = useCallback(() => {
|
|
2923
|
+
const result = inlineFindResults[inlineFindActiveIndex];
|
|
2924
|
+
if (!result) {
|
|
2925
|
+
refreshInlineFindResults(inlineFindQuery, 0);
|
|
2926
|
+
return;
|
|
2927
|
+
}
|
|
2928
|
+
applyRuntimeSelection(
|
|
2929
|
+
activeRuntime,
|
|
2930
|
+
createSelectionFromAnchor(result.anchor, result.storyTarget),
|
|
2931
|
+
);
|
|
2932
|
+
activeRuntime.replaceText(inlineReplaceText);
|
|
2933
|
+
refreshInlineFindResults(inlineFindQuery, inlineFindActiveIndex);
|
|
2934
|
+
}, [
|
|
2935
|
+
activeRuntime,
|
|
2936
|
+
inlineFindActiveIndex,
|
|
2937
|
+
inlineFindQuery,
|
|
2938
|
+
inlineFindResults,
|
|
2939
|
+
inlineReplaceText,
|
|
2940
|
+
refreshInlineFindResults,
|
|
2941
|
+
]);
|
|
2670
2942
|
const handleInlineFindPrevious = useCallback(() => {
|
|
2671
2943
|
if (inlineFindResults.length === 0) {
|
|
2672
2944
|
refreshInlineFindResults(inlineFindQuery, 0);
|
|
@@ -2685,6 +2957,127 @@ export const WordReviewEditor = forwardRef<WordReviewEditorRef, WordReviewEditor
|
|
|
2685
2957
|
navigateInlineFindResult,
|
|
2686
2958
|
refreshInlineFindResults,
|
|
2687
2959
|
]);
|
|
2960
|
+
const navigationSearchScopes = useMemo<readonly NavigationSearchScopeOption[]>(
|
|
2961
|
+
() => [
|
|
2962
|
+
{ id: "main", label: "Main" },
|
|
2963
|
+
{
|
|
2964
|
+
id: "story",
|
|
2965
|
+
label: storyTargetLabel(snapshot.activeStory),
|
|
2966
|
+
disabled: snapshot.activeStory.kind === "main",
|
|
2967
|
+
disabledReason: "Already searching the main story.",
|
|
2968
|
+
},
|
|
2969
|
+
{
|
|
2970
|
+
id: "scope",
|
|
2971
|
+
label: "Scope",
|
|
2972
|
+
disabled: !interactionGuardSnapshot.matchedScopeId,
|
|
2973
|
+
disabledReason: "No workflow scope covers the current selection.",
|
|
2974
|
+
},
|
|
2975
|
+
],
|
|
2976
|
+
[interactionGuardSnapshot.matchedScopeId, snapshot.activeStory],
|
|
2977
|
+
);
|
|
2978
|
+
const navigationGoToGroups = useMemo<readonly NavigationGoToGroup[]>(
|
|
2979
|
+
() =>
|
|
2980
|
+
buildNavigationGoToGroups({
|
|
2981
|
+
documentNavigation,
|
|
2982
|
+
comments: snapshot.comments.threads,
|
|
2983
|
+
revisions: snapshot.trackedChanges.revisions,
|
|
2984
|
+
workflowScopeSnapshot,
|
|
2985
|
+
}),
|
|
2986
|
+
[
|
|
2987
|
+
documentNavigation,
|
|
2988
|
+
snapshot.comments.threads,
|
|
2989
|
+
snapshot.trackedChanges.revisions,
|
|
2990
|
+
workflowScopeSnapshot,
|
|
2991
|
+
],
|
|
2992
|
+
);
|
|
2993
|
+
const handleNavigationModeChange = useCallback(
|
|
2994
|
+
(mode: NavigationCommandMode) => {
|
|
2995
|
+
setNavigationCommandMode(mode);
|
|
2996
|
+
if (mode !== "go-to" && inlineFindQuery.trim()) {
|
|
2997
|
+
refreshInlineFindResults(inlineFindQuery, inlineFindActiveIndex);
|
|
2998
|
+
}
|
|
2999
|
+
},
|
|
3000
|
+
[inlineFindActiveIndex, inlineFindQuery, refreshInlineFindResults],
|
|
3001
|
+
);
|
|
3002
|
+
const handleGoToTarget = useCallback(
|
|
3003
|
+
(groupId: string, itemId: string) => {
|
|
3004
|
+
const group = navigationGoToGroups.find((candidate) => candidate.id === groupId);
|
|
3005
|
+
const item = group?.items.find((candidate) => candidate.id === itemId);
|
|
3006
|
+
if (!group || !item) return;
|
|
3007
|
+
|
|
3008
|
+
if (group.id === "pages") {
|
|
3009
|
+
const page = documentNavigation.pages.find(
|
|
3010
|
+
(candidate) => `page:${candidate.pageIndex}` === item.id,
|
|
3011
|
+
);
|
|
3012
|
+
if (!page) return;
|
|
3013
|
+
applyRuntimeSelection(
|
|
3014
|
+
activeRuntime,
|
|
3015
|
+
createCollapsedPublicSelection(page.startOffset),
|
|
3016
|
+
);
|
|
3017
|
+
handleCloseInlineFind();
|
|
3018
|
+
return;
|
|
3019
|
+
}
|
|
3020
|
+
|
|
3021
|
+
if (group.id === "headings") {
|
|
3022
|
+
const heading = documentNavigation.headings.find(
|
|
3023
|
+
(candidate) => `heading:${candidate.headingId}` === item.id,
|
|
3024
|
+
);
|
|
3025
|
+
if (!heading) return;
|
|
3026
|
+
applyRuntimeSelection(
|
|
3027
|
+
activeRuntime,
|
|
3028
|
+
createCollapsedPublicSelection(heading.offset),
|
|
3029
|
+
);
|
|
3030
|
+
handleCloseInlineFind();
|
|
3031
|
+
return;
|
|
3032
|
+
}
|
|
3033
|
+
|
|
3034
|
+
if (group.id === "comments") {
|
|
3035
|
+
const comment = snapshot.comments.threads.find(
|
|
3036
|
+
(candidate) => `comment:${candidate.commentId}` === item.id,
|
|
3037
|
+
);
|
|
3038
|
+
if (!comment) return;
|
|
3039
|
+
applyRuntimeSelection(activeRuntime, createSelectionFromAnchor(comment.anchor));
|
|
3040
|
+
activeRuntime.openComment(comment.commentId);
|
|
3041
|
+
handleCloseInlineFind();
|
|
3042
|
+
return;
|
|
3043
|
+
}
|
|
3044
|
+
|
|
3045
|
+
if (group.id === "changes") {
|
|
3046
|
+
const revision = snapshot.trackedChanges.revisions.find(
|
|
3047
|
+
(candidate) => `change:${candidate.revisionId}` === item.id,
|
|
3048
|
+
);
|
|
3049
|
+
if (!revision) return;
|
|
3050
|
+
applyRuntimeSelection(
|
|
3051
|
+
activeRuntime,
|
|
3052
|
+
createSelectionFromAnchor(revision.anchor, revision.storyTarget),
|
|
3053
|
+
);
|
|
3054
|
+
handleCloseInlineFind();
|
|
3055
|
+
return;
|
|
3056
|
+
}
|
|
3057
|
+
|
|
3058
|
+
if (group.id === "scopes") {
|
|
3059
|
+
const scope = workflowScopeSnapshot?.scopes.find(
|
|
3060
|
+
(candidate) => `scope:${candidate.scopeId}` === item.id,
|
|
3061
|
+
);
|
|
3062
|
+
if (!scope) return;
|
|
3063
|
+
applyRuntimeSelection(
|
|
3064
|
+
activeRuntime,
|
|
3065
|
+
createSelectionFromAnchor(scope.anchor, scope.storyTarget),
|
|
3066
|
+
);
|
|
3067
|
+
handleCloseInlineFind();
|
|
3068
|
+
}
|
|
3069
|
+
},
|
|
3070
|
+
[
|
|
3071
|
+
activeRuntime,
|
|
3072
|
+
documentNavigation.headings,
|
|
3073
|
+
documentNavigation.pages,
|
|
3074
|
+
handleCloseInlineFind,
|
|
3075
|
+
navigationGoToGroups,
|
|
3076
|
+
snapshot.comments.threads,
|
|
3077
|
+
snapshot.trackedChanges.revisions,
|
|
3078
|
+
workflowScopeSnapshot?.scopes,
|
|
3079
|
+
],
|
|
3080
|
+
);
|
|
2688
3081
|
const suggestionsSnapshot = activeRuntime.getSuggestionsSnapshot();
|
|
2689
3082
|
const caretCommentPoint =
|
|
2690
3083
|
snapshot.selection.isCollapsed && snapshot.selection.activeRange.kind === "range"
|
|
@@ -3117,11 +3510,19 @@ export const WordReviewEditor = forwardRef<WordReviewEditorRef, WordReviewEditor
|
|
|
3117
3510
|
shortcut.shortcut === "zoom-out" ? "out" : "reset";
|
|
3118
3511
|
onZoomRequested(direction);
|
|
3119
3512
|
handled = true;
|
|
3120
|
-
} else if (shortcut.shortcut === "replace"
|
|
3121
|
-
onReplaceRequested
|
|
3513
|
+
} else if (shortcut.shortcut === "replace") {
|
|
3514
|
+
if (onReplaceRequested) {
|
|
3515
|
+
onReplaceRequested({ selectionText: "", selectionRange: snapshot.selection });
|
|
3516
|
+
} else {
|
|
3517
|
+
handleOpenInlineReplace();
|
|
3518
|
+
}
|
|
3122
3519
|
handled = true;
|
|
3123
|
-
} else if (shortcut.shortcut === "go-to"
|
|
3124
|
-
onGoToRequested
|
|
3520
|
+
} else if (shortcut.shortcut === "go-to") {
|
|
3521
|
+
if (onGoToRequested) {
|
|
3522
|
+
onGoToRequested({ selectionText: "", selectionRange: snapshot.selection });
|
|
3523
|
+
} else {
|
|
3524
|
+
handleOpenInlineGoTo();
|
|
3525
|
+
}
|
|
3125
3526
|
handled = true;
|
|
3126
3527
|
} else if (shortcut.shortcut === "spell" && onSpellRequested) {
|
|
3127
3528
|
onSpellRequested({ selectionText: "", selectionRange: snapshot.selection });
|
|
@@ -3619,6 +4020,10 @@ export const WordReviewEditor = forwardRef<WordReviewEditorRef, WordReviewEditor
|
|
|
3619
4020
|
// Browser-native clipboard commands are best-effort fallbacks.
|
|
3620
4021
|
}
|
|
3621
4022
|
};
|
|
4023
|
+
const createAgentRequestId = () =>
|
|
4024
|
+
typeof crypto !== "undefined" && typeof crypto.randomUUID === "function"
|
|
4025
|
+
? `req-${crypto.randomUUID()}`
|
|
4026
|
+
: `req-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
|
|
3622
4027
|
|
|
3623
4028
|
const defaultHost: EditorActionHostCallbacks = {
|
|
3624
4029
|
onUndo: commands.onUndo,
|
|
@@ -3677,11 +4082,11 @@ export const WordReviewEditor = forwardRef<WordReviewEditorRef, WordReviewEditor
|
|
|
3677
4082
|
: handleOpenInlineFind,
|
|
3678
4083
|
onReplaceRequested: onReplaceRequested
|
|
3679
4084
|
? () => onReplaceRequested({ selectionText: "", selectionRange: snapshot.selection })
|
|
3680
|
-
:
|
|
4085
|
+
: handleOpenInlineReplace,
|
|
3681
4086
|
onPrintRequested,
|
|
3682
4087
|
onGoToRequested: onGoToRequested
|
|
3683
4088
|
? () => onGoToRequested({ selectionText: "", selectionRange: snapshot.selection })
|
|
3684
|
-
:
|
|
4089
|
+
: handleOpenInlineGoTo,
|
|
3685
4090
|
onInsertRowAbove: commands.onAddRowBefore,
|
|
3686
4091
|
onInsertRowBelow: commands.onAddRowAfter,
|
|
3687
4092
|
onInsertColumnBefore: commands.onAddColumnBefore,
|
|
@@ -3691,6 +4096,17 @@ export const WordReviewEditor = forwardRef<WordReviewEditorRef, WordReviewEditor
|
|
|
3691
4096
|
onDeleteTable: commands.onDeleteTable,
|
|
3692
4097
|
onMergeCells: commands.onMergeCells,
|
|
3693
4098
|
onSplitCell: commands.onSplitCell,
|
|
4099
|
+
onAskAgentForSelection: () => {
|
|
4100
|
+
const { selection } = snapshot;
|
|
4101
|
+
onEventRef.current?.({
|
|
4102
|
+
type: "agent-on-selection-requested",
|
|
4103
|
+
documentId,
|
|
4104
|
+
requestId: createAgentRequestId(),
|
|
4105
|
+
anchor: selection.activeRange,
|
|
4106
|
+
...(selection.storyTarget ? { storyTarget: selection.storyTarget } : {}),
|
|
4107
|
+
selectionText: "",
|
|
4108
|
+
});
|
|
4109
|
+
},
|
|
3694
4110
|
};
|
|
3695
4111
|
|
|
3696
4112
|
return editorActionHost
|
|
@@ -3701,10 +4117,13 @@ export const WordReviewEditor = forwardRef<WordReviewEditorRef, WordReviewEditor
|
|
|
3701
4117
|
commands,
|
|
3702
4118
|
editorActionHost,
|
|
3703
4119
|
handleOpenInlineFind,
|
|
4120
|
+
handleOpenInlineGoTo,
|
|
4121
|
+
handleOpenInlineReplace,
|
|
3704
4122
|
onFindRequested,
|
|
3705
4123
|
onGoToRequested,
|
|
3706
4124
|
onPrintRequested,
|
|
3707
4125
|
onReplaceRequested,
|
|
4126
|
+
documentId,
|
|
3708
4127
|
snapshot.selection,
|
|
3709
4128
|
styleCatalog,
|
|
3710
4129
|
]);
|
|
@@ -3730,7 +4149,7 @@ export const WordReviewEditor = forwardRef<WordReviewEditorRef, WordReviewEditor
|
|
|
3730
4149
|
documentNavigation={documentNavigation}
|
|
3731
4150
|
reviewMode={reviewMode}
|
|
3732
4151
|
markupDisplay={liveMarkupDisplay}
|
|
3733
|
-
|
|
4152
|
+
unsupportedObjectPreviewsVisible={effectiveShowUnsupportedPreviews}
|
|
3734
4153
|
activeRevisionId={activeRevisionId}
|
|
3735
4154
|
activeSelectionToolKind={activeSelectionTool?.kind ?? null}
|
|
3736
4155
|
showTrackedChanges={showTrackedChanges}
|
|
@@ -3874,13 +4293,25 @@ export const WordReviewEditor = forwardRef<WordReviewEditorRef, WordReviewEditor
|
|
|
3874
4293
|
onOpenInlineFind={handleOpenInlineFind}
|
|
3875
4294
|
inlineFindBar={
|
|
3876
4295
|
inlineFindOpen ? (
|
|
3877
|
-
<
|
|
4296
|
+
<TwNavigationCommandBar
|
|
4297
|
+
mode={navigationCommandMode}
|
|
3878
4298
|
query={inlineFindQuery}
|
|
4299
|
+
replacement={inlineReplaceText}
|
|
3879
4300
|
activeIndex={inlineFindActiveIndex}
|
|
3880
4301
|
resultCount={inlineFindResults.length}
|
|
4302
|
+
searchScope={inlineSearchScope}
|
|
4303
|
+
searchScopes={navigationSearchScopes}
|
|
4304
|
+
goToGroups={navigationGoToGroups}
|
|
4305
|
+
activeGoToGroupId={activeGoToGroupId}
|
|
4306
|
+
onModeChange={handleNavigationModeChange}
|
|
3881
4307
|
onQueryChange={handleInlineFindQueryChange}
|
|
4308
|
+
onReplacementChange={setInlineReplaceText}
|
|
4309
|
+
onSearchScopeChange={handleInlineSearchScopeChange}
|
|
3882
4310
|
onPrevious={handleInlineFindPrevious}
|
|
3883
4311
|
onNext={handleInlineFindNext}
|
|
4312
|
+
onReplaceCurrent={handleInlineReplaceCurrent}
|
|
4313
|
+
onGoToGroupChange={setActiveGoToGroupId}
|
|
4314
|
+
onGoToTarget={handleGoToTarget}
|
|
3884
4315
|
onClose={handleCloseInlineFind}
|
|
3885
4316
|
/>
|
|
3886
4317
|
) : null
|
|
@@ -3930,6 +4361,7 @@ export const WordReviewEditor = forwardRef<WordReviewEditorRef, WordReviewEditor
|
|
|
3930
4361
|
});
|
|
3931
4362
|
}}
|
|
3932
4363
|
onDeselectObject={() => activeRuntime.deselectObject()}
|
|
4364
|
+
onBeginObjectDrag={(input) => api.ui!.surface.beginObjectDrag(input)}
|
|
3933
4365
|
onScopeAskAgent={(payload) => {
|
|
3934
4366
|
// Resolve scope card + story through the mounted UI API seam so
|
|
3935
4367
|
// the shell root does not re-own workflow facet reads.
|
|
@@ -4248,6 +4680,82 @@ function wrapSearchResultIndex(index: number, resultCount: number): number {
|
|
|
4248
4680
|
return ((index % resultCount) + resultCount) % resultCount;
|
|
4249
4681
|
}
|
|
4250
4682
|
|
|
4683
|
+
function storyTargetLabel(target: EditorStoryTarget): string {
|
|
4684
|
+
switch (target.kind) {
|
|
4685
|
+
case "main":
|
|
4686
|
+
return "Story";
|
|
4687
|
+
case "header":
|
|
4688
|
+
return "Header";
|
|
4689
|
+
case "footer":
|
|
4690
|
+
return "Footer";
|
|
4691
|
+
case "footnote":
|
|
4692
|
+
return "Footnote";
|
|
4693
|
+
case "endnote":
|
|
4694
|
+
return "Endnote";
|
|
4695
|
+
}
|
|
4696
|
+
}
|
|
4697
|
+
|
|
4698
|
+
function buildNavigationGoToGroups(input: {
|
|
4699
|
+
documentNavigation: DocumentNavigationSnapshot;
|
|
4700
|
+
comments: readonly CommentSidebarThreadSnapshot[];
|
|
4701
|
+
revisions: readonly TrackedChangeEntrySnapshot[];
|
|
4702
|
+
workflowScopeSnapshot: WorkflowScopeSnapshot | null;
|
|
4703
|
+
}): readonly NavigationGoToGroup[] {
|
|
4704
|
+
const { documentNavigation, comments, revisions, workflowScopeSnapshot } = input;
|
|
4705
|
+
return [
|
|
4706
|
+
{
|
|
4707
|
+
id: "pages",
|
|
4708
|
+
label: "Pages",
|
|
4709
|
+
emptyLabel: "No page targets available.",
|
|
4710
|
+
items: documentNavigation.pages.map((page) => ({
|
|
4711
|
+
id: `page:${page.pageIndex}`,
|
|
4712
|
+
label: `Page ${page.pageIndex + 1}`,
|
|
4713
|
+
detail: `Section ${page.sectionIndex + 1}`,
|
|
4714
|
+
})),
|
|
4715
|
+
},
|
|
4716
|
+
{
|
|
4717
|
+
id: "headings",
|
|
4718
|
+
label: "Headings",
|
|
4719
|
+
emptyLabel: "No headings in this document.",
|
|
4720
|
+
items: documentNavigation.headings.map((heading) => ({
|
|
4721
|
+
id: `heading:${heading.headingId}`,
|
|
4722
|
+
label: heading.text || `Heading ${heading.headingId}`,
|
|
4723
|
+
detail: `Level ${heading.level} · Page ${heading.pageIndex + 1}`,
|
|
4724
|
+
})),
|
|
4725
|
+
},
|
|
4726
|
+
{
|
|
4727
|
+
id: "comments",
|
|
4728
|
+
label: "Comments",
|
|
4729
|
+
emptyLabel: "No comments in this document.",
|
|
4730
|
+
items: comments.map((comment) => ({
|
|
4731
|
+
id: `comment:${comment.commentId}`,
|
|
4732
|
+
label: comment.anchorLabel || comment.excerpt || "Comment",
|
|
4733
|
+
detail: `${comment.status} · ${comment.excerpt || `${comment.entryCount} entries`}`,
|
|
4734
|
+
})),
|
|
4735
|
+
},
|
|
4736
|
+
{
|
|
4737
|
+
id: "changes",
|
|
4738
|
+
label: "Changes",
|
|
4739
|
+
emptyLabel: "No tracked changes in this document.",
|
|
4740
|
+
items: revisions.map((revision) => ({
|
|
4741
|
+
id: `change:${revision.revisionId}`,
|
|
4742
|
+
label: revision.label || revision.anchorLabel || "Tracked change",
|
|
4743
|
+
detail: `${revision.kind} · ${revision.status}`,
|
|
4744
|
+
})),
|
|
4745
|
+
},
|
|
4746
|
+
{
|
|
4747
|
+
id: "scopes",
|
|
4748
|
+
label: "Scopes",
|
|
4749
|
+
emptyLabel: "No workflow scopes available.",
|
|
4750
|
+
items: (workflowScopeSnapshot?.scopes ?? []).map((scope) => ({
|
|
4751
|
+
id: `scope:${scope.scopeId}`,
|
|
4752
|
+
label: scope.label || scope.scopeId,
|
|
4753
|
+
detail: `${scope.mode}${scope.workItemId ? ` · ${scope.workItemId}` : ""}`,
|
|
4754
|
+
})),
|
|
4755
|
+
},
|
|
4756
|
+
];
|
|
4757
|
+
}
|
|
4758
|
+
|
|
4251
4759
|
function readTableRowCantSplit(
|
|
4252
4760
|
document: CanonicalDocumentEnvelope,
|
|
4253
4761
|
tableBlockIndex: number,
|