@beyondwork/docx-react-component 1.0.30 → 1.0.32
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 +6 -0
- package/package.json +1 -1
- package/src/api/public-types.ts +16 -1
- package/src/api/session-state.ts +2 -0
- package/src/io/docx-session.ts +16 -3
- package/src/io/ooxml/parse-footnotes.ts +23 -33
- package/src/io/ooxml/parse-headers-footers.ts +20 -21
- package/src/io/ooxml/workflow-payload.ts +311 -8
- package/src/model/snapshot.ts +113 -1
- package/src/runtime/document-runtime.ts +207 -33
- package/src/runtime/surface-projection.ts +156 -7
- package/src/ui/WordReviewEditor.tsx +13 -5
- package/src/ui/editor-surface-controller.tsx +2 -0
- package/src/ui/headless/selection-tool-resolver.ts +4 -1
- package/src/ui/headless/selection-tool-types.ts +1 -2
- package/src/ui/workflow-surface-blocked-rails.ts +19 -1
- package/src/ui-tailwind/chrome/responsive-chrome.ts +46 -0
- package/src/ui-tailwind/chrome/tw-image-context-toolbar.tsx +4 -4
- package/src/ui-tailwind/chrome/tw-object-context-toolbar.tsx +5 -5
- package/src/ui-tailwind/chrome/tw-selection-tool-blocked.tsx +3 -3
- package/src/ui-tailwind/chrome/tw-selection-tool-comment.tsx +4 -4
- package/src/ui-tailwind/chrome/tw-selection-tool-host.tsx +14 -9
- package/src/ui-tailwind/chrome/tw-selection-tool-structure.tsx +4 -5
- package/src/ui-tailwind/chrome/tw-selection-tool-workflow.tsx +5 -5
- package/src/ui-tailwind/chrome/tw-selection-toolbar.tsx +6 -6
- package/src/ui-tailwind/chrome/tw-suggestion-card.tsx +9 -9
- package/src/ui-tailwind/chrome/tw-table-context-toolbar.tsx +173 -124
- package/src/ui-tailwind/editor-surface/pm-decorations.ts +88 -14
- package/src/ui-tailwind/editor-surface/pm-schema.ts +29 -0
- package/src/ui-tailwind/editor-surface/pm-state-from-snapshot.ts +13 -1
- package/src/ui-tailwind/editor-surface/surface-build-keys.ts +3 -3
- package/src/ui-tailwind/editor-surface/tw-inline-token.tsx +20 -0
- package/src/ui-tailwind/editor-surface/tw-prosemirror-surface.tsx +26 -0
- package/src/ui-tailwind/review/tw-review-rail.tsx +9 -1
- package/src/ui-tailwind/theme/editor-theme.css +8 -0
- package/src/ui-tailwind/toolbar/toolbar-layout.ts +47 -0
- package/src/ui-tailwind/toolbar/tw-toolbar.tsx +367 -22
- package/src/ui-tailwind/tw-review-workspace.tsx +131 -4
|
@@ -62,6 +62,11 @@ import { preserveEditorSelectionMouseDown } from "../ui/headless/preserve-editor
|
|
|
62
62
|
import { TwAlertBanner } from "./chrome/tw-alert-banner";
|
|
63
63
|
import { TwLayoutPanel } from "./chrome/tw-layout-panel";
|
|
64
64
|
import { TwPageRuler } from "./chrome/tw-page-ruler";
|
|
65
|
+
import {
|
|
66
|
+
getInitialReviewRailOpen,
|
|
67
|
+
isNarrowChromeViewport,
|
|
68
|
+
resolveResponsiveChromeState,
|
|
69
|
+
} from "./chrome/responsive-chrome";
|
|
65
70
|
import { ChromePresetToolbar } from "./chrome/chrome-preset-toolbar";
|
|
66
71
|
import {
|
|
67
72
|
resolveChromePreset,
|
|
@@ -258,7 +263,15 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
|
|
|
258
263
|
chromeOptions,
|
|
259
264
|
chromeVisibility: props.chromeVisibility,
|
|
260
265
|
});
|
|
261
|
-
const
|
|
266
|
+
const reviewRailAvailable = chromeVisibility.reviewRail && (caps?.reviewRailVisible ?? true);
|
|
267
|
+
const [viewportWidth, setViewportWidth] = useState<number | undefined>(() => readViewportWidth());
|
|
268
|
+
const [reviewRailOpen, setReviewRailOpen] = useState(() =>
|
|
269
|
+
getInitialReviewRailOpen({
|
|
270
|
+
viewportWidth: readViewportWidth(),
|
|
271
|
+
reviewRailAvailable,
|
|
272
|
+
}),
|
|
273
|
+
);
|
|
274
|
+
const responsiveChromeSignatureRef = useRef<string | null>(null);
|
|
262
275
|
const headings = props.documentNavigation?.headings ?? [];
|
|
263
276
|
const headerVariant = snapshot.pageLayout?.headerVariants[0]?.variant ?? "default";
|
|
264
277
|
const footerVariant = snapshot.pageLayout?.footerVariants[0]?.variant ?? "default";
|
|
@@ -318,6 +331,15 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
|
|
|
318
331
|
snapshot.readOnly ||
|
|
319
332
|
snapshot.activeStory.kind !== "main" ||
|
|
320
333
|
effectiveSelectionMode !== "edit";
|
|
334
|
+
const responsiveChrome = useMemo(
|
|
335
|
+
() =>
|
|
336
|
+
resolveResponsiveChromeState({
|
|
337
|
+
viewportWidth,
|
|
338
|
+
reviewRailAvailable,
|
|
339
|
+
reviewRailOpen,
|
|
340
|
+
}),
|
|
341
|
+
[reviewRailAvailable, reviewRailOpen, viewportWidth],
|
|
342
|
+
);
|
|
321
343
|
const toolbarInteractionPolicy: ToolbarInteractionPolicy | undefined = caps
|
|
322
344
|
? {
|
|
323
345
|
mode: effectiveSelectionMode,
|
|
@@ -341,6 +363,37 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
|
|
|
341
363
|
}
|
|
342
364
|
}, [isPageWorkspace, snapshot.activeStory.kind]);
|
|
343
365
|
|
|
366
|
+
useEffect(() => {
|
|
367
|
+
if (typeof window === "undefined") {
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
const updateViewportWidth = () => {
|
|
372
|
+
setViewportWidth(readViewportWidth());
|
|
373
|
+
};
|
|
374
|
+
|
|
375
|
+
updateViewportWidth();
|
|
376
|
+
window.addEventListener("resize", updateViewportWidth);
|
|
377
|
+
return () => {
|
|
378
|
+
window.removeEventListener("resize", updateViewportWidth);
|
|
379
|
+
};
|
|
380
|
+
}, []);
|
|
381
|
+
|
|
382
|
+
useEffect(() => {
|
|
383
|
+
const responsiveSignature = `${reviewRailAvailable ? "1" : "0"}:${isNarrowChromeViewport(viewportWidth) ? "n" : "d"}`;
|
|
384
|
+
if (responsiveChromeSignatureRef.current === responsiveSignature) {
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
responsiveChromeSignatureRef.current = responsiveSignature;
|
|
389
|
+
setReviewRailOpen(
|
|
390
|
+
getInitialReviewRailOpen({
|
|
391
|
+
viewportWidth,
|
|
392
|
+
reviewRailAvailable,
|
|
393
|
+
}),
|
|
394
|
+
);
|
|
395
|
+
}, [reviewRailAvailable, viewportWidth]);
|
|
396
|
+
|
|
344
397
|
const dismissSelectionToolbar = useCallback(() => {
|
|
345
398
|
props.onDismissSelectionToolbar?.();
|
|
346
399
|
}, [props.onDismissSelectionToolbar]);
|
|
@@ -353,6 +406,25 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
|
|
|
353
406
|
[dismissSelectionToolbar],
|
|
354
407
|
);
|
|
355
408
|
|
|
409
|
+
useEffect(() => {
|
|
410
|
+
if (!responsiveChrome.showDrawerReviewRail || typeof window === "undefined") {
|
|
411
|
+
return;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
const handleKeyDown = (event: KeyboardEvent) => {
|
|
415
|
+
if (event.key !== "Escape") {
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
setReviewRailOpen(false);
|
|
420
|
+
};
|
|
421
|
+
|
|
422
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
423
|
+
return () => {
|
|
424
|
+
window.removeEventListener("keydown", handleKeyDown);
|
|
425
|
+
};
|
|
426
|
+
}, [responsiveChrome.showDrawerReviewRail]);
|
|
427
|
+
|
|
356
428
|
return (
|
|
357
429
|
<Tooltip.Provider delayDuration={400}>
|
|
358
430
|
<div className="flex h-full flex-col bg-canvas text-primary">
|
|
@@ -366,12 +438,15 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
|
|
|
366
438
|
blockedReasons={blockedReasons}
|
|
367
439
|
showDiagnosticsChrome={chromeVisibility.alerts}
|
|
368
440
|
interactionPolicy={toolbarInteractionPolicy}
|
|
441
|
+
compactMode={responsiveChrome.isNarrow}
|
|
369
442
|
workspaceMode={props.workspaceMode}
|
|
370
443
|
zoomLevel={props.zoomLevel}
|
|
371
444
|
formattingState={props.formattingState}
|
|
372
445
|
activeListContext={props.activeListContext}
|
|
373
446
|
styleCatalog={props.styleCatalog}
|
|
374
447
|
showTrackedChanges={props.showTrackedChanges}
|
|
448
|
+
showSidebarToggle={responsiveChrome.showSidebarToggle}
|
|
449
|
+
isSidebarOpen={reviewRailOpen}
|
|
375
450
|
onUndo={runWithSelectionToolbarDismiss(props.onUndo)}
|
|
376
451
|
onRedo={runWithSelectionToolbarDismiss(props.onRedo)}
|
|
377
452
|
onSetParagraphStyle={props.onSetParagraphStyle
|
|
@@ -444,6 +519,10 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
|
|
|
444
519
|
dismissSelectionToolbar();
|
|
445
520
|
props.onWorkspaceModeChange(value);
|
|
446
521
|
}}
|
|
522
|
+
onToggleSidebar={() => {
|
|
523
|
+
dismissSelectionToolbar();
|
|
524
|
+
setReviewRailOpen((open) => !open);
|
|
525
|
+
}}
|
|
447
526
|
onZoomChange={props.onZoomChange
|
|
448
527
|
? (level) => {
|
|
449
528
|
dismissSelectionToolbar();
|
|
@@ -483,7 +562,7 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
|
|
|
483
562
|
workflowBlockedReasons={blockedReasons}
|
|
484
563
|
/> : null}
|
|
485
564
|
|
|
486
|
-
<div className="flex flex-1 min-h-0">
|
|
565
|
+
<div className="relative flex flex-1 min-h-0">
|
|
487
566
|
{/* Collapsible document navigator — page mode only */}
|
|
488
567
|
{isPageWorkspace && chromeVisibility.pageChrome ? (
|
|
489
568
|
<aside
|
|
@@ -889,8 +968,8 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
|
|
|
889
968
|
) : null}
|
|
890
969
|
</div>
|
|
891
970
|
|
|
892
|
-
{/* Review rail —
|
|
893
|
-
{
|
|
971
|
+
{/* Review rail — docked on desktop, drawer-backed on narrow layouts */}
|
|
972
|
+
{responsiveChrome.showDockedReviewRail ? <TwReviewRail
|
|
894
973
|
activeTab={props.activeRailTab}
|
|
895
974
|
currentUserId={props.currentUserId}
|
|
896
975
|
comments={snapshot.comments}
|
|
@@ -917,12 +996,60 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
|
|
|
917
996
|
onAcceptAllChanges={props.onAcceptAllChanges}
|
|
918
997
|
onRejectAllChanges={props.onRejectAllChanges}
|
|
919
998
|
/> : null}
|
|
999
|
+
|
|
1000
|
+
{responsiveChrome.showDrawerReviewRail ? (
|
|
1001
|
+
<div
|
|
1002
|
+
className="pointer-events-none absolute inset-0 z-30 flex justify-end"
|
|
1003
|
+
data-testid="review-rail-drawer"
|
|
1004
|
+
>
|
|
1005
|
+
<button
|
|
1006
|
+
type="button"
|
|
1007
|
+
aria-label="Close sidebar overlay"
|
|
1008
|
+
className="pointer-events-auto absolute inset-0 border-0 bg-[color:rgba(21,26,23,0.08)] dark:bg-[color:rgba(0,0,0,0.32)]"
|
|
1009
|
+
onClick={() => setReviewRailOpen(false)}
|
|
1010
|
+
/>
|
|
1011
|
+
<div className="pointer-events-auto relative h-full">
|
|
1012
|
+
<TwReviewRail
|
|
1013
|
+
variant="drawer"
|
|
1014
|
+
activeTab={props.activeRailTab}
|
|
1015
|
+
currentUserId={props.currentUserId}
|
|
1016
|
+
comments={snapshot.comments}
|
|
1017
|
+
trackedChanges={snapshot.trackedChanges}
|
|
1018
|
+
compatibility={snapshot.compatibility}
|
|
1019
|
+
warnings={snapshot.warnings}
|
|
1020
|
+
markupDisplay={markupDisplay}
|
|
1021
|
+
contextAnalytics={
|
|
1022
|
+
chromeVisibility.contextAnalytics
|
|
1023
|
+
? props.currentScopeContextAnalytics
|
|
1024
|
+
: null
|
|
1025
|
+
}
|
|
1026
|
+
activeCommentId={props.activeCommentId}
|
|
1027
|
+
activeRevisionId={props.activeRevisionId}
|
|
1028
|
+
onActiveTabChange={props.onActiveRailTabChange}
|
|
1029
|
+
onOpenComment={props.onOpenComment}
|
|
1030
|
+
onResolveComment={props.onResolveComment}
|
|
1031
|
+
onReopenComment={props.onReopenComment}
|
|
1032
|
+
onAddReply={props.onAddReply}
|
|
1033
|
+
onEditBody={props.onEditBody}
|
|
1034
|
+
onOpenRevision={props.onOpenRevision}
|
|
1035
|
+
onAcceptRevision={props.onAcceptRevision}
|
|
1036
|
+
onRejectRevision={props.onRejectRevision}
|
|
1037
|
+
onAcceptAllChanges={props.onAcceptAllChanges}
|
|
1038
|
+
onRejectAllChanges={props.onRejectAllChanges}
|
|
1039
|
+
/>
|
|
1040
|
+
</div>
|
|
1041
|
+
</div>
|
|
1042
|
+
) : null}
|
|
920
1043
|
</div>
|
|
921
1044
|
</div>
|
|
922
1045
|
</Tooltip.Provider>
|
|
923
1046
|
);
|
|
924
1047
|
}
|
|
925
1048
|
|
|
1049
|
+
function readViewportWidth(): number | undefined {
|
|
1050
|
+
return typeof window === "undefined" ? undefined : window.innerWidth;
|
|
1051
|
+
}
|
|
1052
|
+
|
|
926
1053
|
function shouldHidePageBorderForSelection(
|
|
927
1054
|
selection: EditorViewStateSnapshot["selection"],
|
|
928
1055
|
): boolean {
|