@beyondwork/docx-react-component 1.0.22 → 1.0.24-rc
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 +81 -38
- package/package.json +1 -1
- package/src/api/public-types.ts +67 -1
- package/src/core/commands/index.ts +625 -5
- package/src/index.ts +5 -0
- package/src/io/docx-session.ts +181 -2
- package/src/io/export/serialize-main-document.ts +21 -1
- package/src/io/normalize/normalize-text.ts +4 -0
- package/src/io/ooxml/parse-main-document.ts +88 -7
- package/src/model/canonical-document.ts +22 -0
- package/src/review/store/revision-store.ts +1 -0
- package/src/review/store/revision-types.ts +2 -0
- package/src/runtime/document-runtime.ts +503 -51
- package/src/runtime/session-capabilities.ts +6 -5
- package/src/runtime/surface-projection.ts +2 -0
- package/src/runtime/table-schema.ts +2 -0
- package/src/runtime/workflow-markup.ts +5 -1
- package/src/ui/WordReviewEditor.tsx +667 -132
- package/src/ui/editor-runtime-boundary.ts +10 -1
- package/src/ui/editor-shell-view.tsx +8 -0
- package/src/ui/editor-surface-controller.tsx +6 -0
- package/src/ui/headless/selection-toolbar-model.ts +12 -0
- package/src/ui-tailwind/chrome/tw-suggestion-card.tsx +139 -0
- package/src/ui-tailwind/editor-surface/pm-command-bridge.ts +6 -0
- package/src/ui-tailwind/editor-surface/pm-decorations.ts +96 -28
- package/src/ui-tailwind/editor-surface/pm-state-from-snapshot.ts +2 -0
- package/src/ui-tailwind/editor-surface/surface-build-keys.ts +6 -0
- package/src/ui-tailwind/editor-surface/tw-prosemirror-surface.tsx +132 -10
- package/src/ui-tailwind/editor-surface/tw-table-node-view.tsx +82 -1
- package/src/ui-tailwind/status/tw-status-bar.tsx +4 -1
- package/src/ui-tailwind/theme/editor-theme.css +10 -0
- package/src/ui-tailwind/toolbar/tw-toolbar.tsx +21 -5
- package/src/ui-tailwind/tw-review-workspace.tsx +110 -32
|
@@ -28,6 +28,7 @@ import type {
|
|
|
28
28
|
StyleCatalogSnapshot,
|
|
29
29
|
SurfaceBlockSnapshot,
|
|
30
30
|
TrackedChangeEntrySnapshot,
|
|
31
|
+
WordReviewEditorChromeVisibility,
|
|
31
32
|
WorkflowScopeSnapshot,
|
|
32
33
|
WorkspaceMode,
|
|
33
34
|
ZoomLevel,
|
|
@@ -49,6 +50,7 @@ import type { SessionCapabilities } from "../runtime/session-capabilities";
|
|
|
49
50
|
import type {
|
|
50
51
|
SelectionToolbarAnchor,
|
|
51
52
|
SelectionToolbarModel,
|
|
53
|
+
SuggestionCardModel,
|
|
52
54
|
} from "../ui/headless/selection-toolbar-model";
|
|
53
55
|
import type { MarkupDisplay } from "../ui/headless/comment-decoration-model";
|
|
54
56
|
import type { EditorCommandBag } from "../ui/editor-command-bag.ts";
|
|
@@ -59,10 +61,13 @@ import { TwLayoutPanel } from "./chrome/tw-layout-panel";
|
|
|
59
61
|
import { TwObjectContextToolbar, type ActiveObjectContext } from "./chrome/tw-object-context-toolbar";
|
|
60
62
|
import { TwPageRuler } from "./chrome/tw-page-ruler";
|
|
61
63
|
import { TwSelectionToolbar } from "./chrome/tw-selection-toolbar";
|
|
64
|
+
import { TwSuggestionCard } from "./chrome/tw-suggestion-card";
|
|
62
65
|
import { TwTableContextToolbar } from "./chrome/tw-table-context-toolbar";
|
|
63
66
|
import { TwReviewRail, type ReviewRailTab } from "./review/tw-review-rail";
|
|
64
67
|
import { TwStatusBar } from "./status/tw-status-bar";
|
|
65
|
-
import { TwToolbar } from "./toolbar/tw-toolbar";
|
|
68
|
+
import { TwToolbar, type ToolbarInteractionPolicy } from "./toolbar/tw-toolbar";
|
|
69
|
+
|
|
70
|
+
export type ReviewWorkspaceChromeVisibility = WordReviewEditorChromeVisibility;
|
|
66
71
|
|
|
67
72
|
export interface TwReviewWorkspaceProps {
|
|
68
73
|
snapshot: RuntimeRenderSnapshot;
|
|
@@ -84,6 +89,7 @@ export interface TwReviewWorkspaceProps {
|
|
|
84
89
|
interactionGuardSnapshot?: InteractionGuardSnapshot;
|
|
85
90
|
commands: EditorCommandBag;
|
|
86
91
|
selectionToolbar?: SelectionToolbarModel | null;
|
|
92
|
+
suggestionCard?: SuggestionCardModel | null;
|
|
87
93
|
selectionToolbarAnchor?: SelectionToolbarAnchor | null;
|
|
88
94
|
documentNavigation?: DocumentNavigationSnapshot;
|
|
89
95
|
onWorkspaceModeChange?: (value: WorkspaceMode) => void;
|
|
@@ -170,6 +176,10 @@ export interface TwReviewWorkspaceProps {
|
|
|
170
176
|
onAddCommentFromSelection?: () => void;
|
|
171
177
|
onExport?: () => void;
|
|
172
178
|
onDismissSelectionToolbar?: () => void;
|
|
179
|
+
onAcceptSuggestion?: () => void;
|
|
180
|
+
onRejectSuggestion?: () => void;
|
|
181
|
+
onEditSuggestion?: () => void;
|
|
182
|
+
onAddCommentFromSuggestion?: () => void;
|
|
173
183
|
onSelectionToolbarFocusCapture?: FocusEventHandler<HTMLDivElement>;
|
|
174
184
|
onSelectionToolbarBlurCapture?: FocusEventHandler<HTMLDivElement>;
|
|
175
185
|
selectionToolbarRef?: Ref<HTMLDivElement>;
|
|
@@ -196,6 +206,7 @@ export interface TwReviewWorkspaceProps {
|
|
|
196
206
|
onRestartNumbering?: () => void;
|
|
197
207
|
onContinueNumbering?: () => void;
|
|
198
208
|
onNavigateHeading?: (headingId: string) => void;
|
|
209
|
+
chromeVisibility?: Partial<ReviewWorkspaceChromeVisibility>;
|
|
199
210
|
}
|
|
200
211
|
|
|
201
212
|
export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
|
|
@@ -220,7 +231,17 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
|
|
|
220
231
|
props.interactionGuardSnapshot?.blockedReasons ??
|
|
221
232
|
props.workflowScopeSnapshot?.blockedReasons ??
|
|
222
233
|
[];
|
|
223
|
-
const
|
|
234
|
+
const chromeVisibility: ReviewWorkspaceChromeVisibility = {
|
|
235
|
+
toolbar: true,
|
|
236
|
+
alerts: true,
|
|
237
|
+
selectionOverlay: true,
|
|
238
|
+
contextToolbars: true,
|
|
239
|
+
pageChrome: true,
|
|
240
|
+
statusBar: true,
|
|
241
|
+
reviewRail: true,
|
|
242
|
+
...props.chromeVisibility,
|
|
243
|
+
};
|
|
244
|
+
const showReviewRail = chromeVisibility.reviewRail && (caps?.reviewRailVisible ?? true);
|
|
224
245
|
const headings = props.documentNavigation?.headings ?? [];
|
|
225
246
|
const headerVariant = snapshot.pageLayout?.headerVariants[0]?.variant ?? "default";
|
|
226
247
|
const footerVariant = snapshot.pageLayout?.footerVariants[0]?.variant ?? "default";
|
|
@@ -267,6 +288,23 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
|
|
|
267
288
|
isPageWorkspace &&
|
|
268
289
|
snapshot.activeStory.kind === "main" &&
|
|
269
290
|
shouldHidePageBorderForSelection(viewState.selection);
|
|
291
|
+
const effectiveSelectionMode = props.interactionGuardSnapshot?.effectiveMode ?? "edit";
|
|
292
|
+
const allowLocalChromeMutations = Boolean(caps?.canEdit) && effectiveSelectionMode === "edit";
|
|
293
|
+
const pageChromeReadOnly =
|
|
294
|
+
snapshot.readOnly ||
|
|
295
|
+
snapshot.activeStory.kind !== "main" ||
|
|
296
|
+
effectiveSelectionMode !== "edit";
|
|
297
|
+
const toolbarInteractionPolicy: ToolbarInteractionPolicy | undefined = caps
|
|
298
|
+
? {
|
|
299
|
+
mode: effectiveSelectionMode,
|
|
300
|
+
canFormatText: caps.canEdit && effectiveSelectionMode === "edit",
|
|
301
|
+
canInsertStructural: caps.canEdit && effectiveSelectionMode === "edit",
|
|
302
|
+
canAddComment:
|
|
303
|
+
caps.canAddComment &&
|
|
304
|
+
effectiveSelectionMode !== "view" &&
|
|
305
|
+
effectiveSelectionMode !== "blocked",
|
|
306
|
+
}
|
|
307
|
+
: undefined;
|
|
270
308
|
|
|
271
309
|
useEffect(() => {
|
|
272
310
|
recordPerfSample("workspace.chrome");
|
|
@@ -294,11 +332,12 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
|
|
|
294
332
|
return (
|
|
295
333
|
<Tooltip.Provider delayDuration={400}>
|
|
296
334
|
<div className="flex h-full flex-col bg-canvas text-primary">
|
|
297
|
-
<TwToolbar
|
|
335
|
+
{chromeVisibility.toolbar ? <TwToolbar
|
|
298
336
|
sourceLabel={snapshot.sourceLabel}
|
|
299
337
|
capabilities={caps}
|
|
300
338
|
compatibility={snapshot.compatibility}
|
|
301
339
|
warnings={snapshot.warnings}
|
|
340
|
+
interactionPolicy={toolbarInteractionPolicy}
|
|
302
341
|
workspaceMode={props.workspaceMode}
|
|
303
342
|
zoomLevel={props.zoomLevel}
|
|
304
343
|
formattingState={props.formattingState}
|
|
@@ -385,17 +424,17 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
|
|
|
385
424
|
props.onShowTrackedChangesChange(show);
|
|
386
425
|
}}
|
|
387
426
|
blockedReasons={blockedReasons}
|
|
388
|
-
/>
|
|
427
|
+
/> : null}
|
|
389
428
|
|
|
390
|
-
<TwAlertBanner
|
|
429
|
+
{chromeVisibility.alerts ? <TwAlertBanner
|
|
391
430
|
snapshot={snapshot}
|
|
392
431
|
preserveOnlyCount={preserveOnlyCount}
|
|
393
432
|
workflowBlockedReasons={blockedReasons}
|
|
394
|
-
/>
|
|
433
|
+
/> : null}
|
|
395
434
|
|
|
396
435
|
<div className="flex flex-1 min-h-0">
|
|
397
436
|
{/* Collapsible document navigator — page mode only */}
|
|
398
|
-
{isPageWorkspace ? (
|
|
437
|
+
{isPageWorkspace && chromeVisibility.pageChrome ? (
|
|
399
438
|
<aside
|
|
400
439
|
aria-label="Document navigator"
|
|
401
440
|
className={`shrink-0 border-r border-border bg-surface transition-[width] duration-200 ${
|
|
@@ -459,7 +498,7 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
|
|
|
459
498
|
) : null}
|
|
460
499
|
|
|
461
500
|
{/* Navigator expand toggle — page mode only when collapsed */}
|
|
462
|
-
{isPageWorkspace && !navOpen ? (
|
|
501
|
+
{isPageWorkspace && chromeVisibility.pageChrome && !navOpen ? (
|
|
463
502
|
<div className="shrink-0 flex items-start pt-2 pl-1">
|
|
464
503
|
<Tooltip.Root>
|
|
465
504
|
<Tooltip.Trigger asChild>
|
|
@@ -500,7 +539,7 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
|
|
|
500
539
|
}`}
|
|
501
540
|
style={isPageWorkspace && zoomScale !== 1 ? { transform: `scale(${zoomScale})`, transformOrigin: "top center" } : undefined}
|
|
502
541
|
>
|
|
503
|
-
{isPageWorkspace && snapshot.pageLayout ? (
|
|
542
|
+
{isPageWorkspace && chromeVisibility.pageChrome && snapshot.pageLayout ? (
|
|
504
543
|
<div className="border-b border-border/70 bg-surface/65 px-5 py-3" data-testid="page-context-summary">
|
|
505
544
|
<div className="flex flex-wrap items-center justify-between gap-2">
|
|
506
545
|
<div className="flex flex-wrap items-center gap-2 text-xs text-secondary">
|
|
@@ -531,7 +570,7 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
|
|
|
531
570
|
<button
|
|
532
571
|
type="button"
|
|
533
572
|
aria-label="Link header to previous"
|
|
534
|
-
disabled={!props.onSetHeaderFooterLink}
|
|
573
|
+
disabled={!props.onSetHeaderFooterLink || !allowLocalChromeMutations}
|
|
535
574
|
onMouseDown={preserveEditorSelectionMouseDown}
|
|
536
575
|
onClick={() => {
|
|
537
576
|
dismissSelectionToolbar();
|
|
@@ -548,7 +587,7 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
|
|
|
548
587
|
<button
|
|
549
588
|
type="button"
|
|
550
589
|
aria-label="Link footer to previous"
|
|
551
|
-
disabled={!props.onSetHeaderFooterLink}
|
|
590
|
+
disabled={!props.onSetHeaderFooterLink || !allowLocalChromeMutations}
|
|
552
591
|
onMouseDown={preserveEditorSelectionMouseDown}
|
|
553
592
|
onClick={() => {
|
|
554
593
|
dismissSelectionToolbar();
|
|
@@ -582,13 +621,13 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
|
|
|
582
621
|
</div>
|
|
583
622
|
</div>
|
|
584
623
|
) : null}
|
|
585
|
-
{isPageWorkspace && snapshot.pageLayout && layoutToolsOpen ? (
|
|
624
|
+
{isPageWorkspace && chromeVisibility.pageChrome && snapshot.pageLayout && layoutToolsOpen ? (
|
|
586
625
|
<div className="px-5 pt-3">
|
|
587
626
|
<TwPageRuler
|
|
588
627
|
pageLayout={snapshot.pageLayout}
|
|
589
628
|
viewState={viewState}
|
|
590
629
|
paragraphLayout={activeParagraphLayout}
|
|
591
|
-
readOnly={
|
|
630
|
+
readOnly={pageChromeReadOnly}
|
|
592
631
|
onReturnToBody={props.onCloseStory
|
|
593
632
|
? runWithSelectionToolbarDismiss(props.onCloseStory)
|
|
594
633
|
: () => undefined}
|
|
@@ -619,7 +658,7 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
|
|
|
619
658
|
/>
|
|
620
659
|
<TwLayoutPanel
|
|
621
660
|
pageLayout={snapshot.pageLayout}
|
|
622
|
-
readOnly={
|
|
661
|
+
readOnly={pageChromeReadOnly}
|
|
623
662
|
onInsertSectionBreak={props.onInsertSectionBreak
|
|
624
663
|
? (type) => {
|
|
625
664
|
dismissSelectionToolbar();
|
|
@@ -647,11 +686,11 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
|
|
|
647
686
|
/>
|
|
648
687
|
</div>
|
|
649
688
|
) : null}
|
|
650
|
-
{contextualSurface ? (
|
|
689
|
+
{chromeVisibility.contextToolbars && contextualSurface ? (
|
|
651
690
|
<div className="px-5 pt-3 space-y-3">
|
|
652
691
|
{contextualSurface === "table" ? (
|
|
653
692
|
<TwTableContextToolbar
|
|
654
|
-
disabled={!
|
|
693
|
+
disabled={!allowLocalChromeMutations}
|
|
655
694
|
tableStyles={props.styleCatalog?.tables ?? []}
|
|
656
695
|
onSetTableStyle={props.onSetTableStyle
|
|
657
696
|
? (styleId) => {
|
|
@@ -679,7 +718,7 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
|
|
|
679
718
|
{contextualSurface === "image" && props.activeImageContext ? (
|
|
680
719
|
<TwImageContextToolbar
|
|
681
720
|
activeImage={props.activeImageContext}
|
|
682
|
-
disabled={!
|
|
721
|
+
disabled={!allowLocalChromeMutations}
|
|
683
722
|
onSetImageLayout={props.onSetImageLayout
|
|
684
723
|
? (mediaId, dimensions) => {
|
|
685
724
|
dismissSelectionToolbar();
|
|
@@ -699,7 +738,44 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
|
|
|
699
738
|
) : null}
|
|
700
739
|
</div>
|
|
701
740
|
) : null}
|
|
702
|
-
{props.
|
|
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 ? (
|
|
703
779
|
<div className="pointer-events-none absolute inset-0 z-20" data-testid="selection-toolbar-overlay">
|
|
704
780
|
<div
|
|
705
781
|
className="pointer-events-auto absolute"
|
|
@@ -722,7 +798,7 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
|
|
|
722
798
|
</div>
|
|
723
799
|
</div>
|
|
724
800
|
) : null}
|
|
725
|
-
{props.selectionToolbar && !selectionToolbarPlacement ? (
|
|
801
|
+
{chromeVisibility.selectionOverlay && props.selectionToolbar && !props.suggestionCard && !selectionToolbarPlacement ? (
|
|
726
802
|
<div
|
|
727
803
|
className="pointer-events-none absolute inset-x-0 top-0 z-20 flex justify-center px-4 pt-3"
|
|
728
804
|
data-testid="selection-toolbar-fallback"
|
|
@@ -748,7 +824,7 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
|
|
|
748
824
|
className={isPageWorkspace ? "relative" : undefined}
|
|
749
825
|
data-line-numbering={pageChromeModel.lineNumberingEnabled ? "enabled" : "disabled"}
|
|
750
826
|
>
|
|
751
|
-
{isPageWorkspace && pageChromeModel.lineNumberingEnabled ? (
|
|
827
|
+
{isPageWorkspace && chromeVisibility.pageChrome && pageChromeModel.lineNumberingEnabled ? (
|
|
752
828
|
<div
|
|
753
829
|
aria-hidden="true"
|
|
754
830
|
className="pointer-events-none absolute inset-y-0 left-0 z-10"
|
|
@@ -767,7 +843,7 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
|
|
|
767
843
|
</div>
|
|
768
844
|
) : null}
|
|
769
845
|
<div
|
|
770
|
-
className={isPageWorkspace && pageChromeModel.lineNumberingEnabled ? "pl-12" : undefined}
|
|
846
|
+
className={isPageWorkspace && chromeVisibility.pageChrome && pageChromeModel.lineNumberingEnabled ? "pl-12" : undefined}
|
|
771
847
|
style={isPageWorkspace ? pageShellMetrics.contentInsetStyle : undefined}
|
|
772
848
|
>
|
|
773
849
|
<div
|
|
@@ -781,7 +857,7 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
|
|
|
781
857
|
}
|
|
782
858
|
: pageChromeModel.documentGridStyle}
|
|
783
859
|
>
|
|
784
|
-
{isPageWorkspace ? (
|
|
860
|
+
{isPageWorkspace && chromeVisibility.pageChrome ? (
|
|
785
861
|
<div
|
|
786
862
|
data-testid="page-header-band"
|
|
787
863
|
className="relative z-10 flex items-center justify-between border-b border-dashed border-border/60 px-4 text-[11px] text-secondary"
|
|
@@ -800,7 +876,7 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
|
|
|
800
876
|
) : null}
|
|
801
877
|
</div>
|
|
802
878
|
) : null}
|
|
803
|
-
{isPageWorkspace && pageChromeModel.showPageBorder && !hidePageBorderForActiveEditing ? (
|
|
879
|
+
{isPageWorkspace && chromeVisibility.pageChrome && pageChromeModel.showPageBorder && !hidePageBorderForActiveEditing ? (
|
|
804
880
|
<div
|
|
805
881
|
aria-hidden="true"
|
|
806
882
|
className="pointer-events-none absolute inset-0 z-0 rounded-[2px]"
|
|
@@ -811,7 +887,7 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
|
|
|
811
887
|
<div className={isPageWorkspace ? "relative z-10" : undefined}>
|
|
812
888
|
{props.document}
|
|
813
889
|
</div>
|
|
814
|
-
{isPageWorkspace ? (
|
|
890
|
+
{isPageWorkspace && chromeVisibility.pageChrome ? (
|
|
815
891
|
<div
|
|
816
892
|
data-testid="page-footer-band"
|
|
817
893
|
className="relative z-10 flex items-center justify-between border-t border-dashed border-border/60 px-4 text-[11px] text-secondary"
|
|
@@ -836,14 +912,16 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
|
|
|
836
912
|
</div>
|
|
837
913
|
</div>
|
|
838
914
|
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
915
|
+
{chromeVisibility.statusBar ? (
|
|
916
|
+
<TwStatusBar
|
|
917
|
+
isDirty={snapshot.isDirty}
|
|
918
|
+
isExportBlocked={snapshot.compatibility.blockExport}
|
|
919
|
+
preserveOnlyCount={preserveOnlyCount}
|
|
920
|
+
commentCount={snapshot.comments.totalCount}
|
|
921
|
+
changeCount={snapshot.trackedChanges.totalCount}
|
|
922
|
+
sessionId={snapshot.sessionId}
|
|
923
|
+
/>
|
|
924
|
+
) : null}
|
|
847
925
|
</div>
|
|
848
926
|
|
|
849
927
|
{/* Review rail — hidden in editing mode unless toggled */}
|