@beyondwork/docx-react-component 1.0.53 → 1.0.54

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 (86) hide show
  1. package/package.json +1 -1
  2. package/src/api/public-types.ts +35 -7
  3. package/src/io/docx-session.ts +30 -6
  4. package/src/runtime/collab/checkpoint-store.ts +1 -1
  5. package/src/runtime/collab/event-types.ts +4 -0
  6. package/src/runtime/collab/runtime-collab-sync.ts +1 -2
  7. package/src/runtime/document-runtime.ts +23 -9
  8. package/src/runtime/layout/inert-layout-facet.ts +1 -0
  9. package/src/runtime/layout/layout-engine-version.ts +58 -1
  10. package/src/runtime/layout/layout-invalidation.ts +150 -30
  11. package/src/runtime/layout/page-graph.ts +19 -0
  12. package/src/runtime/layout/paginated-layout-engine.ts +128 -19
  13. package/src/runtime/layout/project-block-fragments.ts +27 -0
  14. package/src/runtime/layout/public-facet.ts +27 -0
  15. package/src/runtime/render/render-frame-diff.ts +38 -2
  16. package/src/ui/WordReviewEditor.tsx +6 -3
  17. package/src/ui/headless/comment-decoration-model.ts +60 -5
  18. package/src/ui/headless/revision-decoration-model.ts +94 -6
  19. package/src/ui/shared/revision-filters.ts +16 -6
  20. package/src/ui-tailwind/chart/ChartSurface.tsx +236 -0
  21. package/src/ui-tailwind/chart/layout/axis-layout.ts +17 -9
  22. package/src/ui-tailwind/chart/layout/legend-layout.ts +231 -0
  23. package/src/ui-tailwind/chart/layout/plot-area.ts +152 -59
  24. package/src/ui-tailwind/chart/layout/title-layout.ts +184 -0
  25. package/src/ui-tailwind/chart/render/area.tsx +277 -0
  26. package/src/ui-tailwind/chart/render/bar-column.tsx +356 -0
  27. package/src/ui-tailwind/chart/render/bubble.tsx +134 -0
  28. package/src/ui-tailwind/chart/render/combo.tsx +85 -0
  29. package/src/ui-tailwind/chart/render/data-labels.tsx +513 -0
  30. package/src/ui-tailwind/chart/render/font-metrics.ts +298 -0
  31. package/src/ui-tailwind/chart/render/gridlines.ts +228 -0
  32. package/src/ui-tailwind/chart/render/line.tsx +363 -0
  33. package/src/ui-tailwind/chart/render/number-format.ts +120 -16
  34. package/src/ui-tailwind/chart/render/pie.tsx +275 -0
  35. package/src/ui-tailwind/chart/render/progressive-render.ts +103 -0
  36. package/src/ui-tailwind/chart/render/scatter.tsx +228 -0
  37. package/src/ui-tailwind/chart/render/smooth-curve.ts +101 -0
  38. package/src/ui-tailwind/chart/render/svg-primitives.ts +378 -0
  39. package/src/ui-tailwind/chart/render/unsupported.tsx +126 -0
  40. package/src/ui-tailwind/chrome/collab-audience-chip.tsx +11 -0
  41. package/src/ui-tailwind/chrome/collab-negotiation-action-bar.tsx +44 -18
  42. package/src/ui-tailwind/chrome/collab-presence-strip.tsx +68 -7
  43. package/src/ui-tailwind/chrome/collab-role-chip.tsx +21 -2
  44. package/src/ui-tailwind/chrome/collab-tamper-banner.tsx +20 -3
  45. package/src/ui-tailwind/chrome/tw-alert-banner.tsx +102 -37
  46. package/src/ui-tailwind/chrome/tw-command-palette.tsx +358 -0
  47. package/src/ui-tailwind/chrome/tw-comment-preview.tsx +108 -0
  48. package/src/ui-tailwind/chrome/tw-context-menu.tsx +227 -0
  49. package/src/ui-tailwind/chrome/tw-display-mode-selector.tsx +136 -0
  50. package/src/ui-tailwind/chrome/tw-empty-state.tsx +76 -0
  51. package/src/ui-tailwind/chrome/tw-image-context-toolbar.tsx +30 -16
  52. package/src/ui-tailwind/chrome/tw-object-context-toolbar.tsx +23 -4
  53. package/src/ui-tailwind/chrome/tw-paste-drop-toast.tsx +113 -0
  54. package/src/ui-tailwind/chrome/tw-revision-hover-preview.tsx +150 -0
  55. package/src/ui-tailwind/chrome/tw-selection-tool-formatting.tsx +2 -0
  56. package/src/ui-tailwind/chrome/tw-selection-tool-host.tsx +38 -2
  57. package/src/ui-tailwind/chrome/tw-selection-tool-placement.ts +15 -3
  58. package/src/ui-tailwind/chrome/tw-selection-toolbar.tsx +32 -20
  59. package/src/ui-tailwind/chrome/tw-shortcut-hint.tsx +68 -0
  60. package/src/ui-tailwind/chrome/tw-suggestion-card.tsx +10 -10
  61. package/src/ui-tailwind/chrome/tw-table-context-toolbar.tsx +26 -5
  62. package/src/ui-tailwind/chrome/tw-table-grip-layer.tsx +29 -22
  63. package/src/ui-tailwind/chrome/tw-unsaved-modal.tsx +72 -10
  64. package/src/ui-tailwind/chrome-overlay/tw-scope-card.tsx +33 -18
  65. package/src/ui-tailwind/chrome-overlay/tw-table-continuation-header.tsx +94 -0
  66. package/src/ui-tailwind/editor-surface/pm-page-break-decorations.ts +20 -7
  67. package/src/ui-tailwind/editor-surface/scroll-anchor.ts +93 -0
  68. package/src/ui-tailwind/index.ts +11 -0
  69. package/src/ui-tailwind/page-stack/tw-page-chrome-entry.tsx +52 -2
  70. package/src/ui-tailwind/page-stack/tw-page-footer-band.tsx +13 -0
  71. package/src/ui-tailwind/page-stack/tw-page-header-band.tsx +13 -0
  72. package/src/ui-tailwind/page-stack/tw-page-stack-chrome-layer.tsx +8 -0
  73. package/src/ui-tailwind/review/tw-comment-sidebar.tsx +83 -32
  74. package/src/ui-tailwind/review/tw-health-panel.tsx +174 -109
  75. package/src/ui-tailwind/review/tw-rail-card.tsx +9 -1
  76. package/src/ui-tailwind/review/tw-review-rail.tsx +36 -42
  77. package/src/ui-tailwind/review/tw-revision-sidebar.tsx +189 -101
  78. package/src/ui-tailwind/review/tw-workflow-tab.tsx +11 -1
  79. package/src/ui-tailwind/status/tw-status-bar.tsx +114 -46
  80. package/src/ui-tailwind/theme/editor-theme.css +249 -22
  81. package/src/ui-tailwind/toolbar/tw-role-action-region.tsx +14 -1
  82. package/src/ui-tailwind/toolbar/tw-shell-header.tsx +73 -32
  83. package/src/ui-tailwind/toolbar/tw-toolbar-icon-button.tsx +49 -9
  84. package/src/ui-tailwind/toolbar/tw-toolbar.tsx +178 -14
  85. package/src/ui-tailwind/tw-review-workspace.tsx +39 -6
  86. package/src/ui-tailwind/chrome/review-queue-bar.tsx +0 -85
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Bubble chart renderer (Stage 4 Slice 4E).
3
+ *
4
+ * Each data point is drawn as a circle whose radius is proportional to
5
+ * `sqrt(|size|)` (the classic bubble scaling that maps size → area).
6
+ * Null x/y/size values skip the point. Negative sizes use |size|
7
+ * (matching Excel's observed behavior).
8
+ *
9
+ * `bubble3D` is collapsed to 2D per the lane non-goal.
10
+ */
11
+
12
+ import React from "react";
13
+ import { composeSeriesColor } from "../../../io/ooxml/chart/compose-series-color.ts";
14
+ import type {
15
+ BubbleChartModel,
16
+ BubbleSeries,
17
+ } from "../../../io/ooxml/chart/types.ts";
18
+ import type { ResolvedTheme } from "../../../model/canonical-document.ts";
19
+ import type { PlotAreaLayout } from "../layout/plot-area.ts";
20
+
21
+ // ---------------------------------------------------------------------------
22
+ // Public API
23
+ // ---------------------------------------------------------------------------
24
+
25
+ export interface BubbleChartProps {
26
+ model: BubbleChartModel;
27
+ layout: PlotAreaLayout;
28
+ theme: ResolvedTheme | undefined;
29
+ }
30
+
31
+ function BubbleChartImpl({ model, layout, theme }: BubbleChartProps): React.ReactElement {
32
+ const plot = layout.plotRect;
33
+ const { xMin, xMax, yMin, yMax, maxSize } = computeRange(model);
34
+ const xSpan = Math.max(1e-9, xMax - xMin);
35
+ const ySpan = Math.max(1e-9, yMax - yMin);
36
+
37
+ // Max bubble radius = ~6% of the smaller plot dimension so bubbles
38
+ // don't dominate. Scale radius linearly with sqrt(size).
39
+ const maxRadius = Math.max(4, Math.min(plot.w, plot.h) * 0.06);
40
+ const sizeScaleFactor = maxSize > 0 ? maxRadius / Math.sqrt(maxSize) : 0;
41
+
42
+ const bubbles: React.ReactElement[] = [];
43
+
44
+ for (let s = 0; s < model.series.length; s++) {
45
+ const series = model.series[s]!;
46
+ const color = composeSeriesColor(model, theme ?? { colors: {} }, s);
47
+ const n = Math.min(series.xValues.length, series.yValues.length, series.sizes.length);
48
+ for (let i = 0; i < n; i++) {
49
+ const x = series.xValues[i];
50
+ const y = series.yValues[i];
51
+ const size = series.sizes[i];
52
+ if (
53
+ x === null || y === null || size === null ||
54
+ !Number.isFinite(x) || !Number.isFinite(y) || !Number.isFinite(size)
55
+ ) continue;
56
+ const cx = plot.x + ((x - xMin) / xSpan) * plot.w;
57
+ const cy = plot.y + plot.h - ((y - yMin) / ySpan) * plot.h;
58
+ const r = Math.sqrt(Math.abs(size)) * sizeScaleFactor * (series.bubbleScale ?? 1);
59
+ bubbles.push(
60
+ <circle
61
+ key={`bubble-${s}-${i}`}
62
+ cx={cx}
63
+ cy={cy}
64
+ r={Math.max(1, r)}
65
+ fill={color}
66
+ fillOpacity={0.7}
67
+ stroke={color}
68
+ strokeWidth={1}
69
+ data-role="bubble"
70
+ data-series-index={s}
71
+ data-point-index={i}
72
+ />,
73
+ );
74
+ }
75
+ }
76
+
77
+ return (
78
+ <g data-role="bubble-chart" data-bubble3d={model.bubble3D}>
79
+ <g data-role="bubbles">{bubbles}</g>
80
+ <g data-role="data-labels" />
81
+ </g>
82
+ );
83
+ }
84
+
85
+ export const BubbleChart = React.memo(
86
+ BubbleChartImpl,
87
+ (prev, next) =>
88
+ prev.model.rawXml === next.model.rawXml &&
89
+ prev.layout.plotRect.w === next.layout.plotRect.w &&
90
+ prev.layout.plotRect.h === next.layout.plotRect.h &&
91
+ prev.theme === next.theme,
92
+ );
93
+
94
+ // ---------------------------------------------------------------------------
95
+ // Range computation
96
+ // ---------------------------------------------------------------------------
97
+
98
+ function computeRange(model: BubbleChartModel): {
99
+ xMin: number; xMax: number; yMin: number; yMax: number; maxSize: number;
100
+ } {
101
+ const ax = model.xAxis;
102
+ const ay = model.yAxis;
103
+ let xMin = ax.min ?? Infinity;
104
+ let xMax = ax.max ?? -Infinity;
105
+ let yMin = ay.min ?? Infinity;
106
+ let yMax = ay.max ?? -Infinity;
107
+ let maxSize = 0;
108
+ const dataFillX = ax.min === undefined || ax.max === undefined;
109
+ const dataFillY = ay.min === undefined || ay.max === undefined;
110
+
111
+ for (const s of model.series) {
112
+ for (let i = 0; i < s.xValues.length; i++) {
113
+ const x = s.xValues[i];
114
+ const y = s.yValues[i];
115
+ const size = s.sizes[i];
116
+ if (x === null || y === null || size === null) continue;
117
+ if (dataFillX) {
118
+ if (x < xMin) xMin = x;
119
+ if (x > xMax) xMax = x;
120
+ }
121
+ if (dataFillY) {
122
+ if (y < yMin) yMin = y;
123
+ if (y > yMax) yMax = y;
124
+ }
125
+ const absSize = Math.abs(size);
126
+ if (absSize > maxSize) maxSize = absSize;
127
+ }
128
+ }
129
+ if (!Number.isFinite(xMin)) xMin = 0;
130
+ if (!Number.isFinite(xMax)) xMax = 1;
131
+ if (!Number.isFinite(yMin)) yMin = 0;
132
+ if (!Number.isFinite(yMax)) yMax = 1;
133
+ return { xMin, xMax, yMin, yMax, maxSize };
134
+ }
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Combo chart renderer (Stage 4 Slice 4F).
3
+ *
4
+ * Combo charts pack multiple chart-type groups (bar/line/area) into a
5
+ * single plot area. Each group is a full `BarChartModel`,
6
+ * `LineChartModel`, or `AreaChartModel` that was produced by the
7
+ * parser with per-group axis objects (already cloned by
8
+ * `parse-chart-space.ts` so mutation in one group doesn't bleed into
9
+ * another).
10
+ *
11
+ * Draw order: groups render in declaration order so later groups
12
+ * visually stack on top. The convention is bar → line (line renders
13
+ * atop bar), which matches Word's observed behavior when a combo's
14
+ * type-group nodes appear in XML order.
15
+ *
16
+ * Secondary axes: when a group has `secondaryValueAxis`, its bars /
17
+ * lines project onto the secondary scale. Because per-group renderers
18
+ * already honor `valueAxis.min/max` when computing their range, this
19
+ * works without special wiring — the combo just hands each group its
20
+ * own layout and model.
21
+ */
22
+
23
+ import React from "react";
24
+ import type { ComboChartModel } from "../../../io/ooxml/chart/types.ts";
25
+ import type { ResolvedTheme } from "../../../model/canonical-document.ts";
26
+ import type { PlotAreaLayout } from "../layout/plot-area.ts";
27
+ import { BarColumnChart } from "./bar-column.tsx";
28
+ import { LineChart } from "./line.tsx";
29
+ import { AreaChart } from "./area.tsx";
30
+
31
+ // ---------------------------------------------------------------------------
32
+ // Public API
33
+ // ---------------------------------------------------------------------------
34
+
35
+ export interface ComboChartProps {
36
+ model: ComboChartModel;
37
+ layout: PlotAreaLayout;
38
+ theme: ResolvedTheme | undefined;
39
+ }
40
+
41
+ function ComboChartImpl({ model, layout, theme }: ComboChartProps): React.ReactElement {
42
+ // Groups render in declaration order → last group paints on top.
43
+ return (
44
+ <g
45
+ data-role="combo-chart"
46
+ data-group-count={model.groups.length}
47
+ data-has-secondary-axis={model.hasSecondaryAxis}
48
+ >
49
+ {model.groups.map((group, i) => (
50
+ <g key={`combo-group-${i}`} data-role="combo-group" data-group-index={i}>
51
+ {renderGroup(group, layout, theme)}
52
+ </g>
53
+ ))}
54
+ <g data-role="data-labels" />
55
+ </g>
56
+ );
57
+ }
58
+
59
+ export const ComboChart = React.memo(
60
+ ComboChartImpl,
61
+ (prev, next) =>
62
+ prev.model.rawXml === next.model.rawXml &&
63
+ prev.layout.plotRect.w === next.layout.plotRect.w &&
64
+ prev.layout.plotRect.h === next.layout.plotRect.h &&
65
+ prev.theme === next.theme,
66
+ );
67
+
68
+ // ---------------------------------------------------------------------------
69
+ // Group dispatch
70
+ // ---------------------------------------------------------------------------
71
+
72
+ function renderGroup(
73
+ group: ComboChartModel["groups"][number],
74
+ layout: PlotAreaLayout,
75
+ theme: ResolvedTheme | undefined,
76
+ ): React.ReactElement {
77
+ switch (group.kind) {
78
+ case "bar":
79
+ return <BarColumnChart model={group} layout={layout} theme={theme} />;
80
+ case "line":
81
+ return <LineChart model={group} layout={layout} theme={theme} />;
82
+ case "area":
83
+ return <AreaChart model={group} layout={layout} theme={theme} />;
84
+ }
85
+ }