@beyondwork/docx-react-component 1.0.87 → 1.0.89

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.
Files changed (47) hide show
  1. package/package.json +1 -1
  2. package/src/api/v3/_runtime-handle.ts +5 -0
  3. package/src/api/v3/ai/replacement.ts +82 -0
  4. package/src/api/v3/runtime/content.ts +3 -0
  5. package/src/api/v3/runtime/formatting.ts +64 -0
  6. package/src/core/commands/formatting-commands.ts +107 -0
  7. package/src/core/state/text-transaction.ts +11 -4
  8. package/src/runtime/document-runtime.ts +293 -27
  9. package/src/runtime/scopes/_scope-dependencies.ts +1 -0
  10. package/src/runtime/scopes/action-validation.ts +12 -3
  11. package/src/runtime/scopes/audit-bundle.ts +2 -2
  12. package/src/runtime/scopes/compiler-service.ts +70 -0
  13. package/src/runtime/scopes/formatting/apply.ts +262 -0
  14. package/src/runtime/scopes/index.ts +12 -0
  15. package/src/runtime/scopes/replacement/propose.ts +2 -0
  16. package/src/runtime/scopes/scope-kinds/paragraph.ts +1 -0
  17. package/src/runtime/scopes/semantic-scope-types.ts +48 -4
  18. package/src/runtime/scopes/workflow-overlap.ts +9 -11
  19. package/src/shell/session-bootstrap.ts +1 -0
  20. package/src/ui/WordReviewEditor.tsx +277 -28
  21. package/src/ui/editor-command-bag.ts +11 -0
  22. package/src/ui/editor-shell-view.tsx +10 -0
  23. package/src/ui/headless/chrome-registry.ts +6 -6
  24. package/src/ui/headless/role-action-sets.ts +4 -10
  25. package/src/ui/headless/selection-tool-resolver.ts +11 -0
  26. package/src/ui-tailwind/chrome/editor-action-registry.ts +1 -1
  27. package/src/ui-tailwind/chrome/tw-context-band.tsx +7 -7
  28. package/src/ui-tailwind/chrome/tw-detach-handle.tsx +13 -18
  29. package/src/ui-tailwind/chrome/tw-image-context-toolbar.tsx +8 -5
  30. package/src/ui-tailwind/chrome/tw-inline-find-bar.tsx +100 -0
  31. package/src/ui-tailwind/chrome/tw-selection-toolbar.tsx +0 -40
  32. package/src/ui-tailwind/chrome/tw-table-context-toolbar.tsx +9 -7
  33. package/src/ui-tailwind/chrome-overlay/tw-chrome-overlay.tsx +17 -1
  34. package/src/ui-tailwind/chrome-overlay/tw-scope-card-layer.tsx +6 -1
  35. package/src/ui-tailwind/chrome-overlay/tw-scope-rail-layer.tsx +17 -7
  36. package/src/ui-tailwind/editor-surface/preserve-position.ts +61 -11
  37. package/src/ui-tailwind/editor-surface/scroll-anchor.ts +20 -5
  38. package/src/ui-tailwind/editor-surface/tw-prosemirror-surface.tsx +52 -6
  39. package/src/ui-tailwind/editor-surface/tw-table-node-view.tsx +5 -1
  40. package/src/ui-tailwind/review/tw-review-rail.tsx +5 -0
  41. package/src/ui-tailwind/review/tw-workflow-tab.tsx +32 -38
  42. package/src/ui-tailwind/review-workspace/types.ts +2 -0
  43. package/src/ui-tailwind/theme/editor-theme.css +25 -12
  44. package/src/ui-tailwind/toolbar/tw-role-action-region.tsx +13 -4
  45. package/src/ui-tailwind/toolbar/tw-toolbar.tsx +6 -15
  46. package/src/ui-tailwind/tw-review-workspace.tsx +28 -18
  47. package/src/ui-tailwind/workflow-scope-layers.ts +70 -0
@@ -68,6 +68,11 @@ import { useLayoutFacetRenderSignal } from "./review-workspace/use-layout-facet-
68
68
  import { useScrollRootCapture } from "./review-workspace/use-scroll-root-capture.ts";
69
69
  import { usePmSurfaceCapture } from "./review-workspace/use-pm-surface-capture.ts";
70
70
  import { TwReviewWorkspaceNavigator } from "./review-workspace/tw-review-workspace-navigator.tsx";
71
+ import {
72
+ createDefaultWorkflowScopeLayerKeys,
73
+ workflowScopePosturesForLayerKeys,
74
+ type WorkflowScopeLayerKey,
75
+ } from "./workflow-scope-layers";
71
76
 
72
77
  export {
73
78
  FRAME_PX_PER_TWIP_AT_96DPI,
@@ -174,6 +179,13 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
174
179
  useRef<TwWorkspaceChromeHostController | null>(null);
175
180
  const [shellModeOverride, setShellModeOverride] =
176
181
  useState<ShellHeaderMode | null>(null);
182
+ const [workflowLayerFilters, setWorkflowLayerFilters] = useState<
183
+ ReadonlySet<WorkflowScopeLayerKey>
184
+ >(createDefaultWorkflowScopeLayerKeys);
185
+ const visibleScopePostures = useMemo(
186
+ () => workflowScopePosturesForLayerKeys(workflowLayerFilters),
187
+ [workflowLayerFilters],
188
+ );
177
189
  // P8.11 — body slot wrapping `{props.document}` (the PM surface) + scroll
178
190
  // root ref. The chrome layer's `TwPageStackChromeLayer` needs both to
179
191
  // measure per-page rects and to reparent PM's DOM node across band
@@ -533,12 +545,10 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
533
545
  )
534
546
  : null;
535
547
 
536
- // Audit §2.5 — context band mounts as a composition-level sibling of
537
- // the toolbar so the workspace row becomes
538
- // [toolbar left cluster] · [context band] · [toolbar right cluster]
539
- // and the band can render mode-owned content (Phase B.3 additive mount;
540
- // Phase D migrates role-action contents into the band and retires the
541
- // legacy inline role region inside TwToolbar).
548
+ // Audit §2.5 — context band mounts as a composition-level sibling below
549
+ // the shell header only when the active mode has meaningful mode-owned
550
+ // content. Plain editor mode keeps its authoring controls in the toolbar
551
+ // and intentionally does not render an empty "Edit" ribbon.
542
552
  //
543
553
  // `resolveChromeComposition` is pure but each call allocates new Sets +
544
554
  // arrays. `TwReviewWorkspace` re-renders on every PM transaction (the
@@ -573,6 +583,9 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
573
583
  modeOverride: shellModeOverride === "more" ? "more" : undefined,
574
584
  });
575
585
  const showHealthRailTab = composition.rail.visibleTabs.has("health");
586
+ const showContextBand =
587
+ chromeVisibility.toolbar &&
588
+ (composition.mode === "more" || viewState.editorRole !== "editor");
576
589
 
577
590
  const arbiter = useWorkspaceArbiter();
578
591
 
@@ -591,18 +604,12 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
591
604
  * decoupling this branch.
592
605
  */}
593
606
  {/*
594
- * Chrome Closure Pass · Task 1 (designsystem.md §6.3) — the
595
- * role-action region used to render inline in the toolbar's
596
- * center subregion. It now lives inside `TwContextBand` so the
597
- * workspace row reads
598
- * [shell header] · [TwContextBand carrying role actions] · [TwToolbar (formatting only)]
599
- * matching §8.8.1's "Workspace context row / mode-owned band"
600
- * row. Callbacks below mirror what was previously threaded
601
- * through `ChromePresetToolbar` to `TwRoleActionRegion`; the
602
- * toolbar still receives `role` for `isChromeItemOwnedByRoleRegion`
603
- * deferral but no longer renders the region itself.
607
+ * Chrome Closure Pass · Task 1 (designsystem.md §6.3) — review,
608
+ * workflow, and More mode actions live in `TwContextBand`; editor
609
+ * mode stays toolbar-only unless a future pass adds real contextual
610
+ * authoring content.
604
611
  */}
605
- {chromeVisibility.toolbar ? (
612
+ {showContextBand ? (
606
613
  <TwContextBand mode={composition.mode}>
607
614
  {composition.mode === "more" ? (
608
615
  <TwMoreContextBandContent
@@ -615,7 +622,7 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
615
622
  props.onActiveRailTabChange?.("health");
616
623
  }}
617
624
  onOpenOutline={() => setNavOpen(true)}
618
- onOpenSearch={props.reviewRailFooter?.onSearch}
625
+ onOpenSearch={props.onOpenInlineFind ?? props.reviewRailFooter?.onSearch}
619
626
  />
620
627
  ) : viewState.editorRole ? (
621
628
  <TwRoleActionRegion
@@ -1167,6 +1174,7 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
1167
1174
  onSetColumnWidth={props.onSetColumnWidth}
1168
1175
  onSetRowHeight={props.onSetRowHeight}
1169
1176
  activeScopeId={activeScopeId}
1177
+ visibleScopePostures={visibleScopePostures}
1170
1178
  editorRole={viewState.editorRole}
1171
1179
  scopeCardScopeTagEditor={props.scopeCardScopeTagEditor}
1172
1180
  onScopeStripeClick={handleScopeStripeClick}
@@ -1273,6 +1281,8 @@ export function TwReviewWorkspace(inputProps: TwReviewWorkspaceProps) {
1273
1281
  // `getAllScopeRailSegments` (methods removed in v40 / Slice 4C).
1274
1282
  scopeRailSegments: props.workflowFacet?.getAllRailSegments() ?? [],
1275
1283
  activeScopeId,
1284
+ workflowLayerFilters,
1285
+ onWorkflowLayerFiltersChange: setWorkflowLayerFilters,
1276
1286
  onOpenScope: (segment) => {
1277
1287
  handleScopeStripeClick({ scopeId: segment.scopeId });
1278
1288
  },
@@ -0,0 +1,70 @@
1
+ import type { ScopeRailPosture } from "../api/public-types";
2
+
3
+ export type WorkflowScopeLayerKey =
4
+ | "edit"
5
+ | "suggest"
6
+ | "comment"
7
+ | "view"
8
+ | "candidate"
9
+ | "blocked";
10
+
11
+ export interface WorkflowScopeLayerFilter {
12
+ key: WorkflowScopeLayerKey;
13
+ label: string;
14
+ postures: readonly ScopeRailPosture[];
15
+ }
16
+
17
+ export const WORKFLOW_SCOPE_LAYER_FILTERS: readonly WorkflowScopeLayerFilter[] = [
18
+ { key: "edit", label: "Edit", postures: ["edit"] },
19
+ { key: "suggest", label: "Suggest", postures: ["suggest"] },
20
+ { key: "comment", label: "Comment", postures: ["comment"] },
21
+ { key: "view", label: "Review", postures: ["view"] },
22
+ { key: "candidate", label: "Scheduled", postures: ["candidate"] },
23
+ { key: "blocked", label: "Blocked", postures: ["preserve-only", "blocked-import"] },
24
+ ];
25
+
26
+ export function createDefaultWorkflowScopeLayerKeys(): ReadonlySet<WorkflowScopeLayerKey> {
27
+ return new Set(WORKFLOW_SCOPE_LAYER_FILTERS.map((filter) => filter.key));
28
+ }
29
+
30
+ export function workflowScopeLayerKeyForPosture(
31
+ posture: ScopeRailPosture,
32
+ ): WorkflowScopeLayerKey {
33
+ if (posture === "preserve-only" || posture === "blocked-import") {
34
+ return "blocked";
35
+ }
36
+ return posture;
37
+ }
38
+
39
+ export function isWorkflowScopePostureVisible(
40
+ posture: ScopeRailPosture,
41
+ enabledLayers: ReadonlySet<WorkflowScopeLayerKey>,
42
+ ): boolean {
43
+ return enabledLayers.has(workflowScopeLayerKeyForPosture(posture));
44
+ }
45
+
46
+ export function workflowScopePosturesForLayerKeys(
47
+ enabledLayers: ReadonlySet<WorkflowScopeLayerKey>,
48
+ ): ReadonlySet<ScopeRailPosture> {
49
+ const postures = new Set<ScopeRailPosture>();
50
+ for (const filter of WORKFLOW_SCOPE_LAYER_FILTERS) {
51
+ if (!enabledLayers.has(filter.key)) continue;
52
+ for (const posture of filter.postures) {
53
+ postures.add(posture);
54
+ }
55
+ }
56
+ return postures;
57
+ }
58
+
59
+ export function toggleWorkflowScopeLayerKey(
60
+ current: ReadonlySet<WorkflowScopeLayerKey>,
61
+ key: WorkflowScopeLayerKey,
62
+ ): ReadonlySet<WorkflowScopeLayerKey> {
63
+ const next = new Set(current);
64
+ if (next.has(key)) {
65
+ next.delete(key);
66
+ } else {
67
+ next.add(key);
68
+ }
69
+ return next;
70
+ }