@beyondwork/docx-react-component 1.0.52 → 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.
- package/package.json +31 -40
- package/src/api/public-types.ts +67 -7
- package/src/io/chart-preview-resolver.ts +41 -0
- package/src/io/docx-session.ts +217 -23
- package/src/runtime/collab/checkpoint-store.ts +1 -1
- package/src/runtime/collab/event-types.ts +4 -0
- package/src/runtime/collab/runtime-collab-sync.ts +88 -8
- package/src/runtime/document-runtime.ts +182 -9
- package/src/runtime/layout/inert-layout-facet.ts +1 -0
- package/src/runtime/layout/layout-engine-version.ts +97 -2
- package/src/runtime/layout/layout-invalidation.ts +150 -30
- package/src/runtime/layout/page-graph.ts +19 -0
- package/src/runtime/layout/paginated-layout-engine.ts +128 -19
- package/src/runtime/layout/project-block-fragments.ts +27 -0
- package/src/runtime/layout/public-facet.ts +70 -1
- package/src/runtime/prerender/cache-envelope.ts +30 -0
- package/src/runtime/prerender/customxml-cache.ts +17 -3
- package/src/runtime/prerender/prerender-document.ts +17 -1
- package/src/runtime/render/render-frame-diff.ts +38 -2
- package/src/runtime/render/render-kernel.ts +67 -19
- package/src/runtime/surface-projection.ts +28 -0
- package/src/runtime/table-schema.ts +27 -0
- package/src/runtime/table-style-resolver.ts +51 -0
- package/src/ui/WordReviewEditor.tsx +6 -3
- package/src/ui/editor-runtime-boundary.ts +39 -2
- package/src/ui/headless/comment-decoration-model.ts +60 -5
- package/src/ui/headless/revision-decoration-model.ts +94 -6
- package/src/ui/shared/revision-filters.ts +16 -6
- package/src/ui-tailwind/chart/ChartSurface.tsx +236 -0
- package/src/ui-tailwind/chart/layout/axis-layout.ts +17 -9
- package/src/ui-tailwind/chart/layout/legend-layout.ts +231 -0
- package/src/ui-tailwind/chart/layout/plot-area.ts +152 -59
- package/src/ui-tailwind/chart/layout/title-layout.ts +184 -0
- package/src/ui-tailwind/chart/render/area.tsx +277 -0
- package/src/ui-tailwind/chart/render/bar-column.tsx +356 -0
- package/src/ui-tailwind/chart/render/bubble.tsx +134 -0
- package/src/ui-tailwind/chart/render/combo.tsx +85 -0
- package/src/ui-tailwind/chart/render/data-labels.tsx +513 -0
- package/src/ui-tailwind/chart/render/font-metrics.ts +298 -0
- package/src/ui-tailwind/chart/render/gridlines.ts +228 -0
- package/src/ui-tailwind/chart/render/line.tsx +363 -0
- package/src/ui-tailwind/chart/render/number-format.ts +120 -16
- package/src/ui-tailwind/chart/render/pie.tsx +275 -0
- package/src/ui-tailwind/chart/render/progressive-render.ts +103 -0
- package/src/ui-tailwind/chart/render/scatter.tsx +228 -0
- package/src/ui-tailwind/chart/render/smooth-curve.ts +101 -0
- package/src/ui-tailwind/chart/render/svg-primitives.ts +378 -0
- package/src/ui-tailwind/chart/render/unsupported.tsx +126 -0
- package/src/ui-tailwind/chrome/collab-audience-chip.tsx +11 -0
- package/src/ui-tailwind/chrome/collab-negotiation-action-bar.tsx +44 -18
- package/src/ui-tailwind/chrome/collab-presence-strip.tsx +68 -7
- package/src/ui-tailwind/chrome/collab-role-chip.tsx +21 -2
- package/src/ui-tailwind/chrome/collab-tamper-banner.tsx +20 -3
- package/src/ui-tailwind/chrome/tw-alert-banner.tsx +102 -37
- package/src/ui-tailwind/chrome/tw-command-palette.tsx +358 -0
- package/src/ui-tailwind/chrome/tw-comment-preview.tsx +108 -0
- package/src/ui-tailwind/chrome/tw-context-menu.tsx +227 -0
- package/src/ui-tailwind/chrome/tw-display-mode-selector.tsx +136 -0
- package/src/ui-tailwind/chrome/tw-empty-state.tsx +76 -0
- package/src/ui-tailwind/chrome/tw-image-context-toolbar.tsx +30 -16
- package/src/ui-tailwind/chrome/tw-object-context-toolbar.tsx +23 -4
- package/src/ui-tailwind/chrome/tw-paste-drop-toast.tsx +113 -0
- package/src/ui-tailwind/chrome/tw-revision-hover-preview.tsx +150 -0
- package/src/ui-tailwind/chrome/tw-selection-tool-formatting.tsx +2 -0
- package/src/ui-tailwind/chrome/tw-selection-tool-host.tsx +38 -2
- package/src/ui-tailwind/chrome/tw-selection-tool-placement.ts +15 -3
- package/src/ui-tailwind/chrome/tw-selection-toolbar.tsx +32 -20
- package/src/ui-tailwind/chrome/tw-shortcut-hint.tsx +68 -0
- package/src/ui-tailwind/chrome/tw-suggestion-card.tsx +10 -10
- package/src/ui-tailwind/chrome/tw-table-context-toolbar.tsx +26 -5
- package/src/ui-tailwind/chrome/tw-table-grip-layer.tsx +29 -22
- package/src/ui-tailwind/chrome/tw-unsaved-modal.tsx +72 -10
- package/src/ui-tailwind/chrome-overlay/tw-scope-card.tsx +33 -18
- package/src/ui-tailwind/chrome-overlay/tw-table-continuation-header.tsx +94 -0
- package/src/ui-tailwind/editor-surface/perf-probe.ts +1 -0
- package/src/ui-tailwind/editor-surface/pm-page-break-decorations.ts +20 -7
- package/src/ui-tailwind/editor-surface/pm-state-from-snapshot.ts +54 -0
- package/src/ui-tailwind/editor-surface/scroll-anchor.ts +93 -0
- package/src/ui-tailwind/editor-surface/tw-table-node-view.tsx +107 -3
- package/src/ui-tailwind/index.ts +11 -0
- package/src/ui-tailwind/page-stack/tw-footnote-area.tsx +2 -2
- package/src/ui-tailwind/page-stack/tw-page-chrome-entry.tsx +274 -0
- package/src/ui-tailwind/page-stack/tw-page-footer-band.tsx +15 -2
- package/src/ui-tailwind/page-stack/tw-page-header-band.tsx +15 -2
- package/src/ui-tailwind/page-stack/tw-page-stack-chrome-layer.tsx +19 -147
- package/src/ui-tailwind/review/tw-comment-sidebar.tsx +83 -32
- package/src/ui-tailwind/review/tw-health-panel.tsx +174 -109
- package/src/ui-tailwind/review/tw-rail-card.tsx +9 -1
- package/src/ui-tailwind/review/tw-review-rail.tsx +36 -42
- package/src/ui-tailwind/review/tw-revision-sidebar.tsx +189 -101
- package/src/ui-tailwind/review/tw-workflow-tab.tsx +11 -1
- package/src/ui-tailwind/status/tw-status-bar.tsx +114 -46
- package/src/ui-tailwind/theme/chart-palette-adapter.ts +57 -0
- package/src/ui-tailwind/theme/editor-theme.css +275 -46
- package/src/ui-tailwind/theme/tokens.css +345 -0
- package/src/ui-tailwind/theme/tokens.ts +313 -0
- package/src/ui-tailwind/theme/use-density.ts +60 -0
- package/src/ui-tailwind/toolbar/tw-role-action-region.tsx +14 -1
- package/src/ui-tailwind/toolbar/tw-shell-header.tsx +73 -32
- package/src/ui-tailwind/toolbar/tw-toolbar-icon-button.tsx +49 -9
- package/src/ui-tailwind/toolbar/tw-toolbar.tsx +178 -14
- package/src/ui-tailwind/tw-review-workspace.tsx +39 -6
- package/src/ui-tailwind/chrome/review-queue-bar.tsx +0 -85
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @beyondwork/docx-react-component — canonical design tokens
|
|
3
|
+
*
|
|
4
|
+
* Source of truth for every color, shadow, radius, space, and motion value
|
|
5
|
+
* consumed by the chrome and document surface. Values are copied verbatim
|
|
6
|
+
* from `docs/reference/designsystem.md` §10 (starter CSS). Any hex change
|
|
7
|
+
* happens HERE and in `tokens.ts` — never in a component file.
|
|
8
|
+
*
|
|
9
|
+
* Two-layer model:
|
|
10
|
+
* 1. Product names (TypeScript) — `BRAND_TOKENS.color.accent.primary`
|
|
11
|
+
* 2. CSS variables (this file) — `var(--color-accent-primary)`
|
|
12
|
+
*
|
|
13
|
+
* See `docs/wiki/design-tokens.md` for narrative + eviction policy.
|
|
14
|
+
*
|
|
15
|
+
* Host overrides:
|
|
16
|
+
* Allowed — accent family, `--color-bg-app`, `--radius-*`, `--motion-*`
|
|
17
|
+
* Locked — semantic, change, comment, canvas, focus-ring
|
|
18
|
+
* See `docs/reference/designsystem.md` §8.5 + §9.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
:root {
|
|
22
|
+
/* Backgrounds */
|
|
23
|
+
--color-bg-app: #F4F7F5;
|
|
24
|
+
--color-bg-chrome: #FAFCFA;
|
|
25
|
+
--color-bg-sidebar: #F1F6F2;
|
|
26
|
+
--color-bg-canvas: #FFFFFF;
|
|
27
|
+
--color-bg-elevated: #FFFFFF;
|
|
28
|
+
--color-bg-hover: #EAF6EF;
|
|
29
|
+
--color-bg-selected: #E2F2E8;
|
|
30
|
+
--color-bg-muted: #F7FAF8;
|
|
31
|
+
--color-bg-overlay: rgba(21, 26, 23, 0.08);
|
|
32
|
+
|
|
33
|
+
/* Borders */
|
|
34
|
+
--color-border-subtle: #E2EAE4;
|
|
35
|
+
--color-border-default: #D3DED6;
|
|
36
|
+
--color-border-strong: #BECDBF;
|
|
37
|
+
--color-border-accent: #8FC9AD;
|
|
38
|
+
|
|
39
|
+
/* Text */
|
|
40
|
+
--color-text-primary: #151A17;
|
|
41
|
+
--color-text-secondary: #5E6D63;
|
|
42
|
+
--color-text-tertiary: #8A978F;
|
|
43
|
+
--color-text-quiet: #A4AEA8;
|
|
44
|
+
--color-text-inverse: #F7FAF8;
|
|
45
|
+
--color-text-on-accent: #F7FAF8;
|
|
46
|
+
--color-text-on-soft-accent: #18563F;
|
|
47
|
+
|
|
48
|
+
/* Accent (host-overridable) */
|
|
49
|
+
--color-accent-primary: #1F6B4F;
|
|
50
|
+
--color-accent-primary-hover: #18563F;
|
|
51
|
+
--color-accent-primary-active: #124432;
|
|
52
|
+
--color-accent-secondary: #72D6AE;
|
|
53
|
+
--color-accent-secondary-hover: #5FC79C;
|
|
54
|
+
--color-accent-secondary-active: #49B785;
|
|
55
|
+
--color-accent-soft: #DDF1E4;
|
|
56
|
+
--color-accent-soft-hover: #CEEAD8;
|
|
57
|
+
|
|
58
|
+
/* Semantic (locked) */
|
|
59
|
+
--color-semantic-success: #1F8A5B;
|
|
60
|
+
--color-semantic-success-soft: #DDF3E8;
|
|
61
|
+
--color-semantic-warning: #D58B1E;
|
|
62
|
+
--color-semantic-warning-soft: #FBEFD8;
|
|
63
|
+
--color-semantic-error: #D95C67;
|
|
64
|
+
--color-semantic-error-soft: #FBE3E6;
|
|
65
|
+
--color-semantic-info: #2F8FCE;
|
|
66
|
+
--color-semantic-info-soft: #DCEFFC;
|
|
67
|
+
|
|
68
|
+
/* Field */
|
|
69
|
+
--color-field-fill: #F6FAF7;
|
|
70
|
+
--color-field-editable: #EEF8F0;
|
|
71
|
+
--color-field-focus: #DDF1E4;
|
|
72
|
+
--color-field-invalid: #FBE3E6;
|
|
73
|
+
--color-field-warning: #FBEFD8;
|
|
74
|
+
|
|
75
|
+
/* Status */
|
|
76
|
+
--color-status-ready: #1F8A5B;
|
|
77
|
+
--color-status-in-progress: #2F8FCE;
|
|
78
|
+
--color-status-paused: #8A978F;
|
|
79
|
+
--color-status-blocked: #D95C67;
|
|
80
|
+
--color-status-review: #1F6B4F;
|
|
81
|
+
--color-status-draft: #72907E;
|
|
82
|
+
|
|
83
|
+
/* Comment (locked) */
|
|
84
|
+
--color-comment-marker: #1F6B4F;
|
|
85
|
+
--color-comment-marker-hover: #18563F;
|
|
86
|
+
--color-comment-thread-bg: #F3FAF6;
|
|
87
|
+
|
|
88
|
+
/* Change (locked) */
|
|
89
|
+
--color-change-insertion: #DDF3E8;
|
|
90
|
+
--color-change-deletion: #FBE3E6;
|
|
91
|
+
--color-change-comment: #E8F4EC;
|
|
92
|
+
--color-change-selection: #DDF1E4;
|
|
93
|
+
|
|
94
|
+
/* Chart — categorical */
|
|
95
|
+
--color-chart-categorical-1: #1F6B4F;
|
|
96
|
+
--color-chart-categorical-2: #72D6AE;
|
|
97
|
+
--color-chart-categorical-3: #2F8FCE;
|
|
98
|
+
--color-chart-categorical-4: #D58B1E;
|
|
99
|
+
--color-chart-categorical-5: #7A6AF0;
|
|
100
|
+
--color-chart-categorical-6: #D95C67;
|
|
101
|
+
--color-chart-categorical-7: #5E8E7A;
|
|
102
|
+
--color-chart-categorical-8: #A7D9C1;
|
|
103
|
+
|
|
104
|
+
/* Chart — sequential */
|
|
105
|
+
--color-chart-sequential-1: #EAF6EF;
|
|
106
|
+
--color-chart-sequential-2: #D4EEDD;
|
|
107
|
+
--color-chart-sequential-3: #B4DFC8;
|
|
108
|
+
--color-chart-sequential-4: #8FC9AD;
|
|
109
|
+
--color-chart-sequential-5: #5FA985;
|
|
110
|
+
--color-chart-sequential-6: #1F6B4F;
|
|
111
|
+
|
|
112
|
+
/* Chart — diverging */
|
|
113
|
+
--color-chart-diverging-neg-strong: #C94B57;
|
|
114
|
+
--color-chart-diverging-neg: #E9979F;
|
|
115
|
+
--color-chart-diverging-neutral: #E9EFEA;
|
|
116
|
+
--color-chart-diverging-pos: #97D1B3;
|
|
117
|
+
--color-chart-diverging-pos-strong: #1F6B4F;
|
|
118
|
+
|
|
119
|
+
/* Scope tints (§3.7.1) */
|
|
120
|
+
--color-scope-tint-blocked: #FBE3E6;
|
|
121
|
+
--color-scope-tint-in-scope: #E2F2E8;
|
|
122
|
+
--color-scope-tint-suggest: #FBEFD8;
|
|
123
|
+
--color-scope-tint-comment: #F3FAF6;
|
|
124
|
+
--color-scope-tint-scheduled: #DCEFFC;
|
|
125
|
+
--color-scope-tint-proposed: #EAF6EF;
|
|
126
|
+
|
|
127
|
+
/* Shadows */
|
|
128
|
+
--shadow-soft: 0 6px 20px rgba(21, 26, 23, 0.06);
|
|
129
|
+
--shadow-float: 0 12px 32px rgba(21, 26, 23, 0.12);
|
|
130
|
+
--shadow-focus: 0 0 0 3px rgba(114, 214, 174, 0.28);
|
|
131
|
+
|
|
132
|
+
/* Radius (§4.3) */
|
|
133
|
+
--radius-sm: 10px;
|
|
134
|
+
--radius-md: 12px;
|
|
135
|
+
--radius-lg: 14px;
|
|
136
|
+
--radius-xl: 16px;
|
|
137
|
+
--radius-pill: 9999px;
|
|
138
|
+
|
|
139
|
+
/* Spacing (4px base) */
|
|
140
|
+
--space-1: 4px;
|
|
141
|
+
--space-2: 8px;
|
|
142
|
+
--space-3: 12px;
|
|
143
|
+
--space-4: 16px;
|
|
144
|
+
--space-5: 20px;
|
|
145
|
+
--space-6: 24px;
|
|
146
|
+
--space-8: 32px;
|
|
147
|
+
--space-10: 40px;
|
|
148
|
+
--space-12: 48px;
|
|
149
|
+
--space-16: 64px;
|
|
150
|
+
|
|
151
|
+
/* Motion (host-overridable) */
|
|
152
|
+
--motion-fast: 120ms;
|
|
153
|
+
--motion-default: 160ms;
|
|
154
|
+
--motion-slow: 220ms;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/*
|
|
158
|
+
* Dark palette (designsystem §3.4).
|
|
159
|
+
*
|
|
160
|
+
* Canonical selector is `[data-theme="dark"]`; `.dark` class is retained
|
|
161
|
+
* as a compat selector for one release cycle (existing harness markup
|
|
162
|
+
* uses it alongside the attribute). Remove `.dark` after an explicit
|
|
163
|
+
* consumer audit.
|
|
164
|
+
*/
|
|
165
|
+
[data-theme="dark"],
|
|
166
|
+
.dark {
|
|
167
|
+
/* Backgrounds */
|
|
168
|
+
--color-bg-app: #0E1411;
|
|
169
|
+
--color-bg-chrome: #131B17;
|
|
170
|
+
--color-bg-sidebar: #16211B;
|
|
171
|
+
--color-bg-canvas: #1B2620;
|
|
172
|
+
--color-bg-elevated: #202E27;
|
|
173
|
+
--color-bg-hover: #21342A;
|
|
174
|
+
--color-bg-selected: #274234;
|
|
175
|
+
--color-bg-muted: #17211C;
|
|
176
|
+
--color-bg-overlay: rgba(0, 0, 0, 0.32);
|
|
177
|
+
|
|
178
|
+
/* Borders */
|
|
179
|
+
--color-border-subtle: #26352C;
|
|
180
|
+
--color-border-default: #32463A;
|
|
181
|
+
--color-border-strong: #405847;
|
|
182
|
+
--color-border-accent: #4F8E70;
|
|
183
|
+
|
|
184
|
+
/* Text */
|
|
185
|
+
--color-text-primary: #EFF7F2;
|
|
186
|
+
--color-text-secondary: #A5B7AC;
|
|
187
|
+
--color-text-tertiary: #7F9187;
|
|
188
|
+
--color-text-quiet: #67786F;
|
|
189
|
+
--color-text-inverse: #111613;
|
|
190
|
+
--color-text-on-accent: #0F1713;
|
|
191
|
+
--color-text-on-soft-accent: #DDF7E9;
|
|
192
|
+
|
|
193
|
+
/* Accent */
|
|
194
|
+
--color-accent-primary: #53B487;
|
|
195
|
+
--color-accent-primary-hover: #69C598;
|
|
196
|
+
--color-accent-primary-active: #84D8AE;
|
|
197
|
+
--color-accent-secondary: #9AE7C7;
|
|
198
|
+
--color-accent-secondary-hover: #B2F0D5;
|
|
199
|
+
--color-accent-secondary-active: #C7F6E0;
|
|
200
|
+
--color-accent-soft: #294235;
|
|
201
|
+
--color-accent-soft-hover: #31503F;
|
|
202
|
+
|
|
203
|
+
/* Semantic */
|
|
204
|
+
--color-semantic-success: #45C787;
|
|
205
|
+
--color-semantic-success-soft: #1E3A2C;
|
|
206
|
+
--color-semantic-warning: #E7B04D;
|
|
207
|
+
--color-semantic-warning-soft: #3E3117;
|
|
208
|
+
--color-semantic-error: #F07A84;
|
|
209
|
+
--color-semantic-error-soft: #3D2024;
|
|
210
|
+
--color-semantic-info: #64B6E8;
|
|
211
|
+
--color-semantic-info-soft: #183444;
|
|
212
|
+
|
|
213
|
+
/* Field */
|
|
214
|
+
--color-field-fill: #202D25;
|
|
215
|
+
--color-field-editable: #23372B;
|
|
216
|
+
--color-field-focus: #294235;
|
|
217
|
+
--color-field-invalid: #3D2024;
|
|
218
|
+
--color-field-warning: #3E3117;
|
|
219
|
+
|
|
220
|
+
/* Status */
|
|
221
|
+
--color-status-ready: #45C787;
|
|
222
|
+
--color-status-in-progress: #64B6E8;
|
|
223
|
+
--color-status-paused: #7F9187;
|
|
224
|
+
--color-status-blocked: #F07A84;
|
|
225
|
+
--color-status-review: #53B487;
|
|
226
|
+
--color-status-draft: #7DA38F;
|
|
227
|
+
|
|
228
|
+
/* Comment */
|
|
229
|
+
--color-comment-marker: #53B487;
|
|
230
|
+
--color-comment-marker-hover: #69C598;
|
|
231
|
+
--color-comment-thread-bg: #1A2A22;
|
|
232
|
+
|
|
233
|
+
/* Change */
|
|
234
|
+
--color-change-insertion: #1E3A2C;
|
|
235
|
+
--color-change-deletion: #3D2024;
|
|
236
|
+
--color-change-comment: #21342A;
|
|
237
|
+
--color-change-selection: #294235;
|
|
238
|
+
|
|
239
|
+
/* Chart — categorical */
|
|
240
|
+
--color-chart-categorical-1: #53B487;
|
|
241
|
+
--color-chart-categorical-2: #9AE7C7;
|
|
242
|
+
--color-chart-categorical-3: #64B6E8;
|
|
243
|
+
--color-chart-categorical-4: #E7B04D;
|
|
244
|
+
--color-chart-categorical-5: #A996FF;
|
|
245
|
+
--color-chart-categorical-6: #F07A84;
|
|
246
|
+
--color-chart-categorical-7: #7DA38F;
|
|
247
|
+
--color-chart-categorical-8: #355746;
|
|
248
|
+
|
|
249
|
+
/* Chart — sequential */
|
|
250
|
+
--color-chart-sequential-1: #16211B;
|
|
251
|
+
--color-chart-sequential-2: #1D2E25;
|
|
252
|
+
--color-chart-sequential-3: #274234;
|
|
253
|
+
--color-chart-sequential-4: #35654F;
|
|
254
|
+
--color-chart-sequential-5: #53B487;
|
|
255
|
+
--color-chart-sequential-6: #9AE7C7;
|
|
256
|
+
|
|
257
|
+
/* Chart — diverging */
|
|
258
|
+
--color-chart-diverging-neg-strong: #F07A84;
|
|
259
|
+
--color-chart-diverging-neg: #C76069;
|
|
260
|
+
--color-chart-diverging-neutral: #2A3530;
|
|
261
|
+
--color-chart-diverging-pos: #69C598;
|
|
262
|
+
--color-chart-diverging-pos-strong: #9AE7C7;
|
|
263
|
+
|
|
264
|
+
/* Scope tints (§3.7.2) */
|
|
265
|
+
--color-scope-tint-blocked: #3D2024;
|
|
266
|
+
--color-scope-tint-in-scope: #274234;
|
|
267
|
+
--color-scope-tint-suggest: #3E3117;
|
|
268
|
+
--color-scope-tint-comment: #1A2A22;
|
|
269
|
+
--color-scope-tint-scheduled: #183444;
|
|
270
|
+
--color-scope-tint-proposed: #21342A;
|
|
271
|
+
|
|
272
|
+
/* Shadows */
|
|
273
|
+
--shadow-soft: 0 8px 24px rgba(0, 0, 0, 0.28);
|
|
274
|
+
--shadow-float: 0 16px 40px rgba(0, 0, 0, 0.4);
|
|
275
|
+
--shadow-focus: 0 0 0 3px rgba(154, 231, 199, 0.22);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/*
|
|
279
|
+
* Reduced-motion contract (designsystem §4.6 / §7.3).
|
|
280
|
+
* Collapses every motion token so any transition consuming `var(--motion-*)`
|
|
281
|
+
* becomes functionally instant. Components MUST read these tokens — never
|
|
282
|
+
* hardcode a numeric duration.
|
|
283
|
+
*/
|
|
284
|
+
@media (prefers-reduced-motion: reduce) {
|
|
285
|
+
:root {
|
|
286
|
+
--motion-fast: 1ms;
|
|
287
|
+
--motion-default: 1ms;
|
|
288
|
+
--motion-slow: 1ms;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/*
|
|
293
|
+
* Density scale (designsystem §4.2 / Lane 6b.U5 consumer wiring).
|
|
294
|
+
*
|
|
295
|
+
* Components multiply spacing by `--space-density-multiplier`.
|
|
296
|
+
* Standard (1.0) is the default; compact (0.85) and comfortable (1.15)
|
|
297
|
+
* are opt-in via `data-density` on the root element.
|
|
298
|
+
* The hook `use-density.ts` reads and writes this attribute.
|
|
299
|
+
*/
|
|
300
|
+
:root {
|
|
301
|
+
--space-density-multiplier: 1;
|
|
302
|
+
}
|
|
303
|
+
:root[data-density="compact"] {
|
|
304
|
+
--space-density-multiplier: 0.85;
|
|
305
|
+
}
|
|
306
|
+
:root[data-density="standard"] {
|
|
307
|
+
--space-density-multiplier: 1;
|
|
308
|
+
}
|
|
309
|
+
:root[data-density="comfortable"] {
|
|
310
|
+
--space-density-multiplier: 1.15;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/*
|
|
314
|
+
* Back-compat aliases (temporary — remove after full consumer sweep).
|
|
315
|
+
*
|
|
316
|
+
* These bind pre-6a names to their post-6a equivalents so that the
|
|
317
|
+
* existing @theme {} block in editor-theme.css and already-shipped
|
|
318
|
+
* component markup continue to resolve during the phased migration.
|
|
319
|
+
*/
|
|
320
|
+
:root {
|
|
321
|
+
/* Legacy accent seed (was teal) → forest-green primary family */
|
|
322
|
+
--color-accent: var(--color-accent-primary);
|
|
323
|
+
/* Legacy single-name semantic tokens → canonical semantic family */
|
|
324
|
+
--color-danger: var(--color-semantic-error);
|
|
325
|
+
--color-danger-soft: var(--color-semantic-error-soft);
|
|
326
|
+
--color-warning: var(--color-semantic-warning);
|
|
327
|
+
--color-warning-soft: var(--color-semantic-warning-soft);
|
|
328
|
+
--color-success: var(--color-semantic-success);
|
|
329
|
+
--color-success-soft: var(--color-semantic-success-soft);
|
|
330
|
+
--color-info: var(--color-semantic-info);
|
|
331
|
+
--color-info-soft: var(--color-semantic-info-soft);
|
|
332
|
+
/* Legacy review markup names → change family */
|
|
333
|
+
--color-insert: var(--color-accent-primary);
|
|
334
|
+
--color-insert-soft: var(--color-change-insertion);
|
|
335
|
+
--color-delete: var(--color-semantic-error);
|
|
336
|
+
--color-delete-soft: var(--color-change-deletion);
|
|
337
|
+
--color-comment: var(--color-comment-marker);
|
|
338
|
+
--color-comment-soft: var(--color-change-comment);
|
|
339
|
+
--color-comment-strong: var(--color-comment-marker-hover);
|
|
340
|
+
/* Legacy L8 Phase A radius names → §4.3 scale */
|
|
341
|
+
--radius-panel: var(--radius-md);
|
|
342
|
+
--radius-card: var(--radius-sm);
|
|
343
|
+
--radius-control: var(--radius-sm);
|
|
344
|
+
--radius-page: 2px;
|
|
345
|
+
}
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @beyondwork/docx-react-component — design-token manifest
|
|
3
|
+
*
|
|
4
|
+
* Single TypeScript surface that consumers import. Mirrors
|
|
5
|
+
* `docs/reference/designsystem.md` §3.1 (product token names) + §3.3/§3.4
|
|
6
|
+
* (values). Every key here has a CSS variable alias in
|
|
7
|
+
* `./tokens.css` — the pair is enforced by
|
|
8
|
+
* `test/ui-tailwind/token-coverage.test.ts`.
|
|
9
|
+
*
|
|
10
|
+
* Values below are the LIGHT-MODE hex values only. CSS variables own the
|
|
11
|
+
* light/dark fork; runtime reads resolve via `getComputedStyle`. Pure hex
|
|
12
|
+
* strings remain accessible for design-tool export, snapshot tests, and
|
|
13
|
+
* one-off cases where a consumer cannot enter the CSS cascade.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
export const BRAND_TOKENS = {
|
|
17
|
+
color: {
|
|
18
|
+
bg: {
|
|
19
|
+
app: "#F4F7F5",
|
|
20
|
+
chrome: "#FAFCFA",
|
|
21
|
+
sidebar: "#F1F6F2",
|
|
22
|
+
canvas: "#FFFFFF",
|
|
23
|
+
elevated: "#FFFFFF",
|
|
24
|
+
hover: "#EAF6EF",
|
|
25
|
+
selected: "#E2F2E8",
|
|
26
|
+
muted: "#F7FAF8",
|
|
27
|
+
overlay: "rgba(21, 26, 23, 0.08)",
|
|
28
|
+
},
|
|
29
|
+
border: {
|
|
30
|
+
subtle: "#E2EAE4",
|
|
31
|
+
default: "#D3DED6",
|
|
32
|
+
strong: "#BECDBF",
|
|
33
|
+
accent: "#8FC9AD",
|
|
34
|
+
},
|
|
35
|
+
text: {
|
|
36
|
+
primary: "#151A17",
|
|
37
|
+
secondary: "#5E6D63",
|
|
38
|
+
tertiary: "#8A978F",
|
|
39
|
+
quiet: "#A4AEA8",
|
|
40
|
+
inverse: "#F7FAF8",
|
|
41
|
+
onAccent: "#F7FAF8",
|
|
42
|
+
onSoftAccent: "#18563F",
|
|
43
|
+
},
|
|
44
|
+
accent: {
|
|
45
|
+
primary: "#1F6B4F",
|
|
46
|
+
primaryHover: "#18563F",
|
|
47
|
+
primaryActive: "#124432",
|
|
48
|
+
secondary: "#72D6AE",
|
|
49
|
+
secondaryHover: "#5FC79C",
|
|
50
|
+
secondaryActive: "#49B785",
|
|
51
|
+
soft: "#DDF1E4",
|
|
52
|
+
softHover: "#CEEAD8",
|
|
53
|
+
},
|
|
54
|
+
semantic: {
|
|
55
|
+
success: "#1F8A5B",
|
|
56
|
+
successSoft: "#DDF3E8",
|
|
57
|
+
warning: "#D58B1E",
|
|
58
|
+
warningSoft: "#FBEFD8",
|
|
59
|
+
error: "#D95C67",
|
|
60
|
+
errorSoft: "#FBE3E6",
|
|
61
|
+
info: "#2F8FCE",
|
|
62
|
+
infoSoft: "#DCEFFC",
|
|
63
|
+
},
|
|
64
|
+
field: {
|
|
65
|
+
fill: "#F6FAF7",
|
|
66
|
+
editable: "#EEF8F0",
|
|
67
|
+
focus: "#DDF1E4",
|
|
68
|
+
invalid: "#FBE3E6",
|
|
69
|
+
warning: "#FBEFD8",
|
|
70
|
+
},
|
|
71
|
+
status: {
|
|
72
|
+
ready: "#1F8A5B",
|
|
73
|
+
inProgress: "#2F8FCE",
|
|
74
|
+
paused: "#8A978F",
|
|
75
|
+
blocked: "#D95C67",
|
|
76
|
+
review: "#1F6B4F",
|
|
77
|
+
draft: "#72907E",
|
|
78
|
+
},
|
|
79
|
+
comment: {
|
|
80
|
+
marker: "#1F6B4F",
|
|
81
|
+
markerHover: "#18563F",
|
|
82
|
+
threadBg: "#F3FAF6",
|
|
83
|
+
},
|
|
84
|
+
change: {
|
|
85
|
+
insertion: "#DDF3E8",
|
|
86
|
+
deletion: "#FBE3E6",
|
|
87
|
+
comment: "#E8F4EC",
|
|
88
|
+
selection: "#DDF1E4",
|
|
89
|
+
},
|
|
90
|
+
scopeTint: {
|
|
91
|
+
blocked: "#FBE3E6",
|
|
92
|
+
inScope: "#E2F2E8",
|
|
93
|
+
suggest: "#FBEFD8",
|
|
94
|
+
comment: "#F3FAF6",
|
|
95
|
+
scheduled: "#DCEFFC",
|
|
96
|
+
proposed: "#EAF6EF",
|
|
97
|
+
},
|
|
98
|
+
chart: {
|
|
99
|
+
categorical: {
|
|
100
|
+
"1": "#1F6B4F",
|
|
101
|
+
"2": "#72D6AE",
|
|
102
|
+
"3": "#2F8FCE",
|
|
103
|
+
"4": "#D58B1E",
|
|
104
|
+
"5": "#7A6AF0",
|
|
105
|
+
"6": "#D95C67",
|
|
106
|
+
"7": "#5E8E7A",
|
|
107
|
+
"8": "#A7D9C1",
|
|
108
|
+
},
|
|
109
|
+
sequential: {
|
|
110
|
+
"1": "#EAF6EF",
|
|
111
|
+
"2": "#D4EEDD",
|
|
112
|
+
"3": "#B4DFC8",
|
|
113
|
+
"4": "#8FC9AD",
|
|
114
|
+
"5": "#5FA985",
|
|
115
|
+
"6": "#1F6B4F",
|
|
116
|
+
},
|
|
117
|
+
diverging: {
|
|
118
|
+
negStrong: "#C94B57",
|
|
119
|
+
neg: "#E9979F",
|
|
120
|
+
neutral: "#E9EFEA",
|
|
121
|
+
pos: "#97D1B3",
|
|
122
|
+
posStrong: "#1F6B4F",
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
shadow: {
|
|
127
|
+
soft: "0 6px 20px rgba(21, 26, 23, 0.06)",
|
|
128
|
+
float: "0 12px 32px rgba(21, 26, 23, 0.12)",
|
|
129
|
+
focus: "0 0 0 3px rgba(114, 214, 174, 0.28)",
|
|
130
|
+
},
|
|
131
|
+
radius: {
|
|
132
|
+
sm: "10px",
|
|
133
|
+
md: "12px",
|
|
134
|
+
lg: "14px",
|
|
135
|
+
xl: "16px",
|
|
136
|
+
pill: "9999px",
|
|
137
|
+
},
|
|
138
|
+
space: {
|
|
139
|
+
"1": "4px",
|
|
140
|
+
"2": "8px",
|
|
141
|
+
"3": "12px",
|
|
142
|
+
"4": "16px",
|
|
143
|
+
"5": "20px",
|
|
144
|
+
"6": "24px",
|
|
145
|
+
"8": "32px",
|
|
146
|
+
"10": "40px",
|
|
147
|
+
"12": "48px",
|
|
148
|
+
"16": "64px",
|
|
149
|
+
},
|
|
150
|
+
motion: {
|
|
151
|
+
fast: "120ms",
|
|
152
|
+
default: "160ms",
|
|
153
|
+
slow: "220ms",
|
|
154
|
+
},
|
|
155
|
+
} as const;
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Dotted path tuple type used by the coverage test to enumerate every
|
|
159
|
+
* leaf of `BRAND_TOKENS`. Mirrors the `color.accent.primary` / `shadow.soft`
|
|
160
|
+
* form used throughout the spec.
|
|
161
|
+
*/
|
|
162
|
+
export type BrandTokens = typeof BRAND_TOKENS;
|
|
163
|
+
export type BrandTokenPath =
|
|
164
|
+
| `color.bg.${keyof BrandTokens["color"]["bg"]}`
|
|
165
|
+
| `color.border.${keyof BrandTokens["color"]["border"]}`
|
|
166
|
+
| `color.text.${keyof BrandTokens["color"]["text"]}`
|
|
167
|
+
| `color.accent.${keyof BrandTokens["color"]["accent"]}`
|
|
168
|
+
| `color.semantic.${keyof BrandTokens["color"]["semantic"]}`
|
|
169
|
+
| `color.field.${keyof BrandTokens["color"]["field"]}`
|
|
170
|
+
| `color.status.${keyof BrandTokens["color"]["status"]}`
|
|
171
|
+
| `color.comment.${keyof BrandTokens["color"]["comment"]}`
|
|
172
|
+
| `color.change.${keyof BrandTokens["color"]["change"]}`
|
|
173
|
+
| `color.scopeTint.${keyof BrandTokens["color"]["scopeTint"]}`
|
|
174
|
+
| `color.chart.categorical.${keyof BrandTokens["color"]["chart"]["categorical"]}`
|
|
175
|
+
| `color.chart.sequential.${keyof BrandTokens["color"]["chart"]["sequential"]}`
|
|
176
|
+
| `color.chart.diverging.${keyof BrandTokens["color"]["chart"]["diverging"]}`
|
|
177
|
+
| `shadow.${keyof BrandTokens["shadow"]}`
|
|
178
|
+
| `radius.${keyof BrandTokens["radius"]}`
|
|
179
|
+
| `space.${keyof BrandTokens["space"]}`
|
|
180
|
+
| `motion.${keyof BrandTokens["motion"]}`;
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Converts a dotted product-token path into its CSS variable name.
|
|
184
|
+
* productPathToCssVar("color.accent.primary") === "--color-accent-primary"
|
|
185
|
+
* productPathToCssVar("color.chart.categorical.1") === "--color-chart-categorical-1"
|
|
186
|
+
* productPathToCssVar("color.text.onAccent") === "--color-text-on-accent"
|
|
187
|
+
*/
|
|
188
|
+
export function productPathToCssVar(path: string): string {
|
|
189
|
+
const kebab = path
|
|
190
|
+
.split(".")
|
|
191
|
+
.join("-")
|
|
192
|
+
.replace(/([a-z])([A-Z])/g, "$1-$2")
|
|
193
|
+
.toLowerCase();
|
|
194
|
+
return `--${kebab}`;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Enumerates every leaf path in `BRAND_TOKENS`.
|
|
199
|
+
*/
|
|
200
|
+
export function enumerateBrandTokenPaths(): BrandTokenPath[] {
|
|
201
|
+
const out: string[] = [];
|
|
202
|
+
const walk = (node: unknown, prefix: string): void => {
|
|
203
|
+
if (node === null || typeof node !== "object") return;
|
|
204
|
+
for (const [key, value] of Object.entries(node as Record<string, unknown>)) {
|
|
205
|
+
const next = prefix === "" ? key : `${prefix}.${key}`;
|
|
206
|
+
if (typeof value === "string") out.push(next);
|
|
207
|
+
else walk(value, next);
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
walk(BRAND_TOKENS, "");
|
|
211
|
+
return out as BrandTokenPath[];
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Host override contract (designsystem §8.5 / §9).
|
|
216
|
+
*
|
|
217
|
+
* Hosts MAY override these token families to match their brand / workspace.
|
|
218
|
+
*/
|
|
219
|
+
export const HOST_OVERRIDABLE_TOKENS = [
|
|
220
|
+
"color.accent.primary",
|
|
221
|
+
"color.accent.primaryHover",
|
|
222
|
+
"color.accent.primaryActive",
|
|
223
|
+
"color.accent.secondary",
|
|
224
|
+
"color.accent.secondaryHover",
|
|
225
|
+
"color.accent.secondaryActive",
|
|
226
|
+
"color.accent.soft",
|
|
227
|
+
"color.accent.softHover",
|
|
228
|
+
"color.bg.app",
|
|
229
|
+
"radius.sm",
|
|
230
|
+
"radius.md",
|
|
231
|
+
"radius.lg",
|
|
232
|
+
"radius.xl",
|
|
233
|
+
"radius.pill",
|
|
234
|
+
"motion.fast",
|
|
235
|
+
"motion.default",
|
|
236
|
+
"motion.slow",
|
|
237
|
+
] as const satisfies readonly BrandTokenPath[];
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Hosts MUST NOT override these — semantic legibility, review markup,
|
|
241
|
+
* comment marker, canvas, and accessibility contract.
|
|
242
|
+
*/
|
|
243
|
+
export const HOST_LOCKED_TOKENS = [
|
|
244
|
+
"color.semantic.success",
|
|
245
|
+
"color.semantic.successSoft",
|
|
246
|
+
"color.semantic.warning",
|
|
247
|
+
"color.semantic.warningSoft",
|
|
248
|
+
"color.semantic.error",
|
|
249
|
+
"color.semantic.errorSoft",
|
|
250
|
+
"color.semantic.info",
|
|
251
|
+
"color.semantic.infoSoft",
|
|
252
|
+
"color.change.insertion",
|
|
253
|
+
"color.change.deletion",
|
|
254
|
+
"color.change.comment",
|
|
255
|
+
"color.change.selection",
|
|
256
|
+
"color.comment.marker",
|
|
257
|
+
"color.comment.markerHover",
|
|
258
|
+
"color.comment.threadBg",
|
|
259
|
+
"color.bg.canvas",
|
|
260
|
+
"shadow.focus",
|
|
261
|
+
] as const satisfies readonly BrandTokenPath[];
|
|
262
|
+
|
|
263
|
+
export type HostOverridableToken = (typeof HOST_OVERRIDABLE_TOKENS)[number];
|
|
264
|
+
export type HostLockedToken = (typeof HOST_LOCKED_TOKENS)[number];
|
|
265
|
+
|
|
266
|
+
/** Returns true if `path` is in the locked set (must not be overridden by hosts). */
|
|
267
|
+
export function isTokenPathLocked(path: string): boolean {
|
|
268
|
+
return (HOST_LOCKED_TOKENS as readonly string[]).includes(path);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Dev-mode guard. Subscribes to attribute/style mutations on `document.documentElement`
|
|
273
|
+
* and emits `console.warn` if a host overrides a locked CSS variable.
|
|
274
|
+
*
|
|
275
|
+
* No-op in production (`process.env.NODE_ENV === "production"`) and in
|
|
276
|
+
* non-browser environments (SSR, test runners without DOM).
|
|
277
|
+
*
|
|
278
|
+
* Returns a teardown function. Call it to disconnect the observer.
|
|
279
|
+
*/
|
|
280
|
+
export function devGuardLockedTokens(
|
|
281
|
+
root: HTMLElement = typeof document !== "undefined"
|
|
282
|
+
? document.documentElement
|
|
283
|
+
: (null as unknown as HTMLElement),
|
|
284
|
+
): () => void {
|
|
285
|
+
if (
|
|
286
|
+
typeof document === "undefined" ||
|
|
287
|
+
root === null ||
|
|
288
|
+
(typeof (globalThis as Record<string, unknown>)["__WRE_DEV__"] !== "undefined" &&
|
|
289
|
+
!(globalThis as Record<string, unknown>)["__WRE_DEV__"])
|
|
290
|
+
) {
|
|
291
|
+
return () => {};
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
const lockedVars = new Set(
|
|
295
|
+
(HOST_LOCKED_TOKENS as readonly string[]).map((p) => productPathToCssVar(p)),
|
|
296
|
+
);
|
|
297
|
+
|
|
298
|
+
const observer = new MutationObserver(() => {
|
|
299
|
+
const style = root.getAttribute("style") ?? "";
|
|
300
|
+
for (const v of lockedVars) {
|
|
301
|
+
if (style.includes(v)) {
|
|
302
|
+
console.warn(
|
|
303
|
+
`[docx-react-component] Host override of locked token "${v}" detected. ` +
|
|
304
|
+
`Overriding locked tokens may break review-workspace legibility contracts (§9.2). ` +
|
|
305
|
+
`See docs/reference/designsystem.md §9.`,
|
|
306
|
+
);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
observer.observe(root, { attributes: true, attributeFilter: ["style"] });
|
|
312
|
+
return () => observer.disconnect();
|
|
313
|
+
}
|