ooxml-ui 0.22.0 → 0.24.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.
@@ -23,6 +23,8 @@ export interface OfficeStatusButton {
23
23
  text?: string | undefined;
24
24
  pressed?: boolean | undefined;
25
25
  hidden?: boolean | undefined;
26
+ /** Offered but unavailable (a view the product does not provide yet). */
27
+ disabled?: boolean | undefined;
26
28
  }
27
29
  /** Everything the controlled bar shows, already translated. Absent parts are not rendered. */
28
30
  export interface OfficeStatusBarState {
@@ -1,8 +1,8 @@
1
1
  import { createIconSvg, paintIcon, getIcon } from './chunk-HZ422LTR.js';
2
- import { initialsOf } from './chunk-E47762NY.js';
3
- import { OfficeElement, controlStyles, definer, valueOn, flag, present, withTokens, triState } from './chunk-5A4REH6T.js';
2
+ import { initialsOf } from './chunk-XQWRKHC2.js';
3
+ import { OfficeElement, controlStyles, definer, valueOn, flag, present, triState, withTokens } from './chunk-PCZJV6HQ.js';
4
4
  import { tok, OFFICE_TOKENS } from './chunk-HSJH6SUW.js';
5
- import { html, LitElement, render, nothing, svg } from 'lit';
5
+ import { html, LitElement, nothing, render, svg } from 'lit';
6
6
  import { ifDefined } from 'lit/directives/if-defined.js';
7
7
  import { repeat } from 'lit/directives/repeat.js';
8
8
  import { unsafeStatic, html as html$1 } from 'lit/static-html.js';
@@ -489,6 +489,89 @@ var OfficeUiRadio = class extends OfficeElement {
489
489
  }
490
490
  };
491
491
  var defineRadio = definer("office-ui-radio", () => OfficeUiRadio);
492
+ var OfficeUiCheckable = class extends OfficeElement {
493
+ static formAssociated = true;
494
+ static properties = {
495
+ checked: flag,
496
+ disabled: flag,
497
+ value: valueOn
498
+ };
499
+ internals;
500
+ defaultChecked = false;
501
+ constructor() {
502
+ super();
503
+ this.checked = false;
504
+ this.disabled = false;
505
+ this.value = "on";
506
+ try {
507
+ this.internals = this.attachInternals();
508
+ } catch {
509
+ this.internals = void 0;
510
+ }
511
+ this.addEventListener("click", (event) => {
512
+ if (present(this.disabled)) event.preventDefault();
513
+ else this.toggle();
514
+ });
515
+ this.addEventListener("keydown", (event) => {
516
+ const toggles = event.key === " " || this.semantics === "switch" && event.key === "Enter";
517
+ if (!toggles || present(this.disabled)) return;
518
+ event.preventDefault();
519
+ this.toggle();
520
+ });
521
+ }
522
+ connectedCallback() {
523
+ this.defaultChecked = present(this.checked);
524
+ super.connectedCallback();
525
+ }
526
+ formResetCallback() {
527
+ this.checked = this.defaultChecked;
528
+ }
529
+ formDisabledCallback(disabled) {
530
+ this.disabled = disabled;
531
+ }
532
+ toggle() {
533
+ this.checked = !present(this.checked);
534
+ this.dispatchEvent(new Event("input", { bubbles: true, composed: true }));
535
+ this.dispatchEvent(new Event("change", { bubbles: true, composed: true }));
536
+ }
537
+ /** The host carries the semantics: role, state, tab stop and form value. */
538
+ willUpdate() {
539
+ const checked = present(this.checked);
540
+ const disabled = present(this.disabled);
541
+ this.setAttribute("role", this.semantics);
542
+ this.setAttribute("aria-checked", String(checked));
543
+ this.setAttribute("aria-disabled", String(disabled));
544
+ this.setAttribute("tabindex", disabled ? "-1" : "0");
545
+ this.internals?.setFormValue?.(checked && !disabled ? this.value : null);
546
+ }
547
+ /** The tick, shown through CSS when `checked`. */
548
+ renderCheck() {
549
+ return html`<svg
550
+ viewBox="0 0 16 16"
551
+ fill="none"
552
+ stroke="currentColor"
553
+ stroke-width="2"
554
+ stroke-linecap="round"
555
+ stroke-linejoin="round"
556
+ aria-hidden="true"
557
+ >
558
+ <path d="m3 8 3.2 3.2L13 4.5"></path>
559
+ </svg>`;
560
+ }
561
+ };
562
+
563
+ // raw-css:/home/runner/work/ooxml/ooxml/packages/ui/src/form/checkbox.css?raw
564
+ var checkbox_default = ":host {\n display: inline-grid;\n box-sizing: border-box;\n width: var(--office-checkbox-size);\n height: var(--office-checkbox-size);\n flex: none;\n place-items: center;\n border: var(--office-border-width) solid var(--office-checkbox-border);\n border-radius: var(--office-checkbox-radius);\n background: var(--office-checkbox-background);\n color: var(--office-checkbox-accent-foreground);\n cursor: pointer;\n vertical-align: middle;\n}\n:host([checked]) {\n border-color: var(--office-checkbox-accent);\n background: var(--office-checkbox-accent);\n}\n:host(:focus-visible) {\n outline: var(--office-focus-width) solid var(--office-ring);\n outline-offset: var(--office-focus-offset);\n}\n:host([disabled]) {\n opacity: 0.5;\n cursor: not-allowed;\n}\nsvg {\n display: none;\n width: var(--office-icon-size-sm);\n height: var(--office-icon-size-sm);\n}\n:host([checked]) svg {\n display: block;\n}\n\n@media (pointer: coarse), (max-width: 767px) {\n :host {\n width: var(--office-checkbox-size-touch);\n height: var(--office-checkbox-size-touch);\n }\n svg {\n width: var(--office-icon-size-md);\n height: var(--office-icon-size-md);\n }\n}\n@media (forced-colors: active) {\n :host {\n border-color: CanvasText;\n background: Canvas;\n color: CanvasText;\n forced-color-adjust: auto;\n }\n :host([checked]) {\n border-color: Highlight;\n background: Highlight;\n color: HighlightText;\n }\n}\n";
565
+
566
+ // src/form/checkbox.ts
567
+ var OfficeUiCheckbox = class extends OfficeUiCheckable {
568
+ static styles = controlStyles(checkbox_default);
569
+ semantics = "checkbox";
570
+ render() {
571
+ return this.renderCheck();
572
+ }
573
+ };
574
+ var defineCheckbox = definer("office-ui-checkbox", () => OfficeUiCheckbox);
492
575
 
493
576
  // raw-css:/home/runner/work/ooxml/ooxml/packages/ui/src/ribbon/ribbon-toggle.css?raw
494
577
  var ribbon_toggle_default = ":host {\n display: block;\n}\nlabel {\n display: flex;\n align-items: center;\n gap: var(--office-space-1);\n min-height: var(--office-ribbon-row-height);\n padding: 0 var(--office-space-1);\n color: var(--office-foreground);\n font: inherit;\n font-size: var(--office-font-size-sm);\n white-space: nowrap;\n cursor: pointer;\n}\n:host([disabled]) label {\n color: var(--office-muted-foreground);\n cursor: not-allowed;\n}\n\n@media (pointer: coarse), (max-width: 767px) {\n label {\n min-height: var(--office-target-size-touch);\n font-size: var(--office-font-size-sm);\n }\n}\n";
@@ -552,7 +635,9 @@ var OfficeUiRibbonToggle = class extends OfficeElement {
552
635
  `;
553
636
  }
554
637
  };
555
- var defineRibbonToggle = definer("office-ui-ribbon-toggle", () => OfficeUiRibbonToggle);
638
+ var defineRibbonToggle = definer("office-ui-ribbon-toggle", () => OfficeUiRibbonToggle, [
639
+ defineCheckbox
640
+ ]);
556
641
 
557
642
  // raw-css:/home/runner/work/ooxml/ooxml/packages/ui/src/form/search-field.css?raw
558
643
  var search_field_default = "/* Tokens: --office-field-*. */\n:host {\n display: flex;\n align-items: center;\n gap: var(--office-space-2);\n box-sizing: border-box;\n width: 100%;\n height: var(--office-field-height-lg);\n padding: 0 var(--office-space-3);\n border: var(--office-border-width) solid var(--office-field-border);\n border-radius: var(--office-field-radius);\n background: var(--office-field-background);\n color: var(--office-field-placeholder);\n font: inherit;\n}\n:host(:focus-within) {\n border-color: var(--office-field-border-focus);\n}\n:host([variant='titlebar']) {\n height: var(--office-field-height);\n gap: var(--office-space-1-5);\n padding-inline: var(--office-space-3-5);\n border-color: var(--office-border);\n border-radius: var(--office-radius-md);\n background: var(--office-background);\n}\n:host([variant='titlebar']:focus-within) {\n border-color: var(--office-field-border-focus);\n color: var(--office-foreground);\n}\n:host([disabled]) {\n opacity: 0.5;\n cursor: not-allowed;\n}\nsvg {\n width: var(--office-icon-size-md);\n height: var(--office-icon-size-md);\n flex: none;\n}\n:host([variant='titlebar']) svg {\n width: var(--office-icon-size);\n height: var(--office-icon-size);\n}\ninput {\n min-width: 0;\n width: 100%;\n height: 100%;\n flex: 1;\n padding: 0;\n border: 0;\n outline: 0;\n background: transparent;\n color: var(--office-field-foreground);\n font: inherit;\n font-size: var(--office-font-size);\n}\n:host([variant='titlebar']) input {\n font-size: var(--office-font-size-xs);\n color: var(--office-foreground);\n}\ninput::placeholder {\n color: var(--office-field-placeholder);\n opacity: 0.8;\n}\ninput::-webkit-search-cancel-button {\n display: none;\n}\n\n@media (forced-colors: active) {\n :host {\n border-color: CanvasText;\n background: Canvas;\n color: CanvasText;\n }\n :host(:focus-within) {\n outline: var(--office-focus-width) solid Highlight;\n outline-offset: var(--office-focus-offset);\n }\n input {\n color: CanvasText;\n }\n}\n";
@@ -1110,6 +1195,201 @@ var OfficeUiRibbon = class extends OfficeElement {
1110
1195
  };
1111
1196
  var defineRibbon = definer("office-ui-ribbon", () => OfficeUiRibbon);
1112
1197
 
1198
+ // raw-css:/home/runner/work/ooxml/ooxml/packages/ui/src/ribbon/button.css?raw
1199
+ var button_default = ":host {\n display: inline-flex;\n vertical-align: middle;\n}\nbutton {\n box-sizing: border-box;\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--office-space-1-5);\n min-width: var(--office-target-size);\n min-height: var(--office-target-size);\n padding: 0 var(--office-space-2);\n border: var(--office-border-width) solid transparent;\n border-radius: var(--office-radius);\n background: transparent;\n color: var(--office-foreground);\n font: inherit;\n font-size: var(--office-font-size-sm);\n cursor: pointer;\n white-space: nowrap;\n}\n:host([variant='stacked']) button {\n flex-direction: column;\n padding: var(--office-space-1) var(--office-space-2);\n}\nbutton:hover:not(:disabled) {\n background: var(--office-surface);\n}\nbutton:active:not(:disabled) {\n background: var(--office-selected);\n}\nbutton:focus-visible {\n outline: var(--office-focus-width) solid var(--office-ring);\n outline-offset: calc(var(--office-focus-offset) / 2);\n}\nbutton[aria-pressed='true'],\nbutton[aria-expanded='true'] {\n border-color: var(--office-accent);\n background: var(--office-surface);\n}\n:host([active]) button {\n background: var(--office-command-active);\n color: var(--office-accent);\n}\nbutton:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\nsvg {\n width: var(--office-icon-size-ml);\n height: var(--office-icon-size-ml);\n flex: none;\n color: var(--office-command-icon-color);\n fill: none;\n stroke: currentColor;\n stroke-width: var(--office-icon-stroke);\n stroke-linecap: round;\n stroke-linejoin: round;\n}\nsvg.glyph:not([data-painted]) {\n display: none;\n}\n.label[hidden],\n.caret[hidden],\n.badge[hidden] {\n display: none;\n}\n/* Office trails a menu chevron after the last line of the label. */\n.caret {\n display: inline-block;\n width: var(--office-icon-size-xs);\n height: var(--office-icon-size-xs);\n margin-inline-start: var(--office-space-0);\n vertical-align: middle;\n color: var(--office-muted-foreground);\n}\n.badge {\n position: absolute;\n top: 0;\n inset-inline-end: 0;\n padding: 0 var(--office-space-0);\n border-radius: var(--office-radius-full);\n background: var(--office-accent);\n color: var(--office-accent-foreground);\n font-size: var(--office-font-size-3xs);\n}\n\n/* Large ribbon command: a big glyph above a two-line label. */\n:host([size='large']) button {\n flex-direction: column;\n justify-content: flex-start;\n gap: var(--office-space-0);\n min-width: var(--office-command-large-min-width);\n max-width: var(--office-command-large-max-width);\n height: var(--office-command-large-height);\n padding: var(--office-space-0) var(--office-space-1);\n border: 0;\n white-space: normal;\n text-align: center;\n line-height: var(--office-line-height-tight);\n}\n:host([size='large']) svg.glyph {\n width: var(--office-command-large-icon);\n height: var(--office-command-large-icon);\n}\n\n/* Small ribbon command: icon and label in one row. */\n:host([size='small']) button {\n justify-content: flex-start;\n min-width: 0;\n height: var(--office-control-height);\n min-height: var(--office-control-height);\n padding: 0 var(--office-space-1-5);\n border: 0;\n text-align: start;\n}\n:host([size='small']) svg.glyph {\n width: var(--office-command-small-icon);\n height: var(--office-command-small-icon);\n}\n\n/* Tall, label-less tool tiles (pens, erasers). */\n:host([icon-only][tall]) button {\n min-width: var(--office-command-tall-min-width);\n height: var(--office-command-tall-height);\n padding: var(--office-space-1);\n}\n:host([icon-only][tall]) svg.glyph {\n width: var(--office-command-tall-icon);\n height: var(--office-command-tall-icon);\n}\n:host([icon-only][tall][active]) button {\n box-shadow: inset 0 0 0 var(--office-border-width) var(--office-accent);\n}\n\n@media (pointer: coarse), (max-width: 767px) {\n :host([size='small']) button {\n min-height: var(--office-target-size-touch);\n }\n :host([icon-only]) button {\n min-width: var(--office-target-size-touch);\n }\n}\n@media (forced-colors: active) {\n button {\n border-color: ButtonText;\n color: ButtonText;\n background: ButtonFace;\n }\n svg {\n color: ButtonText;\n }\n button:disabled {\n color: GrayText;\n border-color: GrayText;\n }\n button[aria-pressed='true'],\n button[aria-expanded='true'],\n :host([active]) button {\n background: Highlight;\n color: HighlightText;\n }\n}\n";
1200
+
1201
+ // src/ribbon/button.ts
1202
+ var asAttribute = (value) => value === void 0 ? void 0 : String(value);
1203
+ var OfficeUiButton = class extends OfficeElement {
1204
+ static requestEvent = "office-command";
1205
+ static idAttribute = "command";
1206
+ static detailKey = "command";
1207
+ static shadowRootOptions = { ...LitElement.shadowRootOptions, delegatesFocus: true };
1208
+ static styles = controlStyles(button_default);
1209
+ static properties = { disabled: flag, pressed: triState };
1210
+ /** Everything else is an attribute, as it always was (see `OfficeElement.watched`). */
1211
+ static watched = [
1212
+ "label",
1213
+ "icon",
1214
+ "command",
1215
+ "badge",
1216
+ "caret",
1217
+ "keyshortcuts",
1218
+ "size",
1219
+ "variant",
1220
+ "active",
1221
+ "tall",
1222
+ "icon-only",
1223
+ "expanded",
1224
+ "title"
1225
+ ];
1226
+ constructor() {
1227
+ super();
1228
+ this.disabled = false;
1229
+ }
1230
+ /** The registered icon to draw; a product subclass may map names onto its glyph set. */
1231
+ iconName() {
1232
+ return this.getAttribute("icon");
1233
+ }
1234
+ /** The tooltip: `title`, else the label of an icon-only button; a product may always show it. */
1235
+ tooltip(label, iconOnly) {
1236
+ return this.getAttribute("title") ?? (iconOnly ? label : "");
1237
+ }
1238
+ /** Whether the trailing menu chevron shows. */
1239
+ showsCaret() {
1240
+ const caret = this.getAttribute("caret");
1241
+ return caret !== null && caret !== "false";
1242
+ }
1243
+ onKeydown(event) {
1244
+ if ((event.key === " " || event.key === "Enter") && !event.ctrlKey && !event.metaKey && !event.altKey)
1245
+ event.stopPropagation();
1246
+ }
1247
+ onClick() {
1248
+ const { requestEvent, idAttribute, detailKey } = this.constructor;
1249
+ const id = this.getAttribute(idAttribute);
1250
+ if (!present(this.disabled) && id) this.fire(requestEvent, { [detailKey]: id });
1251
+ }
1252
+ render() {
1253
+ const label = this.getAttribute("label") ?? "";
1254
+ const iconOnly = this.hasAttribute("icon-only");
1255
+ const badge = this.getAttribute("badge") ?? "";
1256
+ const expanded = this.getAttribute("expanded");
1257
+ const tooltip = this.tooltip(label, iconOnly);
1258
+ return html`<button
1259
+ part="button"
1260
+ type="button"
1261
+ ?disabled=${present(this.disabled)}
1262
+ title=${tooltip || nothing}
1263
+ aria-label=${ifDefined(iconOnly && label ? label : void 0)}
1264
+ aria-keyshortcuts=${ifDefined(this.getAttribute("keyshortcuts") || void 0)}
1265
+ aria-pressed=${ifDefined(asAttribute(this.pressed))}
1266
+ aria-expanded=${ifDefined(expanded === null ? void 0 : String(expanded !== "false"))}
1267
+ @click=${this.onClick}
1268
+ @keydown=${this.onKeydown}
1269
+ >${glyph(this.iconName())}<span class="label" ?hidden=${iconOnly}
1270
+ >${label}${glyph("chevronDown", "caret", !this.showsCaret())}</span
1271
+ ><span class="badge" aria-hidden="true" ?hidden=${!badge}>${badge}</span></button
1272
+ >`;
1273
+ }
1274
+ };
1275
+ var defineButton = definer("office-ui-button", () => OfficeUiButton);
1276
+
1277
+ // raw-css:/home/runner/work/ooxml/ooxml/packages/ui/src/ribbon/ribbon-group.css?raw
1278
+ var ribbon_group_default = ":host {\n display: inline-flex;\n flex: none;\n align-self: stretch;\n}\n.group {\n position: relative;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n justify-content: space-between;\n min-height: var(--office-ribbon-group-height);\n padding: var(--office-ribbon-group-padding);\n}\n/* Office draws a hairline between groups; a product may stop it short of the top and bottom. */\n.group::after {\n content: '';\n position: absolute;\n top: var(--office-ribbon-separator-inset);\n bottom: var(--office-ribbon-separator-inset);\n inset-inline-end: 0;\n width: var(--office-border-width);\n background: var(--office-ribbon-separator);\n}\n:host(:last-child) .group::after {\n content: none;\n}\n.row {\n display: flex;\n align-items: flex-start;\n gap: var(--office-space-1);\n flex: 1;\n}\n/* One-line groups centre their commands on the whole group box. */\n:host([data-compact-row]) .row {\n align-items: center;\n}\n/* Several small drop-down galleries stack in columns of three. */\n:host([data-stack]) .row {\n flex-direction: column;\n align-items: stretch;\n align-content: flex-start;\n flex-wrap: wrap;\n max-height: var(--office-ribbon-stack-max-height);\n gap: var(--office-space-0);\n}\n::slotted(*) {\n flex-shrink: 0;\n}\n.foot {\n position: relative;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: var(--office-ribbon-caption-padding);\n}\n.caption {\n color: var(--office-muted-foreground);\n font-size: var(--office-ribbon-caption-size);\n line-height: var(--office-ribbon-caption-line-height);\n text-align: center;\n white-space: nowrap;\n}\n.launcher {\n position: absolute;\n inset-inline-end: var(--office-launcher-inset-end);\n bottom: var(--office-launcher-inset-bottom);\n display: inline-grid;\n place-items: center;\n width: var(--office-launcher-width);\n height: var(--office-launcher-height);\n padding: 0;\n border: 0;\n border-radius: var(--office-radius-xs);\n background: transparent;\n color: var(--office-muted-foreground);\n cursor: pointer;\n}\n.launcher:hover:not(:disabled) {\n background: var(--office-surface);\n color: var(--office-foreground);\n}\n.launcher:focus-visible {\n outline: var(--office-focus-width) solid var(--office-ring);\n}\n.launcher:disabled {\n opacity: 0.45;\n cursor: not-allowed;\n}\n.launcher[hidden] {\n display: none;\n}\n.launcher svg {\n width: var(--office-icon-size-xs);\n height: var(--office-icon-size-xs);\n fill: none;\n stroke: currentColor;\n stroke-width: var(--office-icon-stroke);\n stroke-linecap: round;\n stroke-linejoin: round;\n}\n\n/* Collapsed (narrow window): the group is one button; its commands open in a popup. */\n.face {\n display: none;\n}\n:host([data-collapsed]) .face {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: flex-start;\n gap: var(--office-space-0);\n min-width: var(--office-collapsed-group-min-width);\n height: var(--office-command-large-height);\n padding: var(--office-space-0) var(--office-space-1-5);\n border: 0;\n border-radius: var(--office-radius);\n background: transparent;\n color: var(--office-foreground);\n font: inherit;\n font-size: var(--office-font-size-sm);\n cursor: pointer;\n}\n:host([data-collapsed]) .face:hover,\n:host([data-open]) .face {\n background: var(--office-selected);\n}\n.face:focus-visible {\n outline: var(--office-focus-width) solid var(--office-ring);\n outline-offset: var(--office-focus-offset);\n}\n.face svg {\n width: var(--office-command-large-icon);\n height: var(--office-command-large-icon);\n fill: none;\n stroke: currentColor;\n stroke-width: var(--office-icon-stroke);\n stroke-linecap: round;\n stroke-linejoin: round;\n color: var(--office-command-icon-color);\n}\n.face svg.chev {\n width: var(--office-icon-size-xs);\n height: var(--office-icon-size-xs);\n color: currentColor;\n}\n:host([data-collapsed]) .foot,\n:host([data-collapsed]) .row {\n display: none;\n}\n:host([data-collapsed][data-open]) .row {\n display: flex;\n flex-wrap: wrap;\n position: fixed;\n top: var(--office-ribbon-collapse-y);\n left: var(--office-ribbon-collapse-x);\n z-index: var(--office-z-popover);\n box-sizing: border-box;\n max-width: calc(100vw - 2 * var(--office-space-2));\n padding: var(--office-space-2);\n background: var(--office-popover);\n color: var(--office-popover-foreground);\n border: var(--office-border-width) solid var(--office-border);\n border-radius: var(--office-radius-md);\n box-shadow: var(--office-shadow);\n}\n\n@media (forced-colors: active) {\n .group::after {\n background: CanvasText;\n }\n .caption,\n .launcher {\n color: CanvasText;\n }\n :host([data-collapsed][data-open]) .row {\n border-color: CanvasText;\n }\n}\n";
1279
+
1280
+ // src/ribbon/ribbon-group.ts
1281
+ function tokenPx(el, name, fallback) {
1282
+ const value = el.ownerDocument.defaultView?.getComputedStyle(el).getPropertyValue(name).trim();
1283
+ const px = value?.endsWith("px") ? parseFloat(value) : NaN;
1284
+ return Number.isFinite(px) ? px : fallback;
1285
+ }
1286
+ var OfficeUiRibbonGroup = class extends OfficeElement {
1287
+ static launcherEvent = "office-command";
1288
+ static collapseEvent = "office-ribbon-collapse-toggle";
1289
+ static styles = controlStyles(ribbon_group_default);
1290
+ /** The group is configured by attributes, as it always was (see `OfficeElement.watched`). */
1291
+ static watched = [
1292
+ "label",
1293
+ "launcher",
1294
+ "launcher-label",
1295
+ "launcher-disabled",
1296
+ "icon",
1297
+ "data-open"
1298
+ ];
1299
+ observer;
1300
+ /** The launcher's event detail; null emits nothing. */
1301
+ launcherDetail() {
1302
+ const command = this.getAttribute("launcher");
1303
+ return command ? { command } : null;
1304
+ }
1305
+ /** The registered icon on the collapsed face; a product subclass may map names. */
1306
+ iconName() {
1307
+ return this.getAttribute("icon") ?? "grid";
1308
+ }
1309
+ connectedCallback() {
1310
+ super.connectedCallback();
1311
+ this.observe();
1312
+ }
1313
+ disconnectedCallback() {
1314
+ super.disconnectedCallback();
1315
+ this.observer?.disconnect();
1316
+ }
1317
+ observe() {
1318
+ this.observer?.disconnect();
1319
+ if (!this.isConnected) return;
1320
+ const Observer = this.ownerDocument.defaultView?.ResizeObserver;
1321
+ if (Observer) this.observer ??= new Observer(() => this.measure());
1322
+ const slot = this.renderRoot.querySelector("slot");
1323
+ for (const el of slot?.assignedElements() ?? []) this.observer?.observe(el);
1324
+ this.measure();
1325
+ }
1326
+ measure() {
1327
+ const children = [...this.children];
1328
+ const stackable = children.filter((el) => {
1329
+ const gallery = el.matches('[mode="dropdown"]') ? el : el.querySelector('[mode="dropdown"]');
1330
+ return gallery !== null && !gallery.hasAttribute("data-command-large");
1331
+ });
1332
+ this.toggleAttribute(
1333
+ "data-stack",
1334
+ stackable.length > 1 && stackable.length === children.length
1335
+ );
1336
+ const tallest = Math.max(0, ...children.map((el) => el.getBoundingClientRect().height));
1337
+ if (tallest > 0)
1338
+ this.toggleAttribute(
1339
+ "data-compact-row",
1340
+ tallest <= tokenPx(this, "--office-ribbon-compact-row-max", 36)
1341
+ );
1342
+ }
1343
+ onLauncher() {
1344
+ if (this.hasAttribute("launcher-disabled")) return;
1345
+ const detail = this.launcherDetail();
1346
+ if (detail) this.fire(this.constructor.launcherEvent, detail);
1347
+ }
1348
+ /** The overflow controller listens for this and owns which popup is open. */
1349
+ onFace() {
1350
+ this.fire(this.constructor.collapseEvent, void 0);
1351
+ }
1352
+ willUpdate() {
1353
+ this.setAttribute("role", "group");
1354
+ this.setAttribute("aria-label", this.getAttribute("label") ?? "");
1355
+ }
1356
+ render() {
1357
+ const label = this.getAttribute("label") ?? "";
1358
+ const launcherLabel = this.getAttribute("launcher-label") ?? `${label} options`;
1359
+ return html`
1360
+ <div class="group">
1361
+ <button
1362
+ class="face"
1363
+ type="button"
1364
+ aria-haspopup="true"
1365
+ aria-label=${label}
1366
+ aria-expanded=${String(this.hasAttribute("data-open"))}
1367
+ title=${label}
1368
+ @click=${this.onFace}
1369
+ >${glyph(this.iconName(), "face-icon")}<span>${label}</span>${glyph("chevronDown", "chev")}</button
1370
+ >
1371
+ <div class="row">
1372
+ <slot @slotchange=${this.observe}></slot>
1373
+ </div>
1374
+ <div class="foot">
1375
+ <span class="caption">${label}</span>
1376
+ <button
1377
+ class="launcher"
1378
+ type="button"
1379
+ aria-label=${launcherLabel}
1380
+ title=${launcherLabel}
1381
+ ?hidden=${!this.hasAttribute("launcher")}
1382
+ ?disabled=${this.hasAttribute("launcher-disabled")}
1383
+ @click=${this.onLauncher}
1384
+ >${glyph("launcher", "launcher-icon")}</button
1385
+ >
1386
+ </div>
1387
+ </div>
1388
+ `;
1389
+ }
1390
+ };
1391
+ var defineRibbonGroup = definer("office-ui-ribbon-group", () => OfficeUiRibbonGroup);
1392
+
1113
1393
  // raw-css:/home/runner/work/ooxml/ooxml/packages/ui/src/ribbon/ribbon-section.css?raw
1114
1394
  var ribbon_section_default = ":host {\n display: inline-flex;\n align-items: stretch;\n}\n::slotted(*) {\n flex: none;\n}\n";
1115
1395
 
@@ -1212,7 +1492,11 @@ var OfficeUiRibbonSection = class extends OfficeElement {
1212
1492
  }
1213
1493
  }
1214
1494
  };
1215
- var defineRibbonSection = definer("office-ui-ribbon-section", () => OfficeUiRibbonSection);
1495
+ var defineRibbonSection = definer(
1496
+ "office-ui-ribbon-section",
1497
+ () => OfficeUiRibbonSection,
1498
+ [defineRibbonGroup, defineButton]
1499
+ );
1216
1500
 
1217
1501
  // raw-css:/home/runner/work/ooxml/ooxml/packages/ui/src/ribbon/gallery.css?raw
1218
1502
  var gallery_default = "[data-office-gallery] {\n display: inline-flex;\n position: relative;\n flex: none;\n color: var(--office-foreground);\n}\n[data-office-gallery] .gallery-view {\n display: contents;\n}\n[data-office-gallery] button {\n box-sizing: border-box;\n font: inherit;\n color: inherit;\n cursor: pointer;\n border: var(--office-border-width) solid var(--office-border);\n border-radius: var(--office-radius);\n background: var(--office-background);\n}\n[data-office-gallery] button:hover:not(:disabled) {\n background: var(--office-selected);\n}\n[data-office-gallery] button:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n[data-office-gallery] button:focus-visible {\n outline: var(--office-focus-width) solid var(--office-ring);\n outline-offset: var(--office-focus-offset);\n}\n[data-office-gallery] .trigger {\n display: inline-flex;\n align-items: center;\n gap: var(--office-space-1-5);\n min-height: var(--office-gallery-trigger-height);\n padding: 0 var(--office-space-1-5);\n font-size: var(--office-font-size-sm);\n white-space: nowrap;\n}\n[data-office-gallery]:not([mode='inline']) .trigger {\n border-color: transparent;\n background: transparent;\n}\n[data-office-gallery] .trigger svg {\n width: var(--office-icon-size-md);\n height: var(--office-icon-size-md);\n fill: none;\n stroke: currentColor;\n stroke-width: var(--office-icon-stroke);\n stroke-linecap: round;\n stroke-linejoin: round;\n}\n[data-office-gallery][mode='inline'] .trigger,\n[data-office-gallery][chevron-only] .trigger {\n align-self: stretch;\n padding: 0 var(--office-space-1);\n}\n[data-office-gallery] .strip {\n display: flex;\n gap: var(--office-space-0);\n padding: var(--office-space-0);\n align-items: center;\n}\n[data-office-gallery] .tile {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: none;\n padding: var(--office-space-0);\n}\n[data-office-gallery] .tile[aria-pressed='true'] {\n border: var(--office-border-width-thick) solid var(--office-accent);\n background: color-mix(in srgb, var(--office-accent) 15%, var(--office-background));\n}\n[data-office-gallery] .tile svg {\n max-width: 100%;\n max-height: 100%;\n}\n[data-office-gallery][mode='inline'] .strip {\n gap: 0;\n border: var(--office-border-width) solid var(--office-border);\n border-inline-end: 0;\n border-radius: var(--office-radius-sm) 0 0 var(--office-radius-sm);\n background: var(--office-gallery-strip-background);\n}\n[data-office-gallery][mode='inline'] .trigger {\n border-radius: 0 var(--office-radius-sm) var(--office-radius-sm) 0;\n background: var(--office-gallery-strip-background);\n}\n[data-office-gallery] .trigger.command {\n border-color: transparent;\n background: transparent;\n justify-content: flex-start;\n}\n[data-office-gallery] .trigger.command:hover:not(:disabled) {\n border-color: var(--office-border);\n background: var(--office-selected);\n}\n[data-office-gallery] .trigger.command svg {\n color: var(--office-command-icon-color);\n}\n[data-office-gallery] .trigger.command-large {\n flex-direction: column;\n align-items: center;\n justify-content: flex-start;\n gap: var(--office-space-0);\n min-width: var(--office-gallery-command-min-width);\n max-width: var(--office-gallery-command-max-width);\n height: var(--office-gallery-command-height);\n padding: var(--office-space-1);\n font-size: var(--office-font-size-2xs);\n line-height: var(--office-line-height-tight);\n white-space: normal;\n text-align: center;\n}\n[data-office-gallery] .trigger.command-large svg {\n width: var(--office-gallery-command-icon);\n height: var(--office-gallery-command-icon);\n}\n[data-office-gallery] .popup {\n box-sizing: border-box;\n position: fixed;\n z-index: var(--office-z-popover);\n max-width: calc(100vw - var(--office-space-4));\n max-height: var(--office-gallery-popup-max-height);\n overflow: auto;\n padding: var(--office-space-2);\n border: var(--office-border-width) solid var(--office-border);\n border-radius: var(--office-radius-md);\n background: var(--office-popover);\n color: var(--office-popover-foreground);\n box-shadow: var(--office-shadow-lg);\n}\n[data-office-gallery] .popup[hidden] {\n display: none;\n}\n[data-office-gallery] .grid {\n display: grid;\n gap: var(--office-space-1);\n width: max-content;\n max-width: 100%;\n}\n[data-office-gallery] .heading {\n margin: var(--office-space-1) 0 var(--office-space-1-5);\n font-size: var(--office-font-size-xs);\n font-weight: var(--office-font-weight-bold);\n}\n[data-office-gallery] .section + .section {\n margin-top: var(--office-space-2-5);\n}\n@media (pointer: coarse), (max-width: 1023px) {\n [data-office-gallery] .trigger,\n [data-office-gallery] .tile {\n min-height: var(--office-target-size-touch);\n min-width: var(--office-target-size-touch);\n }\n}\n@media (forced-colors: active) {\n [data-office-gallery] button,\n [data-office-gallery] .popup {\n color: ButtonText;\n background: Canvas;\n border-color: ButtonText;\n }\n [data-office-gallery] button:disabled {\n color: GrayText;\n opacity: 1;\n }\n [data-office-gallery] button:focus-visible,\n [data-office-gallery] .tile[aria-pressed='true'] {\n outline: var(--office-focus-width) solid Highlight;\n border-color: Highlight;\n }\n}\n";
@@ -1644,271 +1928,109 @@ var defaultStorage = () => {
1644
1928
  return void 0;
1645
1929
  }
1646
1930
  };
1647
- function readOfficeProfile(storage = defaultStorage(), key = OFFICE_PROFILE_STORAGE_KEY) {
1648
- try {
1649
- const raw = storage?.getItem(key);
1650
- return raw ? sanitizeOfficeProfile(JSON.parse(raw)) : { ...DEFAULT_OFFICE_PROFILE };
1651
- } catch {
1652
- return { ...DEFAULT_OFFICE_PROFILE };
1653
- }
1654
- }
1655
- function writeOfficeProfile(profile, storage = defaultStorage(), key = OFFICE_PROFILE_STORAGE_KEY) {
1656
- try {
1657
- storage?.setItem(key, JSON.stringify(sanitizeOfficeProfile(profile)));
1658
- } catch {
1659
- }
1660
- }
1661
- function clearOfficeProfile(storage = defaultStorage(), key = OFFICE_PROFILE_STORAGE_KEY) {
1662
- try {
1663
- storage?.removeItem(key);
1664
- } catch {
1665
- }
1666
- }
1667
-
1668
- // raw-css:/home/runner/work/ooxml/ooxml/packages/ui/src/chrome/account.css?raw
1669
- var account_default = ":host {\n display: block;\n font-family: var(--office-font);\n font-size: var(--office-font-size);\n}\nh2 {\n margin: 0 0 var(--office-space-3);\n font-size: var(--office-font-size-lg);\n font-weight: 600;\n}\n.who {\n display: flex;\n align-items: center;\n gap: var(--office-space-3);\n margin-bottom: var(--office-space-3);\n}\n.avatar {\n display: grid;\n place-items: center;\n width: var(--office-avatar-size);\n height: var(--office-avatar-size);\n border-radius: 50%;\n color: var(--office-accent-foreground);\n font-weight: var(--office-font-weight-bold);\n font-size: var(--office-font-size-xl);\n flex: none;\n}\n.name {\n font-size: var(--office-font-size-md);\n font-weight: 600;\n}\n.note {\n margin: var(--office-space-0) 0 0;\n color: var(--office-muted-foreground);\n font-size: var(--office-font-size-sm);\n}\nlabel {\n display: grid;\n gap: var(--office-space-1);\n max-width: var(--office-account-field-width);\n margin-bottom: var(--office-space-3);\n}\ninput {\n min-height: var(--office-field-height);\n box-sizing: border-box;\n padding: var(--office-space-0) var(--office-space-1-5);\n font: inherit;\n color: inherit;\n border: var(--office-border-width) solid var(--office-border);\n border-radius: var(--office-radius-sm);\n background: var(--office-background);\n}\n.swatches {\n display: flex;\n flex-wrap: wrap;\n gap: var(--office-space-1-5);\n margin: var(--office-space-1) 0 var(--office-space-3);\n}\n.swatches button {\n width: var(--office-target-size);\n height: var(--office-target-size);\n padding: 0;\n border: var(--office-border-width-thick) solid transparent;\n border-radius: 50%;\n cursor: pointer;\n}\n.swatches button[aria-checked='true'] {\n border-color: var(--office-foreground);\n box-shadow: inset 0 0 0 var(--office-border-width-thick) var(--office-background);\n}\n.swatches button:focus-visible,\ninput:focus-visible {\n outline: var(--office-focus-width) solid var(--office-ring);\n outline-offset: calc(var(--office-focus-offset) / 2);\n}\n@media (forced-colors: active) {\n .swatches button {\n forced-color-adjust: none;\n }\n}\n";
1670
-
1671
- // src/chrome/account.ts
1672
- var OfficeUiAccount = class extends OfficeElement {
1673
- static styles = controlStyles(account_default);
1674
- current = { ...DEFAULT_OFFICE_PROFILE };
1675
- get profile() {
1676
- return { ...this.current };
1677
- }
1678
- set profile(value) {
1679
- this.current = sanitizeOfficeProfile(value);
1680
- this.requestUpdate("profile");
1681
- }
1682
- change(next) {
1683
- this.profile = next;
1684
- this.fire("office-profile-change", { profile: this.profile });
1685
- }
1686
- onSwatchKey(event) {
1687
- const step = { ArrowRight: 1, ArrowDown: 1, ArrowLeft: -1, ArrowUp: -1 }[event.key];
1688
- if (!step) return;
1689
- event.preventDefault();
1690
- const colors = OFFICE_AVATAR_SWATCHES;
1691
- const at = Math.max(0, colors.indexOf(this.current.avatarColor));
1692
- const color = colors[(at + step + colors.length) % colors.length];
1693
- this.change({ ...this.current, avatarColor: color });
1694
- this.renderRoot.querySelector(`[data-color="${color}"]`)?.focus();
1695
- }
1696
- render() {
1697
- const { displayName, avatarColor } = this.current;
1698
- const known = OFFICE_AVATAR_SWATCHES.includes(avatarColor);
1699
- return html`
1700
- <h2>User Information</h2>
1701
- <div class="who">
1702
- <div class="avatar" aria-hidden="true" style="background:${avatarColor}"
1703
- >${profileInitials(this.current)}</div
1704
- >
1705
- <div>
1706
- <div class="name">${displayName || "No display name"}</div>
1707
- <p class="note">Stored on this device only. Never sent anywhere.</p>
1708
- </div>
1709
- </div>
1710
- <label>
1711
- Display name
1712
- <input
1713
- type="text"
1714
- maxlength="64"
1715
- autocomplete="name"
1716
- .value=${displayName}
1717
- @change=${(event) => this.change({
1718
- ...this.current,
1719
- displayName: event.target.value.trim()
1720
- })}
1721
- />
1722
- </label>
1723
- <div id="color-label">Avatar colour</div>
1724
- <div
1725
- class="swatches"
1726
- role="radiogroup"
1727
- aria-labelledby="color-label"
1728
- @keydown=${this.onSwatchKey}
1729
- >
1730
- ${OFFICE_AVATAR_SWATCHES.map((color, index) => {
1731
- const checked = color === avatarColor;
1732
- return html`<button
1733
- type="button"
1734
- role="radio"
1735
- aria-label=${color}
1736
- aria-checked=${String(checked)}
1737
- tabindex=${checked || !known && index === 0 ? 0 : -1}
1738
- data-color=${color}
1739
- style="background:${color}"
1740
- @click=${() => this.change({ ...this.current, avatarColor: color })}
1741
- ></button>`;
1742
- })}
1743
- </div>
1744
- <slot name="sign-in"></slot>
1745
- <slot></slot>
1746
- `;
1747
- }
1748
- };
1749
- var defineAccount = definer("office-ui-account", () => OfficeUiAccount);
1750
-
1751
- // raw-css:/home/runner/work/ooxml/ooxml/packages/ui/src/ribbon/button.css?raw
1752
- var button_default = ":host {\n display: inline-flex;\n vertical-align: middle;\n}\nbutton {\n box-sizing: border-box;\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--office-space-1-5);\n min-width: var(--office-target-size);\n min-height: var(--office-target-size);\n padding: 0 var(--office-space-2);\n border: var(--office-border-width) solid transparent;\n border-radius: var(--office-radius);\n background: transparent;\n color: var(--office-foreground);\n font: inherit;\n font-size: var(--office-font-size-sm);\n cursor: pointer;\n white-space: nowrap;\n}\n:host([variant='stacked']) button {\n flex-direction: column;\n padding: var(--office-space-1) var(--office-space-2);\n}\nbutton:hover:not(:disabled) {\n background: var(--office-surface);\n}\nbutton:active:not(:disabled) {\n background: var(--office-selected);\n}\nbutton:focus-visible {\n outline: var(--office-focus-width) solid var(--office-ring);\n outline-offset: calc(var(--office-focus-offset) / 2);\n}\nbutton[aria-pressed='true'],\nbutton[aria-expanded='true'] {\n border-color: var(--office-accent);\n background: var(--office-surface);\n}\n:host([active]) button {\n background: var(--office-command-active);\n color: var(--office-accent);\n}\nbutton:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\nsvg {\n width: var(--office-icon-size-ml);\n height: var(--office-icon-size-ml);\n flex: none;\n color: var(--office-command-icon-color);\n fill: none;\n stroke: currentColor;\n stroke-width: var(--office-icon-stroke);\n stroke-linecap: round;\n stroke-linejoin: round;\n}\nsvg.glyph:not([data-painted]) {\n display: none;\n}\n.label[hidden],\n.caret[hidden],\n.badge[hidden] {\n display: none;\n}\n/* Office trails a menu chevron after the last line of the label. */\n.caret {\n display: inline-block;\n width: var(--office-icon-size-xs);\n height: var(--office-icon-size-xs);\n margin-inline-start: var(--office-space-0);\n vertical-align: middle;\n color: var(--office-muted-foreground);\n}\n.badge {\n position: absolute;\n top: 0;\n inset-inline-end: 0;\n padding: 0 var(--office-space-0);\n border-radius: var(--office-radius-full);\n background: var(--office-accent);\n color: var(--office-accent-foreground);\n font-size: var(--office-font-size-3xs);\n}\n\n/* Large ribbon command: a big glyph above a two-line label. */\n:host([size='large']) button {\n flex-direction: column;\n justify-content: flex-start;\n gap: var(--office-space-0);\n min-width: var(--office-command-large-min-width);\n max-width: var(--office-command-large-max-width);\n height: var(--office-command-large-height);\n padding: var(--office-space-0) var(--office-space-1);\n border: 0;\n white-space: normal;\n text-align: center;\n line-height: var(--office-line-height-tight);\n}\n:host([size='large']) svg.glyph {\n width: var(--office-command-large-icon);\n height: var(--office-command-large-icon);\n}\n\n/* Small ribbon command: icon and label in one row. */\n:host([size='small']) button {\n justify-content: flex-start;\n min-width: 0;\n height: var(--office-control-height);\n min-height: var(--office-control-height);\n padding: 0 var(--office-space-1-5);\n border: 0;\n text-align: start;\n}\n:host([size='small']) svg.glyph {\n width: var(--office-command-small-icon);\n height: var(--office-command-small-icon);\n}\n\n/* Tall, label-less tool tiles (pens, erasers). */\n:host([icon-only][tall]) button {\n min-width: var(--office-command-tall-min-width);\n height: var(--office-command-tall-height);\n padding: var(--office-space-1);\n}\n:host([icon-only][tall]) svg.glyph {\n width: var(--office-command-tall-icon);\n height: var(--office-command-tall-icon);\n}\n:host([icon-only][tall][active]) button {\n box-shadow: inset 0 0 0 var(--office-border-width) var(--office-accent);\n}\n\n@media (pointer: coarse), (max-width: 767px) {\n :host([size='small']) button {\n min-height: var(--office-target-size-touch);\n }\n :host([icon-only]) button {\n min-width: var(--office-target-size-touch);\n }\n}\n@media (forced-colors: active) {\n button {\n border-color: ButtonText;\n color: ButtonText;\n background: ButtonFace;\n }\n svg {\n color: ButtonText;\n }\n button:disabled {\n color: GrayText;\n border-color: GrayText;\n }\n button[aria-pressed='true'],\n button[aria-expanded='true'],\n :host([active]) button {\n background: Highlight;\n color: HighlightText;\n }\n}\n";
1753
-
1754
- // src/ribbon/button.ts
1755
- var asAttribute = (value) => value === void 0 ? void 0 : String(value);
1756
- var OfficeUiButton = class extends OfficeElement {
1757
- static requestEvent = "office-command";
1758
- static idAttribute = "command";
1759
- static detailKey = "command";
1760
- static shadowRootOptions = { ...LitElement.shadowRootOptions, delegatesFocus: true };
1761
- static styles = controlStyles(button_default);
1762
- static properties = { disabled: flag, pressed: triState };
1763
- /** Everything else is an attribute, as it always was (see `OfficeElement.watched`). */
1764
- static watched = [
1765
- "label",
1766
- "icon",
1767
- "command",
1768
- "badge",
1769
- "caret",
1770
- "keyshortcuts",
1771
- "size",
1772
- "variant",
1773
- "active",
1774
- "tall",
1775
- "icon-only",
1776
- "expanded",
1777
- "title"
1778
- ];
1779
- constructor() {
1780
- super();
1781
- this.disabled = false;
1782
- }
1783
- /** The registered icon to draw; a product subclass may map names onto its glyph set. */
1784
- iconName() {
1785
- return this.getAttribute("icon");
1786
- }
1787
- /** The tooltip: `title`, else the label of an icon-only button; a product may always show it. */
1788
- tooltip(label, iconOnly) {
1789
- return this.getAttribute("title") ?? (iconOnly ? label : "");
1790
- }
1791
- /** Whether the trailing menu chevron shows. */
1792
- showsCaret() {
1793
- const caret = this.getAttribute("caret");
1794
- return caret !== null && caret !== "false";
1795
- }
1796
- onKeydown(event) {
1797
- if ((event.key === " " || event.key === "Enter") && !event.ctrlKey && !event.metaKey && !event.altKey)
1798
- event.stopPropagation();
1799
- }
1800
- onClick() {
1801
- const { requestEvent, idAttribute, detailKey } = this.constructor;
1802
- const id = this.getAttribute(idAttribute);
1803
- if (!present(this.disabled) && id) this.fire(requestEvent, { [detailKey]: id });
1804
- }
1805
- render() {
1806
- const label = this.getAttribute("label") ?? "";
1807
- const iconOnly = this.hasAttribute("icon-only");
1808
- const badge = this.getAttribute("badge") ?? "";
1809
- const expanded = this.getAttribute("expanded");
1810
- const tooltip = this.tooltip(label, iconOnly);
1811
- return html`<button
1812
- part="button"
1813
- type="button"
1814
- ?disabled=${present(this.disabled)}
1815
- title=${tooltip || nothing}
1816
- aria-label=${ifDefined(iconOnly && label ? label : void 0)}
1817
- aria-keyshortcuts=${ifDefined(this.getAttribute("keyshortcuts") || void 0)}
1818
- aria-pressed=${ifDefined(asAttribute(this.pressed))}
1819
- aria-expanded=${ifDefined(expanded === null ? void 0 : String(expanded !== "false"))}
1820
- @click=${this.onClick}
1821
- @keydown=${this.onKeydown}
1822
- >${glyph(this.iconName())}<span class="label" ?hidden=${iconOnly}
1823
- >${label}${glyph("chevronDown", "caret", !this.showsCaret())}</span
1824
- ><span class="badge" aria-hidden="true" ?hidden=${!badge}>${badge}</span></button
1825
- >`;
1826
- }
1827
- };
1828
- var defineButton = definer("office-ui-button", () => OfficeUiButton);
1829
- var OfficeUiCheckable = class extends OfficeElement {
1830
- static formAssociated = true;
1831
- static properties = {
1832
- checked: flag,
1833
- disabled: flag,
1834
- value: valueOn
1835
- };
1836
- internals;
1837
- defaultChecked = false;
1838
- constructor() {
1839
- super();
1840
- this.checked = false;
1841
- this.disabled = false;
1842
- this.value = "on";
1843
- try {
1844
- this.internals = this.attachInternals();
1845
- } catch {
1846
- this.internals = void 0;
1847
- }
1848
- this.addEventListener("click", (event) => {
1849
- if (present(this.disabled)) event.preventDefault();
1850
- else this.toggle();
1851
- });
1852
- this.addEventListener("keydown", (event) => {
1853
- const toggles = event.key === " " || this.semantics === "switch" && event.key === "Enter";
1854
- if (!toggles || present(this.disabled)) return;
1855
- event.preventDefault();
1856
- this.toggle();
1857
- });
1931
+ function readOfficeProfile(storage = defaultStorage(), key = OFFICE_PROFILE_STORAGE_KEY) {
1932
+ try {
1933
+ const raw = storage?.getItem(key);
1934
+ return raw ? sanitizeOfficeProfile(JSON.parse(raw)) : { ...DEFAULT_OFFICE_PROFILE };
1935
+ } catch {
1936
+ return { ...DEFAULT_OFFICE_PROFILE };
1858
1937
  }
1859
- connectedCallback() {
1860
- this.defaultChecked = present(this.checked);
1861
- super.connectedCallback();
1938
+ }
1939
+ function writeOfficeProfile(profile, storage = defaultStorage(), key = OFFICE_PROFILE_STORAGE_KEY) {
1940
+ try {
1941
+ storage?.setItem(key, JSON.stringify(sanitizeOfficeProfile(profile)));
1942
+ } catch {
1862
1943
  }
1863
- formResetCallback() {
1864
- this.checked = this.defaultChecked;
1944
+ }
1945
+ function clearOfficeProfile(storage = defaultStorage(), key = OFFICE_PROFILE_STORAGE_KEY) {
1946
+ try {
1947
+ storage?.removeItem(key);
1948
+ } catch {
1865
1949
  }
1866
- formDisabledCallback(disabled) {
1867
- this.disabled = disabled;
1950
+ }
1951
+
1952
+ // raw-css:/home/runner/work/ooxml/ooxml/packages/ui/src/chrome/account.css?raw
1953
+ var account_default = ":host {\n display: block;\n font-family: var(--office-font);\n font-size: var(--office-font-size);\n}\nh2 {\n margin: 0 0 var(--office-space-3);\n font-size: var(--office-font-size-lg);\n font-weight: 600;\n}\n.who {\n display: flex;\n align-items: center;\n gap: var(--office-space-3);\n margin-bottom: var(--office-space-3);\n}\n.avatar {\n display: grid;\n place-items: center;\n width: var(--office-avatar-size);\n height: var(--office-avatar-size);\n border-radius: 50%;\n color: var(--office-accent-foreground);\n font-weight: var(--office-font-weight-bold);\n font-size: var(--office-font-size-xl);\n flex: none;\n}\n.name {\n font-size: var(--office-font-size-md);\n font-weight: 600;\n}\n.note {\n margin: var(--office-space-0) 0 0;\n color: var(--office-muted-foreground);\n font-size: var(--office-font-size-sm);\n}\nlabel {\n display: grid;\n gap: var(--office-space-1);\n max-width: var(--office-account-field-width);\n margin-bottom: var(--office-space-3);\n}\ninput {\n min-height: var(--office-field-height);\n box-sizing: border-box;\n padding: var(--office-space-0) var(--office-space-1-5);\n font: inherit;\n color: inherit;\n border: var(--office-border-width) solid var(--office-border);\n border-radius: var(--office-radius-sm);\n background: var(--office-background);\n}\n.swatches {\n display: flex;\n flex-wrap: wrap;\n gap: var(--office-space-1-5);\n margin: var(--office-space-1) 0 var(--office-space-3);\n}\n.swatches button {\n width: var(--office-target-size);\n height: var(--office-target-size);\n padding: 0;\n border: var(--office-border-width-thick) solid transparent;\n border-radius: 50%;\n cursor: pointer;\n}\n.swatches button[aria-checked='true'] {\n border-color: var(--office-foreground);\n box-shadow: inset 0 0 0 var(--office-border-width-thick) var(--office-background);\n}\n.swatches button:focus-visible,\ninput:focus-visible {\n outline: var(--office-focus-width) solid var(--office-ring);\n outline-offset: calc(var(--office-focus-offset) / 2);\n}\n@media (forced-colors: active) {\n .swatches button {\n forced-color-adjust: none;\n }\n}\n";
1954
+
1955
+ // src/chrome/account.ts
1956
+ var OfficeUiAccount = class extends OfficeElement {
1957
+ static styles = controlStyles(account_default);
1958
+ current = { ...DEFAULT_OFFICE_PROFILE };
1959
+ get profile() {
1960
+ return { ...this.current };
1868
1961
  }
1869
- toggle() {
1870
- this.checked = !present(this.checked);
1871
- this.dispatchEvent(new Event("input", { bubbles: true, composed: true }));
1872
- this.dispatchEvent(new Event("change", { bubbles: true, composed: true }));
1962
+ set profile(value) {
1963
+ this.current = sanitizeOfficeProfile(value);
1964
+ this.requestUpdate("profile");
1873
1965
  }
1874
- /** The host carries the semantics: role, state, tab stop and form value. */
1875
- willUpdate() {
1876
- const checked = present(this.checked);
1877
- const disabled = present(this.disabled);
1878
- this.setAttribute("role", this.semantics);
1879
- this.setAttribute("aria-checked", String(checked));
1880
- this.setAttribute("aria-disabled", String(disabled));
1881
- this.setAttribute("tabindex", disabled ? "-1" : "0");
1882
- this.internals?.setFormValue?.(checked && !disabled ? this.value : null);
1966
+ change(next) {
1967
+ this.profile = next;
1968
+ this.fire("office-profile-change", { profile: this.profile });
1883
1969
  }
1884
- /** The tick, shown through CSS when `checked`. */
1885
- renderCheck() {
1886
- return html`<svg
1887
- viewBox="0 0 16 16"
1888
- fill="none"
1889
- stroke="currentColor"
1890
- stroke-width="2"
1891
- stroke-linecap="round"
1892
- stroke-linejoin="round"
1893
- aria-hidden="true"
1894
- >
1895
- <path d="m3 8 3.2 3.2L13 4.5"></path>
1896
- </svg>`;
1970
+ onSwatchKey(event) {
1971
+ const step = { ArrowRight: 1, ArrowDown: 1, ArrowLeft: -1, ArrowUp: -1 }[event.key];
1972
+ if (!step) return;
1973
+ event.preventDefault();
1974
+ const colors = OFFICE_AVATAR_SWATCHES;
1975
+ const at = Math.max(0, colors.indexOf(this.current.avatarColor));
1976
+ const color = colors[(at + step + colors.length) % colors.length];
1977
+ this.change({ ...this.current, avatarColor: color });
1978
+ this.renderRoot.querySelector(`[data-color="${color}"]`)?.focus();
1897
1979
  }
1898
- };
1899
-
1900
- // raw-css:/home/runner/work/ooxml/ooxml/packages/ui/src/form/checkbox.css?raw
1901
- var checkbox_default = ":host {\n display: inline-grid;\n box-sizing: border-box;\n width: var(--office-checkbox-size);\n height: var(--office-checkbox-size);\n flex: none;\n place-items: center;\n border: var(--office-border-width) solid var(--office-checkbox-border);\n border-radius: var(--office-checkbox-radius);\n background: var(--office-checkbox-background);\n color: var(--office-checkbox-accent-foreground);\n cursor: pointer;\n vertical-align: middle;\n}\n:host([checked]) {\n border-color: var(--office-checkbox-accent);\n background: var(--office-checkbox-accent);\n}\n:host(:focus-visible) {\n outline: var(--office-focus-width) solid var(--office-ring);\n outline-offset: var(--office-focus-offset);\n}\n:host([disabled]) {\n opacity: 0.5;\n cursor: not-allowed;\n}\nsvg {\n display: none;\n width: var(--office-icon-size-sm);\n height: var(--office-icon-size-sm);\n}\n:host([checked]) svg {\n display: block;\n}\n\n@media (pointer: coarse), (max-width: 767px) {\n :host {\n width: var(--office-checkbox-size-touch);\n height: var(--office-checkbox-size-touch);\n }\n svg {\n width: var(--office-icon-size-md);\n height: var(--office-icon-size-md);\n }\n}\n@media (forced-colors: active) {\n :host {\n border-color: CanvasText;\n background: Canvas;\n color: CanvasText;\n forced-color-adjust: auto;\n }\n :host([checked]) {\n border-color: Highlight;\n background: Highlight;\n color: HighlightText;\n }\n}\n";
1902
-
1903
- // src/form/checkbox.ts
1904
- var OfficeUiCheckbox = class extends OfficeUiCheckable {
1905
- static styles = controlStyles(checkbox_default);
1906
- semantics = "checkbox";
1907
1980
  render() {
1908
- return this.renderCheck();
1981
+ const { displayName, avatarColor } = this.current;
1982
+ const known = OFFICE_AVATAR_SWATCHES.includes(avatarColor);
1983
+ return html`
1984
+ <h2>User Information</h2>
1985
+ <div class="who">
1986
+ <div class="avatar" aria-hidden="true" style="background:${avatarColor}"
1987
+ >${profileInitials(this.current)}</div
1988
+ >
1989
+ <div>
1990
+ <div class="name">${displayName || "No display name"}</div>
1991
+ <p class="note">Stored on this device only. Never sent anywhere.</p>
1992
+ </div>
1993
+ </div>
1994
+ <label>
1995
+ Display name
1996
+ <input
1997
+ type="text"
1998
+ maxlength="64"
1999
+ autocomplete="name"
2000
+ .value=${displayName}
2001
+ @change=${(event) => this.change({
2002
+ ...this.current,
2003
+ displayName: event.target.value.trim()
2004
+ })}
2005
+ />
2006
+ </label>
2007
+ <div id="color-label">Avatar colour</div>
2008
+ <div
2009
+ class="swatches"
2010
+ role="radiogroup"
2011
+ aria-labelledby="color-label"
2012
+ @keydown=${this.onSwatchKey}
2013
+ >
2014
+ ${OFFICE_AVATAR_SWATCHES.map((color, index) => {
2015
+ const checked = color === avatarColor;
2016
+ return html`<button
2017
+ type="button"
2018
+ role="radio"
2019
+ aria-label=${color}
2020
+ aria-checked=${String(checked)}
2021
+ tabindex=${checked || !known && index === 0 ? 0 : -1}
2022
+ data-color=${color}
2023
+ style="background:${color}"
2024
+ @click=${() => this.change({ ...this.current, avatarColor: color })}
2025
+ ></button>`;
2026
+ })}
2027
+ </div>
2028
+ <slot name="sign-in"></slot>
2029
+ <slot></slot>
2030
+ `;
1909
2031
  }
1910
2032
  };
1911
- var defineCheckbox = definer("office-ui-checkbox", () => OfficeUiCheckbox);
2033
+ var defineAccount = definer("office-ui-account", () => OfficeUiAccount);
1912
2034
 
1913
2035
  // raw-css:/home/runner/work/ooxml/ooxml/packages/ui/src/form/switch.css?raw
1914
2036
  var switch_default = "/* Switch metrics are tokens so a host (a title bar) can size it: --office-switch-width, -height,\n * -border-width, -knob-size, -knob-offset, -knob-travel, -track, -track-on, -thumb, -thumb-on. */\n:host {\n --_w: var(--office-switch-width);\n --_h: var(--office-switch-height);\n --_b: var(--office-switch-border-width);\n --_k: var(--office-switch-knob-size);\n --_o: var(--office-switch-knob-offset);\n display: inline-block;\n box-sizing: border-box;\n position: relative;\n width: var(--_w);\n height: var(--_h);\n flex: none;\n border: var(--_b) solid var(--office-switch-border);\n border-radius: var(--office-radius-full);\n background: var(--office-switch-track);\n cursor: pointer;\n vertical-align: middle;\n touch-action: manipulation;\n transition: background-color var(--office-duration);\n}\n.knob {\n display: block;\n position: absolute;\n top: calc((var(--_h) - 2 * var(--_b) - var(--_k)) / 2);\n left: var(--_o);\n width: var(--_k);\n height: var(--_k);\n border-radius: 50%;\n background: var(--office-switch-thumb);\n box-shadow: var(--office-shadow-sm);\n transition: transform var(--office-duration);\n}\n:host([checked]) {\n border-color: var(--office-switch-track-on);\n background: var(--office-switch-track-on);\n}\n:host([checked]) .knob {\n transform: translateX(\n var(--office-switch-knob-travel, calc(var(--_w) - var(--_k) - 2 * var(--_o) - 2 * var(--_b)))\n );\n background: var(--office-switch-thumb-on);\n}\n:host(:focus-visible) {\n outline: var(--office-focus-width) solid var(--office-ring);\n outline-offset: var(--office-focus-offset);\n}\n:host([disabled]) {\n opacity: 0.5;\n cursor: not-allowed;\n}\nsvg {\n display: none;\n}\n\n@media (pointer: coarse), (max-width: 767px) {\n :host {\n --_w: var(--office-switch-width-touch);\n --_h: var(--office-switch-height-touch);\n --_k: var(--office-switch-knob-size-touch);\n }\n}\n@media (forced-colors: active) {\n :host {\n border-color: CanvasText;\n background: Canvas;\n forced-color-adjust: none;\n }\n .knob {\n background: CanvasText;\n }\n :host([checked]) {\n border-color: Highlight;\n background: Highlight;\n }\n :host([checked]) .knob {\n background: HighlightText;\n }\n}\n";
@@ -1933,7 +2055,8 @@ var OfficeUiDialog = class extends OfficeElement {
1933
2055
  static properties = {
1934
2056
  open: flag,
1935
2057
  heading: { type: String },
1936
- dismissible: { type: String }
2058
+ dismissible: { type: String },
2059
+ closeLabel: { type: String, attribute: "close-label" }
1937
2060
  };
1938
2061
  returnFocus = null;
1939
2062
  constructor() {
@@ -1941,6 +2064,7 @@ var OfficeUiDialog = class extends OfficeElement {
1941
2064
  this.open = false;
1942
2065
  this.heading = "";
1943
2066
  this.dismissible = null;
2067
+ this.closeLabel = null;
1944
2068
  this.addEventListener("keydown", (event) => this.onKey(event));
1945
2069
  }
1946
2070
  show() {
@@ -2010,7 +2134,7 @@ var OfficeUiDialog = class extends OfficeElement {
2010
2134
  <button
2011
2135
  class="close"
2012
2136
  type="button"
2013
- aria-label="Close"
2137
+ aria-label=${this.closeLabel || "Close"}
2014
2138
  @click=${() => this.requestClose("close-button")}
2015
2139
  >${glyph("close", "icon")}</button
2016
2140
  >
@@ -2250,7 +2374,7 @@ function clampFlyoutPosition(input) {
2250
2374
  }
2251
2375
 
2252
2376
  // raw-css:/home/runner/work/ooxml/ooxml/packages/ui/src/menu/context-menu.css?raw
2253
- var context_menu_default = ":host {\n display: contents;\n}\n:host([data-controlled]) {\n display: block;\n position: fixed;\n z-index: var(--office-z-popover);\n color: var(--office-popover-foreground);\n font: var(--office-font-size-sm) / var(--office-line-height) var(--office-font);\n}\n:host([data-controlled][hidden]) {\n display: none;\n}\n\n/* Children mode: a popover panel around the slotted menu items. */\n.panel {\n position: fixed;\n inset: auto;\n margin: 0;\n min-width: var(--office-context-menu-min-width);\n padding: var(--office-space-1);\n box-sizing: border-box;\n background: var(--office-background);\n color: var(--office-foreground);\n border: var(--office-border-width) solid var(--office-border);\n border-radius: var(--office-radius);\n box-shadow: var(--office-shadow);\n font-family: var(--office-font);\n}\n.panel[hidden] {\n display: none;\n}\n\n/* Controlled mode: the host is the fixed box; rows are drawn here from `state`. */\n.menu {\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n min-width: var(--office-menu-min-width);\n max-height: calc(100vh - 2 * var(--office-space-2));\n overflow-y: auto;\n padding: var(--office-space-1-5) 0;\n border: var(--office-border-width) solid var(--office-border);\n border-radius: var(--office-radius-md);\n background: var(--office-popover);\n color: inherit;\n box-shadow: var(--office-shadow-lg);\n user-select: none;\n}\n.menu:focus {\n outline: none;\n}\n.item {\n box-sizing: border-box;\n display: flex;\n align-items: center;\n gap: var(--office-space-1-5);\n width: 100%;\n min-height: var(--office-field-height);\n padding: var(--office-space-1-5) var(--office-space-3);\n border: 0;\n background: transparent;\n color: inherit;\n font: inherit;\n text-align: start;\n white-space: nowrap;\n cursor: pointer;\n}\n.item:hover:not(:disabled),\n.item:focus:not(:disabled) {\n background: var(--office-selected);\n outline: none;\n}\n.item:focus-visible {\n outline: var(--office-focus-width) solid var(--office-ring);\n outline-offset: calc(-1 * var(--office-focus-width));\n}\n.item:disabled {\n opacity: 0.45;\n cursor: default;\n}\n.item.danger {\n color: var(--office-danger);\n}\n.item svg {\n width: var(--office-icon-size-md);\n height: var(--office-icon-size-md);\n flex: none;\n fill: none;\n stroke: currentColor;\n stroke-width: var(--office-icon-stroke);\n stroke-linecap: round;\n stroke-linejoin: round;\n}\n.check {\n flex: none;\n width: var(--office-icon-size);\n text-align: center;\n}\n.separator {\n height: var(--office-border-width);\n margin: var(--office-space-1) 0;\n background: var(--office-border);\n}\n.heading {\n padding: var(--office-space-1-5) var(--office-space-3) var(--office-space-0);\n color: var(--office-muted-foreground);\n font-size: var(--office-font-size-2xs);\n font-weight: var(--office-font-weight-bold);\n letter-spacing: 0.06em;\n text-transform: uppercase;\n}\n\n@media (pointer: coarse) {\n .item {\n min-height: var(--office-target-size-touch);\n }\n}\n@media (forced-colors: active) {\n .panel,\n .menu {\n border-color: CanvasText;\n background: Canvas;\n color: CanvasText;\n box-shadow: none;\n }\n .item,\n .item.danger {\n color: CanvasText;\n }\n .item:disabled {\n color: GrayText;\n opacity: 1;\n }\n .item:hover:not(:disabled),\n .item:focus:not(:disabled) {\n background: Highlight;\n color: HighlightText;\n }\n .separator {\n background: CanvasText;\n }\n .heading {\n color: CanvasText;\n }\n}\n";
2377
+ var context_menu_default = ":host {\n display: contents;\n}\n:host([data-controlled]) {\n display: block;\n position: fixed;\n z-index: var(--office-z-popover);\n color: var(--office-popover-foreground);\n font: var(--office-font-size-sm) / var(--office-line-height) var(--office-font);\n}\n:host([data-controlled][hidden]) {\n display: none;\n}\n\n/* Children mode: a popover panel around the slotted menu items. */\n.panel {\n position: fixed;\n inset: auto;\n margin: 0;\n min-width: var(--office-context-menu-min-width);\n padding: var(--office-space-1);\n box-sizing: border-box;\n background: var(--office-background);\n color: var(--office-foreground);\n border: var(--office-border-width) solid var(--office-border);\n border-radius: var(--office-radius);\n box-shadow: var(--office-shadow);\n font-family: var(--office-font);\n}\n.panel[hidden] {\n display: none;\n}\n\n/* Controlled mode: the host is the fixed box; rows are drawn here from `state`. */\n.menu {\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n min-width: var(--office-menu-min-width);\n max-height: calc(100vh - 2 * var(--office-space-2));\n overflow-y: auto;\n padding: var(--office-space-1-5) 0;\n border: var(--office-border-width) solid var(--office-border);\n border-radius: var(--office-radius-md);\n background: var(--office-popover);\n color: inherit;\n box-shadow: var(--office-shadow-lg);\n user-select: none;\n}\n.menu:focus {\n outline: none;\n}\n.item {\n box-sizing: border-box;\n display: flex;\n align-items: center;\n gap: var(--office-space-1-5);\n width: 100%;\n min-height: var(--office-field-height);\n padding: var(--office-space-1-5) var(--office-space-3);\n border: 0;\n background: transparent;\n color: inherit;\n font: inherit;\n text-align: start;\n white-space: nowrap;\n cursor: pointer;\n}\n.item:hover:not(:disabled),\n.item:focus:not(:disabled) {\n background: var(--office-selected);\n outline: none;\n}\n.item:focus-visible {\n outline: var(--office-focus-width) solid var(--office-ring);\n outline-offset: calc(-1 * var(--office-focus-width));\n}\n.item:disabled {\n opacity: 0.45;\n cursor: default;\n}\n.item.danger {\n color: var(--office-danger);\n}\n.item svg {\n width: var(--office-icon-size-md);\n height: var(--office-icon-size-md);\n flex: none;\n fill: none;\n stroke: currentColor;\n stroke-width: var(--office-icon-stroke);\n stroke-linecap: round;\n stroke-linejoin: round;\n}\n.check {\n flex: none;\n width: var(--office-icon-size);\n text-align: center;\n}\n.shortcut {\n margin-inline-start: auto;\n padding-inline-start: var(--office-space-4);\n color: var(--office-muted-foreground);\n}\n.separator {\n height: var(--office-border-width);\n margin: var(--office-space-1) 0;\n background: var(--office-border);\n}\n.heading {\n padding: var(--office-space-1-5) var(--office-space-3) var(--office-space-0);\n color: var(--office-muted-foreground);\n font-size: var(--office-font-size-2xs);\n font-weight: var(--office-font-weight-bold);\n letter-spacing: 0.06em;\n text-transform: uppercase;\n}\n\n@media (pointer: coarse) {\n .item {\n min-height: var(--office-target-size-touch);\n }\n}\n@media (forced-colors: active) {\n .panel,\n .menu {\n border-color: CanvasText;\n background: Canvas;\n color: CanvasText;\n box-shadow: none;\n }\n .item,\n .item.danger {\n color: CanvasText;\n }\n .item:disabled {\n color: GrayText;\n opacity: 1;\n }\n .item:hover:not(:disabled),\n .item:focus:not(:disabled) {\n background: Highlight;\n color: HighlightText;\n }\n .separator {\n background: CanvasText;\n }\n .heading {\n color: CanvasText;\n }\n}\n";
2254
2378
 
2255
2379
  // src/menu/context-menu.ts
2256
2380
  var ITEMS = "office-ui-menu-item:not([disabled]):not([hidden])";
@@ -2537,13 +2661,14 @@ var OfficeUiContextMenu = class extends OfficeElement {
2537
2661
  class=${item.danger ? "item danger" : "item"}
2538
2662
  data-item-id=${item.id}
2539
2663
  title=${ifDefined(item.title)}
2664
+ aria-keyshortcuts=${ifDefined(item.shortcut)}
2540
2665
  role=${checkable ? "menuitemcheckbox" : "menuitem"}
2541
2666
  aria-checked=${ifDefined(checkable ? String(item.checked) : void 0)}
2542
2667
  aria-disabled=${ifDefined(item.disabled ? "true" : void 0)}
2543
2668
  tabindex=${index === this.active ? 0 : -1}
2544
2669
  ?disabled=${Boolean(item.disabled)}
2545
2670
  @click=${() => this.fire(this.config().requestEvent, { id: item.id })}
2546
- >${checkable ? html`<span class="check" aria-hidden="true">${item.checked ? "\u2713" : ""}</span>` : ""}${item.icon ? glyph(item.icon, "icon") : ""}${item.label}</button
2671
+ >${checkable ? html`<span class="check" aria-hidden="true">${item.checked ? "\u2713" : ""}</span>` : ""}${item.icon ? glyph(item.icon, "icon") : ""}${item.label}${item.shortcut ? html`<span class="shortcut" aria-hidden="true">${item.shortcut}</span>` : ""}</button
2547
2672
  >`;
2548
2673
  }
2549
2674
  /** Rows with their rules and headings; a heading opens a labelled group for the rows after it. */
@@ -3059,123 +3184,11 @@ var OfficeUiOptionsDialog = class extends OfficeElement {
3059
3184
  `;
3060
3185
  }
3061
3186
  };
3062
- var defineOptionsDialog = definer("office-ui-options-dialog", () => OfficeUiOptionsDialog);
3063
-
3064
- // raw-css:/home/runner/work/ooxml/ooxml/packages/ui/src/ribbon/ribbon-group.css?raw
3065
- var ribbon_group_default = ":host {\n display: inline-flex;\n flex: none;\n align-self: stretch;\n}\n.group {\n position: relative;\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n justify-content: space-between;\n min-height: var(--office-ribbon-group-height);\n padding: var(--office-ribbon-group-padding);\n}\n/* Office draws a hairline between groups; a product may stop it short of the top and bottom. */\n.group::after {\n content: '';\n position: absolute;\n top: var(--office-ribbon-separator-inset);\n bottom: var(--office-ribbon-separator-inset);\n inset-inline-end: 0;\n width: var(--office-border-width);\n background: var(--office-ribbon-separator);\n}\n:host(:last-child) .group::after {\n content: none;\n}\n.row {\n display: flex;\n align-items: flex-start;\n gap: var(--office-space-1);\n flex: 1;\n}\n/* One-line groups centre their commands on the whole group box. */\n:host([data-compact-row]) .row {\n align-items: center;\n}\n/* Several small drop-down galleries stack in columns of three. */\n:host([data-stack]) .row {\n flex-direction: column;\n align-items: stretch;\n align-content: flex-start;\n flex-wrap: wrap;\n max-height: var(--office-ribbon-stack-max-height);\n gap: var(--office-space-0);\n}\n::slotted(*) {\n flex-shrink: 0;\n}\n.foot {\n position: relative;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: var(--office-ribbon-caption-padding);\n}\n.caption {\n color: var(--office-muted-foreground);\n font-size: var(--office-ribbon-caption-size);\n line-height: var(--office-ribbon-caption-line-height);\n text-align: center;\n white-space: nowrap;\n}\n.launcher {\n position: absolute;\n inset-inline-end: var(--office-launcher-inset-end);\n bottom: var(--office-launcher-inset-bottom);\n display: inline-grid;\n place-items: center;\n width: var(--office-launcher-width);\n height: var(--office-launcher-height);\n padding: 0;\n border: 0;\n border-radius: var(--office-radius-xs);\n background: transparent;\n color: var(--office-muted-foreground);\n cursor: pointer;\n}\n.launcher:hover:not(:disabled) {\n background: var(--office-surface);\n color: var(--office-foreground);\n}\n.launcher:focus-visible {\n outline: var(--office-focus-width) solid var(--office-ring);\n}\n.launcher:disabled {\n opacity: 0.45;\n cursor: not-allowed;\n}\n.launcher[hidden] {\n display: none;\n}\n.launcher svg {\n width: var(--office-icon-size-xs);\n height: var(--office-icon-size-xs);\n fill: none;\n stroke: currentColor;\n stroke-width: var(--office-icon-stroke);\n stroke-linecap: round;\n stroke-linejoin: round;\n}\n\n/* Collapsed (narrow window): the group is one button; its commands open in a popup. */\n.face {\n display: none;\n}\n:host([data-collapsed]) .face {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: flex-start;\n gap: var(--office-space-0);\n min-width: var(--office-collapsed-group-min-width);\n height: var(--office-command-large-height);\n padding: var(--office-space-0) var(--office-space-1-5);\n border: 0;\n border-radius: var(--office-radius);\n background: transparent;\n color: var(--office-foreground);\n font: inherit;\n font-size: var(--office-font-size-sm);\n cursor: pointer;\n}\n:host([data-collapsed]) .face:hover,\n:host([data-open]) .face {\n background: var(--office-selected);\n}\n.face:focus-visible {\n outline: var(--office-focus-width) solid var(--office-ring);\n outline-offset: var(--office-focus-offset);\n}\n.face svg {\n width: var(--office-command-large-icon);\n height: var(--office-command-large-icon);\n fill: none;\n stroke: currentColor;\n stroke-width: var(--office-icon-stroke);\n stroke-linecap: round;\n stroke-linejoin: round;\n color: var(--office-command-icon-color);\n}\n.face svg.chev {\n width: var(--office-icon-size-xs);\n height: var(--office-icon-size-xs);\n color: currentColor;\n}\n:host([data-collapsed]) .foot,\n:host([data-collapsed]) .row {\n display: none;\n}\n:host([data-collapsed][data-open]) .row {\n display: flex;\n flex-wrap: wrap;\n position: fixed;\n top: var(--office-ribbon-collapse-y);\n left: var(--office-ribbon-collapse-x);\n z-index: var(--office-z-popover);\n box-sizing: border-box;\n max-width: calc(100vw - 2 * var(--office-space-2));\n padding: var(--office-space-2);\n background: var(--office-popover);\n color: var(--office-popover-foreground);\n border: var(--office-border-width) solid var(--office-border);\n border-radius: var(--office-radius-md);\n box-shadow: var(--office-shadow);\n}\n\n@media (forced-colors: active) {\n .group::after {\n background: CanvasText;\n }\n .caption,\n .launcher {\n color: CanvasText;\n }\n :host([data-collapsed][data-open]) .row {\n border-color: CanvasText;\n }\n}\n";
3066
-
3067
- // src/ribbon/ribbon-group.ts
3068
- function tokenPx(el, name, fallback) {
3069
- const value = el.ownerDocument.defaultView?.getComputedStyle(el).getPropertyValue(name).trim();
3070
- const px = value?.endsWith("px") ? parseFloat(value) : NaN;
3071
- return Number.isFinite(px) ? px : fallback;
3072
- }
3073
- var OfficeUiRibbonGroup = class extends OfficeElement {
3074
- static launcherEvent = "office-command";
3075
- static collapseEvent = "office-ribbon-collapse-toggle";
3076
- static styles = controlStyles(ribbon_group_default);
3077
- /** The group is configured by attributes, as it always was (see `OfficeElement.watched`). */
3078
- static watched = [
3079
- "label",
3080
- "launcher",
3081
- "launcher-label",
3082
- "launcher-disabled",
3083
- "icon",
3084
- "data-open"
3085
- ];
3086
- observer;
3087
- /** The launcher's event detail; null emits nothing. */
3088
- launcherDetail() {
3089
- const command = this.getAttribute("launcher");
3090
- return command ? { command } : null;
3091
- }
3092
- /** The registered icon on the collapsed face; a product subclass may map names. */
3093
- iconName() {
3094
- return this.getAttribute("icon") ?? "grid";
3095
- }
3096
- connectedCallback() {
3097
- super.connectedCallback();
3098
- this.observe();
3099
- }
3100
- disconnectedCallback() {
3101
- super.disconnectedCallback();
3102
- this.observer?.disconnect();
3103
- }
3104
- observe() {
3105
- this.observer?.disconnect();
3106
- if (!this.isConnected) return;
3107
- const Observer = this.ownerDocument.defaultView?.ResizeObserver;
3108
- if (Observer) this.observer ??= new Observer(() => this.measure());
3109
- const slot = this.renderRoot.querySelector("slot");
3110
- for (const el of slot?.assignedElements() ?? []) this.observer?.observe(el);
3111
- this.measure();
3112
- }
3113
- measure() {
3114
- const children = [...this.children];
3115
- const stackable = children.filter((el) => {
3116
- const gallery = el.matches('[mode="dropdown"]') ? el : el.querySelector('[mode="dropdown"]');
3117
- return gallery !== null && !gallery.hasAttribute("data-command-large");
3118
- });
3119
- this.toggleAttribute(
3120
- "data-stack",
3121
- stackable.length > 1 && stackable.length === children.length
3122
- );
3123
- const tallest = Math.max(0, ...children.map((el) => el.getBoundingClientRect().height));
3124
- if (tallest > 0)
3125
- this.toggleAttribute(
3126
- "data-compact-row",
3127
- tallest <= tokenPx(this, "--office-ribbon-compact-row-max", 36)
3128
- );
3129
- }
3130
- onLauncher() {
3131
- if (this.hasAttribute("launcher-disabled")) return;
3132
- const detail = this.launcherDetail();
3133
- if (detail) this.fire(this.constructor.launcherEvent, detail);
3134
- }
3135
- /** The overflow controller listens for this and owns which popup is open. */
3136
- onFace() {
3137
- this.fire(this.constructor.collapseEvent, void 0);
3138
- }
3139
- willUpdate() {
3140
- this.setAttribute("role", "group");
3141
- this.setAttribute("aria-label", this.getAttribute("label") ?? "");
3142
- }
3143
- render() {
3144
- const label = this.getAttribute("label") ?? "";
3145
- const launcherLabel = this.getAttribute("launcher-label") ?? `${label} options`;
3146
- return html`
3147
- <div class="group">
3148
- <button
3149
- class="face"
3150
- type="button"
3151
- aria-haspopup="true"
3152
- aria-label=${label}
3153
- aria-expanded=${String(this.hasAttribute("data-open"))}
3154
- title=${label}
3155
- @click=${this.onFace}
3156
- >${glyph(this.iconName(), "face-icon")}<span>${label}</span>${glyph("chevronDown", "chev")}</button
3157
- >
3158
- <div class="row">
3159
- <slot @slotchange=${this.observe}></slot>
3160
- </div>
3161
- <div class="foot">
3162
- <span class="caption">${label}</span>
3163
- <button
3164
- class="launcher"
3165
- type="button"
3166
- aria-label=${launcherLabel}
3167
- title=${launcherLabel}
3168
- ?hidden=${!this.hasAttribute("launcher")}
3169
- ?disabled=${this.hasAttribute("launcher-disabled")}
3170
- @click=${this.onLauncher}
3171
- >${glyph("launcher", "launcher-icon")}</button
3172
- >
3173
- </div>
3174
- </div>
3175
- `;
3176
- }
3177
- };
3178
- var defineRibbonGroup = definer("office-ui-ribbon-group", () => OfficeUiRibbonGroup);
3187
+ var defineOptionsDialog = definer(
3188
+ "office-ui-options-dialog",
3189
+ () => OfficeUiOptionsDialog,
3190
+ [defineDialog]
3191
+ );
3179
3192
 
3180
3193
  // raw-css:/home/runner/work/ooxml/ooxml/packages/ui/src/ribbon/ribbon-stack.css?raw
3181
3194
  var ribbon_stack_default = ":host {\n display: inline-flex;\n flex-direction: column;\n align-items: flex-start;\n justify-content: flex-start;\n gap: var(--office-space-px);\n align-self: stretch;\n}\n:host([orientation='horizontal']) {\n flex-direction: row;\n align-items: center;\n gap: var(--office-space-0);\n align-self: auto;\n}\n::slotted(*) {\n flex-shrink: 0;\n}\n";
@@ -3680,6 +3693,7 @@ var OfficeUiStatusBar = class extends OfficeElement {
3680
3693
  aria-label=${spec.label}
3681
3694
  aria-pressed=${ifDefined(spec.pressed === void 0 ? void 0 : String(spec.pressed))}
3682
3695
  ?hidden=${spec.hidden === true}
3696
+ ?disabled=${spec.disabled === true}
3683
3697
  @click=${() => this.activate(spec.id)}
3684
3698
  @keydown=${this.onKeydown}
3685
3699
  >${glyph(spec.icon, "icon")}${spec.text ? html`<span class="label">${spec.text}</span>` : ""}</button
@@ -4225,7 +4239,10 @@ var OfficeUiTitleBar = class extends OfficeElement {
4225
4239
  `;
4226
4240
  }
4227
4241
  };
4228
- var defineTitleBar = definer("office-ui-title-bar", () => OfficeUiTitleBar);
4242
+ var defineTitleBar = definer("office-ui-title-bar", () => OfficeUiTitleBar, [
4243
+ defineSearchField,
4244
+ defineSwitch
4245
+ ]);
4229
4246
 
4230
4247
  // raw-css:/home/runner/work/ooxml/ooxml/packages/ui/src/form/zoom-slider.css?raw
4231
4248
  var zoom_slider_default = ":host {\n display: inline-flex;\n align-items: center;\n gap: var(--office-space-0);\n font-size: var(--office-font-size-xs);\n color: var(--office-foreground);\n font-family: var(--office-font);\n}\nbutton {\n box-sizing: border-box;\n display: inline-grid;\n place-items: center;\n min-width: var(--office-target-size);\n min-height: var(--office-target-size);\n padding: 0;\n border: var(--office-border-width) solid transparent;\n border-radius: var(--office-radius);\n background: transparent;\n color: inherit;\n font: inherit;\n font-size: var(--office-font-size-lg);\n line-height: 1;\n cursor: pointer;\n}\nbutton:hover:not(:disabled) {\n background: var(--office-background);\n}\nbutton:focus-visible,\ninput:focus-visible {\n outline: var(--office-focus-width) solid var(--office-ring);\n outline-offset: calc(var(--office-focus-offset) / 2);\n}\nbutton:disabled,\ninput:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\ninput {\n width: var(--office-zoom-slider-width);\n min-width: var(--office-zoom-slider-min-width);\n margin: 0 var(--office-space-0);\n accent-color: var(--office-accent);\n}\noutput {\n min-width: var(--office-zoom-value-width);\n text-align: center;\n font-variant-numeric: tabular-nums;\n}\nsvg {\n width: var(--office-icon-size-md);\n height: var(--office-icon-size-md);\n fill: none;\n stroke: currentColor;\n stroke-width: var(--office-icon-stroke);\n stroke-linecap: round;\n stroke-linejoin: round;\n}\n:host(:not([fit])) .fit {\n display: none;\n}\n\n@media (pointer: coarse), (max-width: 767px) {\n input {\n flex: 1;\n }\n}\n@media (forced-colors: active) {\n button {\n color: ButtonText;\n }\n button:disabled {\n color: GrayText;\n }\n}\n";
@@ -22,9 +22,11 @@ function defineOnce(registry, tag, make) {
22
22
  function browserRegistry() {
23
23
  return typeof window === "undefined" ? void 0 : window.customElements;
24
24
  }
25
- function definer(tag, make) {
25
+ function definer(tag, make, requires = []) {
26
26
  const define = (registry = browserRegistry()) => {
27
- if (registry) defineOnce(registry, tag, make);
27
+ if (!registry) return;
28
+ for (const dependency of requires) dependency(registry);
29
+ defineOnce(registry, tag, make);
28
30
  };
29
31
  return Object.assign(define, { tag });
30
32
  }
@@ -1,4 +1,4 @@
1
- import { OfficeElement, controlStyles, definer } from './chunk-5A4REH6T.js';
1
+ import { OfficeElement, controlStyles, definer } from './chunk-PCZJV6HQ.js';
2
2
  import { html } from 'lit';
3
3
  import { normalizeHexColor } from 'ooxml-core/color';
4
4
 
@@ -1,6 +1,6 @@
1
1
  import { registerIcon, getIcon } from './chunk-HZ422LTR.js';
2
- import { initialsOf } from './chunk-E47762NY.js';
3
- import { definer, OfficeElement, controlStyles } from './chunk-5A4REH6T.js';
2
+ import { initialsOf } from './chunk-XQWRKHC2.js';
3
+ import { definer, OfficeElement, controlStyles } from './chunk-PCZJV6HQ.js';
4
4
  import { html, nothing, unsafeCSS, svg } from 'lit';
5
5
  import { repeat } from 'lit/directives/repeat.js';
6
6
  import { live } from 'lit/directives/live.js';
@@ -1,4 +1,4 @@
1
- import { OfficeElement, controlStyles, definer } from './chunk-5A4REH6T.js';
1
+ import { OfficeElement, controlStyles, definer } from './chunk-PCZJV6HQ.js';
2
2
  import { html } from 'lit';
3
3
 
4
4
  // raw-css:/home/runner/work/ooxml/ooxml/packages/ui/src/presence/presence.css?raw
package/dist/controls.js CHANGED
@@ -1,5 +1,5 @@
1
- export { CONTROL_DEFINERS, DEFAULT_OFFICE_PROFILE, EMPTY_MENU_STATE, OFFICE_AVATAR_SWATCHES, OFFICE_PROFILE_STORAGE_KEY, OFFICE_TITLE_BAR_SEARCH_LIMIT, OFFICE_TOAST_VISIBLE_LIMIT, attachKeyTips, clampFlyoutPosition, clampOptionNumber, clearOfficeProfile, defineAccount, defineBackstage, defineButton, defineCheckbox, defineCommandSearch, defineContextMenu, defineDialog, defineDialogFooter, defineFindBar, defineGallery, defineIcon, defineMenuButton, defineMenuItem, defineMenuSeparator, defineOptionsDialog, definePasteOptions, definePrintPreview, defineRadio, defineReadOnlyBanner, defineRibbon, defineRibbonGroup, defineRibbonSection, defineRibbonStack, defineRibbonToggle, defineRuler, defineSearchField, defineSelect, defineStatusBar, defineStatusItem, defineSwitch, defineTabStrip, defineTitleBar, defineToasts, defineToolbar, defineZoomSlider, nextEnabledIndex, parseSvgPreview, profileInitials, readOfficeProfile, registerControls, rulerDivisions, sanitizeOfficeProfile, typeAheadIndex, writeOfficeProfile } from './chunk-LKLZOPTO.js';
1
+ export { CONTROL_DEFINERS, DEFAULT_OFFICE_PROFILE, EMPTY_MENU_STATE, OFFICE_AVATAR_SWATCHES, OFFICE_PROFILE_STORAGE_KEY, OFFICE_TITLE_BAR_SEARCH_LIMIT, OFFICE_TOAST_VISIBLE_LIMIT, attachKeyTips, clampFlyoutPosition, clampOptionNumber, clearOfficeProfile, defineAccount, defineBackstage, defineButton, defineCheckbox, defineCommandSearch, defineContextMenu, defineDialog, defineDialogFooter, defineFindBar, defineGallery, defineIcon, defineMenuButton, defineMenuItem, defineMenuSeparator, defineOptionsDialog, definePasteOptions, definePrintPreview, defineRadio, defineReadOnlyBanner, defineRibbon, defineRibbonGroup, defineRibbonSection, defineRibbonStack, defineRibbonToggle, defineRuler, defineSearchField, defineSelect, defineStatusBar, defineStatusItem, defineSwitch, defineTabStrip, defineTitleBar, defineToasts, defineToolbar, defineZoomSlider, nextEnabledIndex, parseSvgPreview, profileInitials, readOfficeProfile, registerControls, rulerDivisions, sanitizeOfficeProfile, typeAheadIndex, writeOfficeProfile } from './chunk-FWZIVXAV.js';
2
2
  import './chunk-HZ422LTR.js';
3
- import './chunk-E47762NY.js';
4
- import './chunk-5A4REH6T.js';
3
+ import './chunk-XQWRKHC2.js';
4
+ import './chunk-PCZJV6HQ.js';
5
5
  import './chunk-HSJH6SUW.js';
@@ -29,10 +29,16 @@ export declare class OfficeUiDialog extends OfficeElement {
29
29
  dismissible: {
30
30
  type: StringConstructor;
31
31
  };
32
+ closeLabel: {
33
+ type: StringConstructor;
34
+ attribute: string;
35
+ };
32
36
  };
33
37
  open: boolean;
34
38
  heading: string;
35
39
  dismissible: string | null;
40
+ /** Name of the close button (English by default), so a product can translate it. */
41
+ closeLabel: string | null;
36
42
  private returnFocus;
37
43
  constructor();
38
44
  show(): void;
package/dist/index.js CHANGED
@@ -1,15 +1,15 @@
1
1
  import { installOfficeUiTheme } from './chunk-2X6QYQ3Q.js';
2
2
  export { THEME_CSS, THEME_STYLE_ID, installOfficeUiTheme } from './chunk-2X6QYQ3Q.js';
3
- import { registerControls } from './chunk-LKLZOPTO.js';
4
- export { CONTROL_DEFINERS, DEFAULT_OFFICE_PROFILE, EMPTY_MENU_STATE, OFFICE_AVATAR_SWATCHES, OFFICE_PROFILE_STORAGE_KEY, OFFICE_TITLE_BAR_SEARCH_LIMIT, OFFICE_TOAST_VISIBLE_LIMIT, attachKeyTips, clampFlyoutPosition, clampOptionNumber, clearOfficeProfile, defineAccount, defineBackstage, defineButton, defineCheckbox, defineCommandSearch, defineContextMenu, defineDialog, defineDialogFooter, defineFindBar, defineGallery, defineIcon, defineMenuButton, defineMenuItem, defineMenuSeparator, defineOptionsDialog, definePasteOptions, definePrintPreview, defineRadio, defineReadOnlyBanner, defineRibbon, defineRibbonGroup, defineRibbonSection, defineRibbonStack, defineRibbonToggle, defineRuler, defineSearchField, defineSelect, defineStatusBar, defineStatusItem, defineSwitch, defineTabStrip, defineTitleBar, defineToasts, defineToolbar, defineZoomSlider, glyph, nextEnabledIndex, parseSvgPreview, profileInitials, readOfficeProfile, registerControls, rulerDivisions, sanitizeOfficeProfile, typeAheadIndex, writeOfficeProfile } from './chunk-LKLZOPTO.js';
5
- import { defineSmartArt } from './chunk-3MDKXKKQ.js';
6
- export { OfficeUiSmartArt, defineSmartArt, renderDiagramDrawing } from './chunk-3MDKXKKQ.js';
7
- import { TEAMS_TAGS, registerTeams } from './chunk-HNGJI5EZ.js';
8
- export { EMOJI, OfficeUiAppRail, OfficeUiAvatar, OfficeUiCallControls, OfficeUiCallGrid, OfficeUiChannelList, OfficeUiChatComposer, OfficeUiChatList, OfficeUiPrejoin, QUICK_REACTIONS, TEAMS_TAGS, TeamsElement, colorFor, dayLabel, defineAppRail, defineAvatar, defineCallControls, defineCallGrid, defineChannelList, defineChatComposer, defineChatList, definePrejoin, formatElapsed, formatSize, formatTime, icon, registerTeams, withStyles } from './chunk-HNGJI5EZ.js';
3
+ import { registerControls } from './chunk-FWZIVXAV.js';
4
+ export { CONTROL_DEFINERS, DEFAULT_OFFICE_PROFILE, EMPTY_MENU_STATE, OFFICE_AVATAR_SWATCHES, OFFICE_PROFILE_STORAGE_KEY, OFFICE_TITLE_BAR_SEARCH_LIMIT, OFFICE_TOAST_VISIBLE_LIMIT, attachKeyTips, clampFlyoutPosition, clampOptionNumber, clearOfficeProfile, defineAccount, defineBackstage, defineButton, defineCheckbox, defineCommandSearch, defineContextMenu, defineDialog, defineDialogFooter, defineFindBar, defineGallery, defineIcon, defineMenuButton, defineMenuItem, defineMenuSeparator, defineOptionsDialog, definePasteOptions, definePrintPreview, defineRadio, defineReadOnlyBanner, defineRibbon, defineRibbonGroup, defineRibbonSection, defineRibbonStack, defineRibbonToggle, defineRuler, defineSearchField, defineSelect, defineStatusBar, defineStatusItem, defineSwitch, defineTabStrip, defineTitleBar, defineToasts, defineToolbar, defineZoomSlider, glyph, nextEnabledIndex, parseSvgPreview, profileInitials, readOfficeProfile, registerControls, rulerDivisions, sanitizeOfficeProfile, typeAheadIndex, writeOfficeProfile } from './chunk-FWZIVXAV.js';
5
+ import { defineSmartArt } from './chunk-RVZAYXTI.js';
6
+ export { OfficeUiSmartArt, defineSmartArt, renderDiagramDrawing } from './chunk-RVZAYXTI.js';
7
+ import { TEAMS_TAGS, registerTeams } from './chunk-TCBUC6BI.js';
8
+ export { EMOJI, OfficeUiAppRail, OfficeUiAvatar, OfficeUiCallControls, OfficeUiCallGrid, OfficeUiChannelList, OfficeUiChatComposer, OfficeUiChatList, OfficeUiPrejoin, QUICK_REACTIONS, TEAMS_TAGS, TeamsElement, colorFor, dayLabel, defineAppRail, defineAvatar, defineCallControls, defineCallGrid, defineChannelList, defineChatComposer, defineChatList, definePrejoin, formatElapsed, formatSize, formatTime, icon, registerTeams, withStyles } from './chunk-TCBUC6BI.js';
9
9
  export { createIconSvg, getIcon, listIcons, paintIcon, registerIcon } from './chunk-HZ422LTR.js';
10
- import { definePresence } from './chunk-E47762NY.js';
11
- export { OfficeUiPresence, definePresence, initialsOf, participantsFromAwareness } from './chunk-E47762NY.js';
12
- export { CONTRACT_REVISION, OfficeElement, controlStyles, flag, readFlag, triState, valueOn, withTokens } from './chunk-5A4REH6T.js';
10
+ import { definePresence } from './chunk-XQWRKHC2.js';
11
+ export { OfficeUiPresence, definePresence, initialsOf, participantsFromAwareness } from './chunk-XQWRKHC2.js';
12
+ export { CONTRACT_REVISION, OfficeElement, controlStyles, flag, readFlag, triState, valueOn, withTokens } from './chunk-PCZJV6HQ.js';
13
13
  export { COMPACT, FOCUS_RING, OFFICE_TOKENS, TOUCH, tok } from './chunk-HSJH6SUW.js';
14
14
 
15
15
  // src/index.ts
@@ -22,6 +22,8 @@ export interface OfficeMenuItem {
22
22
  icon?: string;
23
23
  /** Tooltip, for example why a disabled row is unavailable. */
24
24
  title?: string;
25
+ /** Shortcut hint shown at the trailing edge (Ctrl+C); also its `aria-keyshortcuts`. */
26
+ shortcut?: string;
25
27
  }
26
28
  /** Everything a controlled menu needs to draw. */
27
29
  export interface OfficeMenuState {
package/dist/presence.js CHANGED
@@ -1,3 +1,3 @@
1
- export { OfficeUiPresence, definePresence, initialsOf, participantsFromAwareness } from './chunk-E47762NY.js';
2
- import './chunk-5A4REH6T.js';
1
+ export { OfficeUiPresence, definePresence, initialsOf, participantsFromAwareness } from './chunk-XQWRKHC2.js';
2
+ import './chunk-PCZJV6HQ.js';
3
3
  import './chunk-HSJH6SUW.js';
@@ -12,8 +12,12 @@ export type Definer = ((registry?: CustomElementRegistry) => void) & {
12
12
  };
13
13
  /** The registry of the current window, or undefined where there is no DOM (SSR). */
14
14
  export declare function browserRegistry(): CustomElementRegistry | undefined;
15
- /** Wrap a per-tag `make` factory into a public, SSR-safe, idempotent definer. */
16
- export declare function definer(tag: string, make: () => CustomElementConstructor): Definer;
15
+ /**
16
+ * Wrap a per-tag `make` factory into a public, SSR-safe, idempotent definer. `requires` are the
17
+ * elements this one renders inside its own template; defining the composite defines them first, so
18
+ * a product that registers only the element it uses never gets a silently inert inner control.
19
+ */
20
+ export declare function definer(tag: string, make: () => CustomElementConstructor, requires?: readonly Definer[]): Definer;
17
21
  /** Bubbling, composed event: crosses shadow boundaries like the native ones do. */
18
22
  export declare function emit<T>(host: HTMLElement, type: string, detail: T, cancelable?: boolean): boolean;
19
23
  /**
package/dist/smartart.js CHANGED
@@ -1,3 +1,3 @@
1
- export { OfficeUiSmartArt, defineSmartArt, renderDiagramDrawing } from './chunk-3MDKXKKQ.js';
2
- import './chunk-5A4REH6T.js';
1
+ export { OfficeUiSmartArt, defineSmartArt, renderDiagramDrawing } from './chunk-RVZAYXTI.js';
2
+ import './chunk-PCZJV6HQ.js';
3
3
  import './chunk-HSJH6SUW.js';
package/dist/teams.js CHANGED
@@ -1,5 +1,5 @@
1
- export { EMOJI, OfficeUiAppRail, OfficeUiAvatar, OfficeUiCallControls, OfficeUiCallGrid, OfficeUiChannelList, OfficeUiChatComposer, OfficeUiChatList, OfficeUiPrejoin, QUICK_REACTIONS, TEAMS_TAGS, TeamsElement, colorFor, dayLabel, defineAppRail, defineAvatar, defineCallControls, defineCallGrid, defineChannelList, defineChatComposer, defineChatList, definePrejoin, formatElapsed, formatSize, formatTime, icon, registerTeams, withStyles } from './chunk-HNGJI5EZ.js';
1
+ export { EMOJI, OfficeUiAppRail, OfficeUiAvatar, OfficeUiCallControls, OfficeUiCallGrid, OfficeUiChannelList, OfficeUiChatComposer, OfficeUiChatList, OfficeUiPrejoin, QUICK_REACTIONS, TEAMS_TAGS, TeamsElement, colorFor, dayLabel, defineAppRail, defineAvatar, defineCallControls, defineCallGrid, defineChannelList, defineChatComposer, defineChatList, definePrejoin, formatElapsed, formatSize, formatTime, icon, registerTeams, withStyles } from './chunk-TCBUC6BI.js';
2
2
  import './chunk-HZ422LTR.js';
3
- import './chunk-E47762NY.js';
4
- import './chunk-5A4REH6T.js';
3
+ import './chunk-XQWRKHC2.js';
4
+ import './chunk-PCZJV6HQ.js';
5
5
  import './chunk-HSJH6SUW.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ooxml-ui",
3
- "version": "0.22.0",
3
+ "version": "0.24.0",
4
4
  "description": "Shared, format-neutral web components and styles for the Office viewers (Word, PowerPoint, Excel)",
5
5
  "keywords": [
6
6
  "custom-elements",
@@ -82,7 +82,7 @@
82
82
  },
83
83
  "dependencies": {
84
84
  "lit": "^3.3.3",
85
- "ooxml-core": "^0.15.0"
85
+ "ooxml-core": "^0.16.0"
86
86
  },
87
87
  "devDependencies": {
88
88
  "@types/jsdom": "^30.0.0",