@beyondwork/docx-react-component 1.0.55 → 1.0.57

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 (107) hide show
  1. package/package.json +43 -32
  2. package/src/api/public-types.ts +157 -0
  3. package/src/compare/diff-engine.ts +3 -0
  4. package/src/core/commands/formatting-commands.ts +1 -0
  5. package/src/core/commands/index.ts +17 -11
  6. package/src/core/selection/mapping.ts +18 -1
  7. package/src/core/selection/review-anchors.ts +29 -18
  8. package/src/io/chart-preview-resolver.ts +175 -41
  9. package/src/io/docx-session.ts +57 -2
  10. package/src/io/export/serialize-main-document.ts +82 -0
  11. package/src/io/export/serialize-styles.ts +61 -3
  12. package/src/io/export/table-properties-xml.ts +19 -4
  13. package/src/io/normalize/normalize-text.ts +33 -0
  14. package/src/io/ooxml/parse-anchor.ts +182 -0
  15. package/src/io/ooxml/parse-drawing.ts +319 -0
  16. package/src/io/ooxml/parse-fields.ts +115 -2
  17. package/src/io/ooxml/parse-fill.ts +215 -0
  18. package/src/io/ooxml/parse-font-table.ts +190 -0
  19. package/src/io/ooxml/parse-footnotes.ts +52 -1
  20. package/src/io/ooxml/parse-main-document.ts +241 -1
  21. package/src/io/ooxml/parse-numbering.ts +96 -0
  22. package/src/io/ooxml/parse-picture.ts +107 -0
  23. package/src/io/ooxml/parse-settings.ts +34 -0
  24. package/src/io/ooxml/parse-shapes.ts +87 -0
  25. package/src/io/ooxml/parse-solid-fill.ts +11 -0
  26. package/src/io/ooxml/parse-styles.ts +74 -1
  27. package/src/io/ooxml/parse-theme.ts +60 -0
  28. package/src/io/paste/html-clipboard.ts +449 -0
  29. package/src/io/paste/word-clipboard.ts +5 -1
  30. package/src/legal/_document-root.ts +26 -0
  31. package/src/legal/bookmarks.ts +4 -3
  32. package/src/legal/cross-references.ts +3 -2
  33. package/src/legal/defined-terms.ts +2 -1
  34. package/src/legal/signature-blocks.ts +2 -1
  35. package/src/model/canonical-document.ts +415 -3
  36. package/src/runtime/chart/chart-model-store.ts +73 -10
  37. package/src/runtime/document-runtime.ts +693 -41
  38. package/src/runtime/edit-ops/index.ts +129 -0
  39. package/src/runtime/event-refresh-hints.ts +7 -0
  40. package/src/runtime/field-resolver.ts +341 -0
  41. package/src/runtime/footnote-resolver.ts +55 -0
  42. package/src/runtime/hyperlink-color-resolver.ts +13 -10
  43. package/src/runtime/object-grab/index.ts +51 -0
  44. package/src/runtime/paragraph-style-resolver.ts +105 -0
  45. package/src/runtime/resolved-numbering-geometry.ts +12 -0
  46. package/src/runtime/selection/cursor-ops.ts +186 -15
  47. package/src/runtime/selection/index.ts +17 -1
  48. package/src/runtime/structure-ops/index.ts +77 -0
  49. package/src/runtime/styles-cascade.ts +33 -0
  50. package/src/runtime/surface-projection.ts +186 -12
  51. package/src/runtime/theme-color-resolver.ts +189 -44
  52. package/src/runtime/units.ts +46 -0
  53. package/src/runtime/view-state.ts +13 -2
  54. package/src/ui/WordReviewEditor.tsx +168 -10
  55. package/src/ui/editor-runtime-boundary.ts +94 -1
  56. package/src/ui/editor-shell-view.tsx +1 -1
  57. package/src/ui/runtime-shortcut-dispatch.ts +17 -3
  58. package/src/ui-tailwind/chart/ChartSurface.tsx +36 -10
  59. package/src/ui-tailwind/chart/layout/plot-area.ts +120 -45
  60. package/src/ui-tailwind/chart/render/area.tsx +22 -4
  61. package/src/ui-tailwind/chart/render/bar-column.tsx +37 -11
  62. package/src/ui-tailwind/chart/render/bubble.tsx +6 -2
  63. package/src/ui-tailwind/chart/render/combo.tsx +37 -4
  64. package/src/ui-tailwind/chart/render/line.tsx +28 -5
  65. package/src/ui-tailwind/chart/render/pie.tsx +36 -16
  66. package/src/ui-tailwind/chart/render/progressive-render.ts +8 -1
  67. package/src/ui-tailwind/chart/render/scatter.tsx +9 -4
  68. package/src/ui-tailwind/chrome/avatar-initials.ts +15 -0
  69. package/src/ui-tailwind/chrome/tw-comment-preview.tsx +3 -1
  70. package/src/ui-tailwind/chrome/tw-context-menu.tsx +14 -0
  71. package/src/ui-tailwind/chrome/tw-selection-tool-host.tsx +3 -2
  72. package/src/ui-tailwind/chrome/tw-selection-toolbar.tsx +30 -11
  73. package/src/ui-tailwind/chrome/tw-shortcut-hint.tsx +15 -2
  74. package/src/ui-tailwind/chrome/tw-suggestion-card.tsx +1 -1
  75. package/src/ui-tailwind/chrome/tw-table-context-toolbar.tsx +24 -7
  76. package/src/ui-tailwind/chrome/tw-table-grip-layer.tsx +31 -12
  77. package/src/ui-tailwind/chrome-overlay/page-border-resolver.ts +211 -0
  78. package/src/ui-tailwind/chrome-overlay/tw-chrome-overlay.tsx +1 -0
  79. package/src/ui-tailwind/chrome-overlay/tw-comment-balloon-layer.tsx +74 -0
  80. package/src/ui-tailwind/chrome-overlay/tw-locked-block-layer.tsx +65 -0
  81. package/src/ui-tailwind/chrome-overlay/tw-page-border-overlay.tsx +233 -0
  82. package/src/ui-tailwind/chrome-overlay/tw-page-stack-overlay-layer.tsx +135 -13
  83. package/src/ui-tailwind/chrome-overlay/tw-revision-margin-bar-layer.tsx +51 -0
  84. package/src/ui-tailwind/chrome-overlay/tw-scope-card-layer.tsx +12 -4
  85. package/src/ui-tailwind/chrome-overlay/tw-scope-card.tsx +32 -12
  86. package/src/ui-tailwind/chrome-overlay/tw-toc-outline-sidebar.tsx +133 -0
  87. package/src/ui-tailwind/editor-surface/chart-node-view.tsx +49 -10
  88. package/src/ui-tailwind/editor-surface/float-wrap-resolver.ts +119 -0
  89. package/src/ui-tailwind/editor-surface/pm-command-bridge.ts +236 -9
  90. package/src/ui-tailwind/editor-surface/pm-schema.ts +192 -11
  91. package/src/ui-tailwind/editor-surface/pm-state-from-snapshot.ts +28 -3
  92. package/src/ui-tailwind/editor-surface/shape-renderer.ts +206 -0
  93. package/src/ui-tailwind/editor-surface/surface-layer.ts +66 -0
  94. package/src/ui-tailwind/editor-surface/tw-inline-token.tsx +29 -0
  95. package/src/ui-tailwind/editor-surface/tw-segment-view.tsx +7 -1
  96. package/src/ui-tailwind/page-stack/tw-page-stack-chrome-layer.tsx +22 -6
  97. package/src/ui-tailwind/review/tw-comment-sidebar.tsx +10 -16
  98. package/src/ui-tailwind/review/tw-health-panel.tsx +0 -25
  99. package/src/ui-tailwind/review/tw-rail-card.tsx +38 -17
  100. package/src/ui-tailwind/review/tw-review-rail.tsx +2 -2
  101. package/src/ui-tailwind/review/tw-revision-sidebar.tsx +5 -12
  102. package/src/ui-tailwind/review/tw-workflow-tab.tsx +2 -2
  103. package/src/ui-tailwind/theme/editor-theme.css +1 -0
  104. package/src/ui-tailwind/theme/tokens.css +6 -0
  105. package/src/ui-tailwind/theme/tokens.ts +10 -0
  106. package/src/validation/compatibility-engine.ts +2 -0
  107. package/src/validation/docx-comment-proof.ts +12 -3
@@ -3,13 +3,19 @@
3
3
  * Populated as a side effect of `surface-projection.ts` when a `chart_preview`
4
4
  * node carries `parsedData`. Consumed by `ChartNodeView` to render `ChartSurface`.
5
5
  *
6
- * Charts are preserve-only (rawXml never mutated), so entries are stable for the
7
- * lifetime of the document. `clear()` is called before repopulating on document
8
- * replacement.
6
+ * Charts are preserve-only (rawXml never mutated), so entries are stable for
7
+ * the lifetime of a given document build. Lifecycle management: each surface
8
+ * projection pass tags entries with an `owner` (the `CanonicalDocumentEnvelope`
9
+ * reference) and calls `retainForOwner(owner, seenIds)` at the end of the
10
+ * pass. This evicts (a) entries from previous documents (different owner),
11
+ * and (b) stale entries from earlier builds of the same document whose charts
12
+ * no longer appear. Without this, the store grew unbounded across document
13
+ * loads — a documented v1 gap before this fix.
9
14
  */
10
15
 
11
16
  import type { ChartModel } from "../../io/ooxml/chart/types.ts";
12
17
  import type { ResolvedTheme } from "../../model/canonical-document.ts";
18
+ import { EMU_PER_PX } from "../units.ts";
13
19
 
14
20
  export interface ChartStoreEntry {
15
21
  readonly model: ChartModel;
@@ -19,16 +25,31 @@ export interface ChartStoreEntry {
19
25
  }
20
26
 
21
27
  const _store = new Map<string, ChartStoreEntry>();
28
+ const _owners = new Map<string, object>();
29
+
30
+ // Active build pass — set by `beginBuildPass(owner)` at the top of a
31
+ // surface-projection call, consumed by `endBuildPass()` at the end. JS
32
+ // is single-threaded; nested/concurrent projection passes on the same
33
+ // tick aren't expected. Null when no pass is active.
34
+ let _activeOwner: object | null = null;
35
+ let _activeSeenIds: Set<string> | null = null;
22
36
 
23
37
  export const chartModelStore = {
24
38
  set(chartId: string, entry: ChartStoreEntry): void {
25
39
  _store.set(chartId, entry);
40
+ if (_activeOwner !== null) {
41
+ _owners.set(chartId, _activeOwner);
42
+ _activeSeenIds?.add(chartId);
43
+ }
26
44
  },
27
45
  get(chartId: string): ChartStoreEntry | undefined {
28
46
  return _store.get(chartId);
29
47
  },
30
48
  clear(): void {
31
49
  _store.clear();
50
+ _owners.clear();
51
+ _activeOwner = null;
52
+ _activeSeenIds = null;
32
53
  },
33
54
  size(): number {
34
55
  return _store.size;
@@ -39,9 +60,42 @@ export const chartModelStore = {
39
60
  values(): IterableIterator<ChartStoreEntry> {
40
61
  return _store.values();
41
62
  },
63
+ /**
64
+ * Open a build pass tagged with `owner` (typically the
65
+ * `CanonicalDocumentEnvelope` reference). Every `set(id, entry)` call
66
+ * until `endBuildPass()` records `owner` alongside the entry and adds
67
+ * `id` to the "seen this pass" set. Call exactly once at the top of
68
+ * `createEditorSurfaceSnapshot`.
69
+ */
70
+ beginBuildPass(owner: object): void {
71
+ _activeOwner = owner;
72
+ _activeSeenIds = new Set();
73
+ },
74
+ /**
75
+ * Close the build pass opened by `beginBuildPass`. Evicts every stored
76
+ * entry whose owner differs from the active one (charts from previous
77
+ * documents) AND every entry whose id wasn't seen in this pass (stale
78
+ * entries from earlier builds of the same document). Also records
79
+ * ownership for every `seenId` that was populated via `set` during the
80
+ * pass so subsequent `has(id)` short-circuits maintain correct owner
81
+ * metadata on fresh builds.
82
+ */
83
+ endBuildPass(): void {
84
+ const owner = _activeOwner;
85
+ const seen = _activeSeenIds;
86
+ _activeOwner = null;
87
+ _activeSeenIds = null;
88
+ if (owner === null || seen === null) return;
89
+ for (const id of [..._store.keys()]) {
90
+ const entryOwner = _owners.get(id);
91
+ if (entryOwner !== owner || !seen.has(id)) {
92
+ _store.delete(id);
93
+ _owners.delete(id);
94
+ }
95
+ }
96
+ },
42
97
  };
43
98
 
44
- const EMU_PER_PX = 9525;
45
99
 
46
100
  /**
47
101
  * Extract drawing extent from rawXml and convert EMU → pixels.
@@ -75,14 +129,23 @@ export function extractChartDimensions(rawXml: string): { widthPx: number; heigh
75
129
  * Stable chart ID derived from rawXml content. Charts are never mutated so the
76
130
  * ID is stable for the lifetime of the document load.
77
131
  *
78
- * Uses djb2 hash + length suffix to minimize collisions without importing a
79
- * crypto dependency.
132
+ * Uses a djb2 + FNV-1a dual 32-bit hash plus the length suffix. Concatenating
133
+ * two unrelated 32-bit hashes expands the effective collision space to ~2⁶⁴,
134
+ * which keeps the id safely unique even across documents with hundreds of
135
+ * charts. No crypto dependency required.
80
136
  */
81
137
  export function stableChartId(rawXml: string): string {
82
- let h = 5381;
138
+ let h1 = 5381; // djb2
139
+ let h2 = 0x811c9dc5; // FNV-1a offset basis
83
140
  for (let i = 0; i < rawXml.length; i++) {
84
- h = ((h << 5) + h) ^ rawXml.charCodeAt(i);
85
- h = h | 0;
141
+ const c = rawXml.charCodeAt(i);
142
+ h1 = ((h1 << 5) + h1) ^ c;
143
+ h1 = h1 | 0;
144
+ h2 = (h2 ^ c) >>> 0;
145
+ // FNV prime 16777619 = 0x01000193; use Math.imul to stay in 32-bit.
146
+ h2 = Math.imul(h2, 0x01000193) >>> 0;
86
147
  }
87
- return `chart-${(h >>> 0).toString(16)}-${rawXml.length}`;
148
+ const hex1 = (h1 >>> 0).toString(16).padStart(8, "0");
149
+ const hex2 = h2.toString(16).padStart(8, "0");
150
+ return `chart-${hex1}${hex2}-${rawXml.length}`;
88
151
  }