@forevka/wordcanvas 0.7.1 → 0.7.3
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/dist-lib/assets/{worker-D8rUOKfg.js → worker-CqU4Popa.js} +10903 -10736
- package/dist-lib/assets/worker-Cw5cYW5z.js +2418 -0
- package/dist-lib/blockFactory-DDCRWDnA.js +91 -0
- package/dist-lib/browser-BUrsjziD.js +612 -0
- package/dist-lib/builder.js +13 -13
- package/dist-lib/editorApp-CB_ZArIF.js +9566 -0
- package/dist-lib/export.js +4507 -4456
- package/dist-lib/generate-toc.js +7 -7
- package/dist-lib/import.js +2 -2
- package/dist-lib/lists-DpmgbDyt.js +110 -0
- package/dist-lib/measure.js +2 -2
- package/dist-lib/{measureHost-CMiJKdlk.js → measureHost-BlukHGwx.js} +1 -1
- package/dist-lib/metrics-bvGO8KDK.js +96 -0
- package/dist-lib/paintStyle-vT6jtWbH.js +74 -0
- package/dist-lib/pipeline-UryP-u7Z.js +1850 -0
- package/dist-lib/recalc-docx.js +2 -2
- package/dist-lib/recalcToc-BfXlXZik.js +3985 -0
- package/dist-lib/styleProps-DhqDEfvc.js +149 -0
- package/dist-lib/stylesheet-LTBEGkvG.js +146 -0
- package/dist-lib/toc-D09f4PrI.js +939 -0
- package/dist-lib/{webmcp-6WxRNKCc.js → webmcp-K6UZgQJ0.js} +60 -68
- package/dist-lib/wordcanvas-DBx2ana_.js +734 -0
- package/dist-lib/wordcanvas.js +4 -2
- package/dist-node/{chunk-CDN6WU2P.js → chunk-373K2XRY.js} +40 -22
- package/dist-node/chunk-373K2XRY.js.map +7 -0
- package/dist-node/{chunk-22JHAERT.js → chunk-3PUV3BG6.js} +235 -39
- package/dist-node/chunk-3PUV3BG6.js.map +7 -0
- package/dist-node/{chunk-4ICCHZX4.js → chunk-5RX3IHWE.js} +39 -3
- package/dist-node/chunk-5RX3IHWE.js.map +7 -0
- package/dist-node/{chunk-4PDVRJF6.js → chunk-EMY2P524.js} +32 -2
- package/dist-node/chunk-EMY2P524.js.map +7 -0
- package/dist-node/{chunk-BRAPV465.js → chunk-HWQKGDS2.js} +2 -2
- package/dist-node/{chunk-6AJJMHKY.js → chunk-KJV7GJ3H.js} +1 -1
- package/dist-node/chunk-KJV7GJ3H.js.map +7 -0
- package/dist-node/{chunk-RNB336F3.js → chunk-ZLLSXOO2.js} +92 -14
- package/dist-node/{chunk-RNB336F3.js.map → chunk-ZLLSXOO2.js.map} +2 -2
- package/dist-node/{engine-5FGDJD2H.js → engine-LLA6PCS5.js} +4 -4
- package/dist-node/export.js +89 -24
- package/dist-node/export.js.map +2 -2
- package/dist-node/generate-toc.js +6 -6
- package/dist-node/import.js +3 -3
- package/dist-node/measure.js +2 -2
- package/dist-node/recalc-docx.js +4 -4
- package/package.json +1 -1
- package/types/model.d.ts +46 -0
- package/types/wordcanvas.d.ts +493 -1
- package/dist-lib/assets/worker-wXuuyshQ.js +0 -2258
- package/dist-lib/blockFactory-CUI4Rqiq.js +0 -186
- package/dist-lib/browser-DkKxreJM.js +0 -1305
- package/dist-lib/editorApp-DLXMmtu5.js +0 -8023
- package/dist-lib/lists-Sc5I40JO.js +0 -110
- package/dist-lib/metrics-CkAo4zh8.js +0 -143
- package/dist-lib/pipeline-CbxmCE84.js +0 -1705
- package/dist-lib/recalcToc-g1hFKSNs.js +0 -3935
- package/dist-lib/styleProps-Db5pEkG8.js +0 -127
- package/dist-lib/toc-B6VpkJge.js +0 -213
- package/dist-lib/wordcanvas-CFqpDK0k.js +0 -125
- package/dist-node/chunk-22JHAERT.js.map +0 -7
- package/dist-node/chunk-4ICCHZX4.js.map +0 -7
- package/dist-node/chunk-4PDVRJF6.js.map +0 -7
- package/dist-node/chunk-6AJJMHKY.js.map +0 -7
- package/dist-node/chunk-CDN6WU2P.js.map +0 -7
- /package/dist-node/{chunk-BRAPV465.js.map → chunk-HWQKGDS2.js.map} +0 -0
- /package/dist-node/{engine-5FGDJD2H.js.map → engine-LLA6PCS5.js.map} +0 -0
|
@@ -0,0 +1,734 @@
|
|
|
1
|
+
import "./toc-D09f4PrI.js";
|
|
2
|
+
import { m as f } from "./stylesheet-LTBEGkvG.js";
|
|
3
|
+
import { C as u, I as w, a as m, i as y, F as v, A as k, E as z, D as S } from "./paintStyle-vT6jtWbH.js";
|
|
4
|
+
const E = 1.1, L = 0.25, O = 5, R = 36, l = {
|
|
5
|
+
canvasBackground: "#e8eaed",
|
|
6
|
+
grid: S,
|
|
7
|
+
gridMesh: "rgba(0,0,0,0.08)",
|
|
8
|
+
externalLink: z,
|
|
9
|
+
accent: k,
|
|
10
|
+
footnoteRule: v,
|
|
11
|
+
formattingMark: y,
|
|
12
|
+
tocLeader: m,
|
|
13
|
+
imagePlaceholder: w,
|
|
14
|
+
columnSeparator: u,
|
|
15
|
+
caret: "#1a1a2e",
|
|
16
|
+
searchHighlight: "rgba(251, 188, 4, 0.45)",
|
|
17
|
+
reviewPinResolved: "#9aa0a6",
|
|
18
|
+
reviewPinStroke: "#fff",
|
|
19
|
+
pageGapPx: 24,
|
|
20
|
+
ruler: {
|
|
21
|
+
bg: "#c7cdd6",
|
|
22
|
+
content: "#ffffff",
|
|
23
|
+
line: "#8a8f98",
|
|
24
|
+
label: "#605e5c",
|
|
25
|
+
font: "9px 'Segoe UI', sans-serif"
|
|
26
|
+
}
|
|
27
|
+
}, b = {
|
|
28
|
+
zoomStep: E,
|
|
29
|
+
zoomMin: L,
|
|
30
|
+
zoomMax: O,
|
|
31
|
+
indentStepPx: R,
|
|
32
|
+
gridSpacingPx: 24
|
|
33
|
+
}, I = {
|
|
34
|
+
canvasBackground: "#202124",
|
|
35
|
+
ruler: { bg: "#2a2d31", content: "#3c4043", line: "#5f6368", label: "#bdc1c6" }
|
|
36
|
+
};
|
|
37
|
+
function C(o) {
|
|
38
|
+
return o ? {
|
|
39
|
+
...l,
|
|
40
|
+
...p(o),
|
|
41
|
+
ruler: { ...l.ruler, ...o.ruler ? p(o.ruler) : {} }
|
|
42
|
+
} : l;
|
|
43
|
+
}
|
|
44
|
+
function D(o) {
|
|
45
|
+
return o ? { ...b, ...p(o) } : b;
|
|
46
|
+
}
|
|
47
|
+
function U(o = {}) {
|
|
48
|
+
const e = o.overrideDefaultStyles ? p(o.overrideDefaultStyles) : {};
|
|
49
|
+
return {
|
|
50
|
+
theme: C(o.theme),
|
|
51
|
+
behavior: D(o.behavior),
|
|
52
|
+
typography: e,
|
|
53
|
+
stylesheet: f(e)
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
function p(o) {
|
|
57
|
+
const e = {};
|
|
58
|
+
for (const [t, i] of Object.entries(o)) i !== void 0 && (e[t] = i);
|
|
59
|
+
return e;
|
|
60
|
+
}
|
|
61
|
+
const M = "wordcanvas-styles", T = `
|
|
62
|
+
.wordcanvas-root {
|
|
63
|
+
display: flex; flex-direction: column; height: 100%; min-height: 0; overflow-x: hidden;
|
|
64
|
+
font-family: "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
65
|
+
color: #323130;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/* ===== Word-style ribbon ============================================ */
|
|
69
|
+
.cw-toolbar {
|
|
70
|
+
flex: 0 0 auto; display: flex; flex-direction: column;
|
|
71
|
+
background: #f3f2f1; border-bottom: 1px solid #e1dfdd; user-select: none;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/* --- tab strip --- */
|
|
75
|
+
.rib-tabs {
|
|
76
|
+
display: flex; align-items: flex-end; gap: 1px; height: 32px;
|
|
77
|
+
padding: 4px 8px 0; background: #f3f2f1;
|
|
78
|
+
}
|
|
79
|
+
.rib-tab {
|
|
80
|
+
border: none; background: transparent; cursor: pointer;
|
|
81
|
+
font: inherit; font-size: 13px; color: #323130;
|
|
82
|
+
padding: 5px 11px 6px; border-radius: 4px 4px 0 0; position: relative;
|
|
83
|
+
}
|
|
84
|
+
.rib-tab:hover { background: #eceae9; }
|
|
85
|
+
.rib-tab.active {
|
|
86
|
+
background: #fff; color: #2b579a; font-weight: 600;
|
|
87
|
+
box-shadow: 0 -1px 2px rgba(0,0,0,0.05);
|
|
88
|
+
}
|
|
89
|
+
.rib-tab.active::after {
|
|
90
|
+
content: ""; position: absolute; left: 8px; right: 8px; bottom: 0;
|
|
91
|
+
height: 2px; background: #2b579a;
|
|
92
|
+
}
|
|
93
|
+
.rib-tab.file { background: #2b579a; color: #fff; font-weight: 600; }
|
|
94
|
+
.rib-tab.file:hover { background: #21457e; }
|
|
95
|
+
|
|
96
|
+
/* review controls docked in the ribbon header (right of the tab strip) */
|
|
97
|
+
.cw-header-review { margin-left: auto; display: flex; align-items: center; gap: 8px; padding-bottom: 3px; }
|
|
98
|
+
.cw-mode-select {
|
|
99
|
+
height: 26px; border: 1px solid #d2d0ce; border-radius: 5px; background: #fff;
|
|
100
|
+
font: inherit; font-size: 12.5px; color: #323130; padding: 0 6px; cursor: pointer;
|
|
101
|
+
}
|
|
102
|
+
.cw-mode-select:hover { border-color: #b3b0ad; }
|
|
103
|
+
.cw-header-btn {
|
|
104
|
+
height: 26px; border: 1px solid #d2d0ce; border-radius: 5px; background: #fff; cursor: pointer;
|
|
105
|
+
font: inherit; font-size: 12.5px; font-weight: 600; color: #2b579a; padding: 0 12px;
|
|
106
|
+
display: inline-flex; align-items: center; gap: 5px;
|
|
107
|
+
}
|
|
108
|
+
.cw-header-btn:hover { background: #f3f2f1; }
|
|
109
|
+
.cw-header-btn.active { background: #2b579a; color: #fff; border-color: #2b579a; }
|
|
110
|
+
|
|
111
|
+
/* --- ribbon body: one panel visible at a time --- */
|
|
112
|
+
.rib-bodies {
|
|
113
|
+
background: #fff; border-top: 1px solid #e1dfdd; border-bottom: 1px solid #e1dfdd;
|
|
114
|
+
}
|
|
115
|
+
.rib-panel { display: none; align-items: stretch; min-height: 94px; padding: 0 2px; }
|
|
116
|
+
.rib-panel.active { display: flex; }
|
|
117
|
+
|
|
118
|
+
/* --- group: stacked controls + caption, divider on the right --- */
|
|
119
|
+
.rib-group {
|
|
120
|
+
display: flex; flex-direction: column; align-items: center;
|
|
121
|
+
padding: 5px 7px 3px; position: relative;
|
|
122
|
+
}
|
|
123
|
+
.rib-group + .rib-group::before {
|
|
124
|
+
content: ""; position: absolute; left: 0; top: 8px; bottom: 8px;
|
|
125
|
+
width: 1px; background: #e1dfdd;
|
|
126
|
+
}
|
|
127
|
+
.rib-controls { display: flex; align-items: center; gap: 2px; flex: 1; }
|
|
128
|
+
/* two stacked rows (Font, Paragraph) */
|
|
129
|
+
.rib-rows { display: flex; flex-direction: column; gap: 3px; flex: 1; justify-content: center; }
|
|
130
|
+
.rib-row { display: flex; align-items: center; gap: 2px; }
|
|
131
|
+
.rib-label {
|
|
132
|
+
font-size: 11px; color: #605e5c; padding-top: 3px; white-space: nowrap;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/* --- buttons --- */
|
|
136
|
+
.cw-toolbar button.rib-btn {
|
|
137
|
+
min-width: 26px; height: 26px; display: inline-flex; align-items: center; justify-content: center;
|
|
138
|
+
border: 1px solid transparent; border-radius: 4px; background: transparent; cursor: pointer;
|
|
139
|
+
color: #323130; font-size: 13px; padding: 0 4px; gap: 1px;
|
|
140
|
+
}
|
|
141
|
+
.cw-toolbar button.rib-btn:hover { background: #e1dfdd; }
|
|
142
|
+
.cw-toolbar button.rib-btn:active { background: #d2d0ce; }
|
|
143
|
+
.cw-toolbar button.rib-btn.active { background: #cfe3fb; color: #0b57d0; border-color: #b3d3f5; }
|
|
144
|
+
.cw-toolbar button.rib-btn.active:hover { background: #bcd8fa; }
|
|
145
|
+
.cw-toolbar button.rib-btn.active svg { color: #0b57d0; }
|
|
146
|
+
.cw-toolbar button.rib-btn svg { width: 16px; height: 16px; display: block; }
|
|
147
|
+
.cw-toolbar button.rib-btn .caret { width: 8px; height: 8px; }
|
|
148
|
+
|
|
149
|
+
/* large button (Paste): icon over caption */
|
|
150
|
+
.cw-toolbar button.rib-big {
|
|
151
|
+
flex-direction: column; height: 100%; min-width: 48px; padding: 4px 6px; gap: 2px; justify-content: center;
|
|
152
|
+
}
|
|
153
|
+
.cw-toolbar button.rib-big svg { width: 26px; height: 26px; }
|
|
154
|
+
.cw-toolbar button.rib-big .big-cap { font-size: 11px; display: flex; align-items: center; gap: 1px; }
|
|
155
|
+
|
|
156
|
+
/* swatch button: icon row + colour underline */
|
|
157
|
+
.cw-toolbar button.rib-swatch { flex-direction: column; gap: 0; padding: 2px 3px; }
|
|
158
|
+
.cw-toolbar button.rib-swatch .row { display: flex; align-items: center; gap: 1px; }
|
|
159
|
+
.cw-toolbar button.rib-swatch .bar { width: 18px; height: 3px; margin-top: 1px; border-radius: 1px; }
|
|
160
|
+
|
|
161
|
+
/* disabled stub (feature not supported by the engine yet) */
|
|
162
|
+
.cw-toolbar button.rib-btn:disabled { opacity: 0.38; cursor: default; }
|
|
163
|
+
.cw-toolbar button.rib-btn:disabled:hover { background: transparent; }
|
|
164
|
+
|
|
165
|
+
/* form controls */
|
|
166
|
+
.cw-toolbar select, .cw-toolbar input[type="number"] {
|
|
167
|
+
height: 24px; border: 1px solid #c8c6c4; border-radius: 3px; background: #fff;
|
|
168
|
+
font: inherit; font-size: 13px; color: #323130;
|
|
169
|
+
}
|
|
170
|
+
.cw-toolbar select:hover, .cw-toolbar input[type="number"]:hover { border-color: #8a8886; }
|
|
171
|
+
|
|
172
|
+
/* styles gallery */
|
|
173
|
+
.rib-gallery {
|
|
174
|
+
display: flex; align-items: center; gap: 4px; height: 64px; padding: 0 4px;
|
|
175
|
+
border: 1px solid #c8c6c4; border-radius: 4px; background: #fff;
|
|
176
|
+
overflow-x: auto; max-width: 340px;
|
|
177
|
+
}
|
|
178
|
+
.rib-gallery::-webkit-scrollbar { height: 8px; }
|
|
179
|
+
.rib-gallery::-webkit-scrollbar-thumb { background: #c1c1c1; border-radius: 4px; }
|
|
180
|
+
.style-card {
|
|
181
|
+
flex: 0 0 auto; width: 76px; height: 50px; border: 1px solid #e1dfdd; border-radius: 2px;
|
|
182
|
+
background: #fff; cursor: pointer; display: flex; flex-direction: column;
|
|
183
|
+
align-items: center; justify-content: center; gap: 3px; padding: 2px;
|
|
184
|
+
}
|
|
185
|
+
.style-card:hover { border-color: #2b579a; }
|
|
186
|
+
.style-card.active { border-color: #2b579a; box-shadow: inset 0 0 0 1px #2b579a; background: #eef3fb; }
|
|
187
|
+
.style-card .preview { font-size: 13px; line-height: 1; color: #323130; }
|
|
188
|
+
.style-card .name { font-size: 10px; color: #605e5c; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 72px; }
|
|
189
|
+
|
|
190
|
+
/* work area: optional outline drawer + ruler + the scrolling page canvas */
|
|
191
|
+
.cw-workarea { flex: 1 1 auto; min-height: 0; display: flex; }
|
|
192
|
+
.cw-editorpane { flex: 1 1 auto; min-width: 0; min-height: 0; display: flex; flex-direction: column; }
|
|
193
|
+
/* touch-action: keep one/two-finger PAN (scroll) but disable the browser's
|
|
194
|
+
native pinch-zoom and double-tap-zoom on the document, so our own
|
|
195
|
+
pinch-to-zoom handler (index.ts) owns those gestures. The toolbar/status bar
|
|
196
|
+
keep default touch-action so the ribbon scrolls and taps normally. */
|
|
197
|
+
.cw-app { flex: 1 1 auto; min-height: 0; min-width: 0; overflow: auto; background: #e8eaed; position: relative; touch-action: pan-x pan-y; }
|
|
198
|
+
|
|
199
|
+
/* ruler row: top-left corner spacer (over the vertical ruler) + horizontal ruler */
|
|
200
|
+
.cw-ruler-row { flex: 0 0 22px; display: flex; }
|
|
201
|
+
.cw-ruler-row.hidden { display: none; }
|
|
202
|
+
.cw-ruler-corner { flex: 0 0 22px; width: 22px; background: #e8eaed; border-bottom: 1px solid #d2d0ce; border-right: 1px solid #d2d0ce; }
|
|
203
|
+
.cw-ruler-corner.hidden { display: none; }
|
|
204
|
+
.cw-main-row { flex: 1 1 auto; min-height: 0; min-width: 0; display: flex; }
|
|
205
|
+
/* horizontal ruler (inch ticks, margin shading, draggable indent markers) */
|
|
206
|
+
.cw-ruler { flex: 1 1 auto; height: 22px; position: relative; background: #e8eaed; border-bottom: 1px solid #d2d0ce; overflow: hidden; }
|
|
207
|
+
.cw-ruler.hidden { display: none; }
|
|
208
|
+
.cw-ruler canvas { position: absolute; inset: 0; }
|
|
209
|
+
/* vertical ruler (inch ticks + top/bottom margin shading down the left edge) */
|
|
210
|
+
.cw-vruler { flex: 0 0 22px; width: 22px; position: relative; background: #e8eaed; border-right: 1px solid #d2d0ce; overflow: hidden; }
|
|
211
|
+
.cw-vruler.hidden { display: none; }
|
|
212
|
+
.cw-vruler canvas { position: absolute; inset: 0; }
|
|
213
|
+
/* margin handles: right-pointing triangles at the top/bottom content boundaries */
|
|
214
|
+
.cw-vruler .vruler-marker { position: absolute; left: 0; width: 0; height: 0; cursor: ns-resize; z-index: 2; border-top: 5px solid transparent; border-bottom: 5px solid transparent; border-left: 7px solid #5b6b8c; }
|
|
215
|
+
.cw-ruler .ruler-marker { position: absolute; width: 0; height: 0; cursor: ew-resize; z-index: 2; }
|
|
216
|
+
/* left-indent: bottom-pointing triangle sitting on the baseline */
|
|
217
|
+
.cw-ruler .ruler-left { bottom: 0; border-left: 5px solid transparent; border-right: 5px solid transparent; border-bottom: 7px solid #5b6b8c; }
|
|
218
|
+
/* first-line-indent: top-pointing triangle */
|
|
219
|
+
.cw-ruler .ruler-first { top: 0; border-left: 5px solid transparent; border-right: 5px solid transparent; border-top: 7px solid #5b6b8c; }
|
|
220
|
+
|
|
221
|
+
/* ===== Outline / Navigation drawer ================================== */
|
|
222
|
+
.cw-outline {
|
|
223
|
+
flex: 0 0 264px; width: 264px; min-height: 0; overflow-y: auto;
|
|
224
|
+
background: #fff; border-right: 1px solid #e1dfdd; display: none;
|
|
225
|
+
}
|
|
226
|
+
.cw-outline.open { display: block; }
|
|
227
|
+
.cw-outline .outline-head {
|
|
228
|
+
position: sticky; top: 0; background: #fff; z-index: 1;
|
|
229
|
+
display: flex; align-items: center; justify-content: space-between;
|
|
230
|
+
padding: 9px 8px 9px 14px; border-bottom: 1px solid #e1dfdd;
|
|
231
|
+
font-size: 13px; font-weight: 600; color: #323130;
|
|
232
|
+
}
|
|
233
|
+
.cw-outline .outline-head button {
|
|
234
|
+
border: none; background: transparent; cursor: pointer; color: #605e5c;
|
|
235
|
+
width: 24px; height: 24px; border-radius: 4px; font-size: 17px; line-height: 1;
|
|
236
|
+
}
|
|
237
|
+
.cw-outline .outline-head button:hover { background: #f3f2f1; }
|
|
238
|
+
.cw-outline-list { padding: 4px 0 12px; }
|
|
239
|
+
.outline-item {
|
|
240
|
+
display: block; width: 100%; box-sizing: border-box; text-align: left;
|
|
241
|
+
border: none; border-left: 3px solid transparent; background: transparent; cursor: pointer;
|
|
242
|
+
padding: 4px 12px; color: #323130; font-size: 13px; line-height: 1.35;
|
|
243
|
+
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
|
244
|
+
}
|
|
245
|
+
.outline-item:hover { background: #f3f2f1; }
|
|
246
|
+
.outline-item.active { background: #eef3fb; border-left-color: #2b579a; color: #2b579a; font-weight: 600; }
|
|
247
|
+
.outline-empty { padding: 14px; color: #80868b; font-size: 12px; line-height: 1.4; }
|
|
248
|
+
|
|
249
|
+
/* ===== Review pane (track changes + comments) ======================= */
|
|
250
|
+
.cw-review {
|
|
251
|
+
flex: 0 0 320px; width: 320px; min-height: 0; display: none;
|
|
252
|
+
flex-direction: column; background: #f7f8fa; border-left: 1px solid #e1dfdd;
|
|
253
|
+
font-size: 13px; color: #202124;
|
|
254
|
+
}
|
|
255
|
+
.cw-review.open { display: flex; }
|
|
256
|
+
.cw-review-head {
|
|
257
|
+
display: flex; align-items: center; gap: 8px;
|
|
258
|
+
padding: 10px 10px 10px 14px; background: #fff; border-bottom: 1px solid #e8eaed;
|
|
259
|
+
}
|
|
260
|
+
.cw-review-head .cw-review-title { font-size: 14px; font-weight: 600; color: #202124; }
|
|
261
|
+
.cw-review-head .cw-review-close {
|
|
262
|
+
margin-left: auto; border: none; background: transparent; cursor: pointer;
|
|
263
|
+
color: #5f6368; width: 28px; height: 28px; border-radius: 50%; font-size: 18px; line-height: 1;
|
|
264
|
+
}
|
|
265
|
+
.cw-review-head .cw-review-close:hover { background: #f1f3f4; }
|
|
266
|
+
/* tab strip */
|
|
267
|
+
.cw-review-tabs { display: flex; background: #fff; border-bottom: 1px solid #e8eaed; padding: 0 8px; }
|
|
268
|
+
.cw-review-tab {
|
|
269
|
+
flex: 1 1 0; border: none; background: transparent; cursor: pointer;
|
|
270
|
+
padding: 9px 4px 8px; font-size: 13px; font-weight: 600; color: #5f6368;
|
|
271
|
+
border-bottom: 2px solid transparent; display: flex; align-items: center; justify-content: center; gap: 6px;
|
|
272
|
+
}
|
|
273
|
+
.cw-review-tab:hover { color: #202124; }
|
|
274
|
+
.cw-review-tab.active { color: #1a73e8; border-bottom-color: #1a73e8; }
|
|
275
|
+
.cw-review-tab .cw-pill {
|
|
276
|
+
background: #e8eaed; color: #5f6368; border-radius: 10px; padding: 0 7px;
|
|
277
|
+
font-size: 11px; font-weight: 700; min-width: 18px; text-align: center;
|
|
278
|
+
}
|
|
279
|
+
.cw-review-tab.active .cw-pill { background: #d2e3fc; color: #1a73e8; }
|
|
280
|
+
/* sticky bulk-action bar */
|
|
281
|
+
.cw-review-actions {
|
|
282
|
+
display: flex; gap: 8px; padding: 8px 12px; background: #f7f8fa;
|
|
283
|
+
border-bottom: 1px solid #e8eaed; position: sticky; top: 0; z-index: 1;
|
|
284
|
+
}
|
|
285
|
+
.cw-review-body { flex: 1 1 auto; overflow-y: auto; padding: 10px 12px; }
|
|
286
|
+
.cw-review-empty { padding: 28px 16px; text-align: center; color: #80868b; font-size: 12.5px; line-height: 1.5; }
|
|
287
|
+
.cw-review-empty .cw-review-empty-ico { font-size: 26px; display: block; margin-bottom: 8px; opacity: .6; }
|
|
288
|
+
|
|
289
|
+
/* buttons */
|
|
290
|
+
.cw-btn {
|
|
291
|
+
border: 1px solid #dadce0; background: #fff; color: #3c4043; cursor: pointer;
|
|
292
|
+
border-radius: 6px; padding: 5px 12px; font-size: 12.5px; font-weight: 600;
|
|
293
|
+
display: inline-flex; align-items: center; gap: 5px; line-height: 1;
|
|
294
|
+
}
|
|
295
|
+
.cw-btn:hover { background: #f8f9fa; box-shadow: 0 1px 2px rgba(60,64,67,.15); }
|
|
296
|
+
.cw-btn.cw-btn-primary { background: #1a73e8; border-color: #1a73e8; color: #fff; }
|
|
297
|
+
.cw-btn.cw-btn-primary:hover { background: #1b66c9; }
|
|
298
|
+
.cw-btn.cw-btn-accept { color: #137333; border-color: #c6e0c9; background: #e6f4ea; }
|
|
299
|
+
.cw-btn.cw-btn-accept:hover { background: #d3ecd9; }
|
|
300
|
+
.cw-btn.cw-btn-reject { color: #c5221f; border-color: #f3c7c5; background: #fce8e6; }
|
|
301
|
+
.cw-btn.cw-btn-reject:hover { background: #f9d6d3; }
|
|
302
|
+
.cw-btn.cw-btn-ghost { border-color: transparent; background: transparent; color: #1a73e8; padding: 4px 6px; }
|
|
303
|
+
.cw-btn.cw-btn-ghost:hover { background: #e8f0fe; box-shadow: none; }
|
|
304
|
+
.cw-btn-sm { padding: 4px 9px; font-size: 12px; }
|
|
305
|
+
|
|
306
|
+
/* suggestion card */
|
|
307
|
+
.cw-sug {
|
|
308
|
+
background: #fff; border: 1px solid #e8eaed; border-left: 3px solid var(--cw-author, #1a73e8);
|
|
309
|
+
border-radius: 8px; padding: 10px 12px; margin-bottom: 8px; box-shadow: 0 1px 2px rgba(60,64,67,.06);
|
|
310
|
+
cursor: pointer;
|
|
311
|
+
}
|
|
312
|
+
.cw-sug:hover { background: #f8f9fa; border-color: #d2e3fc; }
|
|
313
|
+
.cw-sug-top { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
|
|
314
|
+
.cw-sug-kind { font-weight: 600; font-size: 12.5px; color: #202124; display: flex; align-items: center; gap: 6px; }
|
|
315
|
+
.cw-sug-kind .cw-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--cw-author, #1a73e8); }
|
|
316
|
+
.cw-sug-meta { margin-left: auto; color: #80868b; font-size: 11.5px; white-space: nowrap; }
|
|
317
|
+
.cw-sug-actions { display: flex; gap: 8px; }
|
|
318
|
+
|
|
319
|
+
/* avatar + comment card */
|
|
320
|
+
.cw-avatar {
|
|
321
|
+
width: 28px; height: 28px; border-radius: 50%; flex: 0 0 28px;
|
|
322
|
+
display: flex; align-items: center; justify-content: center;
|
|
323
|
+
color: #fff; font-size: 12px; font-weight: 700; text-transform: uppercase;
|
|
324
|
+
}
|
|
325
|
+
.cw-thread {
|
|
326
|
+
background: #fff; border: 1px solid #e8eaed; border-radius: 8px;
|
|
327
|
+
padding: 12px; margin-bottom: 10px; box-shadow: 0 1px 2px rgba(60,64,67,.06);
|
|
328
|
+
cursor: pointer;
|
|
329
|
+
}
|
|
330
|
+
.cw-thread:hover { border-color: #d2e3fc; }
|
|
331
|
+
.cw-thread.resolved { opacity: .62; }
|
|
332
|
+
.cw-comment { display: flex; gap: 9px; margin-bottom: 10px; }
|
|
333
|
+
.cw-comment:last-of-type { margin-bottom: 6px; }
|
|
334
|
+
.cw-comment-main { min-width: 0; flex: 1 1 auto; }
|
|
335
|
+
.cw-comment-who { font-weight: 600; font-size: 12.5px; color: #202124; }
|
|
336
|
+
.cw-comment-when { color: #80868b; font-size: 11px; margin-left: 6px; font-weight: 400; }
|
|
337
|
+
.cw-comment-body { color: #3c4043; font-size: 13px; line-height: 1.45; white-space: pre-wrap; word-wrap: break-word; margin-top: 2px; }
|
|
338
|
+
.cw-thread-actions { display: flex; gap: 4px; align-items: center; padding-top: 6px; border-top: 1px solid #f1f3f4; }
|
|
339
|
+
.cw-thread-actions .cw-resolved-tag { color: #137333; font-size: 11.5px; font-weight: 600; display: flex; align-items: center; gap: 4px; }
|
|
340
|
+
|
|
341
|
+
/* inline reply editor inside a thread */
|
|
342
|
+
.cw-reply-box { display: none; gap: 8px; margin-top: 8px; }
|
|
343
|
+
.cw-reply-box.open { display: flex; }
|
|
344
|
+
|
|
345
|
+
/* ===== Comment composer bubble (Google-Docs style, floats by selection) === */
|
|
346
|
+
.cw-comment-bubble {
|
|
347
|
+
position: absolute; z-index: 60; width: 300px;
|
|
348
|
+
background: #fff; border: 1px solid #e0e0e0; border-radius: 10px;
|
|
349
|
+
box-shadow: 0 6px 22px rgba(60,64,67,.28); padding: 12px;
|
|
350
|
+
display: flex; flex-direction: column; gap: 10px;
|
|
351
|
+
}
|
|
352
|
+
.cw-comment-bubble .cw-bubble-row { display: flex; gap: 9px; align-items: flex-start; }
|
|
353
|
+
.cw-comment-bubble textarea {
|
|
354
|
+
flex: 1 1 auto; resize: none; min-height: 48px; max-height: 180px;
|
|
355
|
+
border: none; outline: none; font: 13px/1.45 inherit; color: #202124;
|
|
356
|
+
padding: 4px 0; background: transparent;
|
|
357
|
+
}
|
|
358
|
+
.cw-comment-bubble .cw-bubble-actions { display: flex; justify-content: flex-end; gap: 8px; }
|
|
359
|
+
.cw-comment-bubble .cw-btn.cw-btn-primary:disabled { opacity: .45; cursor: default; box-shadow: none; }
|
|
360
|
+
|
|
361
|
+
/* floating "leave a comment" chip shown beside a suggest-mode selection */
|
|
362
|
+
.cw-comment-chip {
|
|
363
|
+
position: absolute; z-index: 55; width: 34px; height: 34px; border-radius: 50%;
|
|
364
|
+
border: 1px solid #e0e0e0; background: #fff; cursor: pointer; font-size: 16px;
|
|
365
|
+
box-shadow: 0 2px 8px rgba(60,64,67,.28); display: flex; align-items: center; justify-content: center;
|
|
366
|
+
padding: 0; line-height: 1; transition: transform .08s ease, box-shadow .08s ease;
|
|
367
|
+
}
|
|
368
|
+
.cw-comment-chip:hover { transform: scale(1.08); box-shadow: 0 3px 12px rgba(60,64,67,.34); background: #f8f9fa; }
|
|
369
|
+
|
|
370
|
+
/* @-mention autocomplete dropdown + rendered mention chips */
|
|
371
|
+
.cw-mention-menu {
|
|
372
|
+
position: fixed; z-index: 70; background: #fff; border: 1px solid #e0e0e0;
|
|
373
|
+
border-radius: 8px; box-shadow: 0 6px 22px rgba(60,64,67,.28); padding: 4px;
|
|
374
|
+
max-height: 240px; overflow-y: auto; font: 13px/1.3 inherit;
|
|
375
|
+
}
|
|
376
|
+
.cw-mention-item {
|
|
377
|
+
display: flex; align-items: center; gap: 8px; padding: 6px 8px; border-radius: 6px; cursor: pointer; color: #202124;
|
|
378
|
+
}
|
|
379
|
+
.cw-mention-item:hover, .cw-mention-item.active { background: #e8f0fe; }
|
|
380
|
+
.cw-mention-av {
|
|
381
|
+
width: 24px; height: 24px; border-radius: 50%; flex: 0 0 24px;
|
|
382
|
+
display: flex; align-items: center; justify-content: center; color: #fff; font-size: 10px; font-weight: 700; text-transform: uppercase;
|
|
383
|
+
}
|
|
384
|
+
.cw-mention { color: #1a73e8; background: #e8f0fe; border-radius: 4px; padding: 0 3px; font-weight: 600; }
|
|
385
|
+
|
|
386
|
+
/* collapsed ribbon: keep the tab strip, hide the body */
|
|
387
|
+
.cw-toolbar.collapsed .rib-bodies { display: none; }
|
|
388
|
+
|
|
389
|
+
/* ===== Status bar ================================================== */
|
|
390
|
+
.cw-statusbar {
|
|
391
|
+
flex: 0 0 auto; height: 24px; display: flex; align-items: center; justify-content: space-between;
|
|
392
|
+
background: #2b579a; color: #fff; font-size: 12px; padding: 0 10px; user-select: none;
|
|
393
|
+
}
|
|
394
|
+
.cw-statusbar .sb-left, .cw-statusbar .sb-right { display: flex; align-items: center; gap: 16px; }
|
|
395
|
+
.cw-statusbar .sb-right { gap: 8px; }
|
|
396
|
+
.cw-statusbar .sb-item { white-space: nowrap; }
|
|
397
|
+
.cw-statusbar .sb-sep { width: 1px; height: 14px; background: rgba(255,255,255,0.35); }
|
|
398
|
+
.cw-statusbar button.sb-btn {
|
|
399
|
+
background: transparent; border: none; color: #fff; cursor: pointer; font-size: 15px;
|
|
400
|
+
width: 22px; height: 20px; border-radius: 3px; line-height: 1; padding: 0;
|
|
401
|
+
}
|
|
402
|
+
.cw-statusbar button.sb-btn:hover { background: rgba(255,255,255,0.18); }
|
|
403
|
+
.cw-statusbar input[type="range"] { width: 120px; cursor: pointer; accent-color: #fff; }
|
|
404
|
+
.cw-statusbar .sb-zoom { min-width: 38px; text-align: right; }
|
|
405
|
+
|
|
406
|
+
/* ===== Popovers (palettes, menus, pickers, dialogs) ================ */
|
|
407
|
+
.cw-pop {
|
|
408
|
+
position: fixed; background: #fff; border: 1px solid #c8c6c4; border-radius: 6px;
|
|
409
|
+
box-shadow: 0 4px 18px rgba(0,0,0,0.18); z-index: 50; font-size: 13px; padding: 4px;
|
|
410
|
+
}
|
|
411
|
+
.cw-menu { display: flex; flex-direction: column; min-width: 168px; }
|
|
412
|
+
.cw-menu button {
|
|
413
|
+
display: flex; align-items: center; gap: 10px; width: 100%; text-align: left;
|
|
414
|
+
border: none; background: transparent; cursor: pointer; padding: 7px 10px; border-radius: 4px;
|
|
415
|
+
font: inherit; color: #323130;
|
|
416
|
+
}
|
|
417
|
+
.cw-menu button:hover { background: #f3f2f1; }
|
|
418
|
+
.cw-menu .check { width: 14px; color: #2b579a; }
|
|
419
|
+
.cw-menu .sample { color: #605e5c; }
|
|
420
|
+
.cw-pop-title { font-size: 11px; color: #605e5c; padding: 4px 6px 2px; }
|
|
421
|
+
.cw-swatches { display: grid; grid-template-columns: repeat(6, 22px); gap: 4px; padding: 4px 6px; }
|
|
422
|
+
.cw-swatches button { width: 22px; height: 22px; border: 1px solid rgba(0,0,0,0.18); border-radius: 3px; cursor: pointer; padding: 0; }
|
|
423
|
+
.cw-swatches button:hover { outline: 2px solid #2b579a; outline-offset: 1px; }
|
|
424
|
+
.cw-pop .pop-action {
|
|
425
|
+
display: flex; align-items: center; gap: 8px; width: 100%; text-align: left; border: none;
|
|
426
|
+
background: transparent; cursor: pointer; padding: 7px 8px; border-radius: 4px; font: inherit; color: #323130;
|
|
427
|
+
border-top: 1px solid #edebe9; margin-top: 4px;
|
|
428
|
+
}
|
|
429
|
+
.cw-pop .pop-action:hover { background: #f3f2f1; }
|
|
430
|
+
.cw-grid { display: grid; gap: 2px; padding: 8px 8px 2px; }
|
|
431
|
+
.cw-grid .cell { width: 15px; height: 15px; border: 1px solid #c8c6c4; background: #fff; }
|
|
432
|
+
.cw-grid .cell.on { background: #cfe3fb; border-color: #2b579a; }
|
|
433
|
+
.cw-grid-label { text-align: center; font-size: 12px; color: #605e5c; padding: 4px 0 6px; }
|
|
434
|
+
.cw-dialog { display: flex; flex-direction: column; gap: 8px; padding: 10px; min-width: 248px; }
|
|
435
|
+
.cw-dialog label { font-size: 12px; color: #605e5c; display: flex; flex-direction: column; gap: 3px; }
|
|
436
|
+
.cw-dialog input { height: 28px; border: 1px solid #c8c6c4; border-radius: 4px; padding: 0 8px; font: inherit; font-size: 13px; }
|
|
437
|
+
.cw-dialog .row { display: flex; justify-content: flex-end; gap: 6px; margin-top: 2px; }
|
|
438
|
+
.cw-dialog button { height: 28px; border: 1px solid #c8c6c4; background: #fff; border-radius: 4px; cursor: pointer; padding: 0 12px; font: inherit; font-size: 13px; }
|
|
439
|
+
.cw-dialog button.primary { background: #2b579a; color: #fff; border-color: #2b579a; }
|
|
440
|
+
.cw-dialog button.danger { color: #a4262c; }
|
|
441
|
+
|
|
442
|
+
/* ===== Busy overlay (docx import / join / publish) ================= */
|
|
443
|
+
.cw-loading-overlay {
|
|
444
|
+
position: fixed; inset: 0; z-index: 70; background: rgba(0,0,0,0.25);
|
|
445
|
+
display: flex; align-items: center; justify-content: center;
|
|
446
|
+
}
|
|
447
|
+
.cw-loading-card {
|
|
448
|
+
display: flex; flex-direction: column; align-items: center; gap: 12px;
|
|
449
|
+
background: #fff; border: 1px solid #c8c6c4; border-radius: 8px;
|
|
450
|
+
box-shadow: 0 8px 30px rgba(0,0,0,0.25); padding: 22px 28px; min-width: 200px;
|
|
451
|
+
}
|
|
452
|
+
.cw-spinner {
|
|
453
|
+
width: 30px; height: 30px; border-radius: 50%;
|
|
454
|
+
border: 3px solid #e1dfdd; border-top-color: #2b579a;
|
|
455
|
+
animation: cw-spin 0.8s linear infinite;
|
|
456
|
+
}
|
|
457
|
+
@keyframes cw-spin { to { transform: rotate(360deg); } }
|
|
458
|
+
.cw-loading-label { font-size: 13px; color: #323130; text-align: center; }
|
|
459
|
+
.cw-progress { width: 180px; height: 4px; background: #e1dfdd; border-radius: 2px; overflow: hidden; }
|
|
460
|
+
.cw-progress-bar { height: 100%; width: 0%; background: #2b579a; transition: width 0.15s ease; }
|
|
461
|
+
|
|
462
|
+
/* floating mini-toolbar shown above a selected image */
|
|
463
|
+
.cw-img-toolbar {
|
|
464
|
+
position: fixed; display: none; align-items: center; gap: 2px; z-index: 40;
|
|
465
|
+
background: #fff; border: 1px solid #c8c6c4; border-radius: 6px; padding: 3px;
|
|
466
|
+
box-shadow: 0 3px 12px rgba(0,0,0,0.18);
|
|
467
|
+
}
|
|
468
|
+
.cw-img-toolbar button {
|
|
469
|
+
width: 28px; height: 28px; display: inline-flex; align-items: center; justify-content: center;
|
|
470
|
+
border: 1px solid transparent; border-radius: 4px; background: transparent; cursor: pointer; color: #323130;
|
|
471
|
+
}
|
|
472
|
+
.cw-img-toolbar button:hover { background: #e1dfdd; }
|
|
473
|
+
.cw-img-toolbar button.danger:hover { background: #fde7e9; color: #a4262c; }
|
|
474
|
+
.cw-img-toolbar button svg { width: 16px; height: 16px; }
|
|
475
|
+
.cw-img-toolbar .sep { width: 1px; height: 18px; background: #e1dfdd; margin: 0 2px; }
|
|
476
|
+
|
|
477
|
+
/* ===== Mobile / touch responsive layer ============================== */
|
|
478
|
+
/* Activates on touch devices (coarse primary pointer) OR narrow screens.
|
|
479
|
+
Desktop is untouched outside this block. Strategy: collapse the ribbon to one
|
|
480
|
+
horizontally-scrollable row, hide group captions, grow touch targets to ~40px,
|
|
481
|
+
turn the 264px outline into an overlay drawer, and clamp floating panels to
|
|
482
|
+
the viewport (a bottom sheet) so they never render off-screen. */
|
|
483
|
+
@media (pointer: coarse), (max-width: 760px) {
|
|
484
|
+
/* Ribbon body: single scrollable row instead of a tall multi-group block. */
|
|
485
|
+
.rib-panel { min-height: 0; overflow-x: auto; overflow-y: hidden; flex-wrap: nowrap; -webkit-overflow-scrolling: touch; }
|
|
486
|
+
.rib-label { display: none; }
|
|
487
|
+
.rib-group { padding: 4px 6px; }
|
|
488
|
+
/* Touch targets (Apple/Material guideline is ~40-48px). */
|
|
489
|
+
.cw-toolbar button.rib-btn { min-width: 40px; height: 40px; }
|
|
490
|
+
.cw-toolbar button.rib-btn svg { width: 18px; height: 18px; }
|
|
491
|
+
.rib-tab { padding: 9px 14px; font-size: 14px; }
|
|
492
|
+
.cw-toolbar select, .cw-toolbar input[type="number"] { height: 36px; font-size: 14px; }
|
|
493
|
+
|
|
494
|
+
/* Outline: overlay the page instead of stealing 264px of a ~360px screen. */
|
|
495
|
+
.cw-workarea { position: relative; }
|
|
496
|
+
.cw-outline { position: absolute; left: 0; top: 0; bottom: 0; height: auto; width: min(264px, 80vw); z-index: 30; box-shadow: 2px 0 16px rgba(0,0,0,0.18); }
|
|
497
|
+
.cw-review { position: absolute; right: 0; top: 0; bottom: 0; height: auto; width: min(320px, 88vw); z-index: 31; box-shadow: -2px 0 16px rgba(0,0,0,0.18); }
|
|
498
|
+
|
|
499
|
+
/* Status bar: tappable zoom controls. */
|
|
500
|
+
.cw-statusbar { height: 36px; }
|
|
501
|
+
.cw-statusbar button.sb-btn { width: 32px; height: 30px; font-size: 17px; }
|
|
502
|
+
.cw-statusbar input[type="range"] { width: 96px; }
|
|
503
|
+
|
|
504
|
+
/* Floating panels (Page Setup, Find) → bottom sheet; Activity → full-width.
|
|
505
|
+
!important overrides the inline position/size set in editorApp.ts. */
|
|
506
|
+
.cw-float-panel { left: 8px !important; right: 8px !important; top: auto !important; bottom: 8px !important; width: auto !important; max-width: none !important; max-height: 60vh; overflow: auto; }
|
|
507
|
+
.cw-float-drawer { width: 100% !important; }
|
|
508
|
+
.cw-img-toolbar button { width: 34px; height: 34px; }
|
|
509
|
+
|
|
510
|
+
/* Image resize handles: 8px dots are unhittable with a finger — an invisible
|
|
511
|
+
::before pads the touch target to ~24px without changing the visual size. */
|
|
512
|
+
.cw-obj-handle::before { content: ""; position: absolute; inset: -8px; }
|
|
513
|
+
}
|
|
514
|
+
`;
|
|
515
|
+
function x(o, e) {
|
|
516
|
+
if (document.getElementById(o)) return;
|
|
517
|
+
const t = document.createElement("style");
|
|
518
|
+
t.id = o, t.textContent = e, document.head.appendChild(t);
|
|
519
|
+
}
|
|
520
|
+
function N() {
|
|
521
|
+
x(M, T);
|
|
522
|
+
}
|
|
523
|
+
const A = `
|
|
524
|
+
.cw-drag-handle{cursor:move;user-select:none;}
|
|
525
|
+
.cw-drag-handle::before{content:"⠿";color:#b0b4ba;font-size:14px;line-height:1;margin-right:4px;flex:0 0 auto;}`;
|
|
526
|
+
function F(o) {
|
|
527
|
+
x("cw-drag-handle-styles", A);
|
|
528
|
+
const { backdrop: e, modal: t, handle: i, signal: r } = o;
|
|
529
|
+
e.style.pointerEvents = "none", e.style.background = "transparent", e.style.display = "block", t.style.position = "fixed", t.style.margin = "0", t.style.pointerEvents = "auto", i.classList.add("cw-drag-handle");
|
|
530
|
+
const d = (n, c) => {
|
|
531
|
+
const g = Math.max(4, window.innerWidth - t.offsetWidth - 6), h = Math.max(4, window.innerHeight - 44);
|
|
532
|
+
t.style.left = `${Math.min(Math.max(4, n), g)}px`, t.style.top = `${Math.min(Math.max(4, c), h)}px`;
|
|
533
|
+
};
|
|
534
|
+
d(window.innerWidth - t.offsetWidth - 24, 72);
|
|
535
|
+
let a = null;
|
|
536
|
+
i.addEventListener(
|
|
537
|
+
"mousedown",
|
|
538
|
+
(n) => {
|
|
539
|
+
if (o.noDrag && n.target.closest(o.noDrag)) return;
|
|
540
|
+
const c = t.getBoundingClientRect();
|
|
541
|
+
a = { dx: n.clientX - c.left, dy: n.clientY - c.top }, n.preventDefault();
|
|
542
|
+
},
|
|
543
|
+
{ signal: r }
|
|
544
|
+
), window.addEventListener("mousemove", (n) => {
|
|
545
|
+
a && d(n.clientX - a.dx, n.clientY - a.dy);
|
|
546
|
+
}, { signal: r }), window.addEventListener("mouseup", () => {
|
|
547
|
+
a = null;
|
|
548
|
+
}, { signal: r });
|
|
549
|
+
}
|
|
550
|
+
const s = 0.15;
|
|
551
|
+
function B(o, e) {
|
|
552
|
+
const t = e > 0 ? o / e : 1;
|
|
553
|
+
return { phase: "fonts", loaded: o, total: e, percent: s + (1 - s) * t };
|
|
554
|
+
}
|
|
555
|
+
class W {
|
|
556
|
+
handle = null;
|
|
557
|
+
ready;
|
|
558
|
+
handlers = /* @__PURE__ */ new Map();
|
|
559
|
+
constructor(e) {
|
|
560
|
+
this.ready = new Promise((t) => {
|
|
561
|
+
const i = {
|
|
562
|
+
container: e.container,
|
|
563
|
+
backendUrl: e.backendUrl,
|
|
564
|
+
// `docId` is the canonical name; fall back to the deprecated `collabId`.
|
|
565
|
+
collabId: e.docId ?? e.collabId,
|
|
566
|
+
user: e.user,
|
|
567
|
+
onShareLink: e.onShareLink,
|
|
568
|
+
onSave: e.onSave,
|
|
569
|
+
readonly: e.readonly,
|
|
570
|
+
mode: e.mode,
|
|
571
|
+
allowedModes: e.allowedModes,
|
|
572
|
+
knownUsers: e.knownUsers,
|
|
573
|
+
resolveField: e.resolveField,
|
|
574
|
+
agentTools: e.agentTools,
|
|
575
|
+
view: e.view,
|
|
576
|
+
theme: e.theme,
|
|
577
|
+
overrideDefaultStyles: e.overrideDefaultStyles,
|
|
578
|
+
behavior: e.behavior,
|
|
579
|
+
customizeRibbon: e.customizeRibbon,
|
|
580
|
+
onLoadProgress: e.onLoadProgress,
|
|
581
|
+
onReady: (r) => {
|
|
582
|
+
this.handle = r, t(r);
|
|
583
|
+
},
|
|
584
|
+
onEvent: (r) => this.emit(r)
|
|
585
|
+
};
|
|
586
|
+
e.onLoadProgress?.({ phase: "bundle", percent: 0, loaded: 0, total: 0 }), import("./editorApp-CB_ZArIF.js").then((r) => r.e).then((r) => (e.onLoadProgress?.({ phase: "bundle", percent: s, loaded: 0, total: 0 }), r.mountEditorApp(i)));
|
|
587
|
+
});
|
|
588
|
+
}
|
|
589
|
+
/** Subscribe to a collaboration event. Returns an unsubscribe function. */
|
|
590
|
+
on(e, t) {
|
|
591
|
+
let i = this.handlers.get(e);
|
|
592
|
+
return i || this.handlers.set(e, i = /* @__PURE__ */ new Set()), i.add(t), () => this.off(e, t);
|
|
593
|
+
}
|
|
594
|
+
/** Unsubscribe a handler previously passed to on(). */
|
|
595
|
+
off(e, t) {
|
|
596
|
+
this.handlers.get(e)?.delete(t);
|
|
597
|
+
}
|
|
598
|
+
emit(e) {
|
|
599
|
+
const { type: t, ...i } = e;
|
|
600
|
+
for (const r of this.handlers.get(t) ?? []) r(i);
|
|
601
|
+
}
|
|
602
|
+
/** Resolves once the editor is mounted and ready. */
|
|
603
|
+
whenReady() {
|
|
604
|
+
return this.ready;
|
|
605
|
+
}
|
|
606
|
+
/** Create a child document that shares this editor's live styles, fonts and
|
|
607
|
+
* theme. Use it to render a real, document-styled preview of a content slice
|
|
608
|
+
* (e.g. a style sample, a field result, or any blocks/fragment/OOXML) onto a
|
|
609
|
+
* canvas — instead of an HTML approximation — or to mount a canvas-native
|
|
610
|
+
* editor over a slice. Returned synchronously; render() calls before the editor
|
|
611
|
+
* is ready are buffered and flush on ready. (mountEditor() requires the editor
|
|
612
|
+
* to be ready — await whenReady() first.) */
|
|
613
|
+
createChild() {
|
|
614
|
+
let e = null, t = null, i = !1;
|
|
615
|
+
return this.ready.then((r) => {
|
|
616
|
+
i || (e = r.createChild(), t?.(), t = null);
|
|
617
|
+
}), {
|
|
618
|
+
render: (r, d, a) => {
|
|
619
|
+
const n = () => e?.render(r, d, a);
|
|
620
|
+
e ? n() : t = n;
|
|
621
|
+
},
|
|
622
|
+
mountEditor: (r, d, a) => {
|
|
623
|
+
if (!e) throw new Error("WordCanvas.createChild(): await whenReady() before mountEditor()");
|
|
624
|
+
return e.mountEditor(r, d, a);
|
|
625
|
+
},
|
|
626
|
+
destroy: () => {
|
|
627
|
+
i = !0, e?.destroy(), e = null;
|
|
628
|
+
}
|
|
629
|
+
};
|
|
630
|
+
}
|
|
631
|
+
/** Open a .docx. When online, auto-publishes it and surfaces a share link. */
|
|
632
|
+
async openDocx(e) {
|
|
633
|
+
return (await this.ready).openDocx(e);
|
|
634
|
+
}
|
|
635
|
+
/** Export the current document to a .docx Blob — track changes baked to the
|
|
636
|
+
* original baseline, exactly like the toolbar's Export. Wire it to your own
|
|
637
|
+
* Save button and POST it anywhere. Resolves once the editor is ready. */
|
|
638
|
+
async exportDocx() {
|
|
639
|
+
return (await this.ready).exportDocx();
|
|
640
|
+
}
|
|
641
|
+
/** Export the current document to a PDF Blob (see `exportDocx`). */
|
|
642
|
+
async exportPdf() {
|
|
643
|
+
return (await this.ready).exportPdf();
|
|
644
|
+
}
|
|
645
|
+
/** Replace the open document with a programmatically-built one (e.g. a
|
|
646
|
+
* DocumentBuilder result). The input is cloned. Like openDocx, this starts
|
|
647
|
+
* a NEW document: undo history and any live collab session are dropped
|
|
648
|
+
* (the next share() forks). Zoom and scroll position are preserved, so
|
|
649
|
+
* calling this on every data change gives a stable live preview. */
|
|
650
|
+
async setDocument(e) {
|
|
651
|
+
(await this.ready).setDocument(e);
|
|
652
|
+
}
|
|
653
|
+
/** Publish the current document and resolve its shareable link (online only). */
|
|
654
|
+
async share() {
|
|
655
|
+
return (await this.ready).share();
|
|
656
|
+
}
|
|
657
|
+
// ---- review layer (track changes + comments) ----------------------------
|
|
658
|
+
/** Current editor mode. Returns null before the editor is ready. */
|
|
659
|
+
getMode() {
|
|
660
|
+
return this.handle?.getMode() ?? null;
|
|
661
|
+
}
|
|
662
|
+
/** Switch mode. Resolves to false if the mode isn't allowed (or not ready). */
|
|
663
|
+
async setMode(e) {
|
|
664
|
+
return (await this.ready).setMode(e);
|
|
665
|
+
}
|
|
666
|
+
/** Snapshot of the review overlay (suggestions + comment threads). */
|
|
667
|
+
async getReview() {
|
|
668
|
+
return (await this.ready).getReview();
|
|
669
|
+
}
|
|
670
|
+
/** The effective @-mentionable roster: the configured base PLUS whoever is
|
|
671
|
+
* live-editing the document right now (auto-merged from presence). */
|
|
672
|
+
async getKnownUsers() {
|
|
673
|
+
return (await this.ready).getKnownUsers();
|
|
674
|
+
}
|
|
675
|
+
/** Replace the configured base roster (live editors are still merged on top). */
|
|
676
|
+
async setKnownUsers(e) {
|
|
677
|
+
(await this.ready).setKnownUsers(e);
|
|
678
|
+
}
|
|
679
|
+
async acceptSuggestion(e) {
|
|
680
|
+
(await this.ready).acceptSuggestion(e);
|
|
681
|
+
}
|
|
682
|
+
async rejectSuggestion(e) {
|
|
683
|
+
(await this.ready).rejectSuggestion(e);
|
|
684
|
+
}
|
|
685
|
+
async acceptAllSuggestions() {
|
|
686
|
+
(await this.ready).acceptAllSuggestions();
|
|
687
|
+
}
|
|
688
|
+
async rejectAllSuggestions() {
|
|
689
|
+
(await this.ready).rejectAllSuggestions();
|
|
690
|
+
}
|
|
691
|
+
/** Add a comment thread anchored to the current selection (a rich-text body;
|
|
692
|
+
* `mentions` are @-tagged users). Resolves to the thread id, or null if
|
|
693
|
+
* there's no selection. */
|
|
694
|
+
async addComment(e, t) {
|
|
695
|
+
return (await this.ready).addComment(e, t);
|
|
696
|
+
}
|
|
697
|
+
async replyToComment(e, t, i) {
|
|
698
|
+
(await this.ready).replyToComment(e, t, i);
|
|
699
|
+
}
|
|
700
|
+
async resolveThread(e, t = !0) {
|
|
701
|
+
(await this.ready).resolveThread(e, t);
|
|
702
|
+
}
|
|
703
|
+
/** Current selection/caret. Returns null before the editor is ready or when
|
|
704
|
+
* the editor isn't focused. */
|
|
705
|
+
getSelection() {
|
|
706
|
+
return this.handle?.getSelection() ?? null;
|
|
707
|
+
}
|
|
708
|
+
/** Insert plain text at the caret (replacing any selection). */
|
|
709
|
+
async insertText(e) {
|
|
710
|
+
(await this.ready).insertText(e);
|
|
711
|
+
}
|
|
712
|
+
getDocId() {
|
|
713
|
+
return this.handle?.getDocId() ?? null;
|
|
714
|
+
}
|
|
715
|
+
getShareLink() {
|
|
716
|
+
return this.handle?.getShareLink() ?? null;
|
|
717
|
+
}
|
|
718
|
+
destroy() {
|
|
719
|
+
this.handle?.destroy(), this.handle = null, this.handlers.clear();
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
export {
|
|
723
|
+
l as D,
|
|
724
|
+
W,
|
|
725
|
+
L as Z,
|
|
726
|
+
O as a,
|
|
727
|
+
E as b,
|
|
728
|
+
I as d,
|
|
729
|
+
N as e,
|
|
730
|
+
B as f,
|
|
731
|
+
x as i,
|
|
732
|
+
F as m,
|
|
733
|
+
U as r
|
|
734
|
+
};
|