@beyondwork/docx-react-component 1.0.105 → 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.
Files changed (193) hide show
  1. package/package.json +19 -5
  2. package/src/api/geometry-overlay-rects.ts +5 -0
  3. package/src/api/package-version.ts +1 -1
  4. package/src/api/page-anchor-id.ts +5 -0
  5. package/src/api/public-types.ts +16 -9
  6. package/src/api/table-node-specs.ts +6 -0
  7. package/src/api/v3/_create.ts +10 -2
  8. package/src/api/v3/_page-anchor-id.ts +52 -0
  9. package/src/api/v3/_runtime-handle.ts +92 -1
  10. package/src/api/v3/ai/_audit-reference.ts +28 -0
  11. package/src/api/v3/ai/_audit-time.ts +5 -0
  12. package/src/api/v3/ai/_pe2-evidence.ts +310 -6
  13. package/src/api/v3/ai/attach.ts +29 -4
  14. package/src/api/v3/ai/bundle.ts +6 -2
  15. package/src/api/v3/ai/inspect.ts +6 -2
  16. package/src/api/v3/ai/replacement.ts +112 -18
  17. package/src/api/v3/ai/resolve.ts +2 -2
  18. package/src/api/v3/ai/review.ts +177 -3
  19. package/src/api/v3/index.ts +8 -0
  20. package/src/api/v3/runtime/collab.ts +462 -0
  21. package/src/api/v3/runtime/document.ts +503 -20
  22. package/src/api/v3/runtime/geometry.ts +97 -0
  23. package/src/api/v3/runtime/layout.ts +744 -0
  24. package/src/api/v3/runtime/perf-probe.ts +14 -0
  25. package/src/api/v3/runtime/viewport.ts +9 -8
  26. package/src/api/v3/ui/_types.ts +202 -55
  27. package/src/api/v3/ui/chrome-preset-model.ts +5 -5
  28. package/src/api/v3/ui/debug.ts +115 -2
  29. package/src/api/v3/ui/index.ts +17 -0
  30. package/src/api/v3/ui/overlays.ts +0 -8
  31. package/src/api/v3/ui/surface.ts +56 -0
  32. package/src/api/v3/ui/viewport.ts +119 -9
  33. package/src/core/commands/image-commands.ts +1 -0
  34. package/src/core/commands/index.ts +6 -0
  35. package/src/core/schema/text-schema.ts +43 -5
  36. package/src/core/selection/mapping.ts +8 -1
  37. package/src/core/selection/review-anchors.ts +5 -1
  38. package/src/core/state/text-transaction.ts +8 -2
  39. package/src/io/export/serialize-revisions.ts +149 -1
  40. package/src/io/normalize/normalize-text.ts +6 -0
  41. package/src/io/ooxml/parse-bookmark-references.ts +55 -0
  42. package/src/io/ooxml/parse-fields.ts +24 -2
  43. package/src/io/ooxml/parse-headers-footers.ts +38 -5
  44. package/src/io/ooxml/parse-main-document.ts +153 -9
  45. package/src/io/ooxml/parse-numbering.ts +20 -0
  46. package/src/io/ooxml/parse-revisions.ts +19 -8
  47. package/src/io/opc/package-reader.ts +98 -8
  48. package/src/model/anchor.ts +4 -3
  49. package/src/model/canonical-document.ts +220 -2
  50. package/src/model/canonical-hash.ts +221 -0
  51. package/src/model/canonical-layout-inputs.ts +245 -6
  52. package/src/model/layout/index.ts +1 -0
  53. package/src/model/layout/page-graph-types.ts +147 -1
  54. package/src/model/review/revision-types.ts +14 -3
  55. package/src/preservation/store.ts +20 -4
  56. package/src/review/README.md +1 -1
  57. package/src/review/store/revision-actions.ts +14 -2
  58. package/src/runtime/collab/event-types.ts +67 -1
  59. package/src/runtime/collab/runtime-collab-sync.ts +177 -5
  60. package/src/runtime/diagnostics/layout-guard-warning.ts +18 -0
  61. package/src/runtime/document-heading-outline.ts +147 -0
  62. package/src/runtime/document-navigation.ts +8 -243
  63. package/src/runtime/document-runtime.ts +279 -115
  64. package/src/runtime/edit-dispatch/dispatch-text-command.ts +11 -0
  65. package/src/runtime/formatting/layout-inputs.ts +38 -5
  66. package/src/runtime/formatting/numbering/geometry.ts +28 -2
  67. package/src/runtime/geometry/adjacent-geometry-intake.ts +835 -0
  68. package/src/runtime/geometry/caret-geometry.ts +5 -6
  69. package/src/runtime/geometry/geometry-facet.ts +60 -10
  70. package/src/runtime/geometry/geometry-index.ts +661 -16
  71. package/src/runtime/geometry/geometry-types.ts +59 -0
  72. package/src/runtime/geometry/hit-test.ts +11 -1
  73. package/src/runtime/geometry/overlay-rects.ts +5 -3
  74. package/src/runtime/geometry/project-anchors.ts +1 -1
  75. package/src/runtime/geometry/word-layout-v2-line-intake.ts +323 -0
  76. package/src/runtime/layout/index.ts +6 -0
  77. package/src/runtime/layout/layout-engine-instance.ts +6 -1
  78. package/src/runtime/layout/layout-engine-version.ts +188 -16
  79. package/src/runtime/layout/layout-facet-types.ts +6 -0
  80. package/src/runtime/layout/page-graph.ts +23 -4
  81. package/src/runtime/layout/paginated-layout-engine.ts +149 -15
  82. package/src/runtime/layout/project-block-fragments.ts +351 -14
  83. package/src/runtime/layout/public-facet.ts +162 -24
  84. package/src/runtime/layout/table-row-continuation-contract.ts +107 -0
  85. package/src/runtime/layout/table-row-split.ts +92 -35
  86. package/src/runtime/prerender/cache-envelope.ts +2 -2
  87. package/src/runtime/prerender/cache-key.ts +5 -4
  88. package/src/runtime/prerender/customxml-cache.ts +0 -1
  89. package/src/runtime/render/render-kernel.ts +1 -1
  90. package/src/runtime/revision-runtime.ts +112 -10
  91. package/src/runtime/scopes/_scope-dependencies.ts +1 -0
  92. package/src/runtime/scopes/action-validation.ts +22 -2
  93. package/src/runtime/scopes/capabilities.ts +316 -0
  94. package/src/runtime/scopes/compile-scope-bundle.ts +14 -0
  95. package/src/runtime/scopes/compiler-service.ts +108 -4
  96. package/src/runtime/scopes/content-control-evidence.ts +79 -0
  97. package/src/runtime/scopes/create-issue.ts +5 -5
  98. package/src/runtime/scopes/evidence.ts +91 -0
  99. package/src/runtime/scopes/formatting/apply.ts +2 -0
  100. package/src/runtime/scopes/geometry-evidence.ts +130 -0
  101. package/src/runtime/scopes/index.ts +54 -0
  102. package/src/runtime/scopes/issue-lifecycle.ts +224 -0
  103. package/src/runtime/scopes/layout-evidence.ts +374 -0
  104. package/src/runtime/scopes/multi-paragraph-refusal.ts +37 -0
  105. package/src/runtime/scopes/preservation-boundary.ts +7 -1
  106. package/src/runtime/scopes/replacement/apply.ts +97 -34
  107. package/src/runtime/scopes/scope-kinds/paragraph.ts +108 -12
  108. package/src/runtime/scopes/semantic-scope-types.ts +242 -3
  109. package/src/runtime/scopes/visualization.ts +28 -0
  110. package/src/runtime/surface-projection.ts +44 -5
  111. package/src/runtime/telemetry/perf-probe.ts +216 -0
  112. package/src/runtime/virtualized-rendering.ts +36 -1
  113. package/src/runtime/workflow/ai-issue-lifecycle.ts +253 -0
  114. package/src/runtime/workflow/coordinator.ts +39 -11
  115. package/src/runtime/workflow/derived-scope-resolver.ts +63 -9
  116. package/src/runtime/workflow/index.ts +4 -0
  117. package/src/runtime/workflow/overlay-lane-types.ts +58 -0
  118. package/src/runtime/workflow/overlay-lanes.ts +386 -0
  119. package/src/runtime/workflow/overlay-store.ts +2 -2
  120. package/src/runtime/workflow/redline-posture-calibration.ts +257 -0
  121. package/src/runtime/workflow/word-field-matrix-calibration.ts +231 -0
  122. package/src/session/_sync-legacy.ts +17 -27
  123. package/src/session/import/loader.ts +6 -4
  124. package/src/session/import/source-package-evidence.ts +186 -2
  125. package/src/session/index.ts +5 -6
  126. package/src/session/session.ts +30 -56
  127. package/src/session/types.ts +8 -13
  128. package/src/shell/session-bootstrap.ts +155 -81
  129. package/src/ui/WordReviewEditor.tsx +520 -12
  130. package/src/ui/editor-shell-view.tsx +14 -4
  131. package/src/ui/editor-surface-controller.tsx +5 -3
  132. package/src/ui/headless/selection-tool-resolver.ts +1 -2
  133. package/src/ui/presence-overlay-lane.ts +130 -0
  134. package/src/ui/ui-controller-factory.ts +17 -0
  135. package/src/ui-tailwind/chrome/build-context-menu-entries.ts +5 -1
  136. package/src/ui-tailwind/chrome/editor-action-registry.ts +105 -5
  137. package/src/ui-tailwind/chrome/editor-actions-to-palette.ts +7 -0
  138. package/src/ui-tailwind/chrome/layer-debug-contracts.ts +208 -0
  139. package/src/ui-tailwind/chrome/resolve-target-kind.ts +13 -0
  140. package/src/ui-tailwind/chrome/tw-alert-banner.tsx +11 -3
  141. package/src/ui-tailwind/chrome/tw-command-palette.tsx +36 -6
  142. package/src/ui-tailwind/chrome/tw-context-menu.tsx +6 -1
  143. package/src/ui-tailwind/chrome/tw-display-mode-selector.tsx +42 -109
  144. package/src/ui-tailwind/chrome/tw-inline-find-bar.tsx +26 -6
  145. package/src/ui-tailwind/chrome/tw-navigation-command-bar.tsx +328 -0
  146. package/src/ui-tailwind/chrome/tw-object-context-toolbar.tsx +8 -4
  147. package/src/ui-tailwind/chrome/tw-runtime-repl-dialog.tsx +129 -1
  148. package/src/ui-tailwind/chrome/tw-selection-tool-host.tsx +19 -5
  149. package/src/ui-tailwind/chrome/tw-selection-tool-structure.tsx +5 -1
  150. package/src/ui-tailwind/chrome/tw-workspace-chrome-host.tsx +28 -12
  151. package/src/ui-tailwind/chrome-overlay/tw-chrome-overlay.tsx +30 -3
  152. package/src/ui-tailwind/chrome-overlay/tw-object-selection-overlay.tsx +116 -10
  153. package/src/ui-tailwind/chrome-overlay/tw-page-stack-overlay-layer.tsx +223 -94
  154. package/src/ui-tailwind/chrome-overlay/tw-presence-overlay-lane.tsx +157 -0
  155. package/src/ui-tailwind/chrome-overlay/tw-review-overlay-lane-markers.tsx +259 -0
  156. package/src/ui-tailwind/chrome-overlay/tw-scope-card-layer.tsx +5 -2
  157. package/src/ui-tailwind/chrome-overlay/tw-substrate-overlay-lanes.tsx +314 -0
  158. package/src/ui-tailwind/debug/README.md +4 -1
  159. package/src/ui-tailwind/debug/layer11-consumer-readiness.ts +272 -0
  160. package/src/ui-tailwind/debug/layer11-word-field-matrix-evidence.ts +160 -0
  161. package/src/ui-tailwind/editor-surface/perf-probe.ts +14 -215
  162. package/src/ui-tailwind/editor-surface/pm-decorations.ts +42 -0
  163. package/src/ui-tailwind/editor-surface/pm-position-map.ts +38 -2
  164. package/src/ui-tailwind/editor-surface/pm-schema.ts +14 -4
  165. package/src/ui-tailwind/editor-surface/pm-state-from-snapshot.ts +34 -5
  166. package/src/ui-tailwind/editor-surface/runtime-decoration-plugin.ts +9 -19
  167. package/src/ui-tailwind/editor-surface/surface-build-keys.ts +2 -2
  168. package/src/ui-tailwind/editor-surface/tw-page-block-view.helpers.ts +145 -0
  169. package/src/ui-tailwind/editor-surface/tw-page-block-view.tsx +16 -11
  170. package/src/ui-tailwind/editor-surface/tw-prosemirror-surface.tsx +8 -10
  171. package/src/ui-tailwind/editor-surface/tw-table-node-view.tsx +3 -0
  172. package/src/ui-tailwind/page-stack/tw-page-chrome-entry.tsx +4 -2
  173. package/src/ui-tailwind/page-stack/tw-page-stack-chrome-layer.tsx +60 -20
  174. package/src/ui-tailwind/page-stack/tw-region-block-renderer.tsx +16 -11
  175. package/src/ui-tailwind/review/tw-health-panel.tsx +36 -17
  176. package/src/ui-tailwind/review/tw-review-rail.tsx +7 -4
  177. package/src/ui-tailwind/review-workspace/diagnostics-visibility.ts +44 -0
  178. package/src/ui-tailwind/review-workspace/page-shell-metrics.ts +11 -0
  179. package/src/ui-tailwind/review-workspace/tw-review-workspace-rail.tsx +16 -1
  180. package/src/ui-tailwind/review-workspace/types.ts +26 -12
  181. package/src/ui-tailwind/review-workspace/use-diagnostics-signal.ts +40 -11
  182. package/src/ui-tailwind/review-workspace/use-layout-facet-render-signal.ts +2 -1
  183. package/src/ui-tailwind/review-workspace/use-page-markers.ts +15 -26
  184. package/src/ui-tailwind/review-workspace/use-scope-card-state.ts +35 -18
  185. package/src/ui-tailwind/review-workspace/use-selection-toolbar-placement.ts +41 -32
  186. package/src/ui-tailwind/review-workspace/use-status-bar-page-facts.ts +2 -1
  187. package/src/ui-tailwind/review-workspace/use-workspace-side-effects.ts +2 -1
  188. package/src/ui-tailwind/status/tw-status-bar.tsx +6 -5
  189. package/src/ui-tailwind/toolbar/tw-role-action-region.tsx +52 -80
  190. package/src/ui-tailwind/toolbar/tw-shell-header.tsx +12 -48
  191. package/src/ui-tailwind/toolbar/tw-toolbar-icon-button.tsx +9 -4
  192. package/src/ui-tailwind/toolbar/tw-toolbar.tsx +328 -361
  193. package/src/ui-tailwind/tw-review-workspace.tsx +152 -286
@@ -47,6 +47,17 @@ export function dispatchTextCommand(
47
47
  }]);
48
48
  return;
49
49
  }
50
+ if (
51
+ effectiveSelectionMode === "suggest" &&
52
+ command.type === "split-paragraph" &&
53
+ context.activeStory.kind !== "main"
54
+ ) {
55
+ runtime.emitBlockedCommand(getMountedTextCommandName(command), [{
56
+ code: "suggesting_unsupported",
57
+ message: "Structural suggestions are only supported in the main story.",
58
+ }]);
59
+ return;
60
+ }
50
61
 
51
62
  if (listAwareResult) {
52
63
  deps.dispatchStoryMutationResult(runtime, context, listAwareResult, context.timestamp);
@@ -47,12 +47,15 @@ export interface NumberingLayoutInput {
47
47
 
48
48
  export interface FieldLayoutInput {
49
49
  readonly fieldId: string;
50
+ readonly canonicalFieldId?: string;
50
51
  readonly regionId: string;
51
- readonly regionKind: "field" | "toc-region";
52
+ readonly regionKind: CanonicalFieldRegionIdentity["kind"];
52
53
  readonly storyKey: string;
53
54
  readonly fieldIndex: number;
54
55
  readonly paragraphIndex: number;
55
56
  readonly family: FieldFamily;
57
+ readonly sourceRef?: CanonicalFieldRegionIdentity["sourceRef"];
58
+ readonly fieldEvidence?: CanonicalFieldRegionIdentity["fieldEvidence"];
56
59
  readonly instruction: string;
57
60
  readonly cachedText: string;
58
61
  readonly switches?: FieldRegistryEntry["switches"];
@@ -176,12 +179,19 @@ export function toFieldLayoutInput(
176
179
  ): FieldLayoutInput {
177
180
  return {
178
181
  fieldId: `field-${entry.fieldIndex}`,
182
+ ...(region?.canonicalFieldId !== undefined
183
+ ? { canonicalFieldId: region.canonicalFieldId }
184
+ : entry.canonicalFieldId !== undefined
185
+ ? { canonicalFieldId: entry.canonicalFieldId }
186
+ : {}),
179
187
  regionId: region?.regionId ?? `field:${entry.fieldIndex}`,
180
188
  regionKind: region?.kind ?? "field",
181
189
  storyKey: region?.storyKey ?? entry.storyKey ?? MAIN_STORY_KEY,
182
190
  fieldIndex: entry.fieldIndex,
183
191
  paragraphIndex: region?.paragraphIndex ?? entry.paragraphIndex,
184
192
  family: entry.fieldFamily,
193
+ ...(region?.sourceRef !== undefined ? { sourceRef: region.sourceRef } : {}),
194
+ ...(region?.fieldEvidence !== undefined ? { fieldEvidence: region.fieldEvidence } : {}),
185
195
  instruction: entry.instruction,
186
196
  cachedText: entry.displayText,
187
197
  ...(entry.switches ? { switches: entry.switches } : {}),
@@ -197,9 +207,8 @@ export function collectFieldLayoutInputs(
197
207
  resolve?: (entry: FieldRegistryEntry) => ResolvedField | undefined,
198
208
  regions: readonly CanonicalFieldRegionIdentity[] = [],
199
209
  ): readonly FieldLayoutInput[] {
200
- if (!registry) return [];
201
210
  const inputs: FieldLayoutInput[] = [];
202
- const entries = [...registry.supported, ...registry.preserveOnly];
211
+ const entries = [...(registry?.supported ?? []), ...(registry?.preserveOnly ?? [])];
203
212
  const fieldRegions = new Map(
204
213
  regions
205
214
  .filter((region) => region.kind === "field")
@@ -210,11 +219,12 @@ export function collectFieldLayoutInputs(
210
219
  .filter((region) => region.kind === "toc-region" && region.tocId !== undefined)
211
220
  .map((region) => [region.tocId!, region]),
212
221
  );
222
+ const hyperlinkRegions = regions.filter((region) => region.kind === "hyperlink-field");
213
223
  for (const entry of entries) {
214
224
  inputs.push(toFieldLayoutInput(entry, resolve?.(entry), fieldRegions.get(entry.fieldIndex)));
215
225
  }
216
- for (const region of registry.tocRegions ?? []) {
217
- const source = registry.supported.find(
226
+ for (const region of registry?.tocRegions ?? []) {
227
+ const source = registry?.supported.find(
218
228
  (entry) => entry.fieldIndex === region.sourceFieldIndex,
219
229
  );
220
230
  if (!source) continue;
@@ -230,9 +240,32 @@ export function collectFieldLayoutInputs(
230
240
  tocEntryCount: region.cachedEntries.length + region.generatedEntries.length,
231
241
  });
232
242
  }
243
+ for (const region of hyperlinkRegions) {
244
+ inputs.push(toHyperlinkFieldLayoutInput(region));
245
+ }
233
246
  return inputs;
234
247
  }
235
248
 
249
+ function toHyperlinkFieldLayoutInput(
250
+ region: CanonicalFieldRegionIdentity,
251
+ ): FieldLayoutInput {
252
+ return {
253
+ fieldId: `hyperlink-${region.fieldIndex}`,
254
+ canonicalFieldId: region.canonicalFieldId,
255
+ regionId: region.regionId,
256
+ regionKind: "hyperlink-field",
257
+ storyKey: region.storyKey,
258
+ fieldIndex: region.fieldIndex,
259
+ paragraphIndex: region.paragraphIndex,
260
+ family: region.fieldFamily,
261
+ ...(region.sourceRef !== undefined ? { sourceRef: region.sourceRef } : {}),
262
+ ...(region.fieldEvidence !== undefined ? { fieldEvidence: region.fieldEvidence } : {}),
263
+ instruction: "",
264
+ cachedText: "",
265
+ refreshState: region.refreshStatus,
266
+ };
267
+ }
268
+
236
269
  export function buildRevisionLayoutPosture(
237
270
  mode: RevisionLayoutPosture["mode"],
238
271
  displays: readonly RevisionDisplayFlags[] = [],
@@ -72,7 +72,18 @@ export function resolveNumberingDefinitionSet(
72
72
  }
73
73
 
74
74
  const effectiveLevels = buildEffectiveLevelDefinitions(abstractDefinition.levels, instance.overrides);
75
- const effectiveLevel = effectiveLevels.get(numbering.level);
75
+ let effectiveLevel = effectiveLevels.get(numbering.level);
76
+ if (!effectiveLevel && abstractDefinition.multiLevelType === "singleLevel") {
77
+ // ECMA-376 §17.9.16 — `singleLevel` abstractNums define a single ilvl
78
+ // (conventionally 0). When a paragraph references a level that isn't
79
+ // defined, Word (and LibreOffice) render using the sole defined level
80
+ // rather than omitting the marker. Mirror that: pick the first
81
+ // available level. Observed in CCEP `aps-supply-of-services.docx` where
82
+ // paragraph "No-Deforestation" carries `<w:numPr w:ilvl="2" w:numId="8"/>`
83
+ // against a singleLevel abstractNum that defines only ilvl=0 (bullet).
84
+ const [firstDefinedLevel] = effectiveLevels.values();
85
+ effectiveLevel = firstDefinedLevel;
86
+ }
76
87
  if (!effectiveLevel) {
77
88
  return null;
78
89
  }
@@ -205,6 +216,15 @@ function resolveNumberingGeometry(
205
216
  // meaning "no custom indent beyond the list style" — use level geometry directly.
206
217
  // This also covers the prior CO3.8 heuristic (para.left === level.left) since Word
207
218
  // typically writes hanging=left in that situation too.
219
+ //
220
+ // Extension (CCEP bullet fidelity, 2026-04-23 truth-baseline): Word also writes
221
+ // bullet paragraphs with a lone `<w:ind w:hanging="L"/>` (no w:left) where L equals
222
+ // the numbering level's `left`. Example from eu-global-it-services
223
+ // `<w:pStyle w:val="ListParagraph"/> <w:numPr w:ilvl=0 w:numId=34/> <w:ind w:hanging="720"/>`
224
+ // against abstractNum lvl 0 `<w:ind w:left="720" w:hanging="360"/>`. Strict per-attribute
225
+ // override yields `left=720, hanging=720` (marker flush at body margin), but LO/Word
226
+ // actually render `left=720, hanging=360` (marker hangs half the list-level indent).
227
+ // Detect this shape and treat it as a stale Word snapshot — use level geometry directly.
208
228
  const paraInd = paragraph?.indentation;
209
229
  const levelInd = levelGeometry?.indentation;
210
230
  const isDegenerateParaInd =
@@ -212,8 +232,14 @@ function resolveNumberingGeometry(
212
232
  paraInd.hanging !== undefined &&
213
233
  paraInd.left !== undefined &&
214
234
  paraInd.hanging === paraInd.left;
235
+ const isLoneHangingMatchingLevelLeft =
236
+ paraInd !== undefined &&
237
+ paraInd.hanging !== undefined &&
238
+ paraInd.left === undefined &&
239
+ levelInd?.left !== undefined &&
240
+ paraInd.hanging === levelInd.left;
215
241
 
216
- const indentation = isDegenerateParaInd
242
+ const indentation = isDegenerateParaInd || isLoneHangingMatchingLevelLeft
217
243
  ? levelInd ? { ...levelInd } : undefined
218
244
  : mergeParagraphIndentation(levelInd, paraInd);
219
245