ooxml-ui 0.10.2 → 0.12.0

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.
@@ -1,9 +1,878 @@
1
- import { createIconSvg, paintIcon, defineIcon } from './chunk-PCSUQPMC.js';
1
+ import { createIconSvg, paintIcon, defineIcon } from './chunk-YZ2JQNHX.js';
2
2
  import { initialsOf } from './chunk-RLPL7Q6J.js';
3
3
  import { definer, attachStyles, controlCss, emit } from './chunk-EY266IK3.js';
4
4
 
5
- // src/backstage.ts
5
+ // src/chrome-controls.ts
6
+ var ICON = `svg { flex: none; width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 1.45;
7
+ stroke-linecap: round; stroke-linejoin: round; }`;
8
+ function icon(doc, name) {
9
+ const svg = createIconSvg(doc);
10
+ paintIcon(svg, name);
11
+ return svg;
12
+ }
13
+ function emit2(host, type, detail) {
14
+ host.dispatchEvent(new CustomEvent(type, { detail, bubbles: true, composed: true }));
15
+ }
16
+ var config = (el) => el.constructor;
17
+ var FOOTER_CSS = `
18
+ :host { display: block; flex: 1 1 auto; min-width: 0; }
19
+ :host([hidden]) { display: none !important; }
20
+ ${ICON}
21
+ .footer { box-sizing: border-box; display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 8px; }
22
+ button { box-sizing: border-box; display: inline-flex; align-items: center; justify-content: center; gap: 6px;
23
+ min-width: 24px; min-height: 32px; padding: 6px 14px; border: 1px solid var(--office-border, #d1d5db);
24
+ border-radius: 6px; background: var(--office-surface, #f3f4f6); color: var(--office-foreground, #1f2937);
25
+ font: 500 13px/1.2 var(--office-font, system-ui, sans-serif); cursor: pointer; touch-action: manipulation; }
26
+ button:hover:not(:disabled) { background: var(--office-selected, #e5e7eb); }
27
+ button.primary { border-color: var(--office-accent, #2563eb); background: var(--office-accent, #2563eb);
28
+ color: var(--office-accent-foreground, #fff); }
29
+ button.primary:hover:not(:disabled) { opacity: .9; background: var(--office-accent, #2563eb); }
30
+ button.warning { border-color: #d97706; background: #d97706; color: #fff; }
31
+ button.warning:hover:not(:disabled) { opacity: .9; background: #d97706; }
32
+ button.danger { border-color: var(--office-danger, #b91c1c); background: var(--office-danger, #b91c1c); color: #fff; }
33
+ button.danger:hover:not(:disabled) { opacity: .9; background: var(--office-danger, #b91c1c); }
34
+ button.start { margin-right: auto; }
35
+ button.busy::before { content: ''; width: 12px; height: 12px; border: 2px solid currentColor; border-right-color: transparent;
36
+ border-radius: 50%; animation: office-footer-spin .8s linear infinite; }
37
+ @keyframes office-footer-spin { to { transform: rotate(360deg); } }
38
+ @media (prefers-reduced-motion: reduce) { button.busy::before { animation: none; } }
39
+ button:disabled { cursor: not-allowed; opacity: .55; }
40
+ button:focus-visible { outline: 2px solid var(--office-ring, #2563eb); outline-offset: 2px; }
41
+ @media (pointer: coarse), (max-width: 767px) { button { min-width: 44px; min-height: 44px; } }
42
+ @media (forced-colors: active) {
43
+ button, button.primary, button.warning, button.danger { border-color: ButtonText; background: ButtonFace; color: ButtonText; }
44
+ button:hover:not(:disabled) { background: Highlight; color: HighlightText; }
45
+ button.primary { border-width: 2px; }
46
+ button:focus-visible { outline-color: Highlight; }
47
+ }
48
+ `;
49
+ var defineDialogFooter = definer("office-ui-dialog-footer", () => {
50
+ class OfficeUiDialogFooter extends HTMLElement {
51
+ static requestEvent = "office-dialog-footer-request";
52
+ static testIdPrefix = "office-dialog-footer";
53
+ model = { actions: [] };
54
+ row = this.ownerDocument.createElement("div");
55
+ buttons = /* @__PURE__ */ new Map();
56
+ constructor() {
57
+ super();
58
+ const root = this.attachShadow({ mode: "open" });
59
+ attachStyles(root, controlCss(FOOTER_CSS));
60
+ this.row.className = "footer";
61
+ this.row.setAttribute("part", "footer");
62
+ root.append(this.row);
63
+ }
64
+ get state() {
65
+ return this.model;
66
+ }
67
+ set state(value) {
68
+ this.model = value;
69
+ this.render();
70
+ }
71
+ connectedCallback() {
72
+ this.render();
73
+ }
74
+ /** Move keyboard focus to an action, for example the primary one when a dialog opens. */
75
+ focusAction(id) {
76
+ this.render();
77
+ this.buttons.get(id)?.focus();
78
+ }
79
+ button(id) {
80
+ let button = this.buttons.get(id);
81
+ if (!button) {
82
+ button = this.ownerDocument.createElement("button");
83
+ button.type = "button";
84
+ button.dataset.action = id;
85
+ button.addEventListener("click", () => emit2(this, config(this).requestEvent, { id }));
86
+ this.buttons.set(id, button);
87
+ }
88
+ return button;
89
+ }
90
+ patch(button, action) {
91
+ button.className = action.variant === "secondary" ? "" : action.variant ?? "";
92
+ button.disabled = action.disabled === true || action.busy === true;
93
+ if (action.title) button.title = action.title;
94
+ else button.removeAttribute("title");
95
+ button.classList.toggle("start", action.align === "start");
96
+ button.classList.toggle("busy", action.busy === true);
97
+ if (action.busy) button.setAttribute("aria-busy", "true");
98
+ else button.removeAttribute("aria-busy");
99
+ if (action.testId) button.dataset.testid = action.testId;
100
+ else delete button.dataset.testid;
101
+ const glyph = action.icon ?? "";
102
+ if (button.dataset.icon !== glyph || button.dataset.label !== action.label) {
103
+ button.dataset.icon = glyph;
104
+ button.dataset.label = action.label;
105
+ button.replaceChildren(
106
+ ...glyph ? [icon(this.ownerDocument, glyph)] : [],
107
+ this.ownerDocument.createTextNode(action.label)
108
+ );
109
+ }
110
+ }
111
+ render() {
112
+ const wanted = this.model.actions.map((action) => {
113
+ const button = this.button(action.id);
114
+ this.patch(button, action);
115
+ return button;
116
+ });
117
+ for (const [id, button] of this.buttons)
118
+ if (!wanted.includes(button)) {
119
+ button.remove();
120
+ this.buttons.delete(id);
121
+ }
122
+ wanted.forEach((button, index) => {
123
+ const at = this.row.children[index];
124
+ if (at !== button) this.row.insertBefore(button, at ?? null);
125
+ });
126
+ }
127
+ }
128
+ return OfficeUiDialogFooter;
129
+ });
130
+ var OFFICE_TOAST_VISIBLE_LIMIT = 5;
131
+ var TOASTS_CSS = `
132
+ :host { box-sizing: border-box; display: flex; flex-direction: column; overflow-y: auto; max-height: 70%; pointer-events: none; }
133
+ :host([hidden]) { display: none !important; }
134
+ [hidden] { display: none !important; }
135
+ ${ICON}
136
+ .header, .toast, .overflow { pointer-events: auto; }
137
+ .header { display: flex; align-items: center; justify-content: space-between; padding: 0 4px;
138
+ color: var(--office-muted-foreground, #6b7280); font: 600 11px/1.4 var(--office-font, system-ui, sans-serif); }
139
+ .toast { box-sizing: border-box; display: flex; align-items: flex-start; gap: 8px; padding: 8px 10px; margin-top: 8px;
140
+ border: 1px solid var(--office-border, #d1d5db); border-radius: 6px; background: var(--office-popover, var(--office-background, #fff));
141
+ color: var(--office-foreground, #1f2937); box-shadow: 0 8px 20px rgba(0, 0, 0, .2);
142
+ font: 12px/1.4 var(--office-font, system-ui, sans-serif); }
143
+ .toast svg { width: 16px; height: 16px; margin-top: 1px; }
144
+ .toast[data-severity="warning"] svg { color: #f59e0b; }
145
+ .toast[data-severity="info"] svg { color: #3b82f6; }
146
+ .message { flex: 1; min-width: 0; margin: 0; overflow-wrap: anywhere; }
147
+ .overflow { margin: 8px 0 0; text-align: center; color: var(--office-muted-foreground, #6b7280); font: 11px var(--office-font, system-ui, sans-serif); }
148
+ button { box-sizing: border-box; flex: none; display: inline-flex; align-items: center; justify-content: center;
149
+ min-width: 24px; min-height: 24px; padding: 2px 4px; border: 0; border-radius: 4px; background: transparent;
150
+ color: var(--office-muted-foreground, #6b7280); font: inherit; cursor: pointer; touch-action: manipulation; }
151
+ button:hover { background: var(--office-surface, #f3f4f6); color: var(--office-foreground, #1f2937); }
152
+ .dismiss-all { font-weight: 500; text-decoration: underline; text-underline-offset: 2px; }
153
+ button:focus-visible { outline: 2px solid var(--office-ring, #2563eb); outline-offset: 1px; }
154
+ @media (pointer: coarse) { button { min-width: 44px; min-height: 44px; } }
155
+ @media (forced-colors: active) {
156
+ .toast { border-color: CanvasText; background: Canvas; color: CanvasText; }
157
+ .toast svg, button { color: ButtonText; } button:hover { background: Highlight; color: HighlightText; }
158
+ button:focus-visible { outline-color: Highlight; }
159
+ }
160
+ `;
161
+ var defineToasts = definer("office-ui-toasts", () => {
162
+ class OfficeUiToasts extends HTMLElement {
163
+ static requestEvent = "office-toasts-request";
164
+ static testIdPrefix = "office-toast";
165
+ model = { toasts: [] };
166
+ signature = "";
167
+ stack = this.ownerDocument.createElement("div");
168
+ constructor() {
169
+ super();
170
+ const root = this.attachShadow({ mode: "open" });
171
+ attachStyles(root, controlCss(TOASTS_CSS));
172
+ root.append(this.stack);
173
+ }
174
+ get state() {
175
+ return this.model;
176
+ }
177
+ set state(value) {
178
+ this.model = value;
179
+ this.render();
180
+ }
181
+ connectedCallback() {
182
+ this.render();
183
+ }
184
+ render() {
185
+ const s = this.model;
186
+ const { requestEvent, testIdPrefix: p } = config(this);
187
+ this.dataset.testid = `${p}s`;
188
+ this.hidden = s.toasts.length === 0;
189
+ const visible2 = s.toasts.slice(0, OFFICE_TOAST_VISIBLE_LIMIT);
190
+ const hiddenCount = (s.overflowCount ?? 0) + s.toasts.length - visible2.length;
191
+ const labels = [
192
+ s.labels?.title ?? "Compatibility",
193
+ s.labels?.dismissAll ?? "Dismiss all",
194
+ s.labels?.dismiss ?? "Dismiss"
195
+ ];
196
+ const signature = JSON.stringify([
197
+ labels,
198
+ hiddenCount,
199
+ visible2.map((toast) => [toast.id, toast.code, toast.severity, toast.message])
200
+ ]);
201
+ if (signature === this.signature) return;
202
+ this.signature = signature;
203
+ const doc = this.ownerDocument;
204
+ const header = doc.createElement("div");
205
+ header.className = "header";
206
+ const heading = doc.createElement("span");
207
+ heading.textContent = labels[0];
208
+ const dismissAll = doc.createElement("button");
209
+ dismissAll.type = "button";
210
+ dismissAll.className = "dismiss-all";
211
+ dismissAll.dataset.testid = `${p}s-dismiss-all`;
212
+ dismissAll.textContent = labels[1];
213
+ dismissAll.addEventListener("click", () => emit2(this, requestEvent, { id: "dismissAll" }));
214
+ header.append(heading, dismissAll);
215
+ const rows = [header];
216
+ for (const toast of visible2) {
217
+ const item = doc.createElement("div");
218
+ item.className = "toast";
219
+ item.dataset.testid = p;
220
+ if (toast.code) item.dataset.code = toast.code;
221
+ item.dataset.severity = toast.severity;
222
+ item.setAttribute("role", "status");
223
+ const message = doc.createElement("p");
224
+ message.className = "message";
225
+ message.textContent = toast.message;
226
+ const dismiss = doc.createElement("button");
227
+ dismiss.type = "button";
228
+ dismiss.dataset.testid = `${p}-dismiss`;
229
+ dismiss.setAttribute("aria-label", labels[2]);
230
+ dismiss.append(icon(doc, "close"));
231
+ dismiss.addEventListener(
232
+ "click",
233
+ () => emit2(this, requestEvent, { id: "dismiss", toastId: toast.id })
234
+ );
235
+ item.append(icon(doc, toast.severity === "warning" ? "warning" : "info"), message, dismiss);
236
+ rows.push(item);
237
+ }
238
+ if (hiddenCount > 0) {
239
+ const overflow = doc.createElement("p");
240
+ overflow.className = "overflow";
241
+ overflow.textContent = `+${hiddenCount}`;
242
+ rows.push(overflow);
243
+ }
244
+ this.stack.replaceChildren(...rows);
245
+ }
246
+ }
247
+ return OfficeUiToasts;
248
+ });
249
+
250
+ // src/document-notices.ts
251
+ var config2 = (el) => el.constructor;
252
+ var emit3 = (host, type, detail) => host.dispatchEvent(new CustomEvent(type, { detail, bubbles: true, composed: true }));
253
+ var BANNER_CSS = `
254
+ :host { display: block; flex: none; }
255
+ :host([hidden]) { display: none !important; }
256
+ [hidden] { display: none !important; }
257
+ svg { flex: none; width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.45;
258
+ stroke-linecap: round; stroke-linejoin: round; color: #d97706; }
259
+ .banner { box-sizing: border-box; display: flex; align-items: center; gap: 12px; padding: 6px 16px;
260
+ border-bottom: 1px solid rgba(180, 83, 9, .3); background: var(--office-notice-background, #fef3c7);
261
+ color: var(--office-notice-foreground, #78350f); font: 12px/1.4 var(--office-font, system-ui, sans-serif); }
262
+ .text { flex: 1 1 auto; min-width: 0; margin: 0; }
263
+ .form { display: flex; flex: none; align-items: center; gap: 8px; }
264
+ .sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden;
265
+ clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
266
+ button, input { font: inherit; }
267
+ button { box-sizing: border-box; flex: none; min-height: 24px; padding: 4px 12px; border: 1px solid transparent;
268
+ border-radius: 4px; background: transparent; color: inherit; font-weight: 500; cursor: pointer; touch-action: manipulation; }
269
+ button.primary { border-color: rgba(217, 119, 6, .5); }
270
+ button:hover { background: rgba(180, 83, 9, .15); }
271
+ button:disabled { opacity: .6; cursor: not-allowed; }
272
+ button:focus-visible, input:focus-visible { outline: 2px solid var(--office-ring, #2563eb); outline-offset: 1px; }
273
+ input { box-sizing: border-box; min-height: 24px; padding: 4px 8px; border: 1px solid rgba(217, 119, 6, .4);
274
+ border-radius: 4px; background: var(--office-background, #fff); color: var(--office-foreground, #1f2937); }
275
+ .error { flex: none; color: var(--office-danger, #b91c1c); }
276
+ @media (pointer: coarse) { button, input { min-height: 44px; min-width: 44px; } }
277
+ @media (forced-colors: active) {
278
+ .banner { border-bottom-color: CanvasText; background: Canvas; color: CanvasText; }
279
+ svg, .error { color: CanvasText; }
280
+ button, input { border-color: ButtonText; color: ButtonText; background: ButtonFace; }
281
+ button:focus-visible, input:focus-visible { outline-color: Highlight; }
282
+ }
283
+ `;
284
+ var defineReadOnlyBanner = definer("office-ui-read-only-banner", () => {
285
+ class OfficeUiReadOnlyBanner extends HTMLElement {
286
+ static requestEvent = "office-read-only-request";
287
+ static testIdPrefix = "office-readonly";
288
+ model = { kind: null, message: "" };
289
+ promptWasOpen = false;
290
+ pendingFocus = false;
291
+ parts = this.build();
292
+ constructor() {
293
+ super();
294
+ const root = this.attachShadow({ mode: "open" });
295
+ attachStyles(root, controlCss(BANNER_CSS));
296
+ root.append(this.parts.banner);
297
+ }
298
+ get state() {
299
+ return this.model;
300
+ }
301
+ set state(value) {
302
+ this.model = value;
303
+ this.render();
304
+ }
305
+ connectedCallback() {
306
+ this.render();
307
+ if (this.pendingFocus) {
308
+ this.pendingFocus = false;
309
+ this.parts.input.focus();
310
+ }
311
+ }
312
+ build() {
313
+ const doc = this.ownerDocument;
314
+ const p = config2(this).testIdPrefix;
315
+ const el = (tag, className = "") => {
316
+ const node = doc.createElement(tag);
317
+ node.className = className;
318
+ return node;
319
+ };
320
+ const send = (intent) => emit3(this, config2(this).requestEvent, intent);
321
+ const button = (testId, className, intent) => {
322
+ const node = el("button", className);
323
+ node.type = "button";
324
+ node.dataset.testid = `${p}-${testId}`;
325
+ node.addEventListener("click", () => send(intent));
326
+ return node;
327
+ };
328
+ const banner = el("div", "banner");
329
+ banner.setAttribute("role", "status");
330
+ banner.setAttribute("part", "banner");
331
+ const title = el("strong");
332
+ const message = el("span");
333
+ const text2 = el("p", "text");
334
+ text2.append(title, ": ", message);
335
+ const editAnyway = button("edit-anyway", "primary", { id: "editAnyway" });
336
+ const dismiss = button("dismiss", "", { id: "dismiss" });
337
+ const form = el("form", "form");
338
+ form.dataset.testid = `${p}-password-form`;
339
+ const label = el("label", "sr-only");
340
+ const input = el("input");
341
+ input.id = "password";
342
+ input.type = "password";
343
+ input.dataset.testid = `${p}-password-input`;
344
+ label.htmlFor = input.id;
345
+ const unlock = el("button", "primary");
346
+ unlock.type = "submit";
347
+ unlock.dataset.testid = `${p}-unlock`;
348
+ const cancel = button("password-cancel", "", { id: "cancelPassword" });
349
+ const error = el("span", "error");
350
+ error.id = "error";
351
+ error.setAttribute("role", "alert");
352
+ error.dataset.testid = `${p}-password-error`;
353
+ form.addEventListener("submit", (event) => {
354
+ event.preventDefault();
355
+ send({ id: "submitPassword", password: input.value });
356
+ });
357
+ form.append(label, input, unlock, cancel, error);
358
+ const lock = createIconSvg(doc);
359
+ paintIcon(lock, "lock");
360
+ banner.append(lock, text2, editAnyway, dismiss, form);
361
+ return {
362
+ banner,
363
+ title,
364
+ message,
365
+ editAnyway,
366
+ dismiss,
367
+ form,
368
+ label,
369
+ input,
370
+ unlock,
371
+ cancel,
372
+ error
373
+ };
374
+ }
375
+ render() {
376
+ const s = this.model;
377
+ const l = s.labels ?? {};
378
+ const p = this.parts;
379
+ this.dataset.testid = `${config2(this).testIdPrefix}-banner`;
380
+ if (s.kind) this.dataset.kind = s.kind;
381
+ else delete this.dataset.kind;
382
+ p.title.textContent = l.title ?? "Read-only recommended";
383
+ p.message.textContent = s.message;
384
+ p.editAnyway.textContent = l.editAnyway ?? "Edit anyway";
385
+ p.dismiss.textContent = l.dismiss ?? "Dismiss";
386
+ const open = s.passwordPromptOpen === true;
387
+ p.editAnyway.hidden = p.dismiss.hidden = open;
388
+ p.form.hidden = !open;
389
+ p.label.textContent = l.passwordLabel ?? "Password";
390
+ p.input.placeholder = l.passwordPlaceholder ?? "Password";
391
+ p.unlock.textContent = l.unlock ?? "Unlock";
392
+ p.cancel.textContent = l.cancel ?? "Cancel";
393
+ p.input.disabled = p.unlock.disabled = s.checkingPassword === true;
394
+ const failed = s.passwordError ?? null;
395
+ p.input.setAttribute("aria-invalid", String(failed !== null));
396
+ if (failed) p.input.setAttribute("aria-describedby", p.error.id);
397
+ else p.input.removeAttribute("aria-describedby");
398
+ p.error.hidden = failed === null;
399
+ p.error.textContent = failed ?? "";
400
+ if (open && !this.promptWasOpen) {
401
+ if (this.isConnected) p.input.focus();
402
+ else this.pendingFocus = true;
403
+ } else if (!open && this.promptWasOpen) p.input.value = "";
404
+ this.promptWasOpen = open;
405
+ }
406
+ }
407
+ return OfficeUiReadOnlyBanner;
408
+ });
409
+ var PASTE_CSS = `
410
+ :host { position: fixed; z-index: 1100; display: block; }
411
+ :host([hidden]) { display: none !important; }
412
+ .toolbar { box-sizing: border-box; display: flex; align-items: center; gap: 2px; padding: 4px;
413
+ border: 1px solid var(--office-border, #d1d5db); border-radius: 4px; background: var(--office-popover, var(--office-background, #fff));
414
+ box-shadow: 0 10px 25px rgba(0, 0, 0, .2); font: 11px/1.2 var(--office-font, system-ui, sans-serif); }
415
+ button { box-sizing: border-box; min-height: 24px; padding: 4px 8px; border: 0; border-radius: 4px; background: transparent;
416
+ color: var(--office-foreground, #1f2937); font: inherit; white-space: nowrap; cursor: pointer; touch-action: manipulation; }
417
+ button:hover { background: var(--office-surface, #f3f4f6); }
418
+ button:focus-visible { outline: 2px solid var(--office-ring, #2563eb); outline-offset: 1px; }
419
+ @media (pointer: coarse) { button { min-height: 44px; min-width: 44px; } }
420
+ @media (forced-colors: active) {
421
+ .toolbar { border-color: CanvasText; background: Canvas; }
422
+ button { color: ButtonText; } button:hover { background: Highlight; color: HighlightText; }
423
+ button:focus-visible { outline-color: Highlight; }
424
+ }
425
+ `;
426
+ var definePasteOptions = definer("office-ui-paste-options", () => {
427
+ class OfficeUiPasteOptions extends HTMLElement {
428
+ static requestEvent = "office-paste-options-request";
429
+ static dismissEvent = "office-paste-options-dismiss";
430
+ static testIdPrefix = "office-paste-options";
431
+ model = { left: 0, top: 0, options: [] };
432
+ toolbar = this.ownerDocument.createElement("div");
433
+ disarm;
434
+ constructor() {
435
+ super();
436
+ const root = this.attachShadow({ mode: "open" });
437
+ attachStyles(root, controlCss(PASTE_CSS));
438
+ this.toolbar.className = "toolbar";
439
+ this.toolbar.setAttribute("role", "toolbar");
440
+ this.toolbar.tabIndex = -1;
441
+ this.toolbar.addEventListener("mousedown", (event) => event.stopPropagation());
442
+ root.append(this.toolbar);
443
+ }
444
+ get state() {
445
+ return this.model;
446
+ }
447
+ set state(value) {
448
+ this.model = value;
449
+ this.render();
450
+ }
451
+ connectedCallback() {
452
+ this.render();
453
+ const view = this.ownerDocument.defaultView;
454
+ if (!view) return;
455
+ const dismiss = (event) => {
456
+ if (event.composedPath().includes(this.toolbar) && (!(event instanceof KeyboardEvent) || event.key !== "Escape"))
457
+ return;
458
+ emit3(this, config2(this).dismissEvent);
459
+ };
460
+ const timer = view.setTimeout(() => {
461
+ view.addEventListener("pointerdown", dismiss, true);
462
+ view.addEventListener("keydown", dismiss, true);
463
+ }, 0);
464
+ this.disarm = () => {
465
+ view.clearTimeout(timer);
466
+ view.removeEventListener("pointerdown", dismiss, true);
467
+ view.removeEventListener("keydown", dismiss, true);
468
+ };
469
+ }
470
+ disconnectedCallback() {
471
+ this.disarm?.();
472
+ this.disarm = void 0;
473
+ }
474
+ render() {
475
+ const s = this.model;
476
+ this.toolbar.setAttribute("aria-label", s.label ?? "Paste Options");
477
+ this.style.left = `${s.left + 4}px`;
478
+ this.style.top = `${s.top + 4}px`;
479
+ const doc = this.ownerDocument;
480
+ const existing = [...this.toolbar.querySelectorAll("button")];
481
+ const same = existing.length === s.options.length && existing.every((button, i) => button.dataset.format === s.options[i].id);
482
+ if (!same)
483
+ this.toolbar.replaceChildren(
484
+ ...s.options.map((option) => {
485
+ const button = doc.createElement("button");
486
+ button.type = "button";
487
+ button.dataset.format = option.id;
488
+ button.addEventListener("click", () => {
489
+ emit3(this, config2(this).requestEvent, { format: option.id });
490
+ emit3(this, config2(this).dismissEvent);
491
+ });
492
+ return button;
493
+ })
494
+ );
495
+ this.toolbar.querySelectorAll("button").forEach((button, i) => {
496
+ const label = s.options[i].label;
497
+ button.textContent = label;
498
+ button.title = label;
499
+ });
500
+ }
501
+ }
502
+ return OfficeUiPasteOptions;
503
+ });
504
+
505
+ // src/radio.ts
6
506
  var CSS = `
507
+ :host { display: inline-grid; box-sizing: border-box; width: var(--office-checkbox-size, 16px);
508
+ height: var(--office-checkbox-size, 16px); flex: none; place-items: center;
509
+ border: 1px solid var(--office-checkbox-border, var(--office-border, #d1d5db)); border-radius: 50%;
510
+ background: var(--office-checkbox-background, var(--office-background, #fff)); cursor: pointer; vertical-align: middle; }
511
+ :host([checked]) { border-color: var(--office-checkbox-accent, var(--office-accent, #2563eb)); }
512
+ :host(:focus-visible) { outline: 2px solid var(--office-ring, #2563eb); outline-offset: 2px; }
513
+ :host([disabled]) { opacity: .5; cursor: not-allowed; }
514
+ .dot { display: none; width: var(--office-radio-dot-size, 8px); height: var(--office-radio-dot-size, 8px);
515
+ border-radius: 50%; background: var(--office-checkbox-accent, var(--office-accent, #2563eb)); }
516
+ :host([checked]) .dot { display: block; }
517
+ @media (pointer: coarse), (max-width: 767px) {
518
+ :host { width: var(--office-checkbox-size-touch, 22px); height: var(--office-checkbox-size-touch, 22px); }
519
+ .dot { width: var(--office-radio-dot-size-touch, 12px); height: var(--office-radio-dot-size-touch, 12px); }
520
+ }
521
+ @media (forced-colors: active) {
522
+ :host { border-color: CanvasText; background: Canvas; forced-color-adjust: auto; }
523
+ :host([checked]) { border-color: Highlight; }
524
+ .dot { background: Highlight; }
525
+ :host([disabled]) { border-color: GrayText; }
526
+ :host([disabled]) .dot { background: GrayText; }
527
+ :host(:focus-visible) { outline-color: Highlight; }
528
+ }
529
+ `;
530
+ function groupOf(radio, scope) {
531
+ const name = radio.name;
532
+ if (!name || !scope) return [radio];
533
+ return [...scope.querySelectorAll(radio.localName)].filter(
534
+ (other) => other.name === name && other.form === radio.form
535
+ );
536
+ }
537
+ function labelText(label, self) {
538
+ let text2 = "";
539
+ for (const node of label.childNodes) {
540
+ if (node === self) continue;
541
+ if (node.nodeType === 3) text2 += node.textContent ?? "";
542
+ else if (node instanceof Element && !node.localName.includes("-") && !/^(select|input|textarea)$/u.test(node.localName))
543
+ text2 += labelText(node, self);
544
+ }
545
+ return text2;
546
+ }
547
+ function refreshTabStops(group) {
548
+ const enabled = group.filter((item) => !item.disabled);
549
+ const stop = enabled.find((item) => item.checked) ?? enabled[0];
550
+ for (const item of group) item.tabIndex = item === stop ? 0 : -1;
551
+ }
552
+ var defineRadio = definer("office-ui-radio", () => {
553
+ class OfficeUiRadio extends HTMLElement {
554
+ static formAssociated = true;
555
+ static observedAttributes = ["checked", "disabled", "value", "name"];
556
+ internals;
557
+ defaultChecked = false;
558
+ scope = null;
559
+ autoNamed = false;
560
+ constructor() {
561
+ super();
562
+ try {
563
+ this.internals = this.attachInternals();
564
+ } catch {
565
+ this.internals = void 0;
566
+ }
567
+ const root = this.attachShadow({ mode: "open" });
568
+ attachStyles(root, controlCss(CSS));
569
+ const dot = this.ownerDocument.createElement("span");
570
+ dot.className = "dot";
571
+ root.append(dot);
572
+ this.addEventListener("click", (event) => {
573
+ if (this.disabled) {
574
+ event.preventDefault();
575
+ return;
576
+ }
577
+ this.select(true);
578
+ });
579
+ this.addEventListener("keydown", (event) => this.onKey(event));
580
+ this.addEventListener("focus", () => this.syncName());
581
+ }
582
+ connectedCallback() {
583
+ this.defaultChecked = this.checked;
584
+ const root = this.getRootNode();
585
+ this.scope = root instanceof Document || root instanceof ShadowRoot ? root : null;
586
+ this.sync();
587
+ this.syncName();
588
+ }
589
+ disconnectedCallback() {
590
+ if (this.scope)
591
+ refreshTabStops(groupOf(this, this.scope).filter((item) => item !== this));
592
+ }
593
+ /**
594
+ * A custom element is not named by a wrapping `<label>` in every browser's accessibility
595
+ * tree, so mirror the label text into `aria-label` unless the host named it.
596
+ */
597
+ syncName() {
598
+ if (this.hasAttribute("aria-labelledby")) return;
599
+ if (this.hasAttribute("aria-label") && !this.autoNamed) return;
600
+ const label = this.closest("label") ?? this.internals?.labels?.[0];
601
+ const text2 = label ? labelText(label, this).replace(/\s+/gu, " ").trim() : "";
602
+ if (text2) {
603
+ this.autoNamed = true;
604
+ this.setAttribute("aria-label", text2);
605
+ }
606
+ }
607
+ attributeChangedCallback(name) {
608
+ if (name === "checked" && this.checked) this.uncheckPeers();
609
+ this.sync();
610
+ }
611
+ get checked() {
612
+ return this.hasAttribute("checked");
613
+ }
614
+ set checked(next) {
615
+ this.toggleAttribute("checked", Boolean(next));
616
+ }
617
+ get disabled() {
618
+ return this.hasAttribute("disabled");
619
+ }
620
+ set disabled(next) {
621
+ this.toggleAttribute("disabled", Boolean(next));
622
+ }
623
+ get value() {
624
+ return this.getAttribute("value") ?? "on";
625
+ }
626
+ set value(next) {
627
+ this.setAttribute("value", String(next));
628
+ }
629
+ get name() {
630
+ return this.getAttribute("name") ?? "";
631
+ }
632
+ set name(next) {
633
+ this.setAttribute("name", String(next));
634
+ }
635
+ get form() {
636
+ return this.internals?.form ?? null;
637
+ }
638
+ formResetCallback() {
639
+ this.checked = this.defaultChecked;
640
+ }
641
+ formDisabledCallback(disabled) {
642
+ this.disabled = disabled;
643
+ }
644
+ /** Check this radio and, for user intent, announce it. No-op when already checked. */
645
+ select(emit4) {
646
+ if (this.checked) return;
647
+ this.checked = true;
648
+ if (emit4) {
649
+ this.dispatchEvent(new Event("input", { bubbles: true, composed: true }));
650
+ this.dispatchEvent(new Event("change", { bubbles: true, composed: true }));
651
+ }
652
+ }
653
+ peers() {
654
+ return groupOf(this, this.scope ?? this.getRootNode());
655
+ }
656
+ uncheckPeers() {
657
+ for (const peer of this.peers()) if (peer !== this && peer.checked) peer.checked = false;
658
+ }
659
+ onKey(event) {
660
+ if (this.disabled || event.ctrlKey || event.metaKey || event.altKey) return;
661
+ if (event.key === " ") {
662
+ event.preventDefault();
663
+ this.select(true);
664
+ return;
665
+ }
666
+ const list = this.peers().filter((item) => !item.disabled);
667
+ const index = list.indexOf(this);
668
+ const last = list.length - 1;
669
+ const next = event.key === "ArrowRight" || event.key === "ArrowDown" ? (index + 1) % list.length : event.key === "ArrowLeft" || event.key === "ArrowUp" ? (index + last) % list.length : event.key === "Home" ? 0 : event.key === "End" ? last : -1;
670
+ if (next < 0 || index < 0) return;
671
+ event.preventDefault();
672
+ event.stopPropagation();
673
+ const target = list[next];
674
+ target.select(true);
675
+ target.focus();
676
+ }
677
+ sync() {
678
+ this.setAttribute("role", "radio");
679
+ this.setAttribute("aria-checked", String(this.checked));
680
+ this.setAttribute("aria-disabled", String(this.disabled));
681
+ this.internals?.setFormValue?.(this.checked && !this.disabled ? this.value : null);
682
+ if (this.isConnected) {
683
+ this.scope = this.getRootNode();
684
+ refreshTabStops(this.peers());
685
+ } else this.tabIndex = this.disabled ? -1 : 0;
686
+ }
687
+ }
688
+ return OfficeUiRadio;
689
+ });
690
+
691
+ // src/ribbon-toggle.ts
692
+ var CSS2 = `
693
+ :host { display: block; }
694
+ label { display: flex; align-items: center; gap: 4px; min-height: 22px; padding: 0 4px;
695
+ color: var(--office-foreground, #1f2937); font: inherit; font-size: 12px; white-space: nowrap; cursor: pointer; }
696
+ :host([disabled]) label { color: var(--office-muted-foreground, #6b7280); cursor: not-allowed; }
697
+ @media (pointer: coarse), (max-width: 767px) { label { min-height: 44px; font-size: 12px; } }
698
+ `;
699
+ var defineRibbonToggle = definer("office-ui-ribbon-toggle", () => {
700
+ class OfficeUiRibbonToggle extends HTMLElement {
701
+ static requestEvent = "office-toggle";
702
+ static idAttribute = "command";
703
+ static detailKey = "command";
704
+ static get observedAttributes() {
705
+ return ["label", "checked", "disabled", "title"];
706
+ }
707
+ checkbox;
708
+ text;
709
+ constructor() {
710
+ super();
711
+ const doc = this.ownerDocument;
712
+ const root = this.attachShadow({ mode: "open" });
713
+ attachStyles(root, controlCss(CSS2));
714
+ const label = doc.createElement("label");
715
+ this.checkbox = doc.createElement("office-ui-checkbox");
716
+ this.text = doc.createTextNode("");
717
+ label.append(this.checkbox, this.text);
718
+ label.addEventListener("click", (event) => {
719
+ event.preventDefault();
720
+ if (event.target !== this.checkbox) this.checkbox.click();
721
+ });
722
+ this.checkbox.addEventListener("input", (event) => event.stopPropagation());
723
+ this.checkbox.addEventListener("change", (event) => {
724
+ event.stopPropagation();
725
+ const checked = this.checkbox.checked;
726
+ this.sync();
727
+ const { requestEvent, idAttribute, detailKey } = this.constructor;
728
+ const id = this.getAttribute(idAttribute);
729
+ if (!this.hasAttribute("disabled") && id)
730
+ this.dispatchEvent(
731
+ new CustomEvent(requestEvent, {
732
+ detail: { [detailKey]: id, checked },
733
+ bubbles: true,
734
+ composed: true
735
+ })
736
+ );
737
+ });
738
+ root.append(label);
739
+ }
740
+ connectedCallback() {
741
+ this.sync();
742
+ }
743
+ attributeChangedCallback() {
744
+ this.sync();
745
+ }
746
+ get checked() {
747
+ return this.hasAttribute("checked");
748
+ }
749
+ set checked(value) {
750
+ this.toggleAttribute("checked", Boolean(value));
751
+ }
752
+ sync() {
753
+ const label = this.getAttribute("label") ?? "";
754
+ this.text.textContent = label;
755
+ this.checkbox.setAttribute("aria-label", label);
756
+ this.checkbox.title = this.getAttribute("title") ?? label;
757
+ this.checkbox.checked = this.hasAttribute("checked");
758
+ this.checkbox.disabled = this.hasAttribute("disabled");
759
+ }
760
+ }
761
+ return OfficeUiRibbonToggle;
762
+ });
763
+
764
+ // src/search-field.ts
765
+ var SVG_NS = "http://www.w3.org/2000/svg";
766
+ var CSS3 = `
767
+ :host { display: flex; align-items: center; gap: 8px; box-sizing: border-box; width: 100%;
768
+ height: var(--office-field-height-lg, 40px); padding: 0 12px;
769
+ border: 1px solid var(--office-field-border, var(--office-border, #d1d5db));
770
+ border-radius: var(--office-field-radius, 5px); background: var(--office-field-background, var(--office-background, #fff));
771
+ color: var(--office-field-placeholder, var(--office-muted-foreground, #6b7280)); font: inherit; }
772
+ :host(:focus-within) { border-color: var(--office-field-border-focus, var(--office-ring, #2563eb)); }
773
+ :host([variant="titlebar"]) { height: var(--office-field-height, 28px); gap: 7px; padding-inline: 14px;
774
+ border-color: var(--office-border, #d1d5db); border-radius: 6px; background: var(--office-background, #fff); }
775
+ :host([variant="titlebar"]:focus-within) { color: var(--office-foreground, #1f2937); }
776
+ :host([disabled]) { opacity: .5; cursor: not-allowed; }
777
+ svg { width: 16px; height: 16px; flex: none; }
778
+ :host([variant="titlebar"]) svg { width: 14px; height: 14px; }
779
+ input { min-width: 0; width: 100%; height: 100%; flex: 1; padding: 0; border: 0; outline: 0; background: transparent;
780
+ color: var(--office-field-foreground, var(--office-foreground, #1f2937)); font: inherit; font-size: 13px; }
781
+ :host([variant="titlebar"]) input { font-size: 11px; color: var(--office-foreground, #1f2937); }
782
+ input::placeholder { color: var(--office-field-placeholder, var(--office-muted-foreground, #6b7280)); opacity: .8; }
783
+ input::-webkit-search-cancel-button { display: none; }
784
+ @media (forced-colors: active) {
785
+ :host { border-color: CanvasText; background: Canvas; color: CanvasText; }
786
+ :host(:focus-within) { outline: 2px solid Highlight; outline-offset: 2px; }
787
+ input { color: CanvasText; }
788
+ }
789
+ `;
790
+ var defineSearchField = definer("office-ui-search", () => {
791
+ class OfficeUiSearch extends HTMLElement {
792
+ static observedAttributes = ["placeholder", "aria-label", "disabled", "value"];
793
+ input;
794
+ currentValue = "";
795
+ constructor() {
796
+ super();
797
+ const doc = this.ownerDocument;
798
+ const root = this.attachShadow({ mode: "open", delegatesFocus: true });
799
+ attachStyles(root, controlCss(CSS3));
800
+ const icon2 = doc.createElementNS(SVG_NS, "svg");
801
+ icon2.setAttribute("part", "icon");
802
+ icon2.setAttribute("viewBox", "0 0 24 24");
803
+ icon2.setAttribute("fill", "none");
804
+ icon2.setAttribute("stroke", "currentColor");
805
+ icon2.setAttribute("stroke-width", "2");
806
+ icon2.setAttribute("stroke-linecap", "round");
807
+ icon2.setAttribute("aria-hidden", "true");
808
+ const circle = doc.createElementNS(SVG_NS, "circle");
809
+ circle.setAttribute("cx", "11");
810
+ circle.setAttribute("cy", "11");
811
+ circle.setAttribute("r", "8");
812
+ const handle = doc.createElementNS(SVG_NS, "path");
813
+ handle.setAttribute("d", "m21 21-4.35-4.35");
814
+ icon2.append(circle, handle);
815
+ this.input = doc.createElement("input");
816
+ this.input.type = "search";
817
+ this.input.setAttribute("part", "input");
818
+ this.input.addEventListener("input", (event) => {
819
+ event.stopPropagation();
820
+ this.currentValue = this.input.value;
821
+ this.dispatchEvent(new Event("input", { bubbles: true, composed: true }));
822
+ });
823
+ this.input.addEventListener("change", (event) => {
824
+ event.stopPropagation();
825
+ this.dispatchEvent(new Event("change", { bubbles: true, composed: true }));
826
+ });
827
+ root.append(icon2, this.input);
828
+ }
829
+ connectedCallback() {
830
+ this.sync();
831
+ if (this.hasAttribute("value")) this.value = this.getAttribute("value") ?? "";
832
+ }
833
+ attributeChangedCallback(name) {
834
+ if (name === "value") this.value = this.getAttribute("value") ?? "";
835
+ else this.sync();
836
+ }
837
+ get value() {
838
+ return this.currentValue;
839
+ }
840
+ set value(next) {
841
+ this.currentValue = String(next ?? "");
842
+ if (this.input.value !== this.currentValue) this.input.value = this.currentValue;
843
+ }
844
+ get placeholder() {
845
+ return this.getAttribute("placeholder") ?? "";
846
+ }
847
+ set placeholder(next) {
848
+ this.setAttribute("placeholder", String(next ?? ""));
849
+ }
850
+ get disabled() {
851
+ return this.hasAttribute("disabled");
852
+ }
853
+ set disabled(next) {
854
+ this.toggleAttribute("disabled", Boolean(next));
855
+ }
856
+ focus(options) {
857
+ this.input.focus(options);
858
+ }
859
+ select() {
860
+ this.input.select();
861
+ }
862
+ sync() {
863
+ this.input.placeholder = this.getAttribute("placeholder") ?? "";
864
+ this.input.setAttribute(
865
+ "aria-label",
866
+ this.getAttribute("aria-label") ?? this.input.placeholder
867
+ );
868
+ this.input.disabled = this.hasAttribute("disabled");
869
+ }
870
+ }
871
+ return OfficeUiSearch;
872
+ });
873
+
874
+ // src/backstage.ts
875
+ var CSS4 = `
7
876
  :host { position: absolute; inset: 0; z-index: 30; display: none; min-width: 0;
8
877
  background: var(--office-background, #fff); color: var(--office-foreground, #1f2937);
9
878
  font-family: var(--office-font, system-ui, sans-serif); }
@@ -44,7 +913,7 @@ var defineBackstage = definer("office-ui-backstage", () => {
44
913
  super();
45
914
  const doc = this.ownerDocument;
46
915
  const root = this.attachShadow({ mode: "open" });
47
- attachStyles(root, controlCss(CSS));
916
+ attachStyles(root, controlCss(CSS4));
48
917
  this.#frame = doc.createElement("div");
49
918
  this.#frame.className = "frame";
50
919
  this.#frame.setAttribute("role", "dialog");
@@ -176,7 +1045,7 @@ var defineBackstage = definer("office-ui-backstage", () => {
176
1045
  });
177
1046
 
178
1047
  // src/find-bar.ts
179
- var CSS2 = `
1048
+ var CSS5 = `
180
1049
  :host { display: flex; align-items: center; gap: 8px; min-height: 40px; padding: 4px 8px 4px 12px;
181
1050
  border-bottom: 1px solid var(--office-border, #d1d5db); background: var(--office-surface, #f3f4f6);
182
1051
  color: var(--office-foreground, #1f2937); font: 12px var(--office-font, system-ui, sans-serif); }
@@ -218,7 +1087,7 @@ var defineFindBar = definer("office-ui-find-bar", () => {
218
1087
  super();
219
1088
  const doc = this.ownerDocument;
220
1089
  const root = this.attachShadow({ mode: "open", delegatesFocus: true });
221
- attachStyles(root, controlCss(CSS2));
1090
+ attachStyles(root, controlCss(CSS5));
222
1091
  this.#region = doc.createElement("div");
223
1092
  this.#region.setAttribute("role", "search");
224
1093
  const field = doc.createElement("label");
@@ -336,7 +1205,7 @@ var defineFindBar = definer("office-ui-find-bar", () => {
336
1205
  });
337
1206
 
338
1207
  // src/print-preview.ts
339
- var CSS3 = `
1208
+ var CSS6 = `
340
1209
  :host { display: block; max-width: 420px; font: 12px var(--office-font, system-ui, sans-serif);
341
1210
  color: var(--office-foreground, #1f2937); }
342
1211
  .sheet { padding: 12px; border: 1px solid var(--office-border, #d1d5db); background: #fff;
@@ -365,7 +1234,7 @@ var definePrintPreview = definer("office-ui-print-preview", () => {
365
1234
  super();
366
1235
  const doc = this.ownerDocument;
367
1236
  const root = this.attachShadow({ mode: "open" });
368
- attachStyles(root, controlCss(CSS3));
1237
+ attachStyles(root, controlCss(CSS6));
369
1238
  this.#sheet = doc.createElement("div");
370
1239
  this.#sheet.className = "sheet";
371
1240
  this.#sheet.setAttribute("role", "img");
@@ -444,7 +1313,7 @@ var definePrintPreview = definer("office-ui-print-preview", () => {
444
1313
  });
445
1314
 
446
1315
  // src/ribbon-tabs.ts
447
- var CSS4 = `
1316
+ var CSS7 = `
448
1317
  :host { display: block; min-width: 0; }
449
1318
  .head { display: flex; align-items: stretch; min-width: 0; border-bottom: 1px solid var(--office-border, #d1d5db); }
450
1319
  .file { flex: none; min-height: var(--office-ribbon-tab-height, 35px); margin: 0 4px 0 0; padding: 6px 16px; border: 0;
@@ -488,7 +1357,7 @@ var defineRibbon = definer("office-ui-ribbon", () => {
488
1357
  super();
489
1358
  const doc = this.ownerDocument;
490
1359
  const root = this.attachShadow({ mode: "open" });
491
- attachStyles(root, controlCss(CSS4));
1360
+ attachStyles(root, controlCss(CSS7));
492
1361
  const head = doc.createElement("div");
493
1362
  head.className = "head";
494
1363
  head.setAttribute("part", "head");
@@ -610,7 +1479,7 @@ var defineRibbon = definer("office-ui-ribbon", () => {
610
1479
  });
611
1480
 
612
1481
  // src/ruler.ts
613
- var CSS5 = `
1482
+ var CSS8 = `
614
1483
  :host { display: block; box-sizing: border-box; background: var(--office-background, #fff);
615
1484
  color: var(--office-muted-foreground, #605e5c); overflow: hidden; }
616
1485
  :host(:not([orientation="vertical"])) { height: 18px; border-bottom: 1px solid var(--office-border, #d1d5db); }
@@ -629,7 +1498,7 @@ var defineRuler = definer("office-ui-ruler", () => {
629
1498
  constructor() {
630
1499
  super();
631
1500
  const root = this.attachShadow({ mode: "open" });
632
- attachStyles(root, controlCss(CSS5));
1501
+ attachStyles(root, controlCss(CSS8));
633
1502
  this.#canvas = this.ownerDocument.createElement("canvas");
634
1503
  root.append(this.#canvas);
635
1504
  }
@@ -765,7 +1634,7 @@ function clearOfficeProfile(storage = defaultStorage(), key = OFFICE_PROFILE_STO
765
1634
  } catch {
766
1635
  }
767
1636
  }
768
- var CSS6 = `
1637
+ var CSS9 = `
769
1638
  :host { display: block; font-family: var(--office-font, system-ui, sans-serif); font-size: 13px; }
770
1639
  h2 { margin: 0 0 12px; font-size: 15px; font-weight: 600; }
771
1640
  .who { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
@@ -795,7 +1664,7 @@ var defineAccount = definer("office-ui-account", () => {
795
1664
  super();
796
1665
  const doc = this.ownerDocument;
797
1666
  const root = this.attachShadow({ mode: "open" });
798
- attachStyles(root, controlCss(CSS6));
1667
+ attachStyles(root, controlCss(CSS9));
799
1668
  const heading = doc.createElement("h2");
800
1669
  heading.textContent = "User Information";
801
1670
  const who = doc.createElement("div");
@@ -896,7 +1765,7 @@ var defineAccount = definer("office-ui-account", () => {
896
1765
  });
897
1766
 
898
1767
  // src/button.ts
899
- var CSS7 = `
1768
+ var CSS10 = `
900
1769
  :host { display: inline-flex; vertical-align: middle; }
901
1770
  button { box-sizing: border-box; display: inline-flex; align-items: center; justify-content: center;
902
1771
  gap: 6px; min-width: var(--office-target-size, 28px); min-height: var(--office-target-size, 28px);
@@ -937,7 +1806,7 @@ var defineButton = definer("office-ui-button", () => {
937
1806
  constructor() {
938
1807
  super();
939
1808
  const root = this.attachShadow({ mode: "open", delegatesFocus: true });
940
- attachStyles(root, controlCss(CSS7));
1809
+ attachStyles(root, controlCss(CSS10));
941
1810
  this.button = this.ownerDocument.createElement("button");
942
1811
  this.button.type = "button";
943
1812
  this.button.setAttribute("part", "button");
@@ -997,33 +1866,44 @@ var defineButton = definer("office-ui-button", () => {
997
1866
  // src/checkable.ts
998
1867
  var CHECK_SVG = '<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m3 8 3.2 3.2L13 4.5"/></svg>';
999
1868
  var CHECKBOX_CSS = `
1000
- :host { display: inline-grid; box-sizing: border-box; width: 16px; height: 16px; flex: none;
1001
- place-items: center; border: 1px solid var(--office-border, #d1d5db); border-radius: 3px;
1002
- background: var(--office-background, #fff); color: var(--office-accent-foreground, #fff);
1003
- cursor: pointer; vertical-align: middle; }
1004
- :host([checked]) { border-color: var(--office-accent, #2563eb); background: var(--office-accent, #2563eb); }
1869
+ :host { display: inline-grid; box-sizing: border-box; width: var(--office-checkbox-size, 16px); height: var(--office-checkbox-size, 16px);
1870
+ flex: none; place-items: center; border: 1px solid var(--office-checkbox-border, var(--office-border, #d1d5db));
1871
+ border-radius: var(--office-checkbox-radius, 3px); background: var(--office-checkbox-background, var(--office-background, #fff));
1872
+ color: var(--office-checkbox-accent-foreground, var(--office-accent-foreground, #fff)); cursor: pointer; vertical-align: middle; }
1873
+ :host([checked]) { border-color: var(--office-checkbox-accent, var(--office-accent, #2563eb));
1874
+ background: var(--office-checkbox-accent, var(--office-accent, #2563eb)); }
1005
1875
  :host(:focus-visible) { outline: 2px solid var(--office-ring, #2563eb); outline-offset: 2px; }
1006
1876
  :host([disabled]) { opacity: .5; cursor: not-allowed; }
1007
1877
  svg { display: none; width: 12px; height: 12px; }
1008
1878
  :host([checked]) svg { display: block; }
1009
- @media (pointer: coarse), (max-width: 767px) { :host { width: 22px; height: 22px; } svg { width: 16px; height: 16px; } }
1879
+ @media (pointer: coarse), (max-width: 767px) {
1880
+ :host { width: var(--office-checkbox-size-touch, 22px); height: var(--office-checkbox-size-touch, 22px); }
1881
+ svg { width: 16px; height: 16px; }
1882
+ }
1010
1883
  @media (forced-colors: active) {
1011
1884
  :host { border-color: CanvasText; background: Canvas; color: CanvasText; forced-color-adjust: auto; }
1012
1885
  :host([checked]) { border-color: Highlight; background: Highlight; color: HighlightText; }
1013
1886
  }
1014
1887
  `;
1015
1888
  var SWITCH_CSS = `
1016
- :host { display: inline-block; box-sizing: border-box; position: relative; width: 32px; height: 18px;
1017
- flex: none; border: 1px solid var(--office-border, #d1d5db); border-radius: 9px;
1018
- background: var(--office-surface, #f3f4f6); cursor: pointer; vertical-align: middle; }
1019
- :host::after { content: ""; position: absolute; top: 2px; left: 2px; width: 12px; height: 12px;
1020
- border-radius: 50%; background: var(--office-foreground, #1f2937); transition: transform .12s; }
1021
- :host([checked]) { border-color: var(--office-accent, #2563eb); background: var(--office-accent, #2563eb); }
1022
- :host([checked])::after { transform: translateX(14px); background: var(--office-accent-foreground, #fff); }
1889
+ :host { --_w: var(--office-switch-width, 32px); --_h: var(--office-switch-height, 18px);
1890
+ --_b: var(--office-switch-border-width, 1px); --_k: var(--office-switch-knob-size, 12px);
1891
+ --_o: var(--office-switch-knob-offset, 2px);
1892
+ display: inline-block; box-sizing: border-box; position: relative; width: var(--_w); height: var(--_h);
1893
+ flex: none; border: var(--_b) solid var(--office-switch-border, var(--office-border, #d1d5db)); border-radius: 999px;
1894
+ background: var(--office-switch-track, var(--office-surface, #f3f4f6)); cursor: pointer; vertical-align: middle;
1895
+ touch-action: manipulation; transition: background-color .15s; }
1896
+ :host::after { content: ""; position: absolute; top: calc((var(--_h) - 2 * var(--_b) - var(--_k)) / 2); left: var(--_o);
1897
+ width: var(--_k); height: var(--_k); border-radius: 50%; background: var(--office-switch-thumb, var(--office-foreground, #1f2937));
1898
+ box-shadow: 0 1px 2px rgb(0 0 0 / .3); transition: transform .15s; }
1899
+ :host([checked]) { border-color: var(--office-switch-track-on, var(--office-accent, #2563eb));
1900
+ background: var(--office-switch-track-on, var(--office-accent, #2563eb)); }
1901
+ :host([checked])::after { transform: translateX(var(--office-switch-knob-travel, calc(var(--_w) - var(--_k) - 2 * var(--_o) - 2 * var(--_b))));
1902
+ background: var(--office-switch-thumb-on, var(--office-accent-foreground, #fff)); }
1023
1903
  :host(:focus-visible) { outline: 2px solid var(--office-ring, #2563eb); outline-offset: 2px; }
1024
1904
  :host([disabled]) { opacity: .5; cursor: not-allowed; }
1025
1905
  svg { display: none; }
1026
- @media (pointer: coarse), (max-width: 767px) { :host { min-height: 24px; width: 44px; height: 24px; border-radius: 12px; } }
1906
+ @media (pointer: coarse), (max-width: 767px) { :host { --_w: var(--office-switch-width-touch, 44px); --_h: var(--office-switch-height-touch, 24px); --_k: var(--office-switch-knob-size-touch, 18px); } }
1027
1907
  @media (forced-colors: active) {
1028
1908
  :host { border-color: CanvasText; background: Canvas; forced-color-adjust: none; }
1029
1909
  :host::after { background: CanvasText; }
@@ -1112,7 +1992,7 @@ var defineCheckbox = definer(
1112
1992
  var defineSwitch = definer("office-ui-switch", makeCheckable("switch", SWITCH_CSS));
1113
1993
 
1114
1994
  // src/dialog.ts
1115
- var CSS8 = `
1995
+ var CSS11 = `
1116
1996
  :host { display: none; position: fixed; inset: 0; z-index: 1000; align-items: center; justify-content: center; }
1117
1997
  :host([open]) { display: flex; }
1118
1998
  .backdrop { position: absolute; inset: 0; background: rgb(0 0 0 / .4); }
@@ -1145,7 +2025,7 @@ var defineDialog = definer("office-ui-dialog", () => {
1145
2025
  super();
1146
2026
  const doc = this.ownerDocument;
1147
2027
  const root = this.attachShadow({ mode: "open" });
1148
- attachStyles(root, controlCss(CSS8));
2028
+ attachStyles(root, controlCss(CSS11));
1149
2029
  const backdrop = doc.createElement("div");
1150
2030
  backdrop.className = "backdrop";
1151
2031
  this.box = doc.createElement("div");
@@ -1161,9 +2041,9 @@ var defineDialog = definer("office-ui-dialog", () => {
1161
2041
  this.closeButton.type = "button";
1162
2042
  this.closeButton.className = "close";
1163
2043
  this.closeButton.setAttribute("aria-label", "Close");
1164
- const icon = createIconSvg(doc);
1165
- paintIcon(icon, "close");
1166
- this.closeButton.append(icon);
2044
+ const icon2 = createIconSvg(doc);
2045
+ paintIcon(icon2, "close");
2046
+ this.closeButton.append(icon2);
1167
2047
  header.append(this.heading, this.closeButton);
1168
2048
  const body = doc.createElement("div");
1169
2049
  body.className = "body";
@@ -1248,7 +2128,7 @@ var defineDialog = definer("office-ui-dialog", () => {
1248
2128
  });
1249
2129
 
1250
2130
  // src/command-search.ts
1251
- var CSS9 = `
2131
+ var CSS12 = `
1252
2132
  :host { display: inline-flex; align-items: center; min-width: 0; font-family: var(--office-font, system-ui, sans-serif); }
1253
2133
  .field { display: flex; align-items: center; gap: 6px; width: 100%; min-width: 0; height: var(--office-target-size, 28px);
1254
2134
  padding: 0 8px; box-sizing: border-box; border: 1px solid transparent; border-radius: var(--office-radius, 4px);
@@ -1288,7 +2168,7 @@ var defineCommandSearch = definer("office-ui-command-search", () => {
1288
2168
  super();
1289
2169
  const doc = this.ownerDocument;
1290
2170
  const root = this.attachShadow({ mode: "open", delegatesFocus: true });
1291
- attachStyles(root, controlCss(CSS9));
2171
+ attachStyles(root, controlCss(CSS12));
1292
2172
  const field = doc.createElement("div");
1293
2173
  field.className = "field";
1294
2174
  const glass = createIconSvg(doc);
@@ -1445,7 +2325,7 @@ var defineCommandSearch = definer("office-ui-command-search", () => {
1445
2325
  });
1446
2326
 
1447
2327
  // src/context-menu.ts
1448
- var CSS10 = `
2328
+ var CSS13 = `
1449
2329
  :host { display: contents; }
1450
2330
  .panel { position: fixed; inset: auto; margin: 0; min-width: 200px; padding: 4px; box-sizing: border-box;
1451
2331
  background: var(--office-background, #fff); color: var(--office-foreground, #1f2937);
@@ -1481,7 +2361,7 @@ var defineContextMenu = definer("office-ui-context-menu", () => {
1481
2361
  super();
1482
2362
  const doc = this.ownerDocument;
1483
2363
  const root = this.attachShadow({ mode: "open" });
1484
- attachStyles(root, controlCss(CSS10));
2364
+ attachStyles(root, controlCss(CSS13));
1485
2365
  this.panel = doc.createElement("div");
1486
2366
  this.panel.className = "panel";
1487
2367
  this.panel.setAttribute("role", "menu");
@@ -1891,7 +2771,7 @@ function clampOptionNumber(raw, min, max) {
1891
2771
  const parsed = Number(raw);
1892
2772
  return Number.isFinite(parsed) && raw.trim() !== "" ? Math.min(max, Math.max(min, parsed)) : void 0;
1893
2773
  }
1894
- var CSS11 = `
2774
+ var CSS14 = `
1895
2775
  :host { display: contents; }
1896
2776
  office-ui-dialog { --office-dialog-width: min(820px, 100vw); --office-dialog-max-width: min(820px, 100vw); }
1897
2777
  .layout { display: grid; grid-template-columns: 180px minmax(0, 1fr); gap: 0; min-height: min(440px, 70vh); margin: -16px; }
@@ -1940,7 +2820,7 @@ var defineOptionsDialog = definer("office-ui-options-dialog", () => {
1940
2820
  super();
1941
2821
  const doc = this.ownerDocument;
1942
2822
  const root = this.attachShadow({ mode: "open" });
1943
- attachStyles(root, controlCss(CSS11));
2823
+ attachStyles(root, controlCss(CSS14));
1944
2824
  this.#dialog = doc.createElement("office-ui-dialog");
1945
2825
  const layout = doc.createElement("div");
1946
2826
  layout.className = "layout";
@@ -2285,7 +3165,7 @@ var defineToolbar = definer("office-ui-toolbar", () => {
2285
3165
  });
2286
3166
 
2287
3167
  // src/select.ts
2288
- var CSS12 = `
3168
+ var CSS15 = `
2289
3169
  :host { display: inline-block; position: relative; vertical-align: middle; }
2290
3170
  button { box-sizing: border-box; display: flex; align-items: center; justify-content: space-between; gap: 8px;
2291
3171
  width: 100%; min-height: var(--office-target-size, 28px); padding: 0 8px; font: inherit; font-size: 12px;
@@ -2324,7 +3204,7 @@ var defineSelect = definer("office-ui-select", () => {
2324
3204
  super();
2325
3205
  const doc = this.ownerDocument;
2326
3206
  const root = this.attachShadow({ mode: "open", delegatesFocus: true });
2327
- attachStyles(root, controlCss(CSS12));
3207
+ attachStyles(root, controlCss(CSS15));
2328
3208
  this.trigger = doc.createElement("button");
2329
3209
  this.trigger.type = "button";
2330
3210
  this.trigger.setAttribute("role", "combobox");
@@ -2575,7 +3455,7 @@ var defineStatusItem = definer("office-ui-status-item", () => {
2575
3455
  });
2576
3456
 
2577
3457
  // src/tab-strip.ts
2578
- var CSS13 = `
3458
+ var CSS16 = `
2579
3459
  :host { display: flex; align-items: stretch; min-width: 0; min-height: 28px; gap: 2px; padding: 0 6px;
2580
3460
  background: var(--office-surface, #f3f4f6); color: var(--office-muted-foreground, #6b7280);
2581
3461
  border-top: 1px solid var(--office-border, #d1d5db); font-size: 12px;
@@ -2622,15 +3502,15 @@ var defineTabStrip = definer("office-ui-tab-strip", () => {
2622
3502
  super();
2623
3503
  const doc = this.ownerDocument;
2624
3504
  const root = this.attachShadow({ mode: "open" });
2625
- attachStyles(root, controlCss(CSS13));
2626
- const step = (name, icon) => {
3505
+ attachStyles(root, controlCss(CSS16));
3506
+ const step = (name, icon2) => {
2627
3507
  const button = doc.createElement("button");
2628
3508
  button.type = "button";
2629
3509
  button.className = "step";
2630
3510
  button.setAttribute("aria-label", name);
2631
3511
  button.title = name;
2632
3512
  const svg = createIconSvg(doc);
2633
- paintIcon(svg, icon);
3513
+ paintIcon(svg, icon2);
2634
3514
  button.append(svg);
2635
3515
  return button;
2636
3516
  };
@@ -2761,7 +3641,7 @@ var defineTabStrip = definer("office-ui-tab-strip", () => {
2761
3641
  });
2762
3642
 
2763
3643
  // src/zoom-slider.ts
2764
- var CSS14 = `
3644
+ var CSS17 = `
2765
3645
  :host { display: inline-flex; align-items: center; gap: 2px; font-size: 11px;
2766
3646
  color: var(--office-foreground, #1f2937); font-family: var(--office-font, system-ui, sans-serif); }
2767
3647
  button { box-sizing: border-box; display: inline-grid; place-items: center; min-width: var(--office-target-size, 24px);
@@ -2797,7 +3677,7 @@ var defineZoomSlider = definer("office-ui-zoom-slider", () => {
2797
3677
  super();
2798
3678
  const doc = this.ownerDocument;
2799
3679
  const root = this.attachShadow({ mode: "open" });
2800
- attachStyles(root, controlCss(CSS14));
3680
+ attachStyles(root, controlCss(CSS17));
2801
3681
  const button = (name, text2) => {
2802
3682
  const element = doc.createElement("button");
2803
3683
  element.type = "button";
@@ -3064,10 +3944,17 @@ var CONTROL_DEFINERS = [
3064
3944
  defineFindBar,
3065
3945
  defineRuler,
3066
3946
  defineBackstage,
3067
- definePrintPreview
3947
+ definePrintPreview,
3948
+ defineRadio,
3949
+ defineSearchField,
3950
+ defineRibbonToggle,
3951
+ defineDialogFooter,
3952
+ defineToasts,
3953
+ defineReadOnlyBanner,
3954
+ definePasteOptions
3068
3955
  ];
3069
3956
  function registerControls(registry) {
3070
3957
  for (const define of CONTROL_DEFINERS) define(registry);
3071
3958
  }
3072
3959
 
3073
- export { CONTROL_DEFINERS, DEFAULT_OFFICE_PROFILE, OFFICE_AVATAR_SWATCHES, OFFICE_PROFILE_STORAGE_KEY, attachKeyTips, clampOptionNumber, clearOfficeProfile, defineAccount, defineBackstage, defineButton, defineCheckbox, defineCommandSearch, defineContextMenu, defineDialog, defineFindBar, defineMenuButton, defineMenuItem, defineMenuSeparator, defineOptionsDialog, definePrintPreview, defineRibbon, defineRibbonGroup, defineRibbonStack, defineRuler, defineSelect, defineStatusBar, defineStatusItem, defineSwitch, defineTabStrip, defineToolbar, defineZoomSlider, profileInitials, readOfficeProfile, registerControls, rulerDivisions, sanitizeOfficeProfile, writeOfficeProfile };
3960
+ export { CONTROL_DEFINERS, DEFAULT_OFFICE_PROFILE, OFFICE_AVATAR_SWATCHES, OFFICE_PROFILE_STORAGE_KEY, OFFICE_TOAST_VISIBLE_LIMIT, attachKeyTips, clampOptionNumber, clearOfficeProfile, defineAccount, defineBackstage, defineButton, defineCheckbox, defineCommandSearch, defineContextMenu, defineDialog, defineDialogFooter, defineFindBar, defineMenuButton, defineMenuItem, defineMenuSeparator, defineOptionsDialog, definePasteOptions, definePrintPreview, defineRadio, defineReadOnlyBanner, defineRibbon, defineRibbonGroup, defineRibbonStack, defineRibbonToggle, defineRuler, defineSearchField, defineSelect, defineStatusBar, defineStatusItem, defineSwitch, defineTabStrip, defineToasts, defineToolbar, defineZoomSlider, profileInitials, readOfficeProfile, registerControls, rulerDivisions, sanitizeOfficeProfile, writeOfficeProfile };