ooxml-ui 0.14.0 → 0.16.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.
- package/README.md +34 -32
- package/dist/button.d.ts +7 -4
- package/dist/{chunk-BDJW2KDI.js → chunk-4MT4OIAJ.js} +22 -0
- package/dist/{chunk-4WUYOQRL.js → chunk-A46H2JBV.js} +2 -2
- package/dist/{chunk-7CCQN3VM.js → chunk-F4TM7U4P.js} +1 -1
- package/dist/{chunk-EWNLGZPX.js → chunk-G2ZIAXOV.js} +573 -65
- package/dist/{chunk-3BHP4IFP.js → chunk-NDEB6EBU.js} +1 -1
- package/dist/{chunk-WNSUNQIY.js → chunk-VUXNXH4Q.js} +1 -1
- package/dist/{chunk-WKLVWPI7.js → chunk-VYF7LGXZ.js} +2 -2
- package/dist/context-menu.d.ts +15 -5
- package/dist/controls.d.ts +1 -0
- package/dist/controls.js +5 -5
- package/dist/icons.js +3 -3
- package/dist/index.js +11 -11
- package/dist/menu-model.d.ts +75 -0
- package/dist/presence.js +3 -3
- package/dist/ribbon.d.ts +10 -3
- package/dist/smartart.js +3 -3
- package/dist/theme.js +2 -2
- package/dist/tokens.d.ts +22 -0
- package/package.json +13 -7
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { createIconSvg, paintIcon, defineIcon } from './chunk-
|
|
2
|
-
import { initialsOf } from './chunk-
|
|
3
|
-
import { definer, attachStyles, controlCss, emit } from './chunk-
|
|
4
|
-
import { tok, FOCUS_RING, OFFICE_TOKENS } from './chunk-
|
|
1
|
+
import { createIconSvg, paintIcon, defineIcon } from './chunk-VUXNXH4Q.js';
|
|
2
|
+
import { initialsOf } from './chunk-VYF7LGXZ.js';
|
|
3
|
+
import { definer, attachStyles, controlCss, emit } from './chunk-NDEB6EBU.js';
|
|
4
|
+
import { tok, FOCUS_RING, OFFICE_TOKENS } from './chunk-4MT4OIAJ.js';
|
|
5
5
|
|
|
6
6
|
// src/chrome-controls.ts
|
|
7
7
|
var ICON = `svg { flex: none; width: ${tok("--office-icon-size")}; height: ${tok("--office-icon-size")}; fill: none; stroke: currentColor; stroke-width: ${tok("--office-icon-stroke")};
|
|
@@ -702,6 +702,8 @@ var defineRibbonToggle = definer("office-ui-ribbon-toggle", () => {
|
|
|
702
702
|
static requestEvent = "office-toggle";
|
|
703
703
|
static idAttribute = "command";
|
|
704
704
|
static detailKey = "command";
|
|
705
|
+
/** The checkbox drawn inside; a product subclass may use its own aliased tag. */
|
|
706
|
+
static checkboxTag = "office-ui-checkbox";
|
|
705
707
|
static get observedAttributes() {
|
|
706
708
|
return ["label", "checked", "disabled", "title"];
|
|
707
709
|
}
|
|
@@ -713,7 +715,9 @@ var defineRibbonToggle = definer("office-ui-ribbon-toggle", () => {
|
|
|
713
715
|
const root = this.attachShadow({ mode: "open" });
|
|
714
716
|
attachStyles(root, controlCss(CSS2));
|
|
715
717
|
const label = doc.createElement("label");
|
|
716
|
-
this.checkbox = doc.createElement(
|
|
718
|
+
this.checkbox = doc.createElement(
|
|
719
|
+
this.constructor.checkboxTag
|
|
720
|
+
);
|
|
717
721
|
this.text = doc.createTextNode("");
|
|
718
722
|
label.append(this.checkbox, this.text);
|
|
719
723
|
label.addEventListener("click", (event) => {
|
|
@@ -1770,56 +1774,114 @@ var defineAccount = definer("office-ui-account", () => {
|
|
|
1770
1774
|
// src/button.ts
|
|
1771
1775
|
var CSS10 = `
|
|
1772
1776
|
:host { display: inline-flex; vertical-align: middle; }
|
|
1773
|
-
button { box-sizing: border-box; display: inline-flex; align-items: center; justify-content: center;
|
|
1777
|
+
button { box-sizing: border-box; position: relative; display: inline-flex; align-items: center; justify-content: center;
|
|
1774
1778
|
gap: ${tok("--office-space-1-5")}; min-width: ${tok("--office-target-size")}; min-height: ${tok("--office-target-size")};
|
|
1775
1779
|
padding: 0 ${tok("--office-space-2")}; border: ${tok("--office-border-width")} solid transparent; border-radius: ${tok("--office-radius")};
|
|
1776
1780
|
background: transparent; color: ${tok("--office-foreground")}; font: inherit; font-size: ${tok("--office-font-size-sm")};
|
|
1777
1781
|
cursor: pointer; white-space: nowrap; }
|
|
1778
1782
|
:host([variant="stacked"]) button { flex-direction: column; padding: ${tok("--office-space-1")} ${tok("--office-space-2")}; }
|
|
1779
1783
|
button:hover:not(:disabled) { background: ${tok("--office-surface")}; }
|
|
1784
|
+
button:active:not(:disabled) { background: ${tok("--office-selected")}; }
|
|
1780
1785
|
button:focus-visible { outline: ${tok("--office-focus-width")} solid ${tok("--office-ring")}; outline-offset: calc(${tok("--office-focus-offset")} / 2); }
|
|
1781
1786
|
button[aria-pressed="true"], button[aria-expanded="true"] { border-color: ${tok("--office-accent")};
|
|
1782
1787
|
background: ${tok("--office-surface")}; }
|
|
1788
|
+
:host([active]) button { background: ${tok("--office-command-active")}; color: ${tok("--office-accent")}; }
|
|
1783
1789
|
button:disabled { opacity: .5; cursor: not-allowed; }
|
|
1784
|
-
svg { width: ${tok("--office-icon-size-ml")}; height: ${tok("--office-icon-size-ml")};
|
|
1785
|
-
stroke-linecap: round; stroke-linejoin: round; }
|
|
1786
|
-
svg:not([data-painted]) { display: none; }
|
|
1790
|
+
svg { width: ${tok("--office-icon-size-ml")}; height: ${tok("--office-icon-size-ml")}; flex: none; color: ${tok("--office-command-icon-color")};
|
|
1791
|
+
fill: none; stroke: currentColor; stroke-width: ${tok("--office-icon-stroke")}; stroke-linecap: round; stroke-linejoin: round; }
|
|
1792
|
+
svg.glyph:not([data-painted]) { display: none; }
|
|
1793
|
+
.label[hidden], .caret[hidden], .badge[hidden] { display: none; }
|
|
1794
|
+
/* Office trails a menu chevron after the last line of the label. */
|
|
1795
|
+
.caret { display: inline-block; width: ${tok("--office-icon-size-xs")}; height: ${tok("--office-icon-size-xs")};
|
|
1796
|
+
margin-inline-start: ${tok("--office-space-0")}; vertical-align: middle; color: ${tok("--office-muted-foreground")}; }
|
|
1797
|
+
.badge { position: absolute; top: 0; inset-inline-end: 0; padding: 0 ${tok("--office-space-0")}; border-radius: ${tok("--office-radius-full")};
|
|
1798
|
+
background: ${tok("--office-accent")}; color: ${tok("--office-accent-foreground")}; font-size: ${tok("--office-font-size-3xs")}; }
|
|
1799
|
+
/* Large ribbon command: a big glyph above a two-line label. */
|
|
1800
|
+
:host([size="large"]) button { flex-direction: column; justify-content: flex-start; gap: ${tok("--office-space-0")};
|
|
1801
|
+
min-width: ${tok("--office-command-large-min-width")}; max-width: ${tok("--office-command-large-max-width")};
|
|
1802
|
+
height: ${tok("--office-command-large-height")}; padding: ${tok("--office-space-0")} ${tok("--office-space-1")};
|
|
1803
|
+
border: 0; white-space: normal; text-align: center; line-height: ${tok("--office-line-height-tight")}; }
|
|
1804
|
+
:host([size="large"]) svg.glyph { width: ${tok("--office-command-large-icon")}; height: ${tok("--office-command-large-icon")}; }
|
|
1805
|
+
/* Small ribbon command: icon and label in one row. */
|
|
1806
|
+
:host([size="small"]) button { justify-content: flex-start; min-width: 0; height: ${tok("--office-control-height")};
|
|
1807
|
+
min-height: ${tok("--office-control-height")}; padding: 0 ${tok("--office-space-1-5")}; border: 0; text-align: start; }
|
|
1808
|
+
:host([size="small"]) svg.glyph { width: ${tok("--office-command-small-icon")}; height: ${tok("--office-command-small-icon")}; }
|
|
1809
|
+
/* Tall, label-less tool tiles (pens, erasers). */
|
|
1810
|
+
:host([icon-only][tall]) button { min-width: ${tok("--office-command-tall-min-width")}; height: ${tok("--office-command-tall-height")}; padding: ${tok("--office-space-1")}; }
|
|
1811
|
+
:host([icon-only][tall]) svg.glyph { width: ${tok("--office-command-tall-icon")}; height: ${tok("--office-command-tall-icon")}; }
|
|
1812
|
+
:host([icon-only][tall][active]) button { box-shadow: inset 0 0 0 ${tok("--office-border-width")} ${tok("--office-accent")}; }
|
|
1813
|
+
@media (pointer: coarse), (max-width: 767px) {
|
|
1814
|
+
:host([size="small"]) button { min-height: ${tok("--office-target-size-touch")}; }
|
|
1815
|
+
:host([icon-only]) button { min-width: ${tok("--office-target-size-touch")}; }
|
|
1816
|
+
}
|
|
1787
1817
|
@media (forced-colors: active) {
|
|
1788
1818
|
button { border-color: ButtonText; color: ButtonText; background: ButtonFace; }
|
|
1819
|
+
svg { color: ButtonText; }
|
|
1789
1820
|
button:disabled { color: GrayText; border-color: GrayText; }
|
|
1790
|
-
button[aria-pressed="true"], button[aria-expanded="true"] { background: Highlight; color: HighlightText; }
|
|
1821
|
+
button[aria-pressed="true"], button[aria-expanded="true"], :host([active]) button { background: Highlight; color: HighlightText; }
|
|
1791
1822
|
}
|
|
1792
1823
|
`;
|
|
1793
1824
|
var defineButton = definer("office-ui-button", () => {
|
|
1794
1825
|
class OfficeUiButton extends HTMLElement {
|
|
1795
|
-
static
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1826
|
+
static requestEvent = "office-command";
|
|
1827
|
+
static idAttribute = "command";
|
|
1828
|
+
static detailKey = "command";
|
|
1829
|
+
static get observedAttributes() {
|
|
1830
|
+
return [
|
|
1831
|
+
"label",
|
|
1832
|
+
"icon",
|
|
1833
|
+
"command",
|
|
1834
|
+
"disabled",
|
|
1835
|
+
"pressed",
|
|
1836
|
+
"expanded",
|
|
1837
|
+
"icon-only",
|
|
1838
|
+
"title",
|
|
1839
|
+
"keyshortcuts",
|
|
1840
|
+
"badge",
|
|
1841
|
+
"caret",
|
|
1842
|
+
this.idAttribute
|
|
1843
|
+
];
|
|
1844
|
+
}
|
|
1806
1845
|
button;
|
|
1807
1846
|
svg;
|
|
1808
1847
|
text;
|
|
1848
|
+
caret;
|
|
1849
|
+
badge;
|
|
1809
1850
|
constructor() {
|
|
1810
1851
|
super();
|
|
1852
|
+
const doc = this.ownerDocument;
|
|
1811
1853
|
const root = this.attachShadow({ mode: "open", delegatesFocus: true });
|
|
1812
1854
|
attachStyles(root, controlCss(CSS10));
|
|
1813
|
-
this.button =
|
|
1855
|
+
this.button = doc.createElement("button");
|
|
1814
1856
|
this.button.type = "button";
|
|
1815
1857
|
this.button.setAttribute("part", "button");
|
|
1816
|
-
this.svg = createIconSvg(
|
|
1817
|
-
this.
|
|
1818
|
-
this.
|
|
1858
|
+
this.svg = createIconSvg(doc);
|
|
1859
|
+
this.svg.classList.add("glyph");
|
|
1860
|
+
this.text = doc.createElement("span");
|
|
1861
|
+
this.text.className = "label";
|
|
1862
|
+
this.caret = createIconSvg(doc);
|
|
1863
|
+
this.caret.classList.add("caret");
|
|
1864
|
+
paintIcon(this.caret, "chevronDown");
|
|
1865
|
+
this.badge = doc.createElement("span");
|
|
1866
|
+
this.badge.className = "badge";
|
|
1867
|
+
this.badge.setAttribute("aria-hidden", "true");
|
|
1868
|
+
this.button.append(this.svg, this.text, this.badge);
|
|
1819
1869
|
root.append(this.button);
|
|
1870
|
+
this.button.addEventListener("keydown", (event) => {
|
|
1871
|
+
if ((event.key === " " || event.key === "Enter") && !event.ctrlKey && !event.metaKey && !event.altKey)
|
|
1872
|
+
event.stopPropagation();
|
|
1873
|
+
});
|
|
1820
1874
|
this.button.addEventListener("click", () => {
|
|
1821
|
-
const
|
|
1822
|
-
|
|
1875
|
+
const { requestEvent, idAttribute, detailKey } = this.constructor;
|
|
1876
|
+
const id = this.getAttribute(idAttribute);
|
|
1877
|
+
if (!this.button.disabled && id)
|
|
1878
|
+
this.dispatchEvent(
|
|
1879
|
+
new CustomEvent(requestEvent, {
|
|
1880
|
+
detail: { [detailKey]: id },
|
|
1881
|
+
bubbles: true,
|
|
1882
|
+
composed: true
|
|
1883
|
+
})
|
|
1884
|
+
);
|
|
1823
1885
|
});
|
|
1824
1886
|
}
|
|
1825
1887
|
connectedCallback() {
|
|
@@ -1842,10 +1904,21 @@ var defineButton = definer("office-ui-button", () => {
|
|
|
1842
1904
|
if (value === void 0) this.removeAttribute("pressed");
|
|
1843
1905
|
else this.setAttribute("pressed", String(value));
|
|
1844
1906
|
}
|
|
1907
|
+
/** The registered icon to draw; a product subclass may map names onto its glyph set. */
|
|
1908
|
+
iconName() {
|
|
1909
|
+
return this.getAttribute("icon");
|
|
1910
|
+
}
|
|
1911
|
+
/** Whether the trailing menu chevron shows. */
|
|
1912
|
+
showsCaret() {
|
|
1913
|
+
const caret = this.getAttribute("caret");
|
|
1914
|
+
return caret !== null && caret !== "false";
|
|
1915
|
+
}
|
|
1845
1916
|
sync() {
|
|
1846
1917
|
const label = this.getAttribute("label") ?? "";
|
|
1847
1918
|
const iconOnly = this.hasAttribute("icon-only");
|
|
1848
1919
|
this.text.textContent = label;
|
|
1920
|
+
this.text.append(this.caret);
|
|
1921
|
+
this.caret.toggleAttribute("hidden", !this.showsCaret());
|
|
1849
1922
|
this.text.hidden = iconOnly;
|
|
1850
1923
|
if (iconOnly && label) this.button.setAttribute("aria-label", label);
|
|
1851
1924
|
else this.button.removeAttribute("aria-label");
|
|
@@ -1854,8 +1927,10 @@ var defineButton = definer("office-ui-button", () => {
|
|
|
1854
1927
|
const shortcuts = this.getAttribute("keyshortcuts");
|
|
1855
1928
|
if (shortcuts) this.button.setAttribute("aria-keyshortcuts", shortcuts);
|
|
1856
1929
|
else this.button.removeAttribute("aria-keyshortcuts");
|
|
1857
|
-
if (paintIcon(this.svg, this.
|
|
1930
|
+
if (paintIcon(this.svg, this.iconName())) this.svg.setAttribute("data-painted", "");
|
|
1858
1931
|
else this.svg.removeAttribute("data-painted");
|
|
1932
|
+
this.badge.textContent = this.getAttribute("badge") ?? "";
|
|
1933
|
+
this.badge.hidden = !this.badge.textContent;
|
|
1859
1934
|
for (const attr of ["pressed", "expanded"]) {
|
|
1860
1935
|
const value = this.getAttribute(attr);
|
|
1861
1936
|
if (value === null) this.button.removeAttribute(`aria-${attr}`);
|
|
@@ -2327,21 +2402,85 @@ var defineCommandSearch = definer("office-ui-command-search", () => {
|
|
|
2327
2402
|
return OfficeUiCommandSearch;
|
|
2328
2403
|
});
|
|
2329
2404
|
|
|
2405
|
+
// src/menu-model.ts
|
|
2406
|
+
var EMPTY_MENU_STATE = { x: 0, y: 0, label: "", items: [] };
|
|
2407
|
+
function nextEnabledIndex(items, from, step) {
|
|
2408
|
+
const count = items.length;
|
|
2409
|
+
for (let offset = 1; offset <= count; offset += 1) {
|
|
2410
|
+
const index = ((from + step * offset) % count + count) % count;
|
|
2411
|
+
if (!items[index]?.disabled) return index;
|
|
2412
|
+
}
|
|
2413
|
+
return -1;
|
|
2414
|
+
}
|
|
2415
|
+
function typeAheadIndex(items, from, query) {
|
|
2416
|
+
const needle = query.toLowerCase();
|
|
2417
|
+
const cycling = [...needle].every((char) => char === needle[0]);
|
|
2418
|
+
const prefix = cycling ? needle[0] : needle;
|
|
2419
|
+
for (let offset = cycling ? 1 : 0; offset <= items.length; offset += 1) {
|
|
2420
|
+
const index = (from + offset + items.length) % items.length;
|
|
2421
|
+
const item = items[index];
|
|
2422
|
+
if (item && !item.disabled && item.label.trim().toLowerCase().startsWith(prefix ?? ""))
|
|
2423
|
+
return index;
|
|
2424
|
+
}
|
|
2425
|
+
return -1;
|
|
2426
|
+
}
|
|
2427
|
+
function clampFlyoutPosition(input) {
|
|
2428
|
+
const margin = input.margin ?? 8;
|
|
2429
|
+
const maxLeft = input.viewportWidth - input.width - margin;
|
|
2430
|
+
const maxTop = input.viewportHeight - input.height - margin;
|
|
2431
|
+
return {
|
|
2432
|
+
left: Math.max(margin, input.width > 0 ? Math.min(input.x, maxLeft) : input.x),
|
|
2433
|
+
top: Math.max(margin, input.height > 0 ? Math.min(input.y, maxTop) : input.y)
|
|
2434
|
+
};
|
|
2435
|
+
}
|
|
2436
|
+
|
|
2330
2437
|
// src/context-menu.ts
|
|
2331
2438
|
var CSS13 = `
|
|
2332
2439
|
:host { display: contents; }
|
|
2440
|
+
:host([data-controlled]) { display: block; position: fixed; z-index: ${tok("--office-z-popover")};
|
|
2441
|
+
color: ${tok("--office-popover-foreground")}; font: ${tok("--office-font-size-sm")}/${tok("--office-line-height")} ${tok("--office-font")}; }
|
|
2442
|
+
:host([data-controlled][hidden]) { display: none; }
|
|
2333
2443
|
.panel { position: fixed; inset: auto; margin: 0; min-width: ${tok("--office-context-menu-min-width")}; padding: ${tok("--office-space-1")}; box-sizing: border-box;
|
|
2334
2444
|
background: ${tok("--office-background")}; color: ${tok("--office-foreground")};
|
|
2335
2445
|
border: ${tok("--office-border-width")} solid ${tok("--office-border")}; border-radius: ${tok("--office-radius")};
|
|
2336
2446
|
box-shadow: ${tok("--office-shadow")}; font-family: ${tok("--office-font")}; }
|
|
2337
2447
|
.panel[hidden] { display: none; }
|
|
2338
|
-
|
|
2448
|
+
/* Controlled mode: the host is the fixed box; rows are drawn here from \`state\`. */
|
|
2449
|
+
.menu { box-sizing: border-box; display: flex; flex-direction: column; min-width: ${tok("--office-menu-min-width")};
|
|
2450
|
+
max-height: calc(100vh - 2 * ${tok("--office-space-2")}); overflow-y: auto; padding: ${tok("--office-space-1-5")} 0;
|
|
2451
|
+
border: ${tok("--office-border-width")} solid ${tok("--office-border")}; border-radius: ${tok("--office-radius-md")};
|
|
2452
|
+
background: ${tok("--office-popover")}; color: inherit; box-shadow: ${tok("--office-shadow-lg")}; user-select: none; }
|
|
2453
|
+
.menu:focus { outline: none; }
|
|
2454
|
+
.item { box-sizing: border-box; display: flex; align-items: center; gap: ${tok("--office-space-1-5")}; width: 100%;
|
|
2455
|
+
min-height: ${tok("--office-field-height")}; padding: ${tok("--office-space-1-5")} ${tok("--office-space-3")}; border: 0;
|
|
2456
|
+
background: transparent; color: inherit; font: inherit; text-align: start; white-space: nowrap; cursor: pointer; }
|
|
2457
|
+
.item:hover:not(:disabled), .item:focus:not(:disabled) { background: ${tok("--office-selected")}; outline: none; }
|
|
2458
|
+
.item:focus-visible { outline: ${tok("--office-focus-width")} solid ${tok("--office-ring")}; outline-offset: calc(-1 * ${tok("--office-focus-width")}); }
|
|
2459
|
+
.item:disabled { opacity: .45; cursor: default; }
|
|
2460
|
+
.item.danger { color: ${tok("--office-danger")}; }
|
|
2461
|
+
.item svg { width: ${tok("--office-icon-size-md")}; height: ${tok("--office-icon-size-md")}; flex: none; fill: none; stroke: currentColor;
|
|
2462
|
+
stroke-width: ${tok("--office-icon-stroke")}; stroke-linecap: round; stroke-linejoin: round; }
|
|
2463
|
+
.check { flex: none; width: ${tok("--office-icon-size")}; text-align: center; }
|
|
2464
|
+
.separator { height: ${tok("--office-border-width")}; margin: ${tok("--office-space-1")} 0; background: ${tok("--office-border")}; }
|
|
2465
|
+
.heading { padding: ${tok("--office-space-1-5")} ${tok("--office-space-3")} ${tok("--office-space-0")}; color: ${tok("--office-muted-foreground")};
|
|
2466
|
+
font-size: ${tok("--office-font-size-2xs")}; font-weight: ${tok("--office-font-weight-bold")}; letter-spacing: .06em; text-transform: uppercase; }
|
|
2467
|
+
@media (pointer: coarse) { .item { min-height: ${tok("--office-target-size-touch")}; } }
|
|
2468
|
+
@media (forced-colors: active) {
|
|
2469
|
+
.panel, .menu { border-color: CanvasText; background: Canvas; color: CanvasText; box-shadow: none; }
|
|
2470
|
+
.item, .item.danger { color: CanvasText; }
|
|
2471
|
+
.item:disabled { color: GrayText; opacity: 1; }
|
|
2472
|
+
.item:hover:not(:disabled), .item:focus:not(:disabled) { background: Highlight; color: HighlightText; }
|
|
2473
|
+
.separator { background: CanvasText; }
|
|
2474
|
+
.heading { color: CanvasText; }
|
|
2475
|
+
}
|
|
2339
2476
|
`;
|
|
2340
2477
|
var SEPARATOR_CSS = `
|
|
2341
2478
|
:host { display: block; height: ${tok("--office-border-width")}; margin: ${tok("--office-space-1")} ${tok("--office-space-1-5")}; background: ${tok("--office-border")}; }
|
|
2342
2479
|
@media (forced-colors: active) { :host { background: CanvasText; } }
|
|
2343
2480
|
`;
|
|
2344
2481
|
var ITEMS = "office-ui-menu-item:not([disabled]):not([hidden])";
|
|
2482
|
+
var TYPE_AHEAD_MS = 700;
|
|
2483
|
+
var openMenus = /* @__PURE__ */ new WeakMap();
|
|
2345
2484
|
var defineMenuSeparator = definer("office-ui-menu-separator", () => {
|
|
2346
2485
|
class OfficeUiMenuSeparator extends HTMLElement {
|
|
2347
2486
|
constructor() {
|
|
@@ -2356,10 +2495,25 @@ var defineMenuSeparator = definer("office-ui-menu-separator", () => {
|
|
|
2356
2495
|
});
|
|
2357
2496
|
var defineContextMenu = definer("office-ui-context-menu", () => {
|
|
2358
2497
|
class OfficeUiContextMenu extends HTMLElement {
|
|
2498
|
+
static requestEvent = "office-menu-request";
|
|
2499
|
+
static closeEvent = "office-menu-close";
|
|
2500
|
+
static markerPattern = /^data-[a-z0-9-]+$/;
|
|
2359
2501
|
static observedAttributes = ["label"];
|
|
2360
2502
|
panel;
|
|
2503
|
+
menu;
|
|
2361
2504
|
returnFocus = null;
|
|
2362
2505
|
outside;
|
|
2506
|
+
model = EMPTY_MENU_STATE;
|
|
2507
|
+
controlled = false;
|
|
2508
|
+
rows = [];
|
|
2509
|
+
active = -1;
|
|
2510
|
+
focused = false;
|
|
2511
|
+
query = "";
|
|
2512
|
+
queryTimer;
|
|
2513
|
+
markers = [];
|
|
2514
|
+
listening = false;
|
|
2515
|
+
signature = "";
|
|
2516
|
+
opener = null;
|
|
2363
2517
|
constructor() {
|
|
2364
2518
|
super();
|
|
2365
2519
|
const doc = this.ownerDocument;
|
|
@@ -2372,22 +2526,49 @@ var defineContextMenu = definer("office-ui-context-menu", () => {
|
|
|
2372
2526
|
this.panel.setAttribute("popover", "auto");
|
|
2373
2527
|
else this.panel.hidden = true;
|
|
2374
2528
|
this.panel.append(doc.createElement("slot"));
|
|
2375
|
-
|
|
2529
|
+
this.menu = doc.createElement("div");
|
|
2530
|
+
this.menu.className = "menu";
|
|
2531
|
+
this.menu.setAttribute("role", "menu");
|
|
2532
|
+
this.menu.setAttribute("aria-orientation", "vertical");
|
|
2533
|
+
this.menu.tabIndex = -1;
|
|
2534
|
+
this.menu.hidden = true;
|
|
2535
|
+
root.append(this.panel, this.menu);
|
|
2376
2536
|
this.panel.addEventListener("toggle", (event) => {
|
|
2377
2537
|
if (event.newState === "closed") this.closed(false);
|
|
2378
2538
|
});
|
|
2379
|
-
this.panel.addEventListener("keydown", (event) => this.
|
|
2539
|
+
this.panel.addEventListener("keydown", (event) => this.onChildKey(event));
|
|
2540
|
+
this.menu.addEventListener("keydown", (event) => this.onRowKey(event));
|
|
2541
|
+
this.menu.addEventListener("pointerover", (event) => {
|
|
2542
|
+
const row = event.target?.closest("button");
|
|
2543
|
+
const index = row ? this.rows.indexOf(row) : -1;
|
|
2544
|
+
if (index >= 0 && !row?.disabled && index !== this.active) this.focusRow(index);
|
|
2545
|
+
});
|
|
2546
|
+
this.menu.addEventListener("contextmenu", (event) => event.preventDefault());
|
|
2380
2547
|
this.addEventListener("office-command", () => this.close());
|
|
2381
2548
|
}
|
|
2382
2549
|
connectedCallback() {
|
|
2383
2550
|
this.panel.setAttribute("aria-label", this.getAttribute("label") ?? "Context menu");
|
|
2551
|
+
if (this.controlled) {
|
|
2552
|
+
this.opener = this.deepActive();
|
|
2553
|
+
this.render();
|
|
2554
|
+
}
|
|
2384
2555
|
}
|
|
2385
2556
|
attributeChangedCallback() {
|
|
2386
2557
|
this.panel.setAttribute("aria-label", this.getAttribute("label") ?? "Context menu");
|
|
2387
2558
|
}
|
|
2388
2559
|
disconnectedCallback() {
|
|
2389
2560
|
this.close();
|
|
2561
|
+
if (!this.controlled) return;
|
|
2562
|
+
this.stopListening();
|
|
2563
|
+
clearTimeout(this.queryTimer);
|
|
2564
|
+
this.focused = false;
|
|
2565
|
+
const opener = this.opener;
|
|
2566
|
+
this.opener = null;
|
|
2567
|
+
const active = this.ownerDocument.activeElement;
|
|
2568
|
+
if (opener?.isConnected && (!active || active === this.ownerDocument.body))
|
|
2569
|
+
opener.focus({ preventScroll: true });
|
|
2390
2570
|
}
|
|
2571
|
+
// ---- Children mode ------------------------------------------------------------------
|
|
2391
2572
|
get open() {
|
|
2392
2573
|
return this.hasAttribute("data-open");
|
|
2393
2574
|
}
|
|
@@ -2410,12 +2591,17 @@ var defineContextMenu = definer("office-ui-context-menu", () => {
|
|
|
2410
2591
|
}
|
|
2411
2592
|
this.setAttribute("data-open", "");
|
|
2412
2593
|
const view = doc.defaultView;
|
|
2413
|
-
const
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2594
|
+
const { left, top } = clampFlyoutPosition({
|
|
2595
|
+
x,
|
|
2596
|
+
y,
|
|
2597
|
+
width: this.panel.offsetWidth,
|
|
2598
|
+
height: this.panel.offsetHeight,
|
|
2599
|
+
viewportWidth: view?.innerWidth ?? x,
|
|
2600
|
+
viewportHeight: view?.innerHeight ?? y,
|
|
2601
|
+
margin: 4
|
|
2602
|
+
});
|
|
2603
|
+
this.panel.style.left = `${Math.round(left)}px`;
|
|
2604
|
+
this.panel.style.top = `${Math.round(top)}px`;
|
|
2419
2605
|
this.items()[0]?.focus();
|
|
2420
2606
|
}
|
|
2421
2607
|
close() {
|
|
@@ -2436,7 +2622,7 @@ var defineContextMenu = definer("office-ui-context-menu", () => {
|
|
|
2436
2622
|
if (restoreFocus) this.returnFocus?.focus?.();
|
|
2437
2623
|
this.returnFocus = null;
|
|
2438
2624
|
}
|
|
2439
|
-
|
|
2625
|
+
onChildKey(event) {
|
|
2440
2626
|
const items = this.items();
|
|
2441
2627
|
const from = items.findIndex(
|
|
2442
2628
|
(item) => item === event.target || item.contains(event.target)
|
|
@@ -2452,8 +2638,217 @@ var defineContextMenu = definer("office-ui-context-menu", () => {
|
|
|
2452
2638
|
else if (event.key === "Escape" || event.key === "Tab") {
|
|
2453
2639
|
if (event.key === "Escape") event.preventDefault();
|
|
2454
2640
|
this.close();
|
|
2641
|
+
} else if (event.key.length === 1 && event.key !== " " && !event.ctrlKey && !event.metaKey && !event.altKey) {
|
|
2642
|
+
const labels = items.map((item) => ({
|
|
2643
|
+
label: item.getAttribute("label") ?? item.textContent ?? ""
|
|
2644
|
+
}));
|
|
2645
|
+
const target = this.typeAhead(labels, from, event.key);
|
|
2646
|
+
if (target >= 0) move(target);
|
|
2647
|
+
}
|
|
2648
|
+
}
|
|
2649
|
+
// ---- Controlled mode ----------------------------------------------------------------
|
|
2650
|
+
get state() {
|
|
2651
|
+
return this.model;
|
|
2652
|
+
}
|
|
2653
|
+
set state(value) {
|
|
2654
|
+
const signature = JSON.stringify(value);
|
|
2655
|
+
this.model = value;
|
|
2656
|
+
if (!this.controlled) {
|
|
2657
|
+
this.controlled = true;
|
|
2658
|
+
this.toggleAttribute("data-controlled", true);
|
|
2659
|
+
this.panel.remove();
|
|
2660
|
+
if (this.isConnected) this.opener = this.deepActive();
|
|
2661
|
+
}
|
|
2662
|
+
if (signature !== this.signature) {
|
|
2663
|
+
this.signature = signature;
|
|
2664
|
+
this.render();
|
|
2455
2665
|
}
|
|
2456
2666
|
}
|
|
2667
|
+
config() {
|
|
2668
|
+
return this.constructor;
|
|
2669
|
+
}
|
|
2670
|
+
deepActive() {
|
|
2671
|
+
let node = this.ownerDocument.activeElement;
|
|
2672
|
+
while (node?.shadowRoot?.activeElement) node = node.shadowRoot.activeElement;
|
|
2673
|
+
return node instanceof HTMLElement && node !== this.ownerDocument.body ? node : null;
|
|
2674
|
+
}
|
|
2675
|
+
render() {
|
|
2676
|
+
const state = this.model;
|
|
2677
|
+
const items = state.items;
|
|
2678
|
+
this.hidden = items.length === 0;
|
|
2679
|
+
this.menu.hidden = items.length === 0;
|
|
2680
|
+
this.applyMarkers(state.markers ?? []);
|
|
2681
|
+
if (state.zIndex !== void 0) this.style.zIndex = String(state.zIndex);
|
|
2682
|
+
else this.style.removeProperty("z-index");
|
|
2683
|
+
const same = items[this.active];
|
|
2684
|
+
this.active = same && !same.disabled ? this.active : nextEnabledIndex(items, -1, 1);
|
|
2685
|
+
this.renderRows();
|
|
2686
|
+
if (items.length === 0) {
|
|
2687
|
+
this.stopListening();
|
|
2688
|
+
this.focused = false;
|
|
2689
|
+
}
|
|
2690
|
+
if (!this.isConnected || items.length === 0) return;
|
|
2691
|
+
this.place();
|
|
2692
|
+
this.listen();
|
|
2693
|
+
if (!this.focused && state.autoFocus !== false) {
|
|
2694
|
+
this.focused = true;
|
|
2695
|
+
this.focusRow(nextEnabledIndex(items, -1, 1));
|
|
2696
|
+
} else if (this.focused && this.active >= 0)
|
|
2697
|
+
this.rows[this.active]?.focus({ preventScroll: true });
|
|
2698
|
+
}
|
|
2699
|
+
renderRows() {
|
|
2700
|
+
const doc = this.ownerDocument;
|
|
2701
|
+
const state = this.model;
|
|
2702
|
+
this.menu.setAttribute("aria-label", state.label);
|
|
2703
|
+
this.rows = [];
|
|
2704
|
+
let container = this.menu;
|
|
2705
|
+
const nodes = [];
|
|
2706
|
+
const place = (node) => container === this.menu ? nodes.push(node) : container.append(node);
|
|
2707
|
+
state.items.forEach((item, index) => {
|
|
2708
|
+
if (item.separatorBefore || item.heading) container = this.menu;
|
|
2709
|
+
if (item.separatorBefore) {
|
|
2710
|
+
const rule = doc.createElement("div");
|
|
2711
|
+
rule.className = "separator";
|
|
2712
|
+
rule.setAttribute("role", "separator");
|
|
2713
|
+
place(rule);
|
|
2714
|
+
}
|
|
2715
|
+
if (item.heading) {
|
|
2716
|
+
const group = doc.createElement("div");
|
|
2717
|
+
group.setAttribute("role", "group");
|
|
2718
|
+
group.setAttribute("aria-label", item.heading);
|
|
2719
|
+
const title = doc.createElement("div");
|
|
2720
|
+
title.className = "heading";
|
|
2721
|
+
title.setAttribute("aria-hidden", "true");
|
|
2722
|
+
title.textContent = item.heading;
|
|
2723
|
+
group.append(title);
|
|
2724
|
+
place(group);
|
|
2725
|
+
container = group;
|
|
2726
|
+
}
|
|
2727
|
+
const row = doc.createElement("button");
|
|
2728
|
+
row.type = "button";
|
|
2729
|
+
row.className = item.danger ? "item danger" : "item";
|
|
2730
|
+
row.dataset.itemId = item.id;
|
|
2731
|
+
row.setAttribute("role", item.checked === void 0 ? "menuitem" : "menuitemcheckbox");
|
|
2732
|
+
if (item.checked !== void 0) {
|
|
2733
|
+
row.setAttribute("aria-checked", String(item.checked));
|
|
2734
|
+
const check = doc.createElement("span");
|
|
2735
|
+
check.className = "check";
|
|
2736
|
+
check.setAttribute("aria-hidden", "true");
|
|
2737
|
+
check.textContent = item.checked ? "\u2713" : "";
|
|
2738
|
+
row.append(check);
|
|
2739
|
+
}
|
|
2740
|
+
if (item.icon) {
|
|
2741
|
+
const glyph = createIconSvg(doc);
|
|
2742
|
+
paintIcon(glyph, item.icon);
|
|
2743
|
+
row.append(glyph);
|
|
2744
|
+
}
|
|
2745
|
+
row.append(doc.createTextNode(item.label));
|
|
2746
|
+
row.tabIndex = index === this.active ? 0 : -1;
|
|
2747
|
+
if (item.disabled) {
|
|
2748
|
+
row.disabled = true;
|
|
2749
|
+
row.setAttribute("aria-disabled", "true");
|
|
2750
|
+
}
|
|
2751
|
+
row.addEventListener(
|
|
2752
|
+
"click",
|
|
2753
|
+
() => this.dispatchEvent(
|
|
2754
|
+
new CustomEvent(this.config().requestEvent, {
|
|
2755
|
+
detail: { id: item.id },
|
|
2756
|
+
bubbles: true,
|
|
2757
|
+
composed: true
|
|
2758
|
+
})
|
|
2759
|
+
)
|
|
2760
|
+
);
|
|
2761
|
+
this.rows.push(row);
|
|
2762
|
+
place(row);
|
|
2763
|
+
});
|
|
2764
|
+
this.menu.replaceChildren(...nodes);
|
|
2765
|
+
}
|
|
2766
|
+
applyMarkers(next) {
|
|
2767
|
+
for (const name of this.markers) this.removeAttribute(name);
|
|
2768
|
+
const pattern = this.config().markerPattern;
|
|
2769
|
+
this.markers = next.filter((name) => pattern.test(name));
|
|
2770
|
+
for (const name of this.markers) this.setAttribute(name, "true");
|
|
2771
|
+
}
|
|
2772
|
+
place() {
|
|
2773
|
+
const view = this.ownerDocument.defaultView;
|
|
2774
|
+
this.style.left = `${this.model.x}px`;
|
|
2775
|
+
this.style.top = `${this.model.y}px`;
|
|
2776
|
+
const box = this.getBoundingClientRect();
|
|
2777
|
+
const { left, top } = clampFlyoutPosition({
|
|
2778
|
+
x: this.model.x,
|
|
2779
|
+
y: this.model.y,
|
|
2780
|
+
width: box.width,
|
|
2781
|
+
height: box.height,
|
|
2782
|
+
viewportWidth: view?.innerWidth ?? box.right,
|
|
2783
|
+
viewportHeight: view?.innerHeight ?? box.bottom
|
|
2784
|
+
});
|
|
2785
|
+
this.style.left = `${left}px`;
|
|
2786
|
+
this.style.top = `${top}px`;
|
|
2787
|
+
}
|
|
2788
|
+
focusRow(index) {
|
|
2789
|
+
if (index < 0) return;
|
|
2790
|
+
this.active = index;
|
|
2791
|
+
this.rows.forEach((row, at) => row.tabIndex = at === index ? 0 : -1);
|
|
2792
|
+
this.rows[index]?.focus({ preventScroll: true });
|
|
2793
|
+
}
|
|
2794
|
+
typeAhead(items, from, key) {
|
|
2795
|
+
this.query += key;
|
|
2796
|
+
clearTimeout(this.queryTimer);
|
|
2797
|
+
this.queryTimer = setTimeout(() => this.query = "", TYPE_AHEAD_MS);
|
|
2798
|
+
return typeAheadIndex(items, from, this.query);
|
|
2799
|
+
}
|
|
2800
|
+
onRowKey(event) {
|
|
2801
|
+
const items = this.model.items;
|
|
2802
|
+
let target = -2;
|
|
2803
|
+
if (event.key === "ArrowDown") target = nextEnabledIndex(items, this.active, 1);
|
|
2804
|
+
else if (event.key === "ArrowUp") target = nextEnabledIndex(items, this.active, -1);
|
|
2805
|
+
else if (event.key === "Home") target = nextEnabledIndex(items, -1, 1);
|
|
2806
|
+
else if (event.key === "End") target = nextEnabledIndex(items, items.length, -1);
|
|
2807
|
+
else if (event.key.length === 1 && event.key !== " " && !event.ctrlKey && !event.metaKey && !event.altKey)
|
|
2808
|
+
target = this.typeAhead(items, this.active, event.key);
|
|
2809
|
+
if (target === -2) return;
|
|
2810
|
+
event.preventDefault();
|
|
2811
|
+
this.focusRow(target);
|
|
2812
|
+
}
|
|
2813
|
+
dismiss(reason) {
|
|
2814
|
+
this.dispatchEvent(
|
|
2815
|
+
new CustomEvent(this.config().closeEvent, {
|
|
2816
|
+
detail: { reason },
|
|
2817
|
+
bubbles: true,
|
|
2818
|
+
composed: true
|
|
2819
|
+
})
|
|
2820
|
+
);
|
|
2821
|
+
}
|
|
2822
|
+
onDocumentKey = (event) => {
|
|
2823
|
+
if (openMenus.get(this.ownerDocument)?.at(-1) !== this) return;
|
|
2824
|
+
if (event.key === "Escape") {
|
|
2825
|
+
event.preventDefault();
|
|
2826
|
+
event.stopPropagation();
|
|
2827
|
+
this.dismiss("escape");
|
|
2828
|
+
} else if (event.key === "Tab") this.dismiss("tab");
|
|
2829
|
+
};
|
|
2830
|
+
onDocumentPointer = (event) => {
|
|
2831
|
+
if (!event.composedPath().includes(this)) this.dismiss("outside");
|
|
2832
|
+
};
|
|
2833
|
+
listen() {
|
|
2834
|
+
if (this.listening) return;
|
|
2835
|
+
this.listening = true;
|
|
2836
|
+
const doc = this.ownerDocument;
|
|
2837
|
+
openMenus.set(doc, [...openMenus.get(doc) ?? [], this]);
|
|
2838
|
+
doc.addEventListener("keydown", this.onDocumentKey, true);
|
|
2839
|
+
doc.addEventListener("pointerdown", this.onDocumentPointer, true);
|
|
2840
|
+
}
|
|
2841
|
+
stopListening() {
|
|
2842
|
+
if (!this.listening) return;
|
|
2843
|
+
this.listening = false;
|
|
2844
|
+
const doc = this.ownerDocument;
|
|
2845
|
+
openMenus.set(
|
|
2846
|
+
doc,
|
|
2847
|
+
(openMenus.get(doc) ?? []).filter((menu) => menu !== this)
|
|
2848
|
+
);
|
|
2849
|
+
doc.removeEventListener("keydown", this.onDocumentKey, true);
|
|
2850
|
+
doc.removeEventListener("pointerdown", this.onDocumentPointer, true);
|
|
2851
|
+
}
|
|
2457
2852
|
}
|
|
2458
2853
|
return OfficeUiContextMenu;
|
|
2459
2854
|
});
|
|
@@ -3037,41 +3432,90 @@ function text(doc, tag, content, className) {
|
|
|
3037
3432
|
// src/ribbon.ts
|
|
3038
3433
|
var GROUP_CSS = `
|
|
3039
3434
|
:host { display: inline-flex; flex: none; align-self: stretch; }
|
|
3040
|
-
.group { box-sizing: border-box; display: flex; flex-direction: column; justify-content: space-between;
|
|
3041
|
-
min-height: ${tok("--office-ribbon-group-height")}; padding: ${tok("--office-
|
|
3042
|
-
|
|
3043
|
-
:
|
|
3044
|
-
|
|
3435
|
+
.group { position: relative; box-sizing: border-box; display: flex; flex-direction: column; justify-content: space-between;
|
|
3436
|
+
min-height: ${tok("--office-ribbon-group-height")}; padding: ${tok("--office-ribbon-group-padding")}; }
|
|
3437
|
+
/* Office draws a hairline between groups; a product may stop it short of the top and bottom. */
|
|
3438
|
+
.group::after { content: ''; position: absolute; top: ${tok("--office-ribbon-separator-inset")}; bottom: ${tok("--office-ribbon-separator-inset")};
|
|
3439
|
+
inset-inline-end: 0; width: ${tok("--office-border-width")}; background: ${tok("--office-ribbon-separator")}; }
|
|
3440
|
+
:host(:last-child) .group::after { content: none; }
|
|
3441
|
+
.row { display: flex; align-items: flex-start; gap: ${tok("--office-space-1")}; flex: 1; }
|
|
3442
|
+
/* One-line groups centre their commands on the whole group box. */
|
|
3443
|
+
:host([data-compact-row]) .row { align-items: center; }
|
|
3444
|
+
/* Several small drop-down galleries stack in columns of three. */
|
|
3445
|
+
:host([data-stack]) .row { flex-direction: column; align-items: stretch; align-content: flex-start; flex-wrap: wrap;
|
|
3446
|
+
max-height: ${tok("--office-ribbon-stack-max-height")}; gap: ${tok("--office-space-0")}; }
|
|
3045
3447
|
::slotted(*) { flex-shrink: 0; }
|
|
3046
|
-
.foot { position: relative; display: flex; justify-content: center; padding
|
|
3047
|
-
.caption { color: ${tok("--office-muted-foreground")}; font-size: ${tok("--office-
|
|
3448
|
+
.foot { position: relative; display: flex; align-items: center; justify-content: center; padding: ${tok("--office-ribbon-caption-padding")}; }
|
|
3449
|
+
.caption { color: ${tok("--office-muted-foreground")}; font-size: ${tok("--office-ribbon-caption-size")};
|
|
3048
3450
|
line-height: ${tok("--office-ribbon-caption-line-height")}; text-align: center; white-space: nowrap; }
|
|
3049
|
-
.launcher { position: absolute; inset-inline-end: -
|
|
3050
|
-
width: ${tok("--office-launcher-width")}; height: ${tok("--office-launcher-height")}; padding: 0; border: 0; border-radius: ${tok("--office-radius-xs")};
|
|
3051
|
-
color: ${tok("--office-muted-foreground")}; cursor: pointer; }
|
|
3052
|
-
.launcher:hover:not(:disabled) { background: ${tok("--office-surface")}; }
|
|
3451
|
+
.launcher { position: absolute; inset-inline-end: ${tok("--office-launcher-inset-end")}; bottom: ${tok("--office-launcher-inset-bottom")}; display: inline-grid; place-items: center;
|
|
3452
|
+
width: ${tok("--office-launcher-width")}; height: ${tok("--office-launcher-height")}; padding: 0; border: 0; border-radius: ${tok("--office-radius-xs")};
|
|
3453
|
+
background: transparent; color: ${tok("--office-muted-foreground")}; cursor: pointer; }
|
|
3454
|
+
.launcher:hover:not(:disabled) { background: ${tok("--office-surface")}; color: ${tok("--office-foreground")}; }
|
|
3053
3455
|
.launcher:focus-visible { outline: ${tok("--office-focus-width")} solid ${tok("--office-ring")}; }
|
|
3054
3456
|
.launcher:disabled { opacity: .45; cursor: not-allowed; }
|
|
3055
3457
|
.launcher[hidden] { display: none; }
|
|
3056
|
-
.launcher svg { width: ${tok("--office-icon-size-xs")}; height: ${tok("--office-icon-size-xs")}; fill: none; stroke: currentColor;
|
|
3057
|
-
stroke-linecap: round; stroke-linejoin: round; }
|
|
3058
|
-
|
|
3458
|
+
.launcher svg { width: ${tok("--office-icon-size-xs")}; height: ${tok("--office-icon-size-xs")}; fill: none; stroke: currentColor;
|
|
3459
|
+
stroke-width: ${tok("--office-icon-stroke")}; stroke-linecap: round; stroke-linejoin: round; }
|
|
3460
|
+
/* Collapsed (narrow window): the group is one button; its commands open in a popup. */
|
|
3461
|
+
.face { display: none; }
|
|
3462
|
+
:host([data-collapsed]) .face { display: flex; flex-direction: column; align-items: center; justify-content: flex-start; gap: ${tok("--office-space-0")};
|
|
3463
|
+
min-width: ${tok("--office-collapsed-group-min-width")}; height: ${tok("--office-command-large-height")}; padding: ${tok("--office-space-0")} ${tok("--office-space-1-5")};
|
|
3464
|
+
border: 0; border-radius: ${tok("--office-radius")}; background: transparent; color: ${tok("--office-foreground")}; font: inherit;
|
|
3465
|
+
font-size: ${tok("--office-font-size-sm")}; cursor: pointer; }
|
|
3466
|
+
:host([data-collapsed]) .face:hover, :host([data-open]) .face { background: ${tok("--office-selected")}; }
|
|
3467
|
+
.face:focus-visible { outline: ${tok("--office-focus-width")} solid ${tok("--office-ring")}; outline-offset: ${tok("--office-focus-offset")}; }
|
|
3468
|
+
.face svg { width: ${tok("--office-command-large-icon")}; height: ${tok("--office-command-large-icon")}; fill: none; stroke: currentColor;
|
|
3469
|
+
stroke-width: ${tok("--office-icon-stroke")}; stroke-linecap: round; stroke-linejoin: round; color: ${tok("--office-command-icon-color")}; }
|
|
3470
|
+
.face svg.chev { width: ${tok("--office-icon-size-xs")}; height: ${tok("--office-icon-size-xs")}; color: currentColor; }
|
|
3471
|
+
:host([data-collapsed]) .foot, :host([data-collapsed]) .row { display: none; }
|
|
3472
|
+
:host([data-collapsed][data-open]) .row { display: flex; flex-wrap: wrap; position: fixed; top: ${tok("--office-ribbon-collapse-y")};
|
|
3473
|
+
left: ${tok("--office-ribbon-collapse-x")}; z-index: ${tok("--office-z-popover")}; box-sizing: border-box;
|
|
3474
|
+
max-width: calc(100vw - 2 * ${tok("--office-space-2")}); padding: ${tok("--office-space-2")}; background: ${tok("--office-popover")};
|
|
3475
|
+
color: ${tok("--office-popover-foreground")}; border: ${tok("--office-border-width")} solid ${tok("--office-border")};
|
|
3476
|
+
border-radius: ${tok("--office-radius-md")}; box-shadow: ${tok("--office-shadow")}; }
|
|
3477
|
+
@media (forced-colors: active) {
|
|
3478
|
+
.group::after { background: CanvasText; } .caption, .launcher { color: CanvasText; }
|
|
3479
|
+
:host([data-collapsed][data-open]) .row { border-color: CanvasText; }
|
|
3480
|
+
}
|
|
3059
3481
|
`;
|
|
3482
|
+
function tokenPx(el, name, fallback) {
|
|
3483
|
+
const value = el.ownerDocument.defaultView?.getComputedStyle(el).getPropertyValue(name).trim();
|
|
3484
|
+
const px = value?.endsWith("px") ? parseFloat(value) : NaN;
|
|
3485
|
+
return Number.isFinite(px) ? px : fallback;
|
|
3486
|
+
}
|
|
3060
3487
|
var defineRibbonGroup = definer("office-ui-ribbon-group", () => {
|
|
3061
3488
|
class OfficeUiRibbonGroup extends HTMLElement {
|
|
3062
|
-
static
|
|
3489
|
+
static launcherEvent = "office-command";
|
|
3490
|
+
static collapseEvent = "office-ribbon-collapse-toggle";
|
|
3491
|
+
static observedAttributes = [
|
|
3492
|
+
"label",
|
|
3493
|
+
"launcher",
|
|
3494
|
+
"launcher-label",
|
|
3495
|
+
"launcher-disabled",
|
|
3496
|
+
"icon",
|
|
3497
|
+
"data-open"
|
|
3498
|
+
];
|
|
3063
3499
|
caption;
|
|
3064
3500
|
launcher;
|
|
3501
|
+
face;
|
|
3502
|
+
faceIcon;
|
|
3503
|
+
faceLabel;
|
|
3504
|
+
slotEl;
|
|
3505
|
+
observer;
|
|
3065
3506
|
constructor() {
|
|
3066
3507
|
super();
|
|
3067
3508
|
const doc = this.ownerDocument;
|
|
3068
3509
|
const root = this.attachShadow({ mode: "open" });
|
|
3069
3510
|
attachStyles(root, controlCss(GROUP_CSS));
|
|
3511
|
+
const config3 = () => this.constructor;
|
|
3070
3512
|
const group = doc.createElement("div");
|
|
3071
3513
|
group.className = "group";
|
|
3072
3514
|
const row = doc.createElement("div");
|
|
3073
3515
|
row.className = "row";
|
|
3074
|
-
|
|
3516
|
+
this.slotEl = doc.createElement("slot");
|
|
3517
|
+
this.slotEl.addEventListener("slotchange", () => this.observe());
|
|
3518
|
+
row.append(this.slotEl);
|
|
3075
3519
|
this.caption = doc.createElement("span");
|
|
3076
3520
|
this.caption.className = "caption";
|
|
3077
3521
|
this.launcher = doc.createElement("button");
|
|
@@ -3081,30 +3525,94 @@ var defineRibbonGroup = definer("office-ui-ribbon-group", () => {
|
|
|
3081
3525
|
paintIcon(glyph, "launcher");
|
|
3082
3526
|
this.launcher.append(glyph);
|
|
3083
3527
|
this.launcher.addEventListener("click", () => {
|
|
3084
|
-
|
|
3085
|
-
|
|
3528
|
+
if (this.launcher.disabled) return;
|
|
3529
|
+
const detail = this.launcherDetail();
|
|
3530
|
+
if (detail)
|
|
3531
|
+
this.dispatchEvent(
|
|
3532
|
+
new CustomEvent(config3().launcherEvent, { detail, bubbles: true, composed: true })
|
|
3533
|
+
);
|
|
3086
3534
|
});
|
|
3087
3535
|
const foot = doc.createElement("div");
|
|
3088
3536
|
foot.className = "foot";
|
|
3089
3537
|
foot.append(this.caption, this.launcher);
|
|
3090
|
-
|
|
3538
|
+
this.face = doc.createElement("button");
|
|
3539
|
+
this.face.type = "button";
|
|
3540
|
+
this.face.className = "face";
|
|
3541
|
+
this.face.setAttribute("aria-haspopup", "true");
|
|
3542
|
+
this.faceIcon = createIconSvg(doc);
|
|
3543
|
+
this.faceLabel = doc.createElement("span");
|
|
3544
|
+
const chevron = createIconSvg(doc);
|
|
3545
|
+
chevron.classList.add("chev");
|
|
3546
|
+
paintIcon(chevron, "chevronDown");
|
|
3547
|
+
this.face.append(this.faceIcon, this.faceLabel, chevron);
|
|
3548
|
+
this.face.addEventListener(
|
|
3549
|
+
"click",
|
|
3550
|
+
() => this.dispatchEvent(
|
|
3551
|
+
new CustomEvent(config3().collapseEvent, { bubbles: true, composed: true })
|
|
3552
|
+
)
|
|
3553
|
+
);
|
|
3554
|
+
group.append(this.face, row, foot);
|
|
3091
3555
|
root.append(group);
|
|
3092
3556
|
}
|
|
3093
3557
|
connectedCallback() {
|
|
3094
3558
|
this.setAttribute("role", "group");
|
|
3095
3559
|
this.sync();
|
|
3560
|
+
this.observe();
|
|
3561
|
+
}
|
|
3562
|
+
disconnectedCallback() {
|
|
3563
|
+
this.observer?.disconnect();
|
|
3096
3564
|
}
|
|
3097
3565
|
attributeChangedCallback() {
|
|
3098
3566
|
this.sync();
|
|
3099
3567
|
}
|
|
3568
|
+
/** The launcher's event detail; null emits nothing. */
|
|
3569
|
+
launcherDetail() {
|
|
3570
|
+
const command = this.getAttribute("launcher");
|
|
3571
|
+
return command ? { command } : null;
|
|
3572
|
+
}
|
|
3573
|
+
/** The registered icon on the collapsed face; a product subclass may map names. */
|
|
3574
|
+
iconName() {
|
|
3575
|
+
return this.getAttribute("icon") ?? "grid";
|
|
3576
|
+
}
|
|
3577
|
+
observe() {
|
|
3578
|
+
this.observer?.disconnect();
|
|
3579
|
+
if (!this.isConnected) return;
|
|
3580
|
+
const Observer = this.ownerDocument.defaultView?.ResizeObserver;
|
|
3581
|
+
if (Observer) this.observer ??= new Observer(() => this.measure());
|
|
3582
|
+
for (const el of this.slotEl.assignedElements()) this.observer?.observe(el);
|
|
3583
|
+
this.measure();
|
|
3584
|
+
}
|
|
3585
|
+
measure() {
|
|
3586
|
+
const children = [...this.children];
|
|
3587
|
+
const stackable = children.filter((el) => {
|
|
3588
|
+
const gallery = el.matches('[mode="dropdown"]') ? el : el.querySelector('[mode="dropdown"]');
|
|
3589
|
+
return gallery !== null && !gallery.hasAttribute("data-command-large");
|
|
3590
|
+
});
|
|
3591
|
+
this.toggleAttribute(
|
|
3592
|
+
"data-stack",
|
|
3593
|
+
stackable.length > 1 && stackable.length === children.length
|
|
3594
|
+
);
|
|
3595
|
+
const tallest = Math.max(0, ...children.map((el) => el.getBoundingClientRect().height));
|
|
3596
|
+
if (tallest > 0)
|
|
3597
|
+
this.toggleAttribute(
|
|
3598
|
+
"data-compact-row",
|
|
3599
|
+
tallest <= tokenPx(this, "--office-ribbon-compact-row-max", 36)
|
|
3600
|
+
);
|
|
3601
|
+
}
|
|
3100
3602
|
sync() {
|
|
3101
3603
|
const label = this.getAttribute("label") ?? "";
|
|
3102
3604
|
this.caption.textContent = label;
|
|
3103
3605
|
this.setAttribute("aria-label", label);
|
|
3104
|
-
|
|
3606
|
+
const launcherLabel = this.getAttribute("launcher-label") ?? `${label} options`;
|
|
3607
|
+
this.launcher.hidden = !this.hasAttribute("launcher");
|
|
3105
3608
|
this.launcher.disabled = this.hasAttribute("launcher-disabled");
|
|
3106
|
-
this.launcher.setAttribute("aria-label",
|
|
3107
|
-
this.launcher.title =
|
|
3609
|
+
this.launcher.setAttribute("aria-label", launcherLabel);
|
|
3610
|
+
this.launcher.title = launcherLabel;
|
|
3611
|
+
this.faceLabel.textContent = label;
|
|
3612
|
+
this.face.title = label;
|
|
3613
|
+
this.face.setAttribute("aria-label", label);
|
|
3614
|
+
this.face.setAttribute("aria-expanded", String(this.hasAttribute("data-open")));
|
|
3615
|
+
paintIcon(this.faceIcon, this.iconName());
|
|
3108
3616
|
}
|
|
3109
3617
|
}
|
|
3110
3618
|
return OfficeUiRibbonGroup;
|
|
@@ -3227,7 +3735,7 @@ function renderSelectMenu(menu, choices, value) {
|
|
|
3227
3735
|
});
|
|
3228
3736
|
menu.replaceChildren(...items);
|
|
3229
3737
|
}
|
|
3230
|
-
function
|
|
3738
|
+
function tokenPx2(el, name, fallback) {
|
|
3231
3739
|
const value = el.ownerDocument.defaultView?.getComputedStyle(el).getPropertyValue(name).trim();
|
|
3232
3740
|
const px = value?.endsWith("px") ? parseFloat(value) : NaN;
|
|
3233
3741
|
return Number.isFinite(px) ? px : fallback;
|
|
@@ -3235,14 +3743,14 @@ function tokenPx(el, name, fallback) {
|
|
|
3235
3743
|
function positionSelectMenu(menu, trigger, host) {
|
|
3236
3744
|
const view = menu.ownerDocument.defaultView;
|
|
3237
3745
|
const rect = trigger.getBoundingClientRect();
|
|
3238
|
-
const margin =
|
|
3239
|
-
const gap =
|
|
3746
|
+
const margin = tokenPx2(host, "--office-space-2", 8);
|
|
3747
|
+
const gap = tokenPx2(host, "--office-space-1", 4);
|
|
3240
3748
|
const width = Math.max(0, view.innerWidth - margin * 2);
|
|
3241
3749
|
const below = Math.max(0, view.innerHeight - rect.bottom - gap - margin);
|
|
3242
3750
|
const above = Math.max(0, rect.top - gap - margin);
|
|
3243
3751
|
menu.style.minWidth = `${Math.min(rect.width, width)}px`;
|
|
3244
3752
|
menu.style.maxWidth = `${width}px`;
|
|
3245
|
-
const cap = host.getAttribute("data-font-picker") === "family" ?
|
|
3753
|
+
const cap = host.getAttribute("data-font-picker") === "family" ? tokenPx2(host, "--office-font-picker-max-height", 320) : tokenPx2(host, "--office-select-max-height", 240);
|
|
3246
3754
|
menu.style.maxHeight = `${cap}px`;
|
|
3247
3755
|
const preferred = menu.getBoundingClientRect().height;
|
|
3248
3756
|
const flip = below < preferred && above > below;
|
|
@@ -4258,4 +4766,4 @@ function registerControls(registry) {
|
|
|
4258
4766
|
for (const define of CONTROL_DEFINERS) define(registry);
|
|
4259
4767
|
}
|
|
4260
4768
|
|
|
4261
|
-
export { CONTROL_DEFINERS, DEFAULT_OFFICE_PROFILE, OFFICE_AVATAR_SWATCHES, OFFICE_PROFILE_STORAGE_KEY, OFFICE_TOAST_VISIBLE_LIMIT, attachKeyTips, clampOptionNumber, clearOfficeProfile, defineAccount, defineBackstage, defineButton, defineCheckbox, defineCommandSearch, defineContextMenu, defineDialog, defineDialogFooter, defineFindBar, defineMenuButton, defineMenuItem, defineMenuSeparator, defineOptionsDialog, definePasteOptions, definePrintPreview, defineRadio, defineReadOnlyBanner, defineRibbon, defineRibbonGroup, defineRibbonStack, defineRibbonToggle, defineRuler, defineSearchField, defineSelect, defineStatusBar, defineStatusItem, defineSwitch, defineTabStrip, defineToasts, defineToolbar, defineZoomSlider, profileInitials, readOfficeProfile, registerControls, rulerDivisions, sanitizeOfficeProfile, writeOfficeProfile };
|
|
4769
|
+
export { CONTROL_DEFINERS, DEFAULT_OFFICE_PROFILE, EMPTY_MENU_STATE, OFFICE_AVATAR_SWATCHES, OFFICE_PROFILE_STORAGE_KEY, OFFICE_TOAST_VISIBLE_LIMIT, attachKeyTips, clampFlyoutPosition, clampOptionNumber, clearOfficeProfile, defineAccount, defineBackstage, defineButton, defineCheckbox, defineCommandSearch, defineContextMenu, defineDialog, defineDialogFooter, defineFindBar, defineMenuButton, defineMenuItem, defineMenuSeparator, defineOptionsDialog, definePasteOptions, definePrintPreview, defineRadio, defineReadOnlyBanner, defineRibbon, defineRibbonGroup, defineRibbonStack, defineRibbonToggle, defineRuler, defineSearchField, defineSelect, defineStatusBar, defineStatusItem, defineSwitch, defineTabStrip, defineToasts, defineToolbar, defineZoomSlider, nextEnabledIndex, profileInitials, readOfficeProfile, registerControls, rulerDivisions, sanitizeOfficeProfile, typeAheadIndex, writeOfficeProfile };
|