ooxml-ui 0.10.1 → 0.11.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); }
@@ -18,6 +887,7 @@ nav button { border: 0; border-radius: 0; background: transparent; color: inheri
18
887
  .item:hover:enabled, .item[aria-current="page"] { background: color-mix(in srgb, #000 22%, transparent); }
19
888
  .item:disabled { opacity: .55; cursor: default; }
20
889
  nav button:focus-visible { outline: 2px solid currentColor; outline-offset: -3px; }
890
+ .items { display: flex; flex-direction: column; }
21
891
  .footer { display: flex; flex-direction: column; margin-top: auto; padding-top: 16px; }
22
892
  .body { flex: 1; min-width: 0; overflow: auto; padding: 28px 40px; }
23
893
  @media (max-width: 760px) {
@@ -25,7 +895,7 @@ nav button:focus-visible { outline: 2px solid currentColor; outline-offset: -3px
25
895
  nav { flex: none; flex-direction: row; flex-wrap: wrap; padding: 6px; }
26
896
  .back { margin: 4px; }
27
897
  .item { min-height: 44px; padding: 6px 12px; }
28
- .footer { flex-direction: row; margin-top: 0; padding-top: 0; }
898
+ .items, .footer { flex-direction: row; flex-wrap: wrap; margin-top: 0; padding-top: 0; }
29
899
  .body { padding: 16px; }
30
900
  }
31
901
  @media (forced-colors: active) { nav { border-inline-end: 1px solid CanvasText; } .item[aria-current="page"] { outline: 2px solid Highlight; } }
@@ -43,7 +913,7 @@ var defineBackstage = definer("office-ui-backstage", () => {
43
913
  super();
44
914
  const doc = this.ownerDocument;
45
915
  const root = this.attachShadow({ mode: "open" });
46
- attachStyles(root, controlCss(CSS));
916
+ attachStyles(root, controlCss(CSS4));
47
917
  this.#frame = doc.createElement("div");
48
918
  this.#frame.className = "frame";
49
919
  this.#frame.setAttribute("role", "dialog");
@@ -56,6 +926,7 @@ var defineBackstage = definer("office-ui-backstage", () => {
56
926
  this.#back.textContent = "\u2190";
57
927
  this.#back.dataset.backstage = "back";
58
928
  this.#main = doc.createElement("div");
929
+ this.#main.className = "items";
59
930
  this.#footer = doc.createElement("div");
60
931
  this.#footer.className = "footer";
61
932
  this.#nav.append(this.#back, this.#main, this.#footer);
@@ -174,7 +1045,7 @@ var defineBackstage = definer("office-ui-backstage", () => {
174
1045
  });
175
1046
 
176
1047
  // src/find-bar.ts
177
- var CSS2 = `
1048
+ var CSS5 = `
178
1049
  :host { display: flex; align-items: center; gap: 8px; min-height: 40px; padding: 4px 8px 4px 12px;
179
1050
  border-bottom: 1px solid var(--office-border, #d1d5db); background: var(--office-surface, #f3f4f6);
180
1051
  color: var(--office-foreground, #1f2937); font: 12px var(--office-font, system-ui, sans-serif); }
@@ -216,7 +1087,7 @@ var defineFindBar = definer("office-ui-find-bar", () => {
216
1087
  super();
217
1088
  const doc = this.ownerDocument;
218
1089
  const root = this.attachShadow({ mode: "open", delegatesFocus: true });
219
- attachStyles(root, controlCss(CSS2));
1090
+ attachStyles(root, controlCss(CSS5));
220
1091
  this.#region = doc.createElement("div");
221
1092
  this.#region.setAttribute("role", "search");
222
1093
  const field = doc.createElement("label");
@@ -334,7 +1205,7 @@ var defineFindBar = definer("office-ui-find-bar", () => {
334
1205
  });
335
1206
 
336
1207
  // src/print-preview.ts
337
- var CSS3 = `
1208
+ var CSS6 = `
338
1209
  :host { display: block; max-width: 420px; font: 12px var(--office-font, system-ui, sans-serif);
339
1210
  color: var(--office-foreground, #1f2937); }
340
1211
  .sheet { padding: 12px; border: 1px solid var(--office-border, #d1d5db); background: #fff;
@@ -363,7 +1234,7 @@ var definePrintPreview = definer("office-ui-print-preview", () => {
363
1234
  super();
364
1235
  const doc = this.ownerDocument;
365
1236
  const root = this.attachShadow({ mode: "open" });
366
- attachStyles(root, controlCss(CSS3));
1237
+ attachStyles(root, controlCss(CSS6));
367
1238
  this.#sheet = doc.createElement("div");
368
1239
  this.#sheet.className = "sheet";
369
1240
  this.#sheet.setAttribute("role", "img");
@@ -442,7 +1313,7 @@ var definePrintPreview = definer("office-ui-print-preview", () => {
442
1313
  });
443
1314
 
444
1315
  // src/ribbon-tabs.ts
445
- var CSS4 = `
1316
+ var CSS7 = `
446
1317
  :host { display: block; min-width: 0; }
447
1318
  .head { display: flex; align-items: stretch; min-width: 0; border-bottom: 1px solid var(--office-border, #d1d5db); }
448
1319
  .file { flex: none; min-height: var(--office-ribbon-tab-height, 35px); margin: 0 4px 0 0; padding: 6px 16px; border: 0;
@@ -486,7 +1357,7 @@ var defineRibbon = definer("office-ui-ribbon", () => {
486
1357
  super();
487
1358
  const doc = this.ownerDocument;
488
1359
  const root = this.attachShadow({ mode: "open" });
489
- attachStyles(root, controlCss(CSS4));
1360
+ attachStyles(root, controlCss(CSS7));
490
1361
  const head = doc.createElement("div");
491
1362
  head.className = "head";
492
1363
  head.setAttribute("part", "head");
@@ -608,7 +1479,7 @@ var defineRibbon = definer("office-ui-ribbon", () => {
608
1479
  });
609
1480
 
610
1481
  // src/ruler.ts
611
- var CSS5 = `
1482
+ var CSS8 = `
612
1483
  :host { display: block; box-sizing: border-box; background: var(--office-background, #fff);
613
1484
  color: var(--office-muted-foreground, #605e5c); overflow: hidden; }
614
1485
  :host(:not([orientation="vertical"])) { height: 18px; border-bottom: 1px solid var(--office-border, #d1d5db); }
@@ -627,7 +1498,7 @@ var defineRuler = definer("office-ui-ruler", () => {
627
1498
  constructor() {
628
1499
  super();
629
1500
  const root = this.attachShadow({ mode: "open" });
630
- attachStyles(root, controlCss(CSS5));
1501
+ attachStyles(root, controlCss(CSS8));
631
1502
  this.#canvas = this.ownerDocument.createElement("canvas");
632
1503
  root.append(this.#canvas);
633
1504
  }
@@ -763,7 +1634,7 @@ function clearOfficeProfile(storage = defaultStorage(), key = OFFICE_PROFILE_STO
763
1634
  } catch {
764
1635
  }
765
1636
  }
766
- var CSS6 = `
1637
+ var CSS9 = `
767
1638
  :host { display: block; font-family: var(--office-font, system-ui, sans-serif); font-size: 13px; }
768
1639
  h2 { margin: 0 0 12px; font-size: 15px; font-weight: 600; }
769
1640
  .who { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
@@ -793,7 +1664,7 @@ var defineAccount = definer("office-ui-account", () => {
793
1664
  super();
794
1665
  const doc = this.ownerDocument;
795
1666
  const root = this.attachShadow({ mode: "open" });
796
- attachStyles(root, controlCss(CSS6));
1667
+ attachStyles(root, controlCss(CSS9));
797
1668
  const heading = doc.createElement("h2");
798
1669
  heading.textContent = "User Information";
799
1670
  const who = doc.createElement("div");
@@ -894,7 +1765,7 @@ var defineAccount = definer("office-ui-account", () => {
894
1765
  });
895
1766
 
896
1767
  // src/button.ts
897
- var CSS7 = `
1768
+ var CSS10 = `
898
1769
  :host { display: inline-flex; vertical-align: middle; }
899
1770
  button { box-sizing: border-box; display: inline-flex; align-items: center; justify-content: center;
900
1771
  gap: 6px; min-width: var(--office-target-size, 28px); min-height: var(--office-target-size, 28px);
@@ -935,7 +1806,7 @@ var defineButton = definer("office-ui-button", () => {
935
1806
  constructor() {
936
1807
  super();
937
1808
  const root = this.attachShadow({ mode: "open", delegatesFocus: true });
938
- attachStyles(root, controlCss(CSS7));
1809
+ attachStyles(root, controlCss(CSS10));
939
1810
  this.button = this.ownerDocument.createElement("button");
940
1811
  this.button.type = "button";
941
1812
  this.button.setAttribute("part", "button");
@@ -1110,7 +1981,7 @@ var defineCheckbox = definer(
1110
1981
  var defineSwitch = definer("office-ui-switch", makeCheckable("switch", SWITCH_CSS));
1111
1982
 
1112
1983
  // src/dialog.ts
1113
- var CSS8 = `
1984
+ var CSS11 = `
1114
1985
  :host { display: none; position: fixed; inset: 0; z-index: 1000; align-items: center; justify-content: center; }
1115
1986
  :host([open]) { display: flex; }
1116
1987
  .backdrop { position: absolute; inset: 0; background: rgb(0 0 0 / .4); }
@@ -1143,7 +2014,7 @@ var defineDialog = definer("office-ui-dialog", () => {
1143
2014
  super();
1144
2015
  const doc = this.ownerDocument;
1145
2016
  const root = this.attachShadow({ mode: "open" });
1146
- attachStyles(root, controlCss(CSS8));
2017
+ attachStyles(root, controlCss(CSS11));
1147
2018
  const backdrop = doc.createElement("div");
1148
2019
  backdrop.className = "backdrop";
1149
2020
  this.box = doc.createElement("div");
@@ -1159,9 +2030,9 @@ var defineDialog = definer("office-ui-dialog", () => {
1159
2030
  this.closeButton.type = "button";
1160
2031
  this.closeButton.className = "close";
1161
2032
  this.closeButton.setAttribute("aria-label", "Close");
1162
- const icon = createIconSvg(doc);
1163
- paintIcon(icon, "close");
1164
- this.closeButton.append(icon);
2033
+ const icon2 = createIconSvg(doc);
2034
+ paintIcon(icon2, "close");
2035
+ this.closeButton.append(icon2);
1165
2036
  header.append(this.heading, this.closeButton);
1166
2037
  const body = doc.createElement("div");
1167
2038
  body.className = "body";
@@ -1246,7 +2117,7 @@ var defineDialog = definer("office-ui-dialog", () => {
1246
2117
  });
1247
2118
 
1248
2119
  // src/command-search.ts
1249
- var CSS9 = `
2120
+ var CSS12 = `
1250
2121
  :host { display: inline-flex; align-items: center; min-width: 0; font-family: var(--office-font, system-ui, sans-serif); }
1251
2122
  .field { display: flex; align-items: center; gap: 6px; width: 100%; min-width: 0; height: var(--office-target-size, 28px);
1252
2123
  padding: 0 8px; box-sizing: border-box; border: 1px solid transparent; border-radius: var(--office-radius, 4px);
@@ -1286,7 +2157,7 @@ var defineCommandSearch = definer("office-ui-command-search", () => {
1286
2157
  super();
1287
2158
  const doc = this.ownerDocument;
1288
2159
  const root = this.attachShadow({ mode: "open", delegatesFocus: true });
1289
- attachStyles(root, controlCss(CSS9));
2160
+ attachStyles(root, controlCss(CSS12));
1290
2161
  const field = doc.createElement("div");
1291
2162
  field.className = "field";
1292
2163
  const glass = createIconSvg(doc);
@@ -1443,7 +2314,7 @@ var defineCommandSearch = definer("office-ui-command-search", () => {
1443
2314
  });
1444
2315
 
1445
2316
  // src/context-menu.ts
1446
- var CSS10 = `
2317
+ var CSS13 = `
1447
2318
  :host { display: contents; }
1448
2319
  .panel { position: fixed; inset: auto; margin: 0; min-width: 200px; padding: 4px; box-sizing: border-box;
1449
2320
  background: var(--office-background, #fff); color: var(--office-foreground, #1f2937);
@@ -1479,7 +2350,7 @@ var defineContextMenu = definer("office-ui-context-menu", () => {
1479
2350
  super();
1480
2351
  const doc = this.ownerDocument;
1481
2352
  const root = this.attachShadow({ mode: "open" });
1482
- attachStyles(root, controlCss(CSS10));
2353
+ attachStyles(root, controlCss(CSS13));
1483
2354
  this.panel = doc.createElement("div");
1484
2355
  this.panel.className = "panel";
1485
2356
  this.panel.setAttribute("role", "menu");
@@ -1889,7 +2760,7 @@ function clampOptionNumber(raw, min, max) {
1889
2760
  const parsed = Number(raw);
1890
2761
  return Number.isFinite(parsed) && raw.trim() !== "" ? Math.min(max, Math.max(min, parsed)) : void 0;
1891
2762
  }
1892
- var CSS11 = `
2763
+ var CSS14 = `
1893
2764
  :host { display: contents; }
1894
2765
  office-ui-dialog { --office-dialog-width: min(820px, 100vw); --office-dialog-max-width: min(820px, 100vw); }
1895
2766
  .layout { display: grid; grid-template-columns: 180px minmax(0, 1fr); gap: 0; min-height: min(440px, 70vh); margin: -16px; }
@@ -1938,7 +2809,7 @@ var defineOptionsDialog = definer("office-ui-options-dialog", () => {
1938
2809
  super();
1939
2810
  const doc = this.ownerDocument;
1940
2811
  const root = this.attachShadow({ mode: "open" });
1941
- attachStyles(root, controlCss(CSS11));
2812
+ attachStyles(root, controlCss(CSS14));
1942
2813
  this.#dialog = doc.createElement("office-ui-dialog");
1943
2814
  const layout = doc.createElement("div");
1944
2815
  layout.className = "layout";
@@ -2283,7 +3154,7 @@ var defineToolbar = definer("office-ui-toolbar", () => {
2283
3154
  });
2284
3155
 
2285
3156
  // src/select.ts
2286
- var CSS12 = `
3157
+ var CSS15 = `
2287
3158
  :host { display: inline-block; position: relative; vertical-align: middle; }
2288
3159
  button { box-sizing: border-box; display: flex; align-items: center; justify-content: space-between; gap: 8px;
2289
3160
  width: 100%; min-height: var(--office-target-size, 28px); padding: 0 8px; font: inherit; font-size: 12px;
@@ -2322,7 +3193,7 @@ var defineSelect = definer("office-ui-select", () => {
2322
3193
  super();
2323
3194
  const doc = this.ownerDocument;
2324
3195
  const root = this.attachShadow({ mode: "open", delegatesFocus: true });
2325
- attachStyles(root, controlCss(CSS12));
3196
+ attachStyles(root, controlCss(CSS15));
2326
3197
  this.trigger = doc.createElement("button");
2327
3198
  this.trigger.type = "button";
2328
3199
  this.trigger.setAttribute("role", "combobox");
@@ -2573,7 +3444,7 @@ var defineStatusItem = definer("office-ui-status-item", () => {
2573
3444
  });
2574
3445
 
2575
3446
  // src/tab-strip.ts
2576
- var CSS13 = `
3447
+ var CSS16 = `
2577
3448
  :host { display: flex; align-items: stretch; min-width: 0; min-height: 28px; gap: 2px; padding: 0 6px;
2578
3449
  background: var(--office-surface, #f3f4f6); color: var(--office-muted-foreground, #6b7280);
2579
3450
  border-top: 1px solid var(--office-border, #d1d5db); font-size: 12px;
@@ -2620,15 +3491,15 @@ var defineTabStrip = definer("office-ui-tab-strip", () => {
2620
3491
  super();
2621
3492
  const doc = this.ownerDocument;
2622
3493
  const root = this.attachShadow({ mode: "open" });
2623
- attachStyles(root, controlCss(CSS13));
2624
- const step = (name, icon) => {
3494
+ attachStyles(root, controlCss(CSS16));
3495
+ const step = (name, icon2) => {
2625
3496
  const button = doc.createElement("button");
2626
3497
  button.type = "button";
2627
3498
  button.className = "step";
2628
3499
  button.setAttribute("aria-label", name);
2629
3500
  button.title = name;
2630
3501
  const svg = createIconSvg(doc);
2631
- paintIcon(svg, icon);
3502
+ paintIcon(svg, icon2);
2632
3503
  button.append(svg);
2633
3504
  return button;
2634
3505
  };
@@ -2759,7 +3630,7 @@ var defineTabStrip = definer("office-ui-tab-strip", () => {
2759
3630
  });
2760
3631
 
2761
3632
  // src/zoom-slider.ts
2762
- var CSS14 = `
3633
+ var CSS17 = `
2763
3634
  :host { display: inline-flex; align-items: center; gap: 2px; font-size: 11px;
2764
3635
  color: var(--office-foreground, #1f2937); font-family: var(--office-font, system-ui, sans-serif); }
2765
3636
  button { box-sizing: border-box; display: inline-grid; place-items: center; min-width: var(--office-target-size, 24px);
@@ -2795,7 +3666,7 @@ var defineZoomSlider = definer("office-ui-zoom-slider", () => {
2795
3666
  super();
2796
3667
  const doc = this.ownerDocument;
2797
3668
  const root = this.attachShadow({ mode: "open" });
2798
- attachStyles(root, controlCss(CSS14));
3669
+ attachStyles(root, controlCss(CSS17));
2799
3670
  const button = (name, text2) => {
2800
3671
  const element = doc.createElement("button");
2801
3672
  element.type = "button";
@@ -3062,10 +3933,17 @@ var CONTROL_DEFINERS = [
3062
3933
  defineFindBar,
3063
3934
  defineRuler,
3064
3935
  defineBackstage,
3065
- definePrintPreview
3936
+ definePrintPreview,
3937
+ defineRadio,
3938
+ defineSearchField,
3939
+ defineRibbonToggle,
3940
+ defineDialogFooter,
3941
+ defineToasts,
3942
+ defineReadOnlyBanner,
3943
+ definePasteOptions
3066
3944
  ];
3067
3945
  function registerControls(registry) {
3068
3946
  for (const define of CONTROL_DEFINERS) define(registry);
3069
3947
  }
3070
3948
 
3071
- 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 };
3949
+ 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 };