ooxml-ui 0.4.1 → 0.6.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 +18 -16
- package/dist/{chunk-RYUUWQ7F.js → chunk-RT6XKAM4.js} +361 -11
- package/dist/command-search.d.ts +16 -0
- package/dist/context-menu.d.ts +10 -0
- package/dist/controls.d.ts +5 -2
- package/dist/controls.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +5 -2
- package/dist/tab-strip.d.ts +3 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -58,22 +58,24 @@ with an incompatible build of this package.
|
|
|
58
58
|
|
|
59
59
|
## Features: elements
|
|
60
60
|
|
|
61
|
-
| Tag
|
|
62
|
-
|
|
|
63
|
-
| `office-ui-button`
|
|
64
|
-
| `office-ui-checkbox`, `office-ui-switch`
|
|
65
|
-
| `office-ui-select`
|
|
66
|
-
| `office-ui-ribbon-group`
|
|
67
|
-
| `office-ui-ribbon-stack`
|
|
68
|
-
| `office-ui-menu-button` / `-menu-item`
|
|
69
|
-
| `office-ui-toolbar`
|
|
70
|
-
| `office-ui-dialog`
|
|
71
|
-
| `office-ui-status-bar` / `-status-item`
|
|
72
|
-
| `office-ui-zoom-slider`
|
|
73
|
-
| `office-ui-tab-strip`
|
|
74
|
-
| `office-ui-
|
|
75
|
-
| `office-ui-
|
|
76
|
-
| `office-ui-
|
|
61
|
+
| Tag | Attributes / properties | Events (all bubble, composed) |
|
|
62
|
+
| ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
|
|
63
|
+
| `office-ui-button` | `label`, `icon`, `command`, `disabled`, `pressed`, `expanded`, `icon-only`, `variant="stacked"`, `keyshortcuts` | `office-command` `{ command }` |
|
|
64
|
+
| `office-ui-checkbox`, `office-ui-switch` | `checked`, `disabled`, `value`, `aria-label`; form-associated | `input`, `change` |
|
|
65
|
+
| `office-ui-select` | `options` `[{ value, label, disabled? }]`, `value`, `selectedIndex`, `disabled` | `input`, `change` |
|
|
66
|
+
| `office-ui-ribbon-group` | `label`, `launcher` (dialog launcher command), `launcher-disabled`; default slot | launcher: `office-command` `{ command }` |
|
|
67
|
+
| `office-ui-ribbon-stack` | `orientation="horizontal"`; default slot (three-row column of small commands by default) | none |
|
|
68
|
+
| `office-ui-menu-button` / `-menu-item` | button: `label`, `icon`, `command` (split button), `variant`, `disabled`, `keyshortcuts`; item: `command`, `label`, `icon`, `disabled`, `checked` | item choice: `office-command` `{ command }` |
|
|
69
|
+
| `office-ui-toolbar` | `aria-label`, `aria-orientation`; arrow-key focus movement | none |
|
|
70
|
+
| `office-ui-dialog` | `open`, `heading`, `dismissible="false"`, `show()`, `close()`; slots default, `footer` | `office-dialog-close` `{ reason }` (cancelable) |
|
|
71
|
+
| `office-ui-status-bar` / `-status-item` | `label`, `value`, `interactive`, `id` | `office-status-activate` `{ id }` |
|
|
72
|
+
| `office-ui-zoom-slider` | `value` (percent), `min`, `max`, `step`, `disabled`, `fit` (fit button name), `label` | `input`, `change`; fit: `office-command` `{ command: 'zoom-fit' }` |
|
|
73
|
+
| `office-ui-tab-strip` | `tabs` `[{ id, label, title? }]`, `selected`, `label`, `previous-label`, `next-label`, `add-label`, `add-disabled`, `add-title`, `disabled` | `office-tab-select` `{ id }` (cancelable); add: `office-command` `{ command: 'tab-add' }` |
|
|
74
|
+
| `office-ui-context-menu` / `office-ui-menu-separator` | `label`; `openAt(x, y)`, `close()`, `open`; `office-ui-menu-item` and separator children | item choice: `office-command` `{ command }` |
|
|
75
|
+
| `office-ui-command-search` | `commands` `[{ id, label, keywords?, disabled?, title? }]`, `placeholder`, `label`, `limit` (Office's "Tell me what you want to do") | choice: `office-command` `{ command }` |
|
|
76
|
+
| `office-ui-presence` | `participants`, `max`, `label` | `office-presence-select` `{ id }` |
|
|
77
|
+
| `office-ui-smartart` | `drawing` (core `DiagramDrawing`), `schemeColors`, `label` | `office-smartart-render` (render report) |
|
|
78
|
+
| `office-ui-icon` | `name`, `label` | none |
|
|
77
79
|
|
|
78
80
|
Setting a property never emits an event; only user activation does. Controls honour
|
|
79
81
|
`prefers-color-scheme`, `forced-colors: active` (system colours and a visible focus ring) and
|
|
@@ -353,6 +353,330 @@ var defineDialog = definer("office-ui-dialog", () => {
|
|
|
353
353
|
return OfficeUiDialog;
|
|
354
354
|
});
|
|
355
355
|
|
|
356
|
+
// src/command-search.ts
|
|
357
|
+
var CSS3 = `
|
|
358
|
+
:host { display: inline-flex; align-items: center; min-width: 0; font-family: var(--office-font, system-ui, sans-serif); }
|
|
359
|
+
.field { display: flex; align-items: center; gap: 6px; width: 100%; min-width: 0; height: var(--office-target-size, 28px);
|
|
360
|
+
padding: 0 8px; box-sizing: border-box; border: 1px solid transparent; border-radius: var(--office-radius, 4px);
|
|
361
|
+
color: var(--office-muted-foreground, #6b7280); }
|
|
362
|
+
.field:hover, .field:focus-within { border-color: var(--office-border, #d1d5db); background: var(--office-background, #fff); }
|
|
363
|
+
input { flex: 1; min-width: 0; border: 0; outline: 0; background: transparent; color: var(--office-foreground, #1f2937);
|
|
364
|
+
font: inherit; font-size: 13px; }
|
|
365
|
+
svg { width: 16px; height: 16px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.5;
|
|
366
|
+
stroke-linecap: round; stroke-linejoin: round; }
|
|
367
|
+
ul { position: fixed; inset: auto; margin: 0; padding: 4px; min-width: 240px; max-height: 320px; overflow: auto;
|
|
368
|
+
box-sizing: border-box; list-style: none; background: var(--office-background, #fff); color: var(--office-foreground, #1f2937);
|
|
369
|
+
border: 1px solid var(--office-border, #d1d5db); border-radius: var(--office-radius, 4px);
|
|
370
|
+
box-shadow: 0 8px 24px rgb(0 0 0 / 18%); font-size: 12px; }
|
|
371
|
+
ul[hidden] { display: none; }
|
|
372
|
+
li { display: flex; flex-direction: column; justify-content: center; min-height: var(--office-target-size, 28px);
|
|
373
|
+
padding: 2px 10px; border-radius: 3px; cursor: pointer; }
|
|
374
|
+
li[data-active] { background: var(--office-surface, #f3f4f6); }
|
|
375
|
+
li[aria-disabled="true"] { cursor: not-allowed; color: var(--office-muted-foreground, #6b7280); }
|
|
376
|
+
li small { color: var(--office-muted-foreground, #6b7280); font-size: 11px; }
|
|
377
|
+
li.empty { cursor: default; color: var(--office-muted-foreground, #6b7280); }
|
|
378
|
+
@media (forced-colors: active) {
|
|
379
|
+
.field, ul { border-color: CanvasText; background: Canvas; color: CanvasText; }
|
|
380
|
+
li[data-active] { background: Highlight; color: HighlightText; }
|
|
381
|
+
}
|
|
382
|
+
`;
|
|
383
|
+
var uid = 0;
|
|
384
|
+
var defineCommandSearch = definer("office-ui-command-search", () => {
|
|
385
|
+
class OfficeUiCommandSearch extends HTMLElement {
|
|
386
|
+
static observedAttributes = ["placeholder", "label"];
|
|
387
|
+
items = [];
|
|
388
|
+
found = [];
|
|
389
|
+
active = -1;
|
|
390
|
+
input;
|
|
391
|
+
list;
|
|
392
|
+
uid = `office-command-search-${++uid}`;
|
|
393
|
+
constructor() {
|
|
394
|
+
super();
|
|
395
|
+
const doc = this.ownerDocument;
|
|
396
|
+
const root = this.attachShadow({ mode: "open", delegatesFocus: true });
|
|
397
|
+
attachStyles(root, controlCss(CSS3));
|
|
398
|
+
const field = doc.createElement("div");
|
|
399
|
+
field.className = "field";
|
|
400
|
+
const glass = createIconSvg(doc);
|
|
401
|
+
paintIcon(glass, "search");
|
|
402
|
+
glass.setAttribute("data-painted", "");
|
|
403
|
+
this.input = doc.createElement("input");
|
|
404
|
+
this.input.type = "search";
|
|
405
|
+
this.input.autocomplete = "off";
|
|
406
|
+
this.input.spellcheck = false;
|
|
407
|
+
this.input.setAttribute("role", "combobox");
|
|
408
|
+
this.input.setAttribute("aria-autocomplete", "list");
|
|
409
|
+
this.input.setAttribute("aria-expanded", "false");
|
|
410
|
+
this.input.setAttribute("aria-controls", `${this.uid}-list`);
|
|
411
|
+
this.list = doc.createElement("ul");
|
|
412
|
+
this.list.id = `${this.uid}-list`;
|
|
413
|
+
this.list.setAttribute("role", "listbox");
|
|
414
|
+
if (typeof this.list.showPopover === "function")
|
|
415
|
+
this.list.setAttribute("popover", "manual");
|
|
416
|
+
else this.list.hidden = true;
|
|
417
|
+
field.append(glass, this.input);
|
|
418
|
+
root.append(field, this.list);
|
|
419
|
+
this.input.addEventListener("input", () => this.update());
|
|
420
|
+
this.input.addEventListener("keydown", (event) => this.onKey(event));
|
|
421
|
+
this.input.addEventListener("blur", () => this.hide());
|
|
422
|
+
this.list.addEventListener("pointerdown", (event) => event.preventDefault());
|
|
423
|
+
this.list.addEventListener("click", (event) => {
|
|
424
|
+
const item = event.target.closest("li[data-index]");
|
|
425
|
+
if (item) this.choose(Number(item.dataset.index));
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
connectedCallback() {
|
|
429
|
+
this.sync();
|
|
430
|
+
}
|
|
431
|
+
disconnectedCallback() {
|
|
432
|
+
this.hide();
|
|
433
|
+
}
|
|
434
|
+
attributeChangedCallback() {
|
|
435
|
+
this.sync();
|
|
436
|
+
}
|
|
437
|
+
get commands() {
|
|
438
|
+
return this.items.map((item) => ({ ...item }));
|
|
439
|
+
}
|
|
440
|
+
set commands(value) {
|
|
441
|
+
this.items = (Array.isArray(value) ? value : []).filter((item) => item && typeof item.id === "string").map((item) => ({ ...item, label: String(item.label ?? "") }));
|
|
442
|
+
if (this.isOpen) this.update();
|
|
443
|
+
}
|
|
444
|
+
get isOpen() {
|
|
445
|
+
return this.input.getAttribute("aria-expanded") === "true";
|
|
446
|
+
}
|
|
447
|
+
sync() {
|
|
448
|
+
this.input.placeholder = this.getAttribute("placeholder") ?? "Tell me what you want to do";
|
|
449
|
+
this.input.setAttribute("aria-label", this.getAttribute("label") ?? this.input.placeholder);
|
|
450
|
+
}
|
|
451
|
+
update() {
|
|
452
|
+
const query = this.input.value.trim().toLowerCase();
|
|
453
|
+
if (!query) return this.hide();
|
|
454
|
+
const limit = Math.max(1, Number(this.getAttribute("limit")) || 8);
|
|
455
|
+
this.found = this.items.filter((item) => `${item.label} ${item.keywords ?? ""}`.toLowerCase().includes(query)).slice(0, limit);
|
|
456
|
+
this.active = this.found.findIndex((item) => !item.disabled);
|
|
457
|
+
this.render();
|
|
458
|
+
this.show();
|
|
459
|
+
}
|
|
460
|
+
render() {
|
|
461
|
+
const doc = this.ownerDocument;
|
|
462
|
+
if (!this.found.length) {
|
|
463
|
+
const empty = doc.createElement("li");
|
|
464
|
+
empty.className = "empty";
|
|
465
|
+
empty.setAttribute("role", "option");
|
|
466
|
+
empty.setAttribute("aria-disabled", "true");
|
|
467
|
+
empty.textContent = "No matching commands";
|
|
468
|
+
this.list.replaceChildren(empty);
|
|
469
|
+
this.input.removeAttribute("aria-activedescendant");
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
472
|
+
this.list.replaceChildren(
|
|
473
|
+
...this.found.map((item, index) => {
|
|
474
|
+
const option = doc.createElement("li");
|
|
475
|
+
option.id = `${this.uid}-${index}`;
|
|
476
|
+
option.dataset.index = String(index);
|
|
477
|
+
option.setAttribute("role", "option");
|
|
478
|
+
option.setAttribute("aria-selected", String(index === this.active));
|
|
479
|
+
if (index === this.active) option.setAttribute("data-active", "");
|
|
480
|
+
const label = doc.createElement("span");
|
|
481
|
+
label.textContent = item.label;
|
|
482
|
+
option.append(label);
|
|
483
|
+
if (item.disabled) {
|
|
484
|
+
option.setAttribute("aria-disabled", "true");
|
|
485
|
+
const reason = doc.createElement("small");
|
|
486
|
+
reason.textContent = item.title ?? "Not available";
|
|
487
|
+
option.append(reason);
|
|
488
|
+
}
|
|
489
|
+
return option;
|
|
490
|
+
})
|
|
491
|
+
);
|
|
492
|
+
if (this.active >= 0)
|
|
493
|
+
this.input.setAttribute("aria-activedescendant", `${this.uid}-${this.active}`);
|
|
494
|
+
else this.input.removeAttribute("aria-activedescendant");
|
|
495
|
+
}
|
|
496
|
+
show() {
|
|
497
|
+
const box = this.input.getBoundingClientRect();
|
|
498
|
+
this.list.style.left = `${Math.round(box.left)}px`;
|
|
499
|
+
this.list.style.top = `${Math.round(box.bottom + 4)}px`;
|
|
500
|
+
if (this.list.hasAttribute("popover")) {
|
|
501
|
+
if (!this.isOpen) this.list.showPopover?.();
|
|
502
|
+
} else this.list.hidden = false;
|
|
503
|
+
this.input.setAttribute("aria-expanded", "true");
|
|
504
|
+
}
|
|
505
|
+
hide() {
|
|
506
|
+
if (!this.isOpen) return;
|
|
507
|
+
if (this.list.hasAttribute("popover")) {
|
|
508
|
+
try {
|
|
509
|
+
this.list.hidePopover?.();
|
|
510
|
+
} catch {
|
|
511
|
+
}
|
|
512
|
+
} else this.list.hidden = true;
|
|
513
|
+
this.input.setAttribute("aria-expanded", "false");
|
|
514
|
+
this.input.removeAttribute("aria-activedescendant");
|
|
515
|
+
}
|
|
516
|
+
move(step) {
|
|
517
|
+
const enabled = this.found.map((item, index) => item.disabled ? -1 : index).filter((i) => i >= 0);
|
|
518
|
+
if (!enabled.length) return;
|
|
519
|
+
const at = enabled.indexOf(this.active);
|
|
520
|
+
this.active = enabled[(at + step + enabled.length) % enabled.length];
|
|
521
|
+
this.render();
|
|
522
|
+
}
|
|
523
|
+
choose(index) {
|
|
524
|
+
const item = this.found[index];
|
|
525
|
+
if (!item || item.disabled) return;
|
|
526
|
+
this.input.value = "";
|
|
527
|
+
this.hide();
|
|
528
|
+
emit(this, "office-command", { command: item.id });
|
|
529
|
+
}
|
|
530
|
+
onKey(event) {
|
|
531
|
+
if (event.key === "ArrowDown" || event.key === "ArrowUp") {
|
|
532
|
+
event.preventDefault();
|
|
533
|
+
if (!this.isOpen) this.update();
|
|
534
|
+
else this.move(event.key === "ArrowDown" ? 1 : -1);
|
|
535
|
+
} else if (event.key === "Enter") {
|
|
536
|
+
event.preventDefault();
|
|
537
|
+
this.choose(this.active);
|
|
538
|
+
} else if (event.key === "Escape") {
|
|
539
|
+
event.preventDefault();
|
|
540
|
+
event.stopPropagation();
|
|
541
|
+
if (this.isOpen) this.hide();
|
|
542
|
+
else this.input.value = "";
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
return OfficeUiCommandSearch;
|
|
547
|
+
});
|
|
548
|
+
|
|
549
|
+
// src/context-menu.ts
|
|
550
|
+
var CSS4 = `
|
|
551
|
+
:host { display: contents; }
|
|
552
|
+
.panel { position: fixed; inset: auto; margin: 0; min-width: 200px; padding: 4px; box-sizing: border-box;
|
|
553
|
+
background: var(--office-background, #fff); color: var(--office-foreground, #1f2937);
|
|
554
|
+
border: 1px solid var(--office-border, #d1d5db); border-radius: var(--office-radius, 4px);
|
|
555
|
+
box-shadow: 0 8px 24px rgb(0 0 0 / 18%); font-family: var(--office-font, system-ui, sans-serif); }
|
|
556
|
+
.panel[hidden] { display: none; }
|
|
557
|
+
@media (forced-colors: active) { .panel { border-color: CanvasText; background: Canvas; color: CanvasText; } }
|
|
558
|
+
`;
|
|
559
|
+
var SEPARATOR_CSS = `
|
|
560
|
+
:host { display: block; height: 1px; margin: 4px 6px; background: var(--office-border, #d1d5db); }
|
|
561
|
+
@media (forced-colors: active) { :host { background: CanvasText; } }
|
|
562
|
+
`;
|
|
563
|
+
var ITEMS = "office-ui-menu-item:not([disabled]):not([hidden])";
|
|
564
|
+
var defineMenuSeparator = definer("office-ui-menu-separator", () => {
|
|
565
|
+
class OfficeUiMenuSeparator extends HTMLElement {
|
|
566
|
+
constructor() {
|
|
567
|
+
super();
|
|
568
|
+
attachStyles(this.attachShadow({ mode: "open" }), controlCss(SEPARATOR_CSS));
|
|
569
|
+
}
|
|
570
|
+
connectedCallback() {
|
|
571
|
+
this.setAttribute("role", "separator");
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
return OfficeUiMenuSeparator;
|
|
575
|
+
});
|
|
576
|
+
var defineContextMenu = definer("office-ui-context-menu", () => {
|
|
577
|
+
class OfficeUiContextMenu extends HTMLElement {
|
|
578
|
+
static observedAttributes = ["label"];
|
|
579
|
+
panel;
|
|
580
|
+
returnFocus = null;
|
|
581
|
+
outside;
|
|
582
|
+
constructor() {
|
|
583
|
+
super();
|
|
584
|
+
const doc = this.ownerDocument;
|
|
585
|
+
const root = this.attachShadow({ mode: "open" });
|
|
586
|
+
attachStyles(root, controlCss(CSS4));
|
|
587
|
+
this.panel = doc.createElement("div");
|
|
588
|
+
this.panel.className = "panel";
|
|
589
|
+
this.panel.setAttribute("role", "menu");
|
|
590
|
+
if (typeof this.panel.showPopover === "function")
|
|
591
|
+
this.panel.setAttribute("popover", "auto");
|
|
592
|
+
else this.panel.hidden = true;
|
|
593
|
+
this.panel.append(doc.createElement("slot"));
|
|
594
|
+
root.append(this.panel);
|
|
595
|
+
this.panel.addEventListener("toggle", (event) => {
|
|
596
|
+
if (event.newState === "closed") this.closed(false);
|
|
597
|
+
});
|
|
598
|
+
this.panel.addEventListener("keydown", (event) => this.onKey(event));
|
|
599
|
+
this.addEventListener("office-command", () => this.close());
|
|
600
|
+
}
|
|
601
|
+
connectedCallback() {
|
|
602
|
+
this.panel.setAttribute("aria-label", this.getAttribute("label") ?? "Context menu");
|
|
603
|
+
}
|
|
604
|
+
attributeChangedCallback() {
|
|
605
|
+
this.panel.setAttribute("aria-label", this.getAttribute("label") ?? "Context menu");
|
|
606
|
+
}
|
|
607
|
+
disconnectedCallback() {
|
|
608
|
+
this.close();
|
|
609
|
+
}
|
|
610
|
+
get open() {
|
|
611
|
+
return this.hasAttribute("data-open");
|
|
612
|
+
}
|
|
613
|
+
items() {
|
|
614
|
+
return [...this.querySelectorAll(ITEMS)];
|
|
615
|
+
}
|
|
616
|
+
/** Show at client coordinates; focus the first enabled item. */
|
|
617
|
+
openAt(x, y) {
|
|
618
|
+
const doc = this.ownerDocument;
|
|
619
|
+
const active = doc.activeElement;
|
|
620
|
+
this.returnFocus = active instanceof HTMLElement ? active : null;
|
|
621
|
+
if (this.panel.hasAttribute("popover")) {
|
|
622
|
+
if (!this.open) this.panel.showPopover?.();
|
|
623
|
+
} else {
|
|
624
|
+
this.panel.hidden = false;
|
|
625
|
+
this.outside ??= (event) => {
|
|
626
|
+
if (!event.composedPath().includes(this)) this.close();
|
|
627
|
+
};
|
|
628
|
+
doc.addEventListener("pointerdown", this.outside, true);
|
|
629
|
+
}
|
|
630
|
+
this.setAttribute("data-open", "");
|
|
631
|
+
const view = doc.defaultView;
|
|
632
|
+
const width = this.panel.offsetWidth;
|
|
633
|
+
const height = this.panel.offsetHeight;
|
|
634
|
+
const left = view && width ? Math.min(x, view.innerWidth - width - 4) : x;
|
|
635
|
+
const top = view && height ? Math.min(y, view.innerHeight - height - 4) : y;
|
|
636
|
+
this.panel.style.left = `${Math.max(4, Math.round(left))}px`;
|
|
637
|
+
this.panel.style.top = `${Math.max(4, Math.round(top))}px`;
|
|
638
|
+
this.items()[0]?.focus();
|
|
639
|
+
}
|
|
640
|
+
close() {
|
|
641
|
+
if (!this.open) return;
|
|
642
|
+
if (this.panel.hasAttribute("popover")) {
|
|
643
|
+
try {
|
|
644
|
+
this.panel.hidePopover?.();
|
|
645
|
+
} catch {
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
this.closed(true);
|
|
649
|
+
}
|
|
650
|
+
closed(restoreFocus) {
|
|
651
|
+
if (!this.open) return;
|
|
652
|
+
this.removeAttribute("data-open");
|
|
653
|
+
if (!this.panel.hasAttribute("popover")) this.panel.hidden = true;
|
|
654
|
+
if (this.outside) this.ownerDocument.removeEventListener("pointerdown", this.outside, true);
|
|
655
|
+
if (restoreFocus) this.returnFocus?.focus?.();
|
|
656
|
+
this.returnFocus = null;
|
|
657
|
+
}
|
|
658
|
+
onKey(event) {
|
|
659
|
+
const items = this.items();
|
|
660
|
+
const from = items.findIndex(
|
|
661
|
+
(item) => item === event.target || item.contains(event.target)
|
|
662
|
+
);
|
|
663
|
+
const move = (index) => {
|
|
664
|
+
event.preventDefault();
|
|
665
|
+
items[(index + items.length) % items.length]?.focus();
|
|
666
|
+
};
|
|
667
|
+
if (event.key === "ArrowDown") move(from + 1);
|
|
668
|
+
else if (event.key === "ArrowUp") move(from - 1);
|
|
669
|
+
else if (event.key === "Home") move(0);
|
|
670
|
+
else if (event.key === "End") move(items.length - 1);
|
|
671
|
+
else if (event.key === "Escape" || event.key === "Tab") {
|
|
672
|
+
if (event.key === "Escape") event.preventDefault();
|
|
673
|
+
this.close();
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
return OfficeUiContextMenu;
|
|
678
|
+
});
|
|
679
|
+
|
|
356
680
|
// src/menu.ts
|
|
357
681
|
var BUTTON_CSS = `
|
|
358
682
|
:host { display: inline-flex; vertical-align: middle; }
|
|
@@ -798,7 +1122,7 @@ var defineToolbar = definer("office-ui-toolbar", () => {
|
|
|
798
1122
|
});
|
|
799
1123
|
|
|
800
1124
|
// src/select.ts
|
|
801
|
-
var
|
|
1125
|
+
var CSS5 = `
|
|
802
1126
|
:host { display: inline-block; position: relative; vertical-align: middle; }
|
|
803
1127
|
button { box-sizing: border-box; display: flex; align-items: center; justify-content: space-between; gap: 8px;
|
|
804
1128
|
width: 100%; min-height: var(--office-target-size, 28px); padding: 0 8px; font: inherit; font-size: 12px;
|
|
@@ -820,7 +1144,7 @@ li[aria-disabled="true"] { opacity: .5; cursor: not-allowed; }
|
|
|
820
1144
|
li[data-active] { background: Highlight; color: HighlightText; }
|
|
821
1145
|
}
|
|
822
1146
|
`;
|
|
823
|
-
var
|
|
1147
|
+
var uid2 = 0;
|
|
824
1148
|
var defineSelect = definer("office-ui-select", () => {
|
|
825
1149
|
class OfficeUiSelect extends HTMLElement {
|
|
826
1150
|
static observedAttributes = ["value", "disabled", "aria-label"];
|
|
@@ -832,12 +1156,12 @@ var defineSelect = definer("office-ui-select", () => {
|
|
|
832
1156
|
trigger;
|
|
833
1157
|
list;
|
|
834
1158
|
label;
|
|
835
|
-
domId = `office-ui-select-${++
|
|
1159
|
+
domId = `office-ui-select-${++uid2}`;
|
|
836
1160
|
constructor() {
|
|
837
1161
|
super();
|
|
838
1162
|
const doc = this.ownerDocument;
|
|
839
1163
|
const root = this.attachShadow({ mode: "open", delegatesFocus: true });
|
|
840
|
-
attachStyles(root, controlCss(
|
|
1164
|
+
attachStyles(root, controlCss(CSS5));
|
|
841
1165
|
this.trigger = doc.createElement("button");
|
|
842
1166
|
this.trigger.type = "button";
|
|
843
1167
|
this.trigger.setAttribute("role", "combobox");
|
|
@@ -1088,7 +1412,7 @@ var defineStatusItem = definer("office-ui-status-item", () => {
|
|
|
1088
1412
|
});
|
|
1089
1413
|
|
|
1090
1414
|
// src/tab-strip.ts
|
|
1091
|
-
var
|
|
1415
|
+
var CSS6 = `
|
|
1092
1416
|
:host { display: flex; align-items: stretch; min-width: 0; min-height: 28px; gap: 2px; padding: 0 6px;
|
|
1093
1417
|
background: var(--office-surface, #f3f4f6); color: var(--office-muted-foreground, #6b7280);
|
|
1094
1418
|
border-top: 1px solid var(--office-border, #d1d5db); font-size: 12px;
|
|
@@ -1097,6 +1421,8 @@ var CSS4 = `
|
|
|
1097
1421
|
min-height: var(--office-target-size, 26px);
|
|
1098
1422
|
padding: 0; border: 0; background: transparent; color: inherit; cursor: pointer; }
|
|
1099
1423
|
.step:disabled { opacity: .4; cursor: default; }
|
|
1424
|
+
.add { font-size: 18px; line-height: 1; }
|
|
1425
|
+
.add[hidden] { display: none; }
|
|
1100
1426
|
.list { display: flex; align-items: stretch; min-width: 0; overflow-x: auto; scrollbar-width: thin; }
|
|
1101
1427
|
.tab { flex: none; max-width: 220px; min-height: var(--office-target-size, 26px); margin-top: -1px;
|
|
1102
1428
|
padding: 2px 14px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
|
|
@@ -1115,16 +1441,25 @@ svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width:
|
|
|
1115
1441
|
`;
|
|
1116
1442
|
var defineTabStrip = definer("office-ui-tab-strip", () => {
|
|
1117
1443
|
class OfficeUiTabStrip extends HTMLElement {
|
|
1118
|
-
static observedAttributes = [
|
|
1444
|
+
static observedAttributes = [
|
|
1445
|
+
"label",
|
|
1446
|
+
"disabled",
|
|
1447
|
+
"selected",
|
|
1448
|
+
"previous-label",
|
|
1449
|
+
"next-label",
|
|
1450
|
+
"add-label",
|
|
1451
|
+
"add-disabled"
|
|
1452
|
+
];
|
|
1119
1453
|
items = [];
|
|
1120
1454
|
list;
|
|
1121
1455
|
previous;
|
|
1122
1456
|
next;
|
|
1457
|
+
add;
|
|
1123
1458
|
constructor() {
|
|
1124
1459
|
super();
|
|
1125
1460
|
const doc = this.ownerDocument;
|
|
1126
1461
|
const root = this.attachShadow({ mode: "open" });
|
|
1127
|
-
attachStyles(root, controlCss(
|
|
1462
|
+
attachStyles(root, controlCss(CSS6));
|
|
1128
1463
|
const step = (name, icon) => {
|
|
1129
1464
|
const button = doc.createElement("button");
|
|
1130
1465
|
button.type = "button";
|
|
@@ -1141,7 +1476,14 @@ var defineTabStrip = definer("office-ui-tab-strip", () => {
|
|
|
1141
1476
|
this.list = doc.createElement("div");
|
|
1142
1477
|
this.list.className = "list";
|
|
1143
1478
|
this.list.setAttribute("role", "tablist");
|
|
1144
|
-
|
|
1479
|
+
this.add = doc.createElement("button");
|
|
1480
|
+
this.add.type = "button";
|
|
1481
|
+
this.add.className = "step add";
|
|
1482
|
+
this.add.textContent = "+";
|
|
1483
|
+
this.add.addEventListener("click", () => {
|
|
1484
|
+
if (!this.add.disabled) emit(this, "office-command", { command: "tab-add" });
|
|
1485
|
+
});
|
|
1486
|
+
root.append(this.previous, this.next, this.list, this.add);
|
|
1145
1487
|
this.previous.addEventListener("click", () => this.move(-1, false));
|
|
1146
1488
|
this.next.addEventListener("click", () => this.move(1, false));
|
|
1147
1489
|
this.list.addEventListener("click", (event) => {
|
|
@@ -1244,6 +1586,11 @@ var defineTabStrip = definer("office-ui-tab-strip", () => {
|
|
|
1244
1586
|
if (selected) tab.scrollIntoView?.({ block: "nearest", inline: "nearest" });
|
|
1245
1587
|
}
|
|
1246
1588
|
this.previous.disabled = disabled || index <= 0;
|
|
1589
|
+
const addLabel = this.getAttribute("add-label");
|
|
1590
|
+
this.add.hidden = !addLabel;
|
|
1591
|
+
this.add.disabled = disabled || this.hasAttribute("add-disabled");
|
|
1592
|
+
this.add.setAttribute("aria-label", addLabel ?? "Add");
|
|
1593
|
+
this.add.title = this.getAttribute("add-title") ?? addLabel ?? "";
|
|
1247
1594
|
this.next.disabled = disabled || index < 0 || index >= this.items.length - 1;
|
|
1248
1595
|
}
|
|
1249
1596
|
}
|
|
@@ -1251,7 +1598,7 @@ var defineTabStrip = definer("office-ui-tab-strip", () => {
|
|
|
1251
1598
|
});
|
|
1252
1599
|
|
|
1253
1600
|
// src/zoom-slider.ts
|
|
1254
|
-
var
|
|
1601
|
+
var CSS7 = `
|
|
1255
1602
|
:host { display: inline-flex; align-items: center; gap: 2px; font-size: 11px;
|
|
1256
1603
|
color: var(--office-foreground, #1f2937); font-family: var(--office-font, system-ui, sans-serif); }
|
|
1257
1604
|
button { box-sizing: border-box; display: inline-grid; place-items: center; min-width: var(--office-target-size, 24px);
|
|
@@ -1287,7 +1634,7 @@ var defineZoomSlider = definer("office-ui-zoom-slider", () => {
|
|
|
1287
1634
|
super();
|
|
1288
1635
|
const doc = this.ownerDocument;
|
|
1289
1636
|
const root = this.attachShadow({ mode: "open" });
|
|
1290
|
-
attachStyles(root, controlCss(
|
|
1637
|
+
attachStyles(root, controlCss(CSS7));
|
|
1291
1638
|
const button = (name, text) => {
|
|
1292
1639
|
const element = doc.createElement("button");
|
|
1293
1640
|
element.type = "button";
|
|
@@ -1391,7 +1738,10 @@ var CONTROL_DEFINERS = [
|
|
|
1391
1738
|
defineRibbonGroup,
|
|
1392
1739
|
defineRibbonStack,
|
|
1393
1740
|
defineMenuItem,
|
|
1741
|
+
defineMenuSeparator,
|
|
1394
1742
|
defineMenuButton,
|
|
1743
|
+
defineContextMenu,
|
|
1744
|
+
defineCommandSearch,
|
|
1395
1745
|
defineToolbar,
|
|
1396
1746
|
defineDialog,
|
|
1397
1747
|
defineStatusBar,
|
|
@@ -1403,4 +1753,4 @@ function registerControls(registry) {
|
|
|
1403
1753
|
for (const define of CONTROL_DEFINERS) define(registry);
|
|
1404
1754
|
}
|
|
1405
1755
|
|
|
1406
|
-
export { CONTROL_DEFINERS, defineButton, defineCheckbox, defineDialog, defineMenuButton, defineMenuItem, defineRibbonGroup, defineRibbonStack, defineSelect, defineStatusBar, defineStatusItem, defineSwitch, defineTabStrip, defineToolbar, defineZoomSlider, registerControls };
|
|
1756
|
+
export { CONTROL_DEFINERS, defineButton, defineCheckbox, defineCommandSearch, defineContextMenu, defineDialog, defineMenuButton, defineMenuItem, defineMenuSeparator, defineRibbonGroup, defineRibbonStack, defineSelect, defineStatusBar, defineStatusItem, defineSwitch, defineTabStrip, defineToolbar, defineZoomSlider, registerControls };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** One searchable command: label and optional keywords; disabled commands show their reason. */
|
|
2
|
+
export interface OfficeSearchCommand {
|
|
3
|
+
id: string;
|
|
4
|
+
label: string;
|
|
5
|
+
keywords?: string;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
title?: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Office's "Tell me what you want to do" box. Set `commands` (`OfficeSearchCommand[]`); typing
|
|
11
|
+
* lists up to `limit` (default 8) matches by label or keywords in a top-layer listbox.
|
|
12
|
+
* ArrowUp/Down move, Enter or click run an enabled match (`office-command` `{ command }`),
|
|
13
|
+
* Escape closes then clears. Disabled matches stay visible with their reason. Attributes:
|
|
14
|
+
* `placeholder`, `label` (accessible name), `limit`. Setting `commands` never emits.
|
|
15
|
+
*/
|
|
16
|
+
export declare const defineCommandSearch: import("./registry.js").Definer;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** A `role="separator"` rule between groups of menu items. */
|
|
2
|
+
export declare const defineMenuSeparator: import("./registry.js").Definer;
|
|
3
|
+
/**
|
|
4
|
+
* Right-click menu of `office-ui-menu-item` and `office-ui-menu-separator` children (Office's
|
|
5
|
+
* shape and text context menus). `openAt(x, y)` shows it at client coordinates in the popover
|
|
6
|
+
* top layer, kept inside the viewport; `close()` hides it. Arrow keys, Home and End move between
|
|
7
|
+
* enabled items; Escape and Tab close and return focus to the element that was focused. Choosing
|
|
8
|
+
* an item closes the menu and its `office-command` bubbles to the host. `label` names the menu.
|
|
9
|
+
*/
|
|
10
|
+
export declare const defineContextMenu: import("./registry.js").Definer;
|
package/dist/controls.d.ts
CHANGED
|
@@ -2,19 +2,22 @@ import { defineButton } from './button.js';
|
|
|
2
2
|
import { defineCheckbox, defineSwitch } from './checkable.js';
|
|
3
3
|
import { defineDialog } from './dialog.js';
|
|
4
4
|
import { defineIcon } from './icons.js';
|
|
5
|
+
import { defineCommandSearch } from './command-search.js';
|
|
6
|
+
import { defineContextMenu, defineMenuSeparator } from './context-menu.js';
|
|
5
7
|
import { defineMenuButton, defineMenuItem } from './menu.js';
|
|
6
8
|
import { defineRibbonGroup, defineRibbonStack, defineToolbar } from './ribbon.js';
|
|
7
9
|
import { defineSelect } from './select.js';
|
|
8
10
|
import { defineStatusBar, defineStatusItem } from './status-bar.js';
|
|
9
11
|
import { defineTabStrip } from './tab-strip.js';
|
|
10
12
|
import { defineZoomSlider } from './zoom-slider.js';
|
|
11
|
-
export { defineButton, defineCheckbox, defineDialog, defineIcon, defineMenuButton, defineMenuItem, defineRibbonGroup, defineRibbonStack, defineSelect, defineStatusBar, defineStatusItem, defineSwitch, defineTabStrip, defineToolbar, defineZoomSlider, };
|
|
13
|
+
export { defineButton, defineCheckbox, defineCommandSearch, defineContextMenu, defineDialog, defineIcon, defineMenuButton, defineMenuItem, defineMenuSeparator, defineRibbonGroup, defineRibbonStack, defineSelect, defineStatusBar, defineStatusItem, defineSwitch, defineTabStrip, defineToolbar, defineZoomSlider, };
|
|
12
14
|
export type { OfficeCommandEvent } from './button.js';
|
|
13
15
|
export type { OfficeDialogCloseEvent, OfficeDialogCloseReason } from './dialog.js';
|
|
14
16
|
export type { OfficeSelectOption } from './select.js';
|
|
15
17
|
export type { OfficeStatusActivateEvent } from './status-bar.js';
|
|
16
18
|
export type { OfficeTab, OfficeTabSelectEvent } from './tab-strip.js';
|
|
19
|
+
export type { OfficeSearchCommand } from './command-search.js';
|
|
17
20
|
/** Every control of this entry. */
|
|
18
|
-
export declare const CONTROL_DEFINERS: readonly [import("./registry.js").Definer, import("./registry.js").Definer, import("./registry.js").Definer, import("./registry.js").Definer, import("./registry.js").Definer, import("./registry.js").Definer, import("./registry.js").Definer, import("./registry.js").Definer, import("./registry.js").Definer, import("./registry.js").Definer, import("./registry.js").Definer, import("./registry.js").Definer, import("./registry.js").Definer, import("./registry.js").Definer, import("./registry.js").Definer];
|
|
21
|
+
export declare const CONTROL_DEFINERS: readonly [import("./registry.js").Definer, import("./registry.js").Definer, import("./registry.js").Definer, import("./registry.js").Definer, import("./registry.js").Definer, import("./registry.js").Definer, import("./registry.js").Definer, import("./registry.js").Definer, import("./registry.js").Definer, import("./registry.js").Definer, import("./registry.js").Definer, import("./registry.js").Definer, import("./registry.js").Definer, import("./registry.js").Definer, import("./registry.js").Definer, import("./registry.js").Definer, import("./registry.js").Definer, import("./registry.js").Definer];
|
|
19
22
|
/** Idempotent, SSR-safe (no-op without a DOM). */
|
|
20
23
|
export declare function registerControls(registry?: CustomElementRegistry): void;
|
package/dist/controls.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { CONTROL_DEFINERS, defineButton, defineCheckbox, defineDialog, defineMenuButton, defineMenuItem, defineRibbonGroup, defineRibbonStack, defineSelect, defineStatusBar, defineStatusItem, defineSwitch, defineTabStrip, defineToolbar, defineZoomSlider, registerControls } from './chunk-
|
|
1
|
+
export { CONTROL_DEFINERS, defineButton, defineCheckbox, defineCommandSearch, defineContextMenu, defineDialog, defineMenuButton, defineMenuItem, defineMenuSeparator, defineRibbonGroup, defineRibbonStack, defineSelect, defineStatusBar, defineStatusItem, defineSwitch, defineTabStrip, defineToolbar, defineZoomSlider, registerControls } from './chunk-RT6XKAM4.js';
|
|
2
2
|
export { defineIcon } from './chunk-PCSUQPMC.js';
|
|
3
3
|
import './chunk-EY266IK3.js';
|
package/dist/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export * from './smartart.js';
|
|
|
5
5
|
export * from './theme.js';
|
|
6
6
|
export { CONTRACT_REVISION, type Definer } from './registry.js';
|
|
7
7
|
/** Every ooxml-ui tag this package defines, in registration order. */
|
|
8
|
-
export declare const OFFICE_UI_TAGS: readonly ["office-ui-icon", "office-ui-button", "office-ui-checkbox", "office-ui-switch", "office-ui-select", "office-ui-ribbon-group", "office-ui-ribbon-stack", "office-ui-menu-item", "office-ui-menu-button", "office-ui-toolbar", "office-ui-dialog", "office-ui-status-bar", "office-ui-status-item", "office-ui-zoom-slider", "office-ui-tab-strip", "office-ui-presence", "office-ui-smartart"];
|
|
8
|
+
export declare const OFFICE_UI_TAGS: readonly ["office-ui-icon", "office-ui-button", "office-ui-checkbox", "office-ui-switch", "office-ui-select", "office-ui-ribbon-group", "office-ui-ribbon-stack", "office-ui-menu-item", "office-ui-menu-button", "office-ui-menu-separator", "office-ui-context-menu", "office-ui-command-search", "office-ui-toolbar", "office-ui-dialog", "office-ui-status-bar", "office-ui-status-item", "office-ui-zoom-slider", "office-ui-tab-strip", "office-ui-presence", "office-ui-smartart"];
|
|
9
9
|
/**
|
|
10
10
|
* Install the theme tokens and define every element. Idempotent and safe to call from every
|
|
11
11
|
* viewer binding; a no-op where there is no DOM (SSR).
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { installOfficeUiTheme } from './chunk-H4KFVIGT.js';
|
|
2
2
|
export { THEME_CSS, THEME_STYLE_ID, installOfficeUiTheme } from './chunk-H4KFVIGT.js';
|
|
3
|
-
import { registerControls } from './chunk-
|
|
4
|
-
export { CONTROL_DEFINERS, defineButton, defineCheckbox, defineDialog, defineMenuButton, defineMenuItem, defineRibbonGroup, defineRibbonStack, defineSelect, defineStatusBar, defineStatusItem, defineSwitch, defineTabStrip, defineToolbar, defineZoomSlider, registerControls } from './chunk-
|
|
3
|
+
import { registerControls } from './chunk-RT6XKAM4.js';
|
|
4
|
+
export { CONTROL_DEFINERS, defineButton, defineCheckbox, defineCommandSearch, defineContextMenu, defineDialog, defineMenuButton, defineMenuItem, defineMenuSeparator, defineRibbonGroup, defineRibbonStack, defineSelect, defineStatusBar, defineStatusItem, defineSwitch, defineTabStrip, defineToolbar, defineZoomSlider, registerControls } from './chunk-RT6XKAM4.js';
|
|
5
5
|
export { ICON_CSS, createIconSvg, defineIcon, getIcon, listIcons, paintIcon, registerIcon } from './chunk-PCSUQPMC.js';
|
|
6
6
|
import { definePresence } from './chunk-RLPL7Q6J.js';
|
|
7
7
|
export { definePresence, initialsOf, participantsFromAwareness } from './chunk-RLPL7Q6J.js';
|
|
@@ -20,6 +20,9 @@ var OFFICE_UI_TAGS = [
|
|
|
20
20
|
"office-ui-ribbon-stack",
|
|
21
21
|
"office-ui-menu-item",
|
|
22
22
|
"office-ui-menu-button",
|
|
23
|
+
"office-ui-menu-separator",
|
|
24
|
+
"office-ui-context-menu",
|
|
25
|
+
"office-ui-command-search",
|
|
23
26
|
"office-ui-toolbar",
|
|
24
27
|
"office-ui-dialog",
|
|
25
28
|
"office-ui-status-bar",
|
package/dist/tab-strip.d.ts
CHANGED
|
@@ -13,6 +13,8 @@ export type OfficeTabSelectEvent = CustomEvent<{
|
|
|
13
13
|
* keys move the selection; the tab list uses a roving tabindex. User selection emits
|
|
14
14
|
* `office-tab-select` `{ id }` (cancelable); setting properties never emits.
|
|
15
15
|
* Attributes: `label` (tab list name, default "Tabs"), `previous-label` and `next-label`
|
|
16
|
-
* (step button names, default "Previous" and "Next"), `disabled
|
|
16
|
+
* (step button names, default "Previous" and "Next"), `disabled`, and `add-label` to show an
|
|
17
|
+
* add button after the tabs (Insert Page, New Sheet) that emits `office-command`
|
|
18
|
+
* `{ command: 'tab-add' }`; `add-disabled` and `add-title` disable and explain it.
|
|
17
19
|
*/
|
|
18
20
|
export declare const defineTabStrip: import("./registry.js").Definer;
|