@beyondwork/docx-react-component 1.0.28 → 1.0.30
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 +26 -37
- package/src/api/public-types.ts +531 -0
- package/src/api/session-state.ts +2 -0
- package/src/core/commands/index.ts +201 -79
- package/src/core/commands/table-structure-commands.ts +138 -5
- package/src/core/state/text-transaction.ts +370 -3
- package/src/index.ts +41 -0
- package/src/io/docx-session.ts +318 -25
- package/src/io/export/serialize-footnotes.ts +41 -46
- package/src/io/export/serialize-headers-footers.ts +36 -40
- package/src/io/export/serialize-main-document.ts +55 -89
- package/src/io/export/serialize-numbering.ts +104 -4
- package/src/io/export/serialize-runtime-revisions.ts +196 -2
- package/src/io/export/split-story-blocks-for-runtime-revisions.ts +252 -0
- package/src/io/export/table-properties-xml.ts +318 -0
- package/src/io/normalize/normalize-text.ts +34 -3
- package/src/io/ooxml/parse-comments.ts +6 -0
- package/src/io/ooxml/parse-footnotes.ts +69 -13
- package/src/io/ooxml/parse-headers-footers.ts +54 -11
- package/src/io/ooxml/parse-main-document.ts +112 -42
- package/src/io/ooxml/parse-numbering.ts +341 -26
- package/src/io/ooxml/parse-revisions.ts +118 -4
- package/src/io/ooxml/parse-styles.ts +176 -0
- package/src/io/ooxml/parse-tables.ts +34 -25
- package/src/io/ooxml/revision-boundaries.ts +127 -3
- package/src/io/ooxml/workflow-payload.ts +544 -0
- package/src/model/canonical-document.ts +91 -1
- package/src/model/snapshot.ts +112 -1
- package/src/preservation/store.ts +73 -3
- package/src/review/store/comment-store.ts +19 -1
- package/src/review/store/revision-actions.ts +29 -0
- package/src/review/store/revision-store.ts +12 -1
- package/src/review/store/revision-types.ts +11 -0
- package/src/runtime/context-analytics.ts +824 -0
- package/src/runtime/document-locations.ts +521 -0
- package/src/runtime/document-navigation.ts +14 -1
- package/src/runtime/document-outline.ts +440 -0
- package/src/runtime/document-runtime.ts +941 -45
- package/src/runtime/event-refresh-hints.ts +137 -0
- package/src/runtime/numbering-prefix.ts +67 -39
- package/src/runtime/page-layout-estimation.ts +100 -7
- package/src/runtime/resolved-numbering-geometry.ts +293 -0
- package/src/runtime/session-capabilities.ts +2 -2
- package/src/runtime/suggestions-snapshot.ts +137 -0
- package/src/runtime/surface-projection.ts +223 -27
- package/src/runtime/table-style-resolver.ts +409 -0
- package/src/runtime/view-state.ts +17 -1
- package/src/runtime/workflow-markup.ts +54 -14
- package/src/ui/WordReviewEditor.tsx +1269 -87
- package/src/ui/editor-command-bag.ts +7 -0
- package/src/ui/editor-runtime-boundary.ts +111 -10
- package/src/ui/editor-shell-view.tsx +17 -15
- package/src/ui/editor-surface-controller.tsx +5 -0
- package/src/ui/headless/selection-tool-context.ts +19 -0
- package/src/ui/headless/selection-tool-resolver.ts +752 -0
- package/src/ui/headless/selection-tool-types.ts +129 -0
- package/src/ui/headless/selection-toolbar-model.ts +10 -33
- package/src/ui/runtime-shortcut-dispatch.ts +365 -0
- package/src/ui-tailwind/chrome/chrome-preset-model.ts +107 -0
- package/src/ui-tailwind/chrome/chrome-preset-toolbar.tsx +15 -0
- package/src/ui-tailwind/chrome/review-queue-bar.tsx +97 -0
- package/src/ui-tailwind/chrome/tw-context-analytics-summary.tsx +122 -0
- package/src/ui-tailwind/chrome/tw-image-context-toolbar.tsx +1 -9
- package/src/ui-tailwind/chrome/tw-object-context-toolbar.tsx +1 -5
- package/src/ui-tailwind/chrome/tw-page-ruler.tsx +8 -29
- package/src/ui-tailwind/chrome/tw-selection-tool-blocked.tsx +23 -0
- package/src/ui-tailwind/chrome/tw-selection-tool-comment.tsx +35 -0
- package/src/ui-tailwind/chrome/tw-selection-tool-formatting.tsx +37 -0
- package/src/ui-tailwind/chrome/tw-selection-tool-host.tsx +298 -0
- package/src/ui-tailwind/chrome/tw-selection-tool-structure.tsx +116 -0
- package/src/ui-tailwind/chrome/tw-selection-tool-suggestion.tsx +29 -0
- package/src/ui-tailwind/chrome/tw-selection-tool-workflow.tsx +27 -0
- package/src/ui-tailwind/chrome/tw-selection-toolbar.tsx +3 -3
- package/src/ui-tailwind/chrome/tw-suggestion-card.tsx +3 -3
- package/src/ui-tailwind/chrome/tw-table-context-toolbar.tsx +86 -14
- package/src/ui-tailwind/editor-surface/pm-command-bridge.ts +57 -52
- package/src/ui-tailwind/editor-surface/pm-decorations.ts +36 -52
- package/src/ui-tailwind/editor-surface/pm-schema.ts +56 -5
- package/src/ui-tailwind/editor-surface/pm-state-from-snapshot.ts +87 -24
- package/src/ui-tailwind/editor-surface/surface-build-keys.ts +4 -0
- package/src/ui-tailwind/editor-surface/tw-prosemirror-surface.tsx +135 -32
- package/src/ui-tailwind/editor-surface/tw-table-node-view.tsx +74 -7
- package/src/ui-tailwind/review/tw-comment-sidebar.tsx +17 -17
- package/src/ui-tailwind/review/tw-review-rail.tsx +19 -17
- package/src/ui-tailwind/review/tw-revision-sidebar.tsx +10 -10
- package/src/ui-tailwind/status/tw-status-bar.tsx +10 -6
- package/src/ui-tailwind/theme/editor-theme.css +58 -40
- package/src/ui-tailwind/toolbar/tw-toolbar-icon-button.tsx +4 -4
- package/src/ui-tailwind/toolbar/tw-toolbar.tsx +250 -181
- package/src/ui-tailwind/tw-review-workspace.tsx +323 -280
- package/src/validation/compatibility-engine.ts +246 -2
- package/src/validation/docx-comment-proof.ts +24 -11
|
@@ -14,6 +14,7 @@ import * as Tooltip from "@radix-ui/react-tooltip";
|
|
|
14
14
|
import { ChevronLeft, ChevronRight, List } from "lucide-react";
|
|
15
15
|
|
|
16
16
|
import type {
|
|
17
|
+
ActiveListContext,
|
|
17
18
|
CommentSidebarThreadSnapshot,
|
|
18
19
|
DocumentNavigationSnapshot,
|
|
19
20
|
EditorViewStateSnapshot,
|
|
@@ -22,12 +23,16 @@ import type {
|
|
|
22
23
|
HeaderFooterLinkPatch,
|
|
23
24
|
InteractionGuardSnapshot,
|
|
24
25
|
InsertImageOptions,
|
|
26
|
+
RuntimeContextAnalyticsSnapshot,
|
|
25
27
|
RuntimeRenderSnapshot,
|
|
28
|
+
ReviewQueueSnapshot,
|
|
26
29
|
SectionPageNumberingPatch,
|
|
27
30
|
SectionBreakType,
|
|
28
31
|
StyleCatalogSnapshot,
|
|
29
32
|
SurfaceBlockSnapshot,
|
|
30
33
|
TrackedChangeEntrySnapshot,
|
|
34
|
+
WordReviewEditorChromeOptions,
|
|
35
|
+
WordReviewEditorChromePreset,
|
|
31
36
|
WordReviewEditorChromeVisibility,
|
|
32
37
|
WorkflowScopeSnapshot,
|
|
33
38
|
WorkspaceMode,
|
|
@@ -48,24 +53,26 @@ import {
|
|
|
48
53
|
import { computeLineMarkersIfEnabled } from "./page-chrome-model.ts";
|
|
49
54
|
import type { SessionCapabilities } from "../runtime/session-capabilities";
|
|
50
55
|
import type {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
} from "../ui/headless/selection-toolbar-model";
|
|
56
|
+
ActiveSelectionToolModel,
|
|
57
|
+
SelectionToolAnchor,
|
|
58
|
+
} from "../ui/headless/selection-tool-types";
|
|
55
59
|
import type { MarkupDisplay } from "../ui/headless/comment-decoration-model";
|
|
56
60
|
import type { EditorCommandBag } from "../ui/editor-command-bag.ts";
|
|
57
61
|
import { preserveEditorSelectionMouseDown } from "../ui/headless/preserve-editor-selection";
|
|
58
62
|
import { TwAlertBanner } from "./chrome/tw-alert-banner";
|
|
59
|
-
import { TwImageContextToolbar, type ActiveImageContext } from "./chrome/tw-image-context-toolbar";
|
|
60
63
|
import { TwLayoutPanel } from "./chrome/tw-layout-panel";
|
|
61
|
-
import { TwObjectContextToolbar, type ActiveObjectContext } from "./chrome/tw-object-context-toolbar";
|
|
62
64
|
import { TwPageRuler } from "./chrome/tw-page-ruler";
|
|
63
|
-
import {
|
|
64
|
-
import {
|
|
65
|
-
|
|
65
|
+
import { ChromePresetToolbar } from "./chrome/chrome-preset-toolbar";
|
|
66
|
+
import {
|
|
67
|
+
resolveChromePreset,
|
|
68
|
+
resolveChromePresetOptions,
|
|
69
|
+
resolveChromeVisibilityForPreset,
|
|
70
|
+
} from "./chrome/chrome-preset-model";
|
|
71
|
+
import { TwReviewQueueBar } from "./chrome/review-queue-bar";
|
|
72
|
+
import { TwSelectionToolHost } from "./chrome/tw-selection-tool-host";
|
|
66
73
|
import { TwReviewRail, type ReviewRailTab } from "./review/tw-review-rail";
|
|
67
74
|
import { TwStatusBar } from "./status/tw-status-bar";
|
|
68
|
-
import {
|
|
75
|
+
import { type ToolbarInteractionPolicy } from "./toolbar/tw-toolbar";
|
|
69
76
|
|
|
70
77
|
export type ReviewWorkspaceChromeVisibility = WordReviewEditorChromeVisibility;
|
|
71
78
|
|
|
@@ -80,6 +87,7 @@ export interface TwReviewWorkspaceProps {
|
|
|
80
87
|
workspaceMode: WorkspaceMode;
|
|
81
88
|
zoomLevel?: ZoomLevel;
|
|
82
89
|
formattingState?: FormattingStateSnapshot;
|
|
90
|
+
activeListContext?: ActiveListContext | null;
|
|
83
91
|
styleCatalog?: StyleCatalogSnapshot;
|
|
84
92
|
activeRailTab: ReviewRailTab;
|
|
85
93
|
activeCommentId?: string;
|
|
@@ -87,10 +95,15 @@ export interface TwReviewWorkspaceProps {
|
|
|
87
95
|
showTrackedChanges: boolean;
|
|
88
96
|
workflowScopeSnapshot?: WorkflowScopeSnapshot | null;
|
|
89
97
|
interactionGuardSnapshot?: InteractionGuardSnapshot;
|
|
98
|
+
chromePreset?: WordReviewEditorChromePreset;
|
|
99
|
+
chromeOptions?: Partial<WordReviewEditorChromeOptions>;
|
|
100
|
+
reviewQueue?: ReviewQueueSnapshot;
|
|
101
|
+
documentContextAnalytics?: RuntimeContextAnalyticsSnapshot | null;
|
|
102
|
+
selectionContextAnalytics?: RuntimeContextAnalyticsSnapshot | null;
|
|
103
|
+
currentScopeContextAnalytics?: RuntimeContextAnalyticsSnapshot | null;
|
|
90
104
|
commands: EditorCommandBag;
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
selectionToolbarAnchor?: SelectionToolbarAnchor | null;
|
|
105
|
+
activeSelectionTool?: ActiveSelectionToolModel | null;
|
|
106
|
+
selectionToolAnchor?: SelectionToolAnchor | null;
|
|
94
107
|
documentNavigation?: DocumentNavigationSnapshot;
|
|
95
108
|
onWorkspaceModeChange?: (value: WorkspaceMode) => void;
|
|
96
109
|
onZoomChange?: (level: ZoomLevel) => void;
|
|
@@ -112,6 +125,8 @@ export interface TwReviewWorkspaceProps {
|
|
|
112
125
|
onSetTextColor?: (color: string) => void;
|
|
113
126
|
onSetHighlightColor?: (color: string | null) => void;
|
|
114
127
|
onSetAlignment?: (alignment: FormattingAlignment) => void;
|
|
128
|
+
onToggleBulletedList?: () => void;
|
|
129
|
+
onToggleNumberedList?: () => void;
|
|
115
130
|
onOutdent?: () => void;
|
|
116
131
|
onIndent?: () => void;
|
|
117
132
|
onAddComment?: () => void;
|
|
@@ -130,8 +145,6 @@ export interface TwReviewWorkspaceProps {
|
|
|
130
145
|
onMergeCells?: () => void;
|
|
131
146
|
onSplitCell?: () => void;
|
|
132
147
|
onSetCellBackground?: (color: string) => void;
|
|
133
|
-
activeImageContext?: ActiveImageContext | null;
|
|
134
|
-
activeObjectContext?: ActiveObjectContext | null;
|
|
135
148
|
onSetImageLayout?: (
|
|
136
149
|
mediaId: string,
|
|
137
150
|
dimensions: { widthEmu: number; heightEmu: number },
|
|
@@ -205,6 +218,11 @@ export interface TwReviewWorkspaceProps {
|
|
|
205
218
|
onSetParagraphTabStops?: (tabStops: Array<{ pos: number; val?: string; leader?: string }>) => void;
|
|
206
219
|
onRestartNumbering?: () => void;
|
|
207
220
|
onContinueNumbering?: () => void;
|
|
221
|
+
onUpdateFields?: () => void;
|
|
222
|
+
onUpdateTableOfContents?: () => void;
|
|
223
|
+
onGoToPreviousReviewItem?: () => void;
|
|
224
|
+
onGoToNextReviewItem?: () => void;
|
|
225
|
+
onMarkSectionForReview?: () => void;
|
|
208
226
|
onNavigateHeading?: (headingId: string) => void;
|
|
209
227
|
chromeVisibility?: Partial<ReviewWorkspaceChromeVisibility>;
|
|
210
228
|
}
|
|
@@ -223,6 +241,10 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
|
|
|
223
241
|
const [layoutToolsOpen, setLayoutToolsOpen] = useState(false);
|
|
224
242
|
const zoomLevel = props.zoomLevel ?? 100;
|
|
225
243
|
const zoomScale = typeof zoomLevel === "number" ? zoomLevel / 100 : 1;
|
|
244
|
+
const pageZoomBucket =
|
|
245
|
+
!isPageWorkspace ? undefined : zoomScale < 1 ? "low" : zoomScale > 1 ? "high" : "base";
|
|
246
|
+
const chromePreset = resolveChromePreset(props.chromePreset, props.reviewMode);
|
|
247
|
+
const chromeOptions = resolveChromePresetOptions(chromePreset, props.chromeOptions);
|
|
226
248
|
const preserveOnlyCount = caps?.preserveOnlyCount ??
|
|
227
249
|
snapshot.compatibility.featureEntries.filter(
|
|
228
250
|
(entry) => entry.featureClass === "preserve-only",
|
|
@@ -231,16 +253,11 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
|
|
|
231
253
|
props.interactionGuardSnapshot?.blockedReasons ??
|
|
232
254
|
props.workflowScopeSnapshot?.blockedReasons ??
|
|
233
255
|
[];
|
|
234
|
-
const chromeVisibility
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
pageChrome: true,
|
|
240
|
-
statusBar: true,
|
|
241
|
-
reviewRail: true,
|
|
242
|
-
...props.chromeVisibility,
|
|
243
|
-
};
|
|
256
|
+
const chromeVisibility = resolveChromeVisibilityForPreset({
|
|
257
|
+
chromePreset,
|
|
258
|
+
chromeOptions,
|
|
259
|
+
chromeVisibility: props.chromeVisibility,
|
|
260
|
+
});
|
|
244
261
|
const showReviewRail = chromeVisibility.reviewRail && (caps?.reviewRailVisible ?? true);
|
|
245
262
|
const headings = props.documentNavigation?.headings ?? [];
|
|
246
263
|
const headerVariant = snapshot.pageLayout?.headerVariants[0]?.variant ?? "default";
|
|
@@ -249,21 +266,17 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
|
|
|
249
266
|
viewState.selection.activeRange.kind === "node"
|
|
250
267
|
? viewState.selection.activeRange.at
|
|
251
268
|
: viewState.selection.head;
|
|
269
|
+
const shouldResolveActiveParagraphLayout =
|
|
270
|
+
isPageWorkspace &&
|
|
271
|
+
chromeVisibility.pageChrome &&
|
|
272
|
+
layoutToolsOpen;
|
|
252
273
|
const activeParagraphLayout = useMemo(
|
|
253
|
-
() =>
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
274
|
+
() =>
|
|
275
|
+
shouldResolveActiveParagraphLayout
|
|
276
|
+
? resolveActiveParagraphLayout(snapshot.surface, selectionPosition)
|
|
277
|
+
: null,
|
|
278
|
+
[selectionPosition, shouldResolveActiveParagraphLayout, snapshot.surface],
|
|
258
279
|
);
|
|
259
|
-
const contextualSurface =
|
|
260
|
-
props.activeImageContext
|
|
261
|
-
? "image"
|
|
262
|
-
: props.activeObjectContext
|
|
263
|
-
? "object"
|
|
264
|
-
: isTableContext
|
|
265
|
-
? "table"
|
|
266
|
-
: null;
|
|
267
280
|
const pageChromeModel = useMemo(
|
|
268
281
|
() =>
|
|
269
282
|
buildPageChromeModel(
|
|
@@ -275,21 +288,32 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
|
|
|
275
288
|
[props.documentNavigation, snapshot.activeStory, snapshot.pageLayout, snapshot.surface],
|
|
276
289
|
);
|
|
277
290
|
const selectionToolbarPlacement = resolveSelectionToolbarPlacement(
|
|
278
|
-
props.
|
|
291
|
+
props.selectionToolAnchor,
|
|
279
292
|
selectionToolbarRootRef.current,
|
|
280
293
|
zoomScale,
|
|
281
294
|
);
|
|
295
|
+
const effectiveSelectionMode = props.interactionGuardSnapshot?.effectiveMode ?? "edit";
|
|
296
|
+
const allowLocalChromeMutations = Boolean(caps?.canEdit) && effectiveSelectionMode === "edit";
|
|
297
|
+
const gatedSelectionTool = useMemo(() => {
|
|
298
|
+
if (!props.activeSelectionTool) {
|
|
299
|
+
return null;
|
|
300
|
+
}
|
|
301
|
+
if (props.activeSelectionTool.kind === "structure-context" && !chromeVisibility.contextToolbars) {
|
|
302
|
+
return null;
|
|
303
|
+
}
|
|
304
|
+
return props.activeSelectionTool;
|
|
305
|
+
}, [props.activeSelectionTool, chromeVisibility.contextToolbars]);
|
|
282
306
|
const activePage = props.documentNavigation?.pages[props.documentNavigation.activePageIndex] ?? null;
|
|
283
307
|
const pageShellMetrics = useMemo(
|
|
284
308
|
() => buildPageShellMetrics(snapshot.pageLayout),
|
|
285
309
|
[snapshot.pageLayout],
|
|
286
310
|
);
|
|
311
|
+
const headerBandLabel = resolvePageBandLabel("header", snapshot.activeStory);
|
|
312
|
+
const footerBandLabel = resolvePageBandLabel("footer", snapshot.activeStory);
|
|
287
313
|
const hidePageBorderForActiveEditing =
|
|
288
314
|
isPageWorkspace &&
|
|
289
315
|
snapshot.activeStory.kind === "main" &&
|
|
290
316
|
shouldHidePageBorderForSelection(viewState.selection);
|
|
291
|
-
const effectiveSelectionMode = props.interactionGuardSnapshot?.effectiveMode ?? "edit";
|
|
292
|
-
const allowLocalChromeMutations = Boolean(caps?.canEdit) && effectiveSelectionMode === "edit";
|
|
293
317
|
const pageChromeReadOnly =
|
|
294
318
|
snapshot.readOnly ||
|
|
295
319
|
snapshot.activeStory.kind !== "main" ||
|
|
@@ -332,99 +356,126 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
|
|
|
332
356
|
return (
|
|
333
357
|
<Tooltip.Provider delayDuration={400}>
|
|
334
358
|
<div className="flex h-full flex-col bg-canvas text-primary">
|
|
335
|
-
{chromeVisibility.toolbar ?
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
props.
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
props.
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
props.
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
359
|
+
{chromeVisibility.toolbar ? (
|
|
360
|
+
<div className="px-3 pt-3">
|
|
361
|
+
<ChromePresetToolbar
|
|
362
|
+
chromePreset={chromePreset}
|
|
363
|
+
capabilities={caps}
|
|
364
|
+
compatibility={snapshot.compatibility}
|
|
365
|
+
warnings={snapshot.warnings}
|
|
366
|
+
blockedReasons={blockedReasons}
|
|
367
|
+
showDiagnosticsChrome={chromeVisibility.alerts}
|
|
368
|
+
interactionPolicy={toolbarInteractionPolicy}
|
|
369
|
+
workspaceMode={props.workspaceMode}
|
|
370
|
+
zoomLevel={props.zoomLevel}
|
|
371
|
+
formattingState={props.formattingState}
|
|
372
|
+
activeListContext={props.activeListContext}
|
|
373
|
+
styleCatalog={props.styleCatalog}
|
|
374
|
+
showTrackedChanges={props.showTrackedChanges}
|
|
375
|
+
onUndo={runWithSelectionToolbarDismiss(props.onUndo)}
|
|
376
|
+
onRedo={runWithSelectionToolbarDismiss(props.onRedo)}
|
|
377
|
+
onSetParagraphStyle={props.onSetParagraphStyle
|
|
378
|
+
? (styleId) => {
|
|
379
|
+
dismissSelectionToolbar();
|
|
380
|
+
props.onSetParagraphStyle?.(styleId);
|
|
381
|
+
}
|
|
382
|
+
: undefined}
|
|
383
|
+
onToggleBold={runWithSelectionToolbarDismiss(props.onToggleBold)}
|
|
384
|
+
onToggleItalic={runWithSelectionToolbarDismiss(props.onToggleItalic)}
|
|
385
|
+
onToggleUnderline={runWithSelectionToolbarDismiss(props.onToggleUnderline)}
|
|
386
|
+
onToggleStrikethrough={runWithSelectionToolbarDismiss(props.onToggleStrikethrough)}
|
|
387
|
+
onToggleSuperscript={runWithSelectionToolbarDismiss(props.onToggleSuperscript)}
|
|
388
|
+
onToggleSubscript={runWithSelectionToolbarDismiss(props.onToggleSubscript)}
|
|
389
|
+
onSetFontFamily={props.onSetFontFamily
|
|
390
|
+
? (fontFamily) => {
|
|
391
|
+
dismissSelectionToolbar();
|
|
392
|
+
props.onSetFontFamily?.(fontFamily);
|
|
393
|
+
}
|
|
394
|
+
: undefined}
|
|
395
|
+
onSetFontSize={props.onSetFontSize
|
|
396
|
+
? (fontSize) => {
|
|
397
|
+
dismissSelectionToolbar();
|
|
398
|
+
props.onSetFontSize?.(fontSize);
|
|
399
|
+
}
|
|
400
|
+
: undefined}
|
|
401
|
+
onSetTextColor={props.onSetTextColor
|
|
402
|
+
? (color) => {
|
|
403
|
+
dismissSelectionToolbar();
|
|
404
|
+
props.onSetTextColor?.(color);
|
|
405
|
+
}
|
|
406
|
+
: undefined}
|
|
407
|
+
onSetHighlightColor={props.onSetHighlightColor
|
|
408
|
+
? (color) => {
|
|
409
|
+
dismissSelectionToolbar();
|
|
410
|
+
props.onSetHighlightColor?.(color);
|
|
411
|
+
}
|
|
412
|
+
: undefined}
|
|
413
|
+
onSetAlignment={props.onSetAlignment
|
|
414
|
+
? (alignment) => {
|
|
415
|
+
dismissSelectionToolbar();
|
|
416
|
+
props.onSetAlignment?.(alignment);
|
|
417
|
+
}
|
|
418
|
+
: undefined}
|
|
419
|
+
onToggleBulletedList={runWithSelectionToolbarDismiss(props.onToggleBulletedList)}
|
|
420
|
+
onToggleNumberedList={runWithSelectionToolbarDismiss(props.onToggleNumberedList)}
|
|
421
|
+
onOutdent={runWithSelectionToolbarDismiss(props.onOutdent)}
|
|
422
|
+
onIndent={runWithSelectionToolbarDismiss(props.onIndent)}
|
|
423
|
+
onAddComment={runWithSelectionToolbarDismiss(props.onAddComment)}
|
|
424
|
+
onInsertPageBreak={runWithSelectionToolbarDismiss(props.onInsertPageBreak)}
|
|
425
|
+
onInsertTable={runWithSelectionToolbarDismiss(props.onInsertTable)}
|
|
426
|
+
onInsertSectionBreak={props.onInsertSectionBreak
|
|
427
|
+
? (type) => {
|
|
428
|
+
dismissSelectionToolbar();
|
|
429
|
+
props.onInsertSectionBreak?.(type);
|
|
430
|
+
}
|
|
431
|
+
: undefined}
|
|
432
|
+
onInsertImage={props.onInsertImage
|
|
433
|
+
? (options) => {
|
|
434
|
+
dismissSelectionToolbar();
|
|
435
|
+
props.onInsertImage?.(options);
|
|
436
|
+
}
|
|
437
|
+
: undefined}
|
|
438
|
+
onExport={runWithSelectionToolbarDismiss(props.onExport)}
|
|
439
|
+
activeStory={snapshot.activeStory}
|
|
440
|
+
onCloseStory={props.onCloseStory
|
|
441
|
+
? runWithSelectionToolbarDismiss(props.onCloseStory)
|
|
442
|
+
: undefined}
|
|
443
|
+
onWorkspaceModeChange={(value) => {
|
|
444
|
+
dismissSelectionToolbar();
|
|
445
|
+
props.onWorkspaceModeChange(value);
|
|
446
|
+
}}
|
|
447
|
+
onZoomChange={props.onZoomChange
|
|
448
|
+
? (level) => {
|
|
449
|
+
dismissSelectionToolbar();
|
|
450
|
+
props.onZoomChange?.(level);
|
|
451
|
+
}
|
|
452
|
+
: undefined}
|
|
453
|
+
onRestartNumbering={runWithSelectionToolbarDismiss(props.onRestartNumbering)}
|
|
454
|
+
onContinueNumbering={runWithSelectionToolbarDismiss(props.onContinueNumbering)}
|
|
455
|
+
onUpdateFields={runWithSelectionToolbarDismiss(props.onUpdateFields)}
|
|
456
|
+
onUpdateTableOfContents={runWithSelectionToolbarDismiss(props.onUpdateTableOfContents)}
|
|
457
|
+
onShowTrackedChangesChange={(show) => {
|
|
458
|
+
dismissSelectionToolbar();
|
|
459
|
+
props.onShowTrackedChangesChange(show);
|
|
460
|
+
}}
|
|
461
|
+
/>
|
|
462
|
+
</div>
|
|
463
|
+
) : null}
|
|
464
|
+
|
|
465
|
+
{chromePreset === "review" && chromeOptions.showReviewQueueBar && props.reviewQueue ? (
|
|
466
|
+
<TwReviewQueueBar
|
|
467
|
+
queue={props.reviewQueue}
|
|
468
|
+
onPrevious={props.onGoToPreviousReviewItem
|
|
469
|
+
? runWithSelectionToolbarDismiss(props.onGoToPreviousReviewItem)
|
|
470
|
+
: undefined}
|
|
471
|
+
onNext={props.onGoToNextReviewItem
|
|
472
|
+
? runWithSelectionToolbarDismiss(props.onGoToNextReviewItem)
|
|
473
|
+
: undefined}
|
|
474
|
+
onMarkSection={chromeOptions.showSectionTagAction && props.onMarkSectionForReview
|
|
475
|
+
? runWithSelectionToolbarDismiss(props.onMarkSectionForReview)
|
|
476
|
+
: undefined}
|
|
477
|
+
/>
|
|
478
|
+
) : null}
|
|
428
479
|
|
|
429
480
|
{chromeVisibility.alerts ? <TwAlertBanner
|
|
430
481
|
snapshot={snapshot}
|
|
@@ -527,16 +578,17 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
|
|
|
527
578
|
{/* Document column */}
|
|
528
579
|
<div className="flex flex-1 flex-col min-w-0">
|
|
529
580
|
<div
|
|
530
|
-
className=
|
|
581
|
+
className="flex-1 overflow-y-auto bg-surface"
|
|
531
582
|
data-wre-scroll-root="true"
|
|
532
583
|
>
|
|
533
584
|
<div
|
|
534
585
|
ref={selectionToolbarRootRef}
|
|
535
|
-
className={`mx-auto min-h-full ${
|
|
586
|
+
className={`mx-auto min-h-full w-full ${
|
|
536
587
|
isPageWorkspace
|
|
537
588
|
? "wre-page-chrome wre-page-surface relative max-w-[840px] my-8 overflow-hidden"
|
|
538
|
-
: "wre-canvas-surface relative
|
|
589
|
+
: "wre-canvas-surface relative my-8 overflow-hidden"
|
|
539
590
|
}`}
|
|
591
|
+
data-zoom-bucket={pageZoomBucket}
|
|
540
592
|
style={isPageWorkspace && zoomScale !== 1 ? { transform: `scale(${zoomScale})`, transformOrigin: "top center" } : undefined}
|
|
541
593
|
>
|
|
542
594
|
{isPageWorkspace && chromeVisibility.pageChrome && snapshot.pageLayout ? (
|
|
@@ -686,139 +738,47 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
|
|
|
686
738
|
/>
|
|
687
739
|
</div>
|
|
688
740
|
) : null}
|
|
689
|
-
{chromeVisibility.
|
|
690
|
-
<
|
|
691
|
-
{
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
{
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
dismissSelectionToolbar();
|
|
731
|
-
props.onSetImageFrame?.(mediaId, offsets);
|
|
732
|
-
}
|
|
733
|
-
: undefined}
|
|
734
|
-
/>
|
|
735
|
-
) : null}
|
|
736
|
-
{contextualSurface === "object" && props.activeObjectContext ? (
|
|
737
|
-
<TwObjectContextToolbar activeObject={props.activeObjectContext} />
|
|
738
|
-
) : null}
|
|
739
|
-
</div>
|
|
740
|
-
) : null}
|
|
741
|
-
{chromeVisibility.selectionOverlay && props.suggestionCard && selectionToolbarPlacement ? (
|
|
742
|
-
<div className="pointer-events-none absolute inset-0 z-20" data-testid="suggestion-card-overlay">
|
|
743
|
-
<div
|
|
744
|
-
className="pointer-events-auto absolute"
|
|
745
|
-
data-placement={selectionToolbarPlacement.placement}
|
|
746
|
-
style={selectionToolbarPlacement.style}
|
|
747
|
-
>
|
|
748
|
-
<TwSuggestionCard
|
|
749
|
-
model={props.suggestionCard}
|
|
750
|
-
onFocusCapture={props.onSelectionToolbarFocusCapture}
|
|
751
|
-
onBlurCapture={props.onSelectionToolbarBlurCapture}
|
|
752
|
-
onAccept={props.onAcceptSuggestion}
|
|
753
|
-
onReject={props.onRejectSuggestion}
|
|
754
|
-
onEditSuggestion={props.onEditSuggestion}
|
|
755
|
-
onAddComment={props.onAddCommentFromSuggestion ?? props.onAddComment}
|
|
756
|
-
/>
|
|
757
|
-
</div>
|
|
758
|
-
</div>
|
|
759
|
-
) : null}
|
|
760
|
-
{chromeVisibility.selectionOverlay && props.suggestionCard && !selectionToolbarPlacement ? (
|
|
761
|
-
<div
|
|
762
|
-
className="pointer-events-none absolute inset-x-0 top-0 z-20 flex justify-center px-4 pt-3"
|
|
763
|
-
data-testid="suggestion-card-fallback"
|
|
764
|
-
>
|
|
765
|
-
<div className="pointer-events-auto" data-placement="fallback">
|
|
766
|
-
<TwSuggestionCard
|
|
767
|
-
model={props.suggestionCard}
|
|
768
|
-
onFocusCapture={props.onSelectionToolbarFocusCapture}
|
|
769
|
-
onBlurCapture={props.onSelectionToolbarBlurCapture}
|
|
770
|
-
onAccept={props.onAcceptSuggestion}
|
|
771
|
-
onReject={props.onRejectSuggestion}
|
|
772
|
-
onEditSuggestion={props.onEditSuggestion}
|
|
773
|
-
onAddComment={props.onAddCommentFromSuggestion ?? props.onAddComment}
|
|
774
|
-
/>
|
|
775
|
-
</div>
|
|
776
|
-
</div>
|
|
777
|
-
) : null}
|
|
778
|
-
{chromeVisibility.selectionOverlay && props.selectionToolbar && !props.suggestionCard && selectionToolbarPlacement ? (
|
|
779
|
-
<div className="pointer-events-none absolute inset-0 z-20" data-testid="selection-toolbar-overlay">
|
|
780
|
-
<div
|
|
781
|
-
className="pointer-events-auto absolute"
|
|
782
|
-
data-placement={selectionToolbarPlacement.placement}
|
|
783
|
-
style={selectionToolbarPlacement.style}
|
|
784
|
-
>
|
|
785
|
-
<TwSelectionToolbar
|
|
786
|
-
ref={props.selectionToolbarRef}
|
|
787
|
-
model={props.selectionToolbar}
|
|
788
|
-
disabledReason={props.selectionToolbar.disabledReason}
|
|
789
|
-
onFocusCapture={props.onSelectionToolbarFocusCapture}
|
|
790
|
-
onBlurCapture={props.onSelectionToolbarBlurCapture}
|
|
791
|
-
onToggleBold={props.onToggleBold}
|
|
792
|
-
onToggleItalic={props.onToggleItalic}
|
|
793
|
-
onToggleUnderline={props.onToggleUnderline}
|
|
794
|
-
onSetTextColor={props.onSetSelectionTextColor}
|
|
795
|
-
onSetHighlightColor={props.onSetSelectionHighlightColor}
|
|
796
|
-
onAddComment={props.onAddCommentFromSelection ?? props.onAddComment}
|
|
797
|
-
/>
|
|
798
|
-
</div>
|
|
799
|
-
</div>
|
|
800
|
-
) : null}
|
|
801
|
-
{chromeVisibility.selectionOverlay && props.selectionToolbar && !props.suggestionCard && !selectionToolbarPlacement ? (
|
|
802
|
-
<div
|
|
803
|
-
className="pointer-events-none absolute inset-x-0 top-0 z-20 flex justify-center px-4 pt-3"
|
|
804
|
-
data-testid="selection-toolbar-fallback"
|
|
805
|
-
>
|
|
806
|
-
<div className="pointer-events-auto" data-placement="fallback">
|
|
807
|
-
<TwSelectionToolbar
|
|
808
|
-
ref={props.selectionToolbarRef}
|
|
809
|
-
model={props.selectionToolbar}
|
|
810
|
-
disabledReason={props.selectionToolbar.disabledReason}
|
|
811
|
-
onFocusCapture={props.onSelectionToolbarFocusCapture}
|
|
812
|
-
onBlurCapture={props.onSelectionToolbarBlurCapture}
|
|
813
|
-
onToggleBold={props.onToggleBold}
|
|
814
|
-
onToggleItalic={props.onToggleItalic}
|
|
815
|
-
onToggleUnderline={props.onToggleUnderline}
|
|
816
|
-
onSetTextColor={props.onSetSelectionTextColor}
|
|
817
|
-
onSetHighlightColor={props.onSetSelectionHighlightColor}
|
|
818
|
-
onAddComment={props.onAddCommentFromSelection ?? props.onAddComment}
|
|
819
|
-
/>
|
|
820
|
-
</div>
|
|
821
|
-
</div>
|
|
741
|
+
{chromeVisibility.selectionOverlay && gatedSelectionTool ? (
|
|
742
|
+
<TwSelectionToolHost
|
|
743
|
+
tool={gatedSelectionTool}
|
|
744
|
+
contextAnalytics={
|
|
745
|
+
chromeVisibility.contextAnalytics
|
|
746
|
+
? props.selectionContextAnalytics
|
|
747
|
+
: null
|
|
748
|
+
}
|
|
749
|
+
placement={selectionToolbarPlacement}
|
|
750
|
+
rootRef={props.selectionToolbarRef}
|
|
751
|
+
onFocusCapture={props.onSelectionToolbarFocusCapture}
|
|
752
|
+
onBlurCapture={props.onSelectionToolbarBlurCapture}
|
|
753
|
+
onToggleBold={props.onToggleBold}
|
|
754
|
+
onToggleItalic={props.onToggleItalic}
|
|
755
|
+
onToggleUnderline={props.onToggleUnderline}
|
|
756
|
+
onSetTextColor={props.onSetSelectionTextColor}
|
|
757
|
+
onSetHighlightColor={props.onSetSelectionHighlightColor}
|
|
758
|
+
onAddComment={
|
|
759
|
+
gatedSelectionTool.kind === "suggestion-review"
|
|
760
|
+
? (props.onAddCommentFromSuggestion ?? props.onAddComment)
|
|
761
|
+
: (props.onAddCommentFromSelection ?? props.onAddComment)
|
|
762
|
+
}
|
|
763
|
+
onAcceptSuggestion={props.onAcceptSuggestion}
|
|
764
|
+
onRejectSuggestion={props.onRejectSuggestion}
|
|
765
|
+
onEditSuggestion={props.onEditSuggestion}
|
|
766
|
+
onSetTableStyle={props.onSetTableStyle}
|
|
767
|
+
onAddRowBefore={props.onAddRowBefore}
|
|
768
|
+
onAddRowAfter={props.onAddRowAfter}
|
|
769
|
+
onAddColumnBefore={props.onAddColumnBefore}
|
|
770
|
+
onAddColumnAfter={props.onAddColumnAfter}
|
|
771
|
+
onDeleteRow={props.onDeleteRow}
|
|
772
|
+
onDeleteColumn={props.onDeleteColumn}
|
|
773
|
+
onDeleteTable={props.onDeleteTable}
|
|
774
|
+
onMergeCells={props.onMergeCells}
|
|
775
|
+
onSplitCell={props.onSplitCell}
|
|
776
|
+
onSetCellBackground={props.onSetCellBackground}
|
|
777
|
+
onSetImageLayout={props.onSetImageLayout}
|
|
778
|
+
onSetImageFrame={props.onSetImageFrame}
|
|
779
|
+
onRestartNumbering={props.onRestartNumbering}
|
|
780
|
+
onContinueNumbering={props.onContinueNumbering}
|
|
781
|
+
/>
|
|
822
782
|
) : null}
|
|
823
783
|
<div
|
|
824
784
|
className={isPageWorkspace ? "relative" : undefined}
|
|
@@ -860,10 +820,10 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
|
|
|
860
820
|
{isPageWorkspace && chromeVisibility.pageChrome ? (
|
|
861
821
|
<div
|
|
862
822
|
data-testid="page-header-band"
|
|
863
|
-
className="relative z-10 flex items-center justify-between border-b border-
|
|
823
|
+
className="relative z-10 flex items-center justify-between border-b border-border/50 bg-surface/45 px-4 text-[11px] text-secondary backdrop-blur-[1px]"
|
|
864
824
|
style={pageShellMetrics.headerBandStyle}
|
|
865
825
|
>
|
|
866
|
-
<span className="uppercase tracking-[0.12em] text-tertiary">
|
|
826
|
+
<span className="uppercase tracking-[0.12em] text-tertiary">{headerBandLabel}</span>
|
|
867
827
|
{snapshot.pageLayout?.headerVariants[0] ? (
|
|
868
828
|
<button
|
|
869
829
|
type="button"
|
|
@@ -890,10 +850,10 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
|
|
|
890
850
|
{isPageWorkspace && chromeVisibility.pageChrome ? (
|
|
891
851
|
<div
|
|
892
852
|
data-testid="page-footer-band"
|
|
893
|
-
className="relative z-10 flex items-center justify-between border-t border-
|
|
853
|
+
className="relative z-10 flex items-center justify-between border-t border-border/50 bg-surface/45 px-4 text-[11px] text-secondary backdrop-blur-[1px]"
|
|
894
854
|
style={pageShellMetrics.footerBandStyle}
|
|
895
855
|
>
|
|
896
|
-
<span className="uppercase tracking-[0.12em] text-tertiary">
|
|
856
|
+
<span className="uppercase tracking-[0.12em] text-tertiary">{footerBandLabel}</span>
|
|
897
857
|
{snapshot.pageLayout?.footerVariants[0] ? (
|
|
898
858
|
<button
|
|
899
859
|
type="button"
|
|
@@ -920,6 +880,11 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
|
|
|
920
880
|
commentCount={snapshot.comments.totalCount}
|
|
921
881
|
changeCount={snapshot.trackedChanges.totalCount}
|
|
922
882
|
sessionId={snapshot.sessionId}
|
|
883
|
+
contextAnalytics={
|
|
884
|
+
chromeVisibility.contextAnalytics
|
|
885
|
+
? props.documentContextAnalytics
|
|
886
|
+
: null
|
|
887
|
+
}
|
|
923
888
|
/>
|
|
924
889
|
) : null}
|
|
925
890
|
</div>
|
|
@@ -933,6 +898,11 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
|
|
|
933
898
|
compatibility={snapshot.compatibility}
|
|
934
899
|
warnings={snapshot.warnings}
|
|
935
900
|
markupDisplay={markupDisplay}
|
|
901
|
+
contextAnalytics={
|
|
902
|
+
chromeVisibility.contextAnalytics
|
|
903
|
+
? props.currentScopeContextAnalytics
|
|
904
|
+
: null
|
|
905
|
+
}
|
|
936
906
|
activeCommentId={props.activeCommentId}
|
|
937
907
|
activeRevisionId={props.activeRevisionId}
|
|
938
908
|
onActiveTabChange={props.onActiveRailTabChange}
|
|
@@ -971,22 +941,68 @@ function resolveActiveParagraphLayout(
|
|
|
971
941
|
rightIndent: number;
|
|
972
942
|
firstLineOffset: number;
|
|
973
943
|
tabStops: Array<{ pos: number; val?: string; leader?: string }>;
|
|
944
|
+
indentationReadOnly?: boolean;
|
|
945
|
+
tabStopsReadOnly?: boolean;
|
|
974
946
|
} | null {
|
|
975
947
|
const paragraph = surface ? findActiveParagraph(surface.blocks, position) : null;
|
|
976
948
|
if (!paragraph) {
|
|
977
949
|
return null;
|
|
978
950
|
}
|
|
951
|
+
const resolvedIndentation = paragraph.resolvedNumbering?.geometry.indentation;
|
|
952
|
+
const resolvedTabStops = paragraph.resolvedNumbering?.geometry.tabStops;
|
|
953
|
+
const indentation = resolvedIndentation ?? paragraph.indentation;
|
|
954
|
+
const tabStops = resolvedTabStops ?? paragraph.tabStops;
|
|
979
955
|
|
|
980
956
|
return {
|
|
981
|
-
leftIndent:
|
|
982
|
-
rightIndent:
|
|
957
|
+
leftIndent: indentation?.left ?? 0,
|
|
958
|
+
rightIndent: indentation?.right ?? 0,
|
|
983
959
|
firstLineOffset:
|
|
984
|
-
|
|
985
|
-
(
|
|
986
|
-
tabStops:
|
|
960
|
+
indentation?.firstLine ??
|
|
961
|
+
(indentation?.hanging ? -indentation.hanging : 0),
|
|
962
|
+
tabStops: tabStops ? [...tabStops] : [],
|
|
963
|
+
indentationReadOnly:
|
|
964
|
+
Boolean(resolvedIndentation) &&
|
|
965
|
+
!areIndentationsEqual(resolvedIndentation, paragraph.indentation),
|
|
966
|
+
tabStopsReadOnly:
|
|
967
|
+
Boolean(resolvedTabStops) &&
|
|
968
|
+
!areTabStopsEqual(resolvedTabStops, paragraph.tabStops),
|
|
987
969
|
};
|
|
988
970
|
}
|
|
989
971
|
|
|
972
|
+
function areIndentationsEqual(
|
|
973
|
+
left:
|
|
974
|
+
| Extract<SurfaceBlockSnapshot, { kind: "paragraph" }>["indentation"]
|
|
975
|
+
| undefined,
|
|
976
|
+
right:
|
|
977
|
+
| Extract<SurfaceBlockSnapshot, { kind: "paragraph" }>["indentation"]
|
|
978
|
+
| undefined,
|
|
979
|
+
): boolean {
|
|
980
|
+
return (
|
|
981
|
+
left?.left === right?.left &&
|
|
982
|
+
left?.right === right?.right &&
|
|
983
|
+
left?.firstLine === right?.firstLine &&
|
|
984
|
+
left?.hanging === right?.hanging
|
|
985
|
+
);
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
function areTabStopsEqual(
|
|
989
|
+
left: ReadonlyArray<{ pos: number; val?: string; leader?: string }> | undefined,
|
|
990
|
+
right: ReadonlyArray<{ pos: number; val?: string; leader?: string }> | undefined,
|
|
991
|
+
): boolean {
|
|
992
|
+
if (!left?.length && !right?.length) {
|
|
993
|
+
return true;
|
|
994
|
+
}
|
|
995
|
+
if (!left || !right || left.length !== right.length) {
|
|
996
|
+
return false;
|
|
997
|
+
}
|
|
998
|
+
return left.every(
|
|
999
|
+
(tabStop, index) =>
|
|
1000
|
+
tabStop.pos === right[index]?.pos &&
|
|
1001
|
+
tabStop.val === right[index]?.val &&
|
|
1002
|
+
tabStop.leader === right[index]?.leader,
|
|
1003
|
+
);
|
|
1004
|
+
}
|
|
1005
|
+
|
|
990
1006
|
function findActiveParagraph(
|
|
991
1007
|
blocks: readonly SurfaceBlockSnapshot[],
|
|
992
1008
|
position: number,
|
|
@@ -1120,6 +1136,9 @@ function buildPageShellMetrics(
|
|
|
1120
1136
|
},
|
|
1121
1137
|
pageFrameStyle: {
|
|
1122
1138
|
backgroundColor: "var(--color-page-bg)",
|
|
1139
|
+
borderRadius: "8px",
|
|
1140
|
+
boxShadow: "0 24px 48px -32px rgba(15, 23, 42, 0.38), 0 8px 20px -18px rgba(15, 23, 42, 0.22)",
|
|
1141
|
+
border: "1px solid rgba(148, 163, 184, 0.2)",
|
|
1123
1142
|
},
|
|
1124
1143
|
headerBandStyle: {
|
|
1125
1144
|
minHeight: `${headerBandHeightPx}px`,
|
|
@@ -1130,6 +1149,30 @@ function buildPageShellMetrics(
|
|
|
1130
1149
|
};
|
|
1131
1150
|
}
|
|
1132
1151
|
|
|
1152
|
+
function resolvePageBandLabel(
|
|
1153
|
+
region: "header" | "footer",
|
|
1154
|
+
activeStory: RuntimeRenderSnapshot["activeStory"],
|
|
1155
|
+
): string {
|
|
1156
|
+
const regionLabel = region === "header" ? "header" : "footer";
|
|
1157
|
+
let label: string;
|
|
1158
|
+
if (activeStory.kind !== region) {
|
|
1159
|
+
label = region === "header" ? "Header" : "Footer";
|
|
1160
|
+
} else {
|
|
1161
|
+
switch (activeStory.variant) {
|
|
1162
|
+
case "first":
|
|
1163
|
+
label = `First page ${regionLabel}`;
|
|
1164
|
+
break;
|
|
1165
|
+
case "even":
|
|
1166
|
+
label = `Even page ${regionLabel}`;
|
|
1167
|
+
break;
|
|
1168
|
+
default:
|
|
1169
|
+
label = `Default ${regionLabel}`;
|
|
1170
|
+
break;
|
|
1171
|
+
}
|
|
1172
|
+
}
|
|
1173
|
+
return label;
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1133
1176
|
function buildLineNumberMarkers(
|
|
1134
1177
|
blocks: readonly SurfaceBlockSnapshot[],
|
|
1135
1178
|
pages: ReadonlyArray<DocumentNavigationSnapshot["pages"][number]>,
|
|
@@ -1316,7 +1359,7 @@ function createInsetValue(spaceTwips: number | undefined, percent: number): stri
|
|
|
1316
1359
|
}
|
|
1317
1360
|
|
|
1318
1361
|
function resolveSelectionToolbarPlacement(
|
|
1319
|
-
anchor:
|
|
1362
|
+
anchor: SelectionToolAnchor | null | undefined,
|
|
1320
1363
|
root: HTMLDivElement | null,
|
|
1321
1364
|
zoomScale: number,
|
|
1322
1365
|
): { placement: "right" | "left" | "above" | "below"; style: CSSProperties } | null {
|