@spfx-fast/sharepoint-ui 0.4.2 → 0.5.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/QUICKSTART.md +18 -0
- package/README.md +19 -24
- package/components.json +240 -5694
- package/dist/accordion.d.ts +11 -0
- package/dist/accordion.js +4 -0
- package/dist/alert.d.ts +3 -0
- package/dist/alert.js +4 -0
- package/dist/attachment-list.d.ts +15 -0
- package/dist/attachment-list.js +14 -0
- package/dist/avatar-group.d.ts +12 -0
- package/dist/avatar-group.js +7 -0
- package/dist/avatar.d.ts +6 -0
- package/dist/avatar.js +5 -0
- package/dist/badge.d.ts +3 -0
- package/dist/badge.js +4 -0
- package/dist/breadcrumb.d.ts +10 -0
- package/dist/breadcrumb.js +9 -0
- package/dist/button-group.d.ts +6 -0
- package/dist/button-group.js +4 -0
- package/dist/button.d.ts +3 -0
- package/dist/button.js +4 -0
- package/dist/card.d.ts +3 -0
- package/dist/card.js +4 -0
- package/dist/carousel.d.ts +11 -0
- package/dist/carousel.js +6 -0
- package/dist/checkbox.d.ts +3 -0
- package/dist/checkbox.js +4 -0
- package/dist/combobox.d.ts +9 -0
- package/dist/combobox.js +6 -0
- package/dist/command-bar.d.ts +6 -0
- package/dist/command-bar.js +4 -0
- package/dist/copy-button.d.ts +7 -0
- package/dist/copy-button.js +19 -0
- package/dist/data-grid.d.ts +25 -0
- package/dist/data-grid.js +39 -0
- package/dist/date-range-picker.d.ts +12 -0
- package/dist/date-range-picker.js +4 -0
- package/dist/dialog.d.ts +9 -0
- package/dist/dialog.js +21 -0
- package/dist/divider.d.ts +3 -0
- package/dist/divider.js +4 -0
- package/dist/drawer.d.ts +6 -0
- package/dist/drawer.js +5 -0
- package/dist/empty-state.d.ts +7 -0
- package/dist/empty-state.js +5 -0
- package/dist/field.d.ts +15 -0
- package/dist/field.js +11 -0
- package/dist/file-dropzone.d.ts +15 -0
- package/dist/file-dropzone.js +21 -0
- package/dist/filter-bar.d.ts +9 -0
- package/dist/filter-bar.js +9 -0
- package/dist/image.d.ts +5 -0
- package/dist/image.js +4 -0
- package/dist/index.d.ts +68 -76
- package/dist/index.js +60 -66
- package/dist/input.d.ts +3 -0
- package/dist/input.js +4 -0
- package/dist/label.d.ts +3 -0
- package/dist/label.js +4 -0
- package/dist/link.d.ts +3 -0
- package/dist/link.js +9 -0
- package/dist/list-view.d.ts +29 -0
- package/dist/list-view.js +14 -0
- package/dist/list.d.ts +6 -0
- package/dist/list.js +5 -0
- package/dist/lookup-picker.d.ts +12 -0
- package/dist/lookup-picker.js +4 -0
- package/dist/menu.d.ts +6 -0
- package/dist/menu.js +4 -0
- package/dist/nav.d.ts +12 -0
- package/dist/nav.js +4 -0
- package/dist/pagination.d.ts +11 -0
- package/dist/pagination.js +5 -0
- package/dist/person-picker.d.ts +13 -0
- package/dist/person-picker.js +4 -0
- package/dist/persona.d.ts +7 -0
- package/dist/persona.js +5 -0
- package/dist/popover.d.ts +6 -0
- package/dist/popover.js +4 -0
- package/dist/progress-bar.d.ts +5 -0
- package/dist/progress-bar.js +5 -0
- package/dist/radio-group.d.ts +6 -0
- package/dist/radio-group.js +4 -0
- package/dist/radio.d.ts +3 -0
- package/dist/radio.js +4 -0
- package/dist/rating.d.ts +8 -0
- package/dist/rating.js +5 -0
- package/dist/react.d.ts +1 -4583
- package/dist/react.js +1 -6837
- package/dist/select.d.ts +3 -0
- package/dist/select.js +4 -0
- package/dist/sharepoint-field.d.ts +18 -0
- package/dist/sharepoint-field.js +54 -0
- package/dist/skeleton.d.ts +6 -0
- package/dist/skeleton.js +9 -0
- package/dist/spinner.d.ts +5 -0
- package/dist/spinner.js +4 -0
- package/dist/swatch-picker.d.ts +17 -0
- package/dist/swatch-picker.js +11 -0
- package/dist/switch.d.ts +3 -0
- package/dist/switch.js +4 -0
- package/dist/table.d.ts +6 -0
- package/dist/table.js +4 -0
- package/dist/tabs.d.ts +14 -0
- package/dist/tabs.js +30 -0
- package/dist/tag-group.d.ts +6 -0
- package/dist/tag-group.js +4 -0
- package/dist/tag-picker.d.ts +12 -0
- package/dist/tag-picker.js +4 -0
- package/dist/tag.d.ts +7 -0
- package/dist/tag.js +5 -0
- package/dist/text.d.ts +5 -0
- package/dist/text.js +4 -0
- package/dist/textarea.d.ts +3 -0
- package/dist/textarea.js +4 -0
- package/dist/theme.d.ts +15 -167
- package/dist/theme.js +36 -162
- package/dist/toast.d.ts +9 -0
- package/dist/toast.js +12 -0
- package/dist/tree.d.ts +13 -0
- package/dist/tree.js +9 -0
- package/dist/view-card.d.ts +8 -0
- package/dist/view-card.js +4 -0
- package/dist/view-switcher.d.ts +13 -0
- package/dist/view-switcher.js +7 -0
- package/dist/virtual-list.d.ts +11 -0
- package/dist/virtual-list.js +25 -0
- package/measurements.json +365 -0
- package/package.json +19 -42
- package/src/theme.css +125 -0
- package/AGENTS.md +0 -211
- package/dist/appearance.d.ts +0 -6
- package/dist/appearance.js +0 -217
- package/dist/elements/accordion.d.ts +0 -9
- package/dist/elements/accordion.js +0 -338
- package/dist/elements/alert.d.ts +0 -2
- package/dist/elements/alert.js +0 -62
- package/dist/elements/avatar-group-primitives.d.ts +0 -3
- package/dist/elements/avatar-group-primitives.js +0 -189
- package/dist/elements/avatar-group.d.ts +0 -2
- package/dist/elements/avatar-group.js +0 -110
- package/dist/elements/avatar.d.ts +0 -4
- package/dist/elements/avatar.js +0 -251
- package/dist/elements/badge.d.ts +0 -8
- package/dist/elements/badge.js +0 -182
- package/dist/elements/breadcrumb.d.ts +0 -4
- package/dist/elements/breadcrumb.js +0 -233
- package/dist/elements/button-group.d.ts +0 -1
- package/dist/elements/button-group.js +0 -20
- package/dist/elements/button-variants.d.ts +0 -6
- package/dist/elements/button-variants.js +0 -339
- package/dist/elements/button.d.ts +0 -5
- package/dist/elements/button.js +0 -233
- package/dist/elements/card-primitives.d.ts +0 -3
- package/dist/elements/card-primitives.js +0 -83
- package/dist/elements/card.d.ts +0 -5
- package/dist/elements/card.js +0 -213
- package/dist/elements/carousel.d.ts +0 -92
- package/dist/elements/carousel.js +0 -1112
- package/dist/elements/color-picker.d.ts +0 -24
- package/dist/elements/color-picker.js +0 -1004
- package/dist/elements/combobox.d.ts +0 -1
- package/dist/elements/combobox.js +0 -1012
- package/dist/elements/data-grid-model.d.ts +0 -117
- package/dist/elements/data-grid-model.js +0 -294
- package/dist/elements/data-grid.d.ts +0 -29
- package/dist/elements/data-grid.js +0 -1567
- package/dist/elements/date-picker.d.ts +0 -1
- package/dist/elements/date-picker.js +0 -486
- package/dist/elements/dialog.d.ts +0 -23
- package/dist/elements/dialog.js +0 -409
- package/dist/elements/divider.d.ts +0 -2
- package/dist/elements/divider.js +0 -66
- package/dist/elements/drawer.d.ts +0 -3
- package/dist/elements/drawer.js +0 -308
- package/dist/elements/field-composition.d.ts +0 -26
- package/dist/elements/field-composition.js +0 -133
- package/dist/elements/field.d.ts +0 -1
- package/dist/elements/field.js +0 -67
- package/dist/elements/file-upload.d.ts +0 -6
- package/dist/elements/file-upload.js +0 -211
- package/dist/elements/floating-position.d.ts +0 -26
- package/dist/elements/floating-position.js +0 -39
- package/dist/elements/image.d.ts +0 -28
- package/dist/elements/image.js +0 -38
- package/dist/elements/info.d.ts +0 -9
- package/dist/elements/info.js +0 -102
- package/dist/elements/input.d.ts +0 -5
- package/dist/elements/input.js +0 -255
- package/dist/elements/label.d.ts +0 -15
- package/dist/elements/label.js +0 -56
- package/dist/elements/link.d.ts +0 -1
- package/dist/elements/link.js +0 -92
- package/dist/elements/list.d.ts +0 -19
- package/dist/elements/list.js +0 -297
- package/dist/elements/menu.d.ts +0 -33
- package/dist/elements/menu.js +0 -1103
- package/dist/elements/message-bar.d.ts +0 -10
- package/dist/elements/message-bar.js +0 -299
- package/dist/elements/nav.d.ts +0 -32
- package/dist/elements/nav.js +0 -791
- package/dist/elements/overflow.d.ts +0 -9
- package/dist/elements/overflow.js +0 -218
- package/dist/elements/persona.d.ts +0 -3
- package/dist/elements/persona.js +0 -125
- package/dist/elements/popover.d.ts +0 -77
- package/dist/elements/popover.js +0 -840
- package/dist/elements/progress-bar.d.ts +0 -4
- package/dist/elements/progress-bar.js +0 -82
- package/dist/elements/radio-group.d.ts +0 -1
- package/dist/elements/radio-group.js +0 -303
- package/dist/elements/rating-display.d.ts +0 -2
- package/dist/elements/rating-display.js +0 -125
- package/dist/elements/rating.d.ts +0 -2
- package/dist/elements/rating.js +0 -206
- package/dist/elements/rich-text-editor.d.ts +0 -18
- package/dist/elements/rich-text-editor.js +0 -508
- package/dist/elements/search.d.ts +0 -3
- package/dist/elements/search.js +0 -207
- package/dist/elements/select.d.ts +0 -6
- package/dist/elements/select.js +0 -291
- package/dist/elements/shared.d.ts +0 -19
- package/dist/elements/shared.js +0 -396
- package/dist/elements/skeleton.d.ts +0 -6
- package/dist/elements/skeleton.js +0 -91
- package/dist/elements/slider.d.ts +0 -1
- package/dist/elements/slider.js +0 -248
- package/dist/elements/spin-button.d.ts +0 -7
- package/dist/elements/spin-button.js +0 -499
- package/dist/elements/spinner.d.ts +0 -4
- package/dist/elements/spinner.js +0 -124
- package/dist/elements/swatch-picker.d.ts +0 -5
- package/dist/elements/swatch-picker.js +0 -363
- package/dist/elements/table.d.ts +0 -21
- package/dist/elements/table.js +0 -261
- package/dist/elements/tabs.d.ts +0 -1
- package/dist/elements/tabs.js +0 -276
- package/dist/elements/tag-picker.d.ts +0 -29
- package/dist/elements/tag-picker.js +0 -697
- package/dist/elements/tags.d.ts +0 -21
- package/dist/elements/tags.js +0 -421
- package/dist/elements/teaching-popover.d.ts +0 -32
- package/dist/elements/teaching-popover.js +0 -412
- package/dist/elements/text.d.ts +0 -9
- package/dist/elements/text.js +0 -75
- package/dist/elements/textarea.d.ts +0 -1
- package/dist/elements/textarea.js +0 -182
- package/dist/elements/toast.d.ts +0 -25
- package/dist/elements/toast.js +0 -337
- package/dist/elements/toaster.d.ts +0 -6
- package/dist/elements/toaster.js +0 -356
- package/dist/elements/toggle.d.ts +0 -2
- package/dist/elements/toggle.js +0 -246
- package/dist/elements/toolbar.d.ts +0 -12
- package/dist/elements/toolbar.js +0 -381
- package/dist/elements/tooltip.d.ts +0 -76
- package/dist/elements/tooltip.js +0 -510
- package/dist/elements/tree-model.d.ts +0 -19
- package/dist/elements/tree-model.js +0 -34
- package/dist/elements/tree.d.ts +0 -5
- package/dist/elements/tree.js +0 -273
- package/dist/elements/view-card.d.ts +0 -2
- package/dist/elements/view-card.js +0 -78
- package/dist/elements/virtual-list.d.ts +0 -41
- package/dist/elements/virtual-list.js +0 -369
- package/dist/elements.d.ts +0 -72
- package/dist/elements.js +0 -207
- package/dist/virtualizer-hooks.d.ts +0 -80
- package/dist/virtualizer-hooks.js +0 -253
- package/scripts/generate-token-index.mjs +0 -43
- package/scripts/sync-component-catalog-signatures.mjs +0 -55
- package/scripts/validate-component-catalog.mjs +0 -44
- package/skills/sharepoint-ui/SKILL.md +0 -12
- package/skills/sharepoint-ui/references/choosing-components.md +0 -20
- package/skills/sharepoint-ui/references/sharepoint-patterns.md +0 -17
- package/tokens.json +0 -3777
package/dist/elements/button.js
DELETED
|
@@ -1,233 +0,0 @@
|
|
|
1
|
-
import { base, stopHostAccessibleNameSync, syncHostAccessibleName } from "./shared.js";
|
|
2
|
-
const buttonCss = `${base}button{box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;gap:8px;min-height:var(--spui-control-height,32px);padding-inline:var(--spui-control-padding-inline,14px);border:1px solid var(--spui-control-border,var(--spui-ui-stroke,var(--spui-semantic-button-border,var(--colorNeutralStroke1,#8a8886))));border-radius:var(--spui-control-radius,4px);background:var(--spui-control-background,var(--spui-ui-surface,var(--spui-semantic-button-background,var(--colorNeutralBackground1,#fff))));box-shadow:var(--spui-control-shadow,none);color:var(--spui-ui-text,var(--spui-semantic-button-text,var(--colorNeutralForeground1,#323130)));font:inherit;line-height:1.25;text-align:center;text-decoration:none;cursor:pointer;transition:background-color var(--spui-motion-duration-normal,.15s) var(--spui-motion-easing-standard,cubic-bezier(.2,0,0,1)),border-color var(--spui-motion-duration-normal,.15s) var(--spui-motion-easing-standard,cubic-bezier(.2,0,0,1)),transform var(--spui-motion-duration-normal,.15s) var(--spui-motion-easing-standard,cubic-bezier(.2,0,0,1))}button:hover:not(:disabled):not([aria-disabled=true]){background:var(--spui-button-secondary-hover,color-mix(in srgb,var(--spui-control-background,var(--spui-ui-surface,#fff)) 90%,var(--spui-ui-text,#242424) 10%))}button:active:not(:disabled):not([aria-disabled=true]){transform:scale(.98)}button.primary{border-color:var(--spui-primary-background,var(--spui-ui-accent,var(--spui-semantic-primary-button-background,var(--colorBrandBackground,#0078d4))));background:var(--spui-primary-background,var(--spui-ui-accent,var(--spui-semantic-primary-button-background,var(--colorBrandBackground,#0078d4))));color:var(--spui-ui-accent-text,var(--spui-semantic-primary-button-text,var(--colorNeutralForegroundOnBrand,#fff)))}button.primary:hover:not(:disabled):not([aria-disabled=true]){background:var(--spui-primary-hover,var(--spui-ui-accent-hover,var(--colorBrandBackgroundHover,#106ebe)))}button.primary:active:not(:disabled):not([aria-disabled=true]){background:var(--spui-ui-accent-pressed,var(--colorBrandBackgroundPressed,var(--spui-ui-accent-hover,#106ebe)))}button.outline{background:transparent}button.subtle,button.transparent{border-color:transparent;box-shadow:none}button.subtle{background:var(--spui-button-subtle-background,transparent)}button.transparent{background:transparent}button:disabled,button[aria-disabled=true]{opacity:.55;cursor:not-allowed}:host([size=small]) button{min-height:24px;padding-inline:8px;font-size:12px}:host([size=large]) button{min-height:40px;padding-inline:16px;font-size:16px}:host([shape=circular]) button{border-radius:999px}:host([shape=square]) button{border-radius:0}:host([data-spui-split-primary]) button{border-start-end-radius:0;border-end-end-radius:0}:host([data-spui-split-trigger]) button{border-start-start-radius:0;border-end-start-radius:0}:host([icon-only]) button{min-width:var(--spui-control-height,32px);padding-inline:0}:host([size=small][icon-only]) button{min-width:24px}:host([size=large][icon-only]) button{min-width:40px}:host([vertical]) button{flex-direction:column}.icon{display:inline-flex;align-items:center;justify-content:center;line-height:0}:host([vertical]) .icon{font-size:24px}.content{display:inline-flex;align-items:center;justify-content:center}:host([icon-position=after]) .icon{order:2}:host([icon-position=after]) .content{order:1}@media(prefers-reduced-motion:reduce){button{transition:none}}@media(forced-colors:active){button{border-color:ButtonText}button.primary{border-color:Highlight;background:Highlight;color:HighlightText}}`;
|
|
3
|
-
export const buttonControlCss = buttonCss.replace(/\bbutton(?=[.#:[\s,{])/g, ":is(button,a)");
|
|
4
|
-
const buttonSheets = new WeakMap();
|
|
5
|
-
const buttonSheetUnsupported = new WeakSet();
|
|
6
|
-
function buttonStyleNode(document) {
|
|
7
|
-
const style = document.createElement("style");
|
|
8
|
-
style.textContent = buttonControlCss;
|
|
9
|
-
return style;
|
|
10
|
-
}
|
|
11
|
-
function applyButtonStyle(shadow, button) {
|
|
12
|
-
const document = shadow.ownerDocument;
|
|
13
|
-
let sheet = buttonSheets.get(document);
|
|
14
|
-
if (!sheet && !buttonSheetUnsupported.has(document)) {
|
|
15
|
-
try {
|
|
16
|
-
if (typeof shadow.adoptedStyleSheets === "undefined" || !document.defaultView?.CSSStyleSheet)
|
|
17
|
-
throw new Error("Constructable stylesheets are unavailable");
|
|
18
|
-
sheet = new document.defaultView.CSSStyleSheet();
|
|
19
|
-
sheet.replaceSync(buttonControlCss);
|
|
20
|
-
buttonSheets.set(document, sheet);
|
|
21
|
-
}
|
|
22
|
-
catch {
|
|
23
|
-
buttonSheetUnsupported.add(document);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
if (sheet) {
|
|
27
|
-
if (!shadow.adoptedStyleSheets.includes(sheet))
|
|
28
|
-
shadow.adoptedStyleSheets = [...shadow.adoptedStyleSheets, sheet];
|
|
29
|
-
shadow.replaceChildren(button);
|
|
30
|
-
}
|
|
31
|
-
else
|
|
32
|
-
shadow.replaceChildren(buttonStyleNode(document), button);
|
|
33
|
-
}
|
|
34
|
-
const unsafeHref = (href) => /^(?:javascript|data|vbscript):/i.test(href.trim());
|
|
35
|
-
export function defineButton() {
|
|
36
|
-
if (customElements.get("spui-button"))
|
|
37
|
-
return;
|
|
38
|
-
class SpuiButton extends HTMLElement {
|
|
39
|
-
static formAssociated = true;
|
|
40
|
-
static observedAttributes = ["as", "href", "target", "rel", "download", "hreflang", "referrerpolicy", "form", "formaction", "formenctype", "formnovalidate", "formtarget", "name", "value", "variant", "appearance", "size", "shape", "icon-only", "icon-position", "vertical", "disabled", "disabled-focusable", "type", "tabindex", "aria-label", "aria-labelledby", "aria-description", "aria-describedby", "aria-pressed", "aria-expanded", "aria-haspopup", "aria-controls", "aria-current", "aria-disabled", "title"];
|
|
41
|
-
internals = this.attachInternals();
|
|
42
|
-
formSubmitter;
|
|
43
|
-
formDisabled = false;
|
|
44
|
-
get form() { return this.internals.form; }
|
|
45
|
-
connectedCallback() { this.render(); }
|
|
46
|
-
formDisabledCallback(disabled) { this.formDisabled = disabled; this.render(); }
|
|
47
|
-
disconnectedCallback() { stopHostAccessibleNameSync(this); this.formSubmitter?.remove(); this.formSubmitter = undefined; }
|
|
48
|
-
attributeChangedCallback(name) {
|
|
49
|
-
if (!this.isConnected)
|
|
50
|
-
return;
|
|
51
|
-
if (name === "aria-label" || name === "aria-labelledby") {
|
|
52
|
-
const button = this.shadowRoot?.querySelector("button,a");
|
|
53
|
-
if (button)
|
|
54
|
-
syncHostAccessibleName(this, button);
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
if (["aria-description", "aria-describedby", "aria-pressed", "aria-expanded", "aria-haspopup", "aria-controls", "title"].includes(name)) {
|
|
58
|
-
const button = this.shadowRoot?.querySelector("button,a");
|
|
59
|
-
const value = this.getAttribute(name);
|
|
60
|
-
if (button && (name === "aria-description" || name === "aria-describedby"))
|
|
61
|
-
syncHostAccessibleName(this, button);
|
|
62
|
-
else if (button)
|
|
63
|
-
value === null ? button.removeAttribute(name) : button.setAttribute(name, value);
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
if (name === "tabindex") {
|
|
67
|
-
const button = this.shadowRoot?.querySelector("button,a");
|
|
68
|
-
const value = this.getAttribute(name);
|
|
69
|
-
if (button)
|
|
70
|
-
value === null ? button.removeAttribute("tabindex") : button.setAttribute("tabindex", value);
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
this.render();
|
|
74
|
-
}
|
|
75
|
-
render() {
|
|
76
|
-
const shadow = this.shadowRoot ?? this.attachShadow({ mode: "open", delegatesFocus: true });
|
|
77
|
-
const previous = shadow.querySelector("button,a");
|
|
78
|
-
const restoreFocus = previous !== null && previous === shadow.activeElement;
|
|
79
|
-
const as = this.getAttribute("as") === "a" ? "a" : "button";
|
|
80
|
-
const button = document.createElement(as);
|
|
81
|
-
const type = this.getAttribute("type");
|
|
82
|
-
if (button instanceof HTMLButtonElement)
|
|
83
|
-
button.type = type === "submit" || type === "reset" ? type : "button";
|
|
84
|
-
const href = this.getAttribute("href")?.trim() ?? "";
|
|
85
|
-
const disabled = this.formDisabled || this.hasAttribute("disabled") || this.getAttribute("aria-disabled") === "true";
|
|
86
|
-
const disabledFocusable = this.hasAttribute("disabled-focusable");
|
|
87
|
-
const inactive = disabled || disabledFocusable;
|
|
88
|
-
const hasHref = as === "a" && !!href && !unsafeHref(href);
|
|
89
|
-
if (button instanceof HTMLAnchorElement) {
|
|
90
|
-
if (!inactive && hasHref)
|
|
91
|
-
button.href = href;
|
|
92
|
-
for (const name of ["target", "rel", "download", "hreflang", "referrerpolicy"]) {
|
|
93
|
-
const value = this.getAttribute(name);
|
|
94
|
-
if (value !== null)
|
|
95
|
-
button.setAttribute(name, value);
|
|
96
|
-
}
|
|
97
|
-
if (!disabled && button.target.toLowerCase() === "_blank") {
|
|
98
|
-
const rel = new Set((button.getAttribute("rel") ?? "").split(/\s+/).filter(Boolean));
|
|
99
|
-
rel.add("noopener");
|
|
100
|
-
rel.add("noreferrer");
|
|
101
|
-
button.rel = [...rel].join(" ");
|
|
102
|
-
}
|
|
103
|
-
if (inactive)
|
|
104
|
-
button.setAttribute("aria-disabled", "true");
|
|
105
|
-
if (disabledFocusable)
|
|
106
|
-
button.tabIndex = this.hasAttribute("tabindex") ? Number(this.getAttribute("tabindex")) : 0;
|
|
107
|
-
else if (!hasHref && !disabled)
|
|
108
|
-
button.tabIndex = this.hasAttribute("tabindex") ? Number(this.getAttribute("tabindex")) : 0;
|
|
109
|
-
if (hasHref)
|
|
110
|
-
button.setAttribute("role", "link");
|
|
111
|
-
else
|
|
112
|
-
button.setAttribute("role", "button");
|
|
113
|
-
button.addEventListener("click", event => { if (disabled || !hasHref) {
|
|
114
|
-
event.preventDefault();
|
|
115
|
-
if (disabled)
|
|
116
|
-
event.stopPropagation();
|
|
117
|
-
} });
|
|
118
|
-
button.addEventListener("keydown", event => {
|
|
119
|
-
if (disabled) {
|
|
120
|
-
if (event.key === "Enter" || event.key === " ") {
|
|
121
|
-
event.preventDefault();
|
|
122
|
-
event.stopPropagation();
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
else if (event.key === "Enter") {
|
|
126
|
-
event.preventDefault();
|
|
127
|
-
button.click();
|
|
128
|
-
}
|
|
129
|
-
else if (event.key === " ")
|
|
130
|
-
event.preventDefault();
|
|
131
|
-
});
|
|
132
|
-
button.addEventListener("keyup", event => {
|
|
133
|
-
if (disabled) {
|
|
134
|
-
if (event.key === "Enter" || event.key === " ") {
|
|
135
|
-
event.preventDefault();
|
|
136
|
-
event.stopPropagation();
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
else if (event.key === " " && !hasHref) {
|
|
140
|
-
event.preventDefault();
|
|
141
|
-
button.click();
|
|
142
|
-
}
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
else {
|
|
146
|
-
button.disabled = disabled && !disabledFocusable;
|
|
147
|
-
if (disabled && disabledFocusable) {
|
|
148
|
-
button.setAttribute("aria-disabled", "true");
|
|
149
|
-
button.addEventListener("click", event => { event.preventDefault(); event.stopImmediatePropagation(); event.stopPropagation(); });
|
|
150
|
-
}
|
|
151
|
-
for (const name of ["formaction", "formenctype", "formmethod", "formnovalidate", "formtarget"]) {
|
|
152
|
-
const value = this.getAttribute(name);
|
|
153
|
-
if (value === null)
|
|
154
|
-
button.removeAttribute(name);
|
|
155
|
-
else
|
|
156
|
-
button.setAttribute(name, value);
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
this.syncFormSubmitter(as, type, disabled);
|
|
160
|
-
if (button instanceof HTMLButtonElement && (type === "submit" || type === "reset"))
|
|
161
|
-
button.addEventListener("click", event => {
|
|
162
|
-
this.syncFormSubmitter(as, type, disabled);
|
|
163
|
-
document.addEventListener("click", () => { if (!event.defaultPrevented && !disabled && this.formSubmitter?.isConnected)
|
|
164
|
-
this.formSubmitter.click(); }, { once: true });
|
|
165
|
-
});
|
|
166
|
-
if (this.hasAttribute("tabindex"))
|
|
167
|
-
button.setAttribute("tabindex", this.getAttribute("tabindex"));
|
|
168
|
-
for (const name of ["aria-description", "aria-describedby", "aria-pressed", "aria-expanded", "aria-haspopup", "aria-controls", "aria-current", "title"]) {
|
|
169
|
-
const value = this.getAttribute(name);
|
|
170
|
-
if (value !== null)
|
|
171
|
-
button.setAttribute(name, value);
|
|
172
|
-
}
|
|
173
|
-
const appearance = this.getAttribute("appearance") ?? (this.getAttribute("variant") === "primary" ? "primary" : "secondary");
|
|
174
|
-
button.className = appearance === "primary" ? "primary" : appearance === "outline" || appearance === "subtle" || appearance === "transparent" ? appearance : "secondary";
|
|
175
|
-
button.part.add("control");
|
|
176
|
-
const icon = document.createElement("span");
|
|
177
|
-
icon.className = "icon";
|
|
178
|
-
icon.setAttribute("aria-hidden", "true");
|
|
179
|
-
const iconSlot = document.createElement("slot");
|
|
180
|
-
iconSlot.name = "icon";
|
|
181
|
-
icon.append(iconSlot);
|
|
182
|
-
iconSlot.addEventListener("slotchange", () => { icon.hidden = !iconSlot.assignedNodes({ flatten: true }).length; });
|
|
183
|
-
icon.hidden = !iconSlot.assignedNodes({ flatten: true }).length;
|
|
184
|
-
const content = document.createElement("span");
|
|
185
|
-
content.className = "content";
|
|
186
|
-
content.append(document.createElement("slot"));
|
|
187
|
-
button.append(icon, content);
|
|
188
|
-
applyButtonStyle(shadow, button);
|
|
189
|
-
syncHostAccessibleName(this, button);
|
|
190
|
-
if (restoreFocus)
|
|
191
|
-
button.focus();
|
|
192
|
-
}
|
|
193
|
-
syncFormSubmitter(as, type, disabled) {
|
|
194
|
-
if (type !== "submit" && type !== "reset") {
|
|
195
|
-
this.formSubmitter?.remove();
|
|
196
|
-
this.formSubmitter = undefined;
|
|
197
|
-
return;
|
|
198
|
-
}
|
|
199
|
-
const form = as === "button" ? this.internals.form ?? this.closest("form") : null;
|
|
200
|
-
if (!form) {
|
|
201
|
-
this.formSubmitter?.remove();
|
|
202
|
-
this.formSubmitter = undefined;
|
|
203
|
-
return;
|
|
204
|
-
}
|
|
205
|
-
const submitter = this.formSubmitter ?? document.createElement("button");
|
|
206
|
-
submitter.hidden = true;
|
|
207
|
-
submitter.tabIndex = -1;
|
|
208
|
-
submitter.setAttribute("aria-hidden", "true");
|
|
209
|
-
submitter.type = type;
|
|
210
|
-
submitter.disabled = disabled;
|
|
211
|
-
submitter.name = this.getAttribute("name") ?? "";
|
|
212
|
-
submitter.value = this.getAttribute("value") ?? "";
|
|
213
|
-
for (const name of ["formaction", "formenctype", "formmethod", "formnovalidate", "formtarget"]) {
|
|
214
|
-
const value = this.getAttribute(name);
|
|
215
|
-
if (value === null)
|
|
216
|
-
submitter.removeAttribute(name);
|
|
217
|
-
else
|
|
218
|
-
submitter.setAttribute(name, value);
|
|
219
|
-
}
|
|
220
|
-
const formId = this.getAttribute("form");
|
|
221
|
-
if (formId)
|
|
222
|
-
submitter.setAttribute("form", formId);
|
|
223
|
-
else
|
|
224
|
-
submitter.removeAttribute("form");
|
|
225
|
-
if (!this.formSubmitter)
|
|
226
|
-
submitter.addEventListener("click", event => event.stopPropagation());
|
|
227
|
-
if (!this.formSubmitter || submitter.form !== form)
|
|
228
|
-
form.append(submitter);
|
|
229
|
-
this.formSubmitter = submitter;
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
customElements.define("spui-button", SpuiButton);
|
|
233
|
-
}
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import { base } from "./shared.js";
|
|
2
|
-
export function defineCardHeader() {
|
|
3
|
-
if (customElements.get("spui-card-header"))
|
|
4
|
-
return;
|
|
5
|
-
class SpuiCardHeader extends HTMLElement {
|
|
6
|
-
connectedCallback() {
|
|
7
|
-
if (this.shadowRoot)
|
|
8
|
-
return;
|
|
9
|
-
const shadow = this.attachShadow({ mode: "open" });
|
|
10
|
-
const style = document.createElement("style");
|
|
11
|
-
style.textContent = `${base}:host{display:block;min-width:0}.layout{display:grid;grid-template-columns:max-content minmax(0,1fr) max-content;align-items:center;column-gap:var(--spui-control-gap,12px);row-gap:3px}.main{display:grid;grid-template-columns:minmax(0,1fr);row-gap:3px;min-width:0}slot[name=image]{grid-column:1;grid-row:1 / span 2}slot[name=action]{grid-column:3;grid-row:1 / span 2;justify-self:end}slot[name=header]{font-size:var(--spui-card-header-size,14px);font-weight:600;line-height:1.35}slot[name=description]{color:var(--spui-ui-muted,var(--spui-semantic-body-text,#616161));font-size:12px;line-height:1.4}::slotted([slot=image]){display:inline-flex;max-width:48px;max-height:48px;align-items:center;justify-content:center}::slotted([slot=action]){display:inline-flex;align-items:center;justify-content:flex-end}@media(forced-colors:active){slot[name=description]{color:CanvasText}}`;
|
|
12
|
-
const layout = document.createElement("div");
|
|
13
|
-
layout.className = "layout";
|
|
14
|
-
layout.part.add("root");
|
|
15
|
-
const image = document.createElement("slot");
|
|
16
|
-
image.name = "image";
|
|
17
|
-
image.part.add("image");
|
|
18
|
-
const main = document.createElement("div");
|
|
19
|
-
main.className = "main";
|
|
20
|
-
main.part.add("content");
|
|
21
|
-
const header = document.createElement("slot");
|
|
22
|
-
header.name = "header";
|
|
23
|
-
header.part.add("header");
|
|
24
|
-
const defaultHeader = document.createElement("slot");
|
|
25
|
-
const description = document.createElement("slot");
|
|
26
|
-
description.name = "description";
|
|
27
|
-
description.part.add("description");
|
|
28
|
-
main.append(header);
|
|
29
|
-
header.append(defaultHeader);
|
|
30
|
-
main.append(description);
|
|
31
|
-
const action = document.createElement("slot");
|
|
32
|
-
action.name = "action";
|
|
33
|
-
action.part.add("action");
|
|
34
|
-
layout.append(image, main, action);
|
|
35
|
-
shadow.append(style, layout);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
customElements.define("spui-card-header", SpuiCardHeader);
|
|
39
|
-
}
|
|
40
|
-
export function defineCardFooter() {
|
|
41
|
-
if (customElements.get("spui-card-footer"))
|
|
42
|
-
return;
|
|
43
|
-
class SpuiCardFooter extends HTMLElement {
|
|
44
|
-
connectedCallback() {
|
|
45
|
-
if (this.shadowRoot)
|
|
46
|
-
return;
|
|
47
|
-
const shadow = this.attachShadow({ mode: "open" });
|
|
48
|
-
const style = document.createElement("style");
|
|
49
|
-
style.textContent = `${base}:host{display:flex;flex-wrap:wrap;align-items:center;gap:var(--spui-control-gap,12px);min-width:0}slot[name=action]{margin-inline-start:auto}::slotted([slot=action]){display:inline-flex;align-items:center;justify-content:flex-end}@media(forced-colors:active){:host{color:CanvasText}}`;
|
|
50
|
-
const content = document.createElement("slot");
|
|
51
|
-
content.part.add("content");
|
|
52
|
-
const action = document.createElement("slot");
|
|
53
|
-
action.name = "action";
|
|
54
|
-
action.part.add("action");
|
|
55
|
-
shadow.append(style, content, action);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
customElements.define("spui-card-footer", SpuiCardFooter);
|
|
59
|
-
}
|
|
60
|
-
export function defineCardPreview() {
|
|
61
|
-
if (customElements.get("spui-card-preview"))
|
|
62
|
-
return;
|
|
63
|
-
class SpuiCardPreview extends HTMLElement {
|
|
64
|
-
connectedCallback() {
|
|
65
|
-
if (this.shadowRoot)
|
|
66
|
-
return;
|
|
67
|
-
const shadow = this.attachShadow({ mode: "open" });
|
|
68
|
-
const style = document.createElement("style");
|
|
69
|
-
style.textContent = `${base}:host{position:relative;display:block;min-width:0;overflow:hidden;margin-inline:calc(-1 * var(--spui-card-padding,16px));border-radius:inherit}:host(:first-child){margin-block-start:calc(-1 * var(--spui-card-padding,16px))}.preview{position:relative;min-width:0;overflow:hidden}slot:not([name=logo]){display:block}::slotted(img),::slotted(video),::slotted(picture){display:block;width:100%;max-width:100%;height:auto;max-height:360px;object-fit:cover}slot[name=logo]{position:absolute;inset-block-end:10px;inset-inline-start:10px;display:flex;align-items:center;justify-content:center;max-width:calc(100% - 20px);padding:4px;border:1px solid var(--spui-ui-stroke,#d1d1d1);border-radius:var(--spui-control-radius,6px);background:var(--spui-ui-surface,#fff);box-shadow:var(--spui-card-shadow,0 1px 3px #0002)}::slotted([slot=logo]){max-width:100%;max-height:40px}@media(forced-colors:active){:host{border:1px solid CanvasText}slot[name=logo]{border-color:CanvasText;background:Canvas;box-shadow:none}}`;
|
|
70
|
-
const preview = document.createElement("div");
|
|
71
|
-
preview.className = "preview";
|
|
72
|
-
preview.part.add("root");
|
|
73
|
-
const content = document.createElement("slot");
|
|
74
|
-
content.part.add("content");
|
|
75
|
-
const logo = document.createElement("slot");
|
|
76
|
-
logo.name = "logo";
|
|
77
|
-
logo.part.add("logo");
|
|
78
|
-
preview.append(content, logo);
|
|
79
|
-
shadow.append(style, preview);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
customElements.define("spui-card-preview", SpuiCardPreview);
|
|
83
|
-
}
|
package/dist/elements/card.d.ts
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
export type CardAppearance = "filled" | "filled-alternative" | "outline" | "subtle";
|
|
2
|
-
export type CardOrientation = "horizontal" | "vertical";
|
|
3
|
-
export type CardSize = "small" | "medium" | "large";
|
|
4
|
-
export type CardFocusMode = "off" | "no-tab" | "tab-exit" | "tab-only";
|
|
5
|
-
export declare function defineCard(): void;
|
package/dist/elements/card.js
DELETED
|
@@ -1,213 +0,0 @@
|
|
|
1
|
-
import { base } from "./shared.js";
|
|
2
|
-
const focusableSelector = 'a[href],area[href],button,input:not([type="hidden"]),select,textarea,iframe,object,embed,audio[controls],video[controls],summary,[contenteditable]:not([contenteditable="false"]),[tabindex]';
|
|
3
|
-
function findCardFocusables(card) {
|
|
4
|
-
const found = [];
|
|
5
|
-
const visit = (element) => {
|
|
6
|
-
if (element instanceof HTMLElement && element.matches(focusableSelector) && element.tabIndex >= 0 && !element.matches(":disabled,[hidden],[aria-hidden=true]") && element.getClientRects().length > 0)
|
|
7
|
-
found.push(element);
|
|
8
|
-
if (element instanceof HTMLSlotElement) {
|
|
9
|
-
const assigned = element.assignedElements({ flatten: true });
|
|
10
|
-
for (const child of assigned.length ? assigned : [...element.children])
|
|
11
|
-
visit(child);
|
|
12
|
-
return;
|
|
13
|
-
}
|
|
14
|
-
const children = element.shadowRoot ? [...element.shadowRoot.children] : [...element.children];
|
|
15
|
-
for (const child of children)
|
|
16
|
-
visit(child);
|
|
17
|
-
};
|
|
18
|
-
for (const child of card.children)
|
|
19
|
-
visit(child);
|
|
20
|
-
return found;
|
|
21
|
-
}
|
|
22
|
-
function deepestActiveElement(document) {
|
|
23
|
-
let active = document.activeElement;
|
|
24
|
-
while (active?.shadowRoot?.activeElement)
|
|
25
|
-
active = active.shadowRoot.activeElement;
|
|
26
|
-
return active;
|
|
27
|
-
}
|
|
28
|
-
export function defineCard() {
|
|
29
|
-
if (customElements.get("spui-card"))
|
|
30
|
-
return;
|
|
31
|
-
class SpuiCard extends HTMLElement {
|
|
32
|
-
static observedAttributes = ["aria-label", "selectable", "selected", "default-selected", "disabled", "selection-label", "focus-mode"];
|
|
33
|
-
defaultSelectedValue;
|
|
34
|
-
focusGroupActive = false;
|
|
35
|
-
managedTabIndex = false;
|
|
36
|
-
managedRole = false;
|
|
37
|
-
selectionInput() {
|
|
38
|
-
const slot = this.shadowRoot?.querySelector("slot[name=checkbox]");
|
|
39
|
-
return slot?.assignedElements({ flatten: true }).find((element) => element instanceof HTMLInputElement)
|
|
40
|
-
?? this.shadowRoot?.querySelector(".selection") ?? undefined;
|
|
41
|
-
}
|
|
42
|
-
get selected() { return this.hasAttribute("selected"); }
|
|
43
|
-
set selected(value) { this.toggleAttribute("selected", Boolean(value)); }
|
|
44
|
-
get defaultSelected() { return this.defaultSelectedValue ?? this.hasAttribute("default-selected"); }
|
|
45
|
-
set defaultSelected(value) { this.defaultSelectedValue = Boolean(value); this.setAttribute("selectable", ""); if (!this.hasAttribute("selected"))
|
|
46
|
-
this.toggleAttribute("selected", this.defaultSelectedValue); }
|
|
47
|
-
get focusMode() { const value = this.getAttribute("focus-mode"); return value === "no-tab" || value === "tab-exit" || value === "tab-only" ? value : "off"; }
|
|
48
|
-
set focusMode(value) { if (value === "off")
|
|
49
|
-
this.removeAttribute("focus-mode");
|
|
50
|
-
else
|
|
51
|
-
this.setAttribute("focus-mode", value); }
|
|
52
|
-
connectedCallback() {
|
|
53
|
-
if (this.hasAttribute("default-selected")) {
|
|
54
|
-
this.defaultSelectedValue = this.hasAttribute("default-selected");
|
|
55
|
-
this.setAttribute("selectable", "");
|
|
56
|
-
if (this.hasAttribute("default-selected") && !this.hasAttribute("selected"))
|
|
57
|
-
this.toggleAttribute("selected", this.defaultSelectedValue ?? true);
|
|
58
|
-
this.removeAttribute("default-selected");
|
|
59
|
-
}
|
|
60
|
-
if (this.hasAttribute("aria-label"))
|
|
61
|
-
this.setAttribute("role", "region");
|
|
62
|
-
if (!this.shadowRoot) {
|
|
63
|
-
const shadow = this.attachShadow({ mode: "open" });
|
|
64
|
-
const style = document.createElement("style");
|
|
65
|
-
style.textContent = `${base}:host{display:block;position:relative;min-width:0;border:1px solid var(--spui-card-border,var(--spui-ui-stroke,var(--spui-semantic-card-border,var(--colorNeutralStroke2,#edebe9))));border-radius:var(--spui-card-radius,8px);background:var(--spui-card-background,var(--spui-ui-surface,var(--spui-semantic-card-background,var(--colorNeutralBackground1,#fff))));box-shadow:var(--spui-card-shadow,0 1px 3px #0001)}.content{min-width:0;padding:var(--spui-card-padding,16px)}:host([selectable]){cursor:pointer}:host([selectable]) .content{padding-inline-start:44px}:host([selected]){border-color:var(--spui-selection-border,var(--spui-semantic-focus-border,var(--colorCompoundBrandStroke,#0f6cbd)));background:var(--spui-selection-background,color-mix(in srgb,var(--spui-base-accent,var(--spui-ui-accent,#0f6cbd)) 7%,var(--spui-card-background,var(--spui-ui-surface,#fff)) 93%))}.selection{position:absolute;inset-block-start:12px;inset-inline-start:12px;width:18px;height:18px;margin:0;accent-color:var(--spui-base-accent,var(--spui-ui-accent,#0f6cbd));cursor:pointer}:host(:focus-within){outline:2px solid var(--spui-focus-ring,var(--spui-semantic-focus-border,var(--colorStrokeFocus2,#005a9e)));outline-offset:2px}:host([disabled]),:host([disabled]) .selection{cursor:default}:host([appearance=filled-alternative]){background:color-mix(in srgb,var(--spui-base-surface,var(--spui-ui-surface,#fff)) 90%,var(--spui-base-text,var(--spui-ui-text,#242424)) 10%)}:host([appearance=outline]){background:transparent;box-shadow:none}:host([appearance=subtle]){border-color:transparent;background:var(--spui-ui-canvas,var(--spui-semantic-body-background,#f5f5f5));box-shadow:none}:host([size=small]){--spui-card-padding:12px;--spui-control-gap:8px}:host([size=large]){--spui-card-padding:20px;--spui-control-gap:12px}:host([orientation=horizontal]) .content>slot{display:flex;flex-wrap:wrap;align-items:center;gap:var(--spui-control-gap,8px)}:host([data-spui-appearance=glass]),:host-context([data-spui-appearance=glass]){backdrop-filter:var(--spui-card-backdrop,none)}:host([selected]){border-color:var(--spui-selection-border,var(--spui-semantic-focus-border,var(--colorCompoundBrandStroke,#0f6cbd)));background:var(--spui-selection-background,color-mix(in srgb,var(--spui-base-accent,var(--spui-ui-accent,#0f6cbd)) 7%,var(--spui-card-background,var(--spui-ui-surface,#fff)) 93%))}@media(forced-colors:active){:host{border-color:CanvasText;box-shadow:none}:host([appearance=subtle]),:host([appearance=outline]){background:Canvas}:host([selected]){outline:2px solid Highlight}.selection{accent-color:Highlight}}`;
|
|
66
|
-
style.textContent += ":host([has-floating-action]) .content{padding-block-start:48px}.floating-action{position:absolute;z-index:1;inset-block-start:8px;inset-inline-end:8px;display:flex;align-items:center;justify-content:center}.floating-action:empty{display:none}";
|
|
67
|
-
const root = document.createElement("div");
|
|
68
|
-
root.className = "root";
|
|
69
|
-
root.part.add("root");
|
|
70
|
-
root.style.position = "relative";
|
|
71
|
-
root.style.minWidth = "0";
|
|
72
|
-
const content = document.createElement("div");
|
|
73
|
-
content.className = "content";
|
|
74
|
-
content.part.add("content");
|
|
75
|
-
content.append(document.createElement("slot"));
|
|
76
|
-
const floatingAction = document.createElement("div");
|
|
77
|
-
floatingAction.className = "floating-action";
|
|
78
|
-
const floatingSlot = document.createElement("slot");
|
|
79
|
-
floatingSlot.name = "floating-action";
|
|
80
|
-
floatingSlot.addEventListener("slotchange", () => this.toggleAttribute("has-floating-action", floatingSlot.assignedNodes({ flatten: true }).length > 0));
|
|
81
|
-
floatingAction.append(floatingSlot);
|
|
82
|
-
const checkbox = document.createElement("input");
|
|
83
|
-
checkbox.className = "selection";
|
|
84
|
-
checkbox.type = "checkbox";
|
|
85
|
-
checkbox.part.add("selection");
|
|
86
|
-
checkbox.addEventListener("change", event => this.setSelected(checkbox.checked, event));
|
|
87
|
-
const checkboxSlot = document.createElement("slot");
|
|
88
|
-
checkboxSlot.name = "checkbox";
|
|
89
|
-
checkboxSlot.append(checkbox);
|
|
90
|
-
checkboxSlot.addEventListener("slotchange", () => this.syncSelection());
|
|
91
|
-
root.append(checkboxSlot, floatingAction, content);
|
|
92
|
-
shadow.append(style, root);
|
|
93
|
-
this.addEventListener("change", event => {
|
|
94
|
-
const input = event.target;
|
|
95
|
-
if (input instanceof HTMLInputElement && input.slot === "checkbox")
|
|
96
|
-
this.setSelected(input.checked, event);
|
|
97
|
-
});
|
|
98
|
-
this.addEventListener("click", event => {
|
|
99
|
-
if (!this.isSelectable() || this.hasAttribute("disabled") || event.composedPath().some(target => target instanceof Element && target !== this && target.matches("a,button,input,select,textarea,[contenteditable=true],[role=button],[role=link],[role=checkbox]")))
|
|
100
|
-
return;
|
|
101
|
-
this.setSelected(!this.selected, event);
|
|
102
|
-
});
|
|
103
|
-
this.addEventListener("keydown", event => this.handleCardKeydown(event));
|
|
104
|
-
this.addEventListener("focusout", () => setTimeout(() => {
|
|
105
|
-
const active = deepestActiveElement(this.ownerDocument);
|
|
106
|
-
if (active !== this && !this.contains(active))
|
|
107
|
-
this.focusGroupActive = false;
|
|
108
|
-
}, 0));
|
|
109
|
-
}
|
|
110
|
-
this.syncSelection();
|
|
111
|
-
this.syncFocusMode();
|
|
112
|
-
}
|
|
113
|
-
attributeChangedCallback(name) {
|
|
114
|
-
if (name === "aria-label" && this.hasAttribute("aria-label") && !this.hasAttribute("role"))
|
|
115
|
-
this.setAttribute("role", "region");
|
|
116
|
-
if (this.shadowRoot) {
|
|
117
|
-
this.syncSelection();
|
|
118
|
-
this.syncFocusMode();
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
isSelectable() { return this.hasAttribute("selectable") || this.hasAttribute("selected") || Boolean(this.defaultSelectedValue); }
|
|
122
|
-
syncSelection() {
|
|
123
|
-
const checkbox = this.selectionInput();
|
|
124
|
-
if (!checkbox)
|
|
125
|
-
return;
|
|
126
|
-
const selectable = this.isSelectable();
|
|
127
|
-
if (!checkbox.hasAttribute("type"))
|
|
128
|
-
checkbox.type = "checkbox";
|
|
129
|
-
checkbox.hidden = !selectable;
|
|
130
|
-
checkbox.disabled = this.hasAttribute("disabled");
|
|
131
|
-
checkbox.checked = this.selected;
|
|
132
|
-
checkbox.setAttribute("aria-label", this.getAttribute("selection-label") || `Select ${this.getAttribute("aria-label") || "card"}`);
|
|
133
|
-
}
|
|
134
|
-
syncFocusMode() {
|
|
135
|
-
const enabled = this.focusMode !== "off" && !this.isSelectable() && !this.hasAttribute("disabled");
|
|
136
|
-
if (enabled && !this.hasAttribute("tabindex")) {
|
|
137
|
-
this.tabIndex = 0;
|
|
138
|
-
this.managedTabIndex = true;
|
|
139
|
-
}
|
|
140
|
-
else if (!enabled && this.managedTabIndex) {
|
|
141
|
-
this.removeAttribute("tabindex");
|
|
142
|
-
this.managedTabIndex = false;
|
|
143
|
-
}
|
|
144
|
-
if (enabled && !this.hasAttribute("role")) {
|
|
145
|
-
this.setAttribute("role", "group");
|
|
146
|
-
this.managedRole = true;
|
|
147
|
-
}
|
|
148
|
-
else if (!enabled && this.managedRole) {
|
|
149
|
-
this.removeAttribute("role");
|
|
150
|
-
this.managedRole = false;
|
|
151
|
-
}
|
|
152
|
-
if (!enabled)
|
|
153
|
-
this.focusGroupActive = false;
|
|
154
|
-
}
|
|
155
|
-
handleFocusKeydown(event) {
|
|
156
|
-
const mode = this.focusMode;
|
|
157
|
-
if (mode === "off" || this.hasAttribute("disabled") || this.isSelectable())
|
|
158
|
-
return;
|
|
159
|
-
const focusables = findCardFocusables(this);
|
|
160
|
-
const focused = event.composedPath().find(target => target instanceof HTMLElement && focusables.includes(target)) ?? deepestActiveElement(this.ownerDocument);
|
|
161
|
-
if ((mode === "no-tab" || mode === "tab-exit") && event.key === "Enter" && focused === this && focusables.length) {
|
|
162
|
-
event.preventDefault();
|
|
163
|
-
this.focusGroupActive = true;
|
|
164
|
-
focusables[0].focus();
|
|
165
|
-
return;
|
|
166
|
-
}
|
|
167
|
-
if (!this.focusGroupActive)
|
|
168
|
-
return;
|
|
169
|
-
if (event.key === "Escape") {
|
|
170
|
-
event.preventDefault();
|
|
171
|
-
this.focusGroupActive = false;
|
|
172
|
-
this.focus();
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
if (event.key !== "Tab" || !focusables.length)
|
|
176
|
-
return;
|
|
177
|
-
const index = focusables.indexOf(focused);
|
|
178
|
-
if (mode === "no-tab") {
|
|
179
|
-
if (event.shiftKey && index <= 0) {
|
|
180
|
-
event.preventDefault();
|
|
181
|
-
focusables.at(-1)?.focus();
|
|
182
|
-
}
|
|
183
|
-
else if (!event.shiftKey && index === focusables.length - 1) {
|
|
184
|
-
event.preventDefault();
|
|
185
|
-
focusables[0].focus();
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
else if (mode === "tab-exit" && ((event.shiftKey && index === 0) || (!event.shiftKey && index === focusables.length - 1))) {
|
|
189
|
-
this.focusGroupActive = false;
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
handleCardKeydown(event) {
|
|
193
|
-
if (event.key === "Enter" && !this.hasAttribute("disabled") && this.isSelectable()) {
|
|
194
|
-
const target = event.composedPath()[0];
|
|
195
|
-
if (target === this || target === this.selectionInput()) {
|
|
196
|
-
event.preventDefault();
|
|
197
|
-
this.setSelected(!this.selected, event);
|
|
198
|
-
return;
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
this.handleFocusKeydown(event);
|
|
202
|
-
}
|
|
203
|
-
setSelected(selected, sourceEvent) {
|
|
204
|
-
if (this.hasAttribute("disabled") || !this.isSelectable() || this.selected === selected) {
|
|
205
|
-
this.syncSelection();
|
|
206
|
-
return;
|
|
207
|
-
}
|
|
208
|
-
this.toggleAttribute("selected", selected);
|
|
209
|
-
this.dispatchEvent(new CustomEvent("spui-selection-change", { bubbles: true, composed: true, detail: { selected, event: sourceEvent } }));
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
customElements.define("spui-card", SpuiCard);
|
|
213
|
-
}
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
export type CarouselAlign = "start" | "center" | "end";
|
|
2
|
-
export type CarouselAppearance = "flat" | "elevated";
|
|
3
|
-
export type CarouselMotion = "slide" | "fade" | {
|
|
4
|
-
kind: "slide";
|
|
5
|
-
duration?: number;
|
|
6
|
-
};
|
|
7
|
-
export type CarouselAnnouncerFunction = (index: number, totalSlides: number, slideGroupList: number[][]) => string;
|
|
8
|
-
export type CarouselIndexChangeData = {
|
|
9
|
-
event: MouseEvent;
|
|
10
|
-
type: "click";
|
|
11
|
-
index: number;
|
|
12
|
-
} | {
|
|
13
|
-
event: FocusEvent;
|
|
14
|
-
type: "focus";
|
|
15
|
-
index: number;
|
|
16
|
-
} | {
|
|
17
|
-
event: PointerEvent | MouseEvent;
|
|
18
|
-
type: "drag";
|
|
19
|
-
index: number;
|
|
20
|
-
} | {
|
|
21
|
-
event: Event;
|
|
22
|
-
type: "autoplay" | "scroll" | "programmatic";
|
|
23
|
-
index: number;
|
|
24
|
-
} | {
|
|
25
|
-
event: KeyboardEvent;
|
|
26
|
-
type: "keydown";
|
|
27
|
-
index: number;
|
|
28
|
-
};
|
|
29
|
-
export type CarouselIndexChangeSource = CarouselIndexChangeData extends infer T ? T extends {
|
|
30
|
-
index: number;
|
|
31
|
-
} ? Omit<T, "index"> : never : never;
|
|
32
|
-
export interface SharePointCarouselElement extends HTMLElement {
|
|
33
|
-
align: CarouselAlign;
|
|
34
|
-
appearance: CarouselAppearance;
|
|
35
|
-
motion: CarouselMotion;
|
|
36
|
-
motionDuration: number;
|
|
37
|
-
slideWidth: string;
|
|
38
|
-
groupSize: number | "auto";
|
|
39
|
-
draggable: boolean;
|
|
40
|
-
whitespace: boolean;
|
|
41
|
-
selectedIndex: number;
|
|
42
|
-
defaultSelectedIndex: number;
|
|
43
|
-
activeIndex: number;
|
|
44
|
-
defaultActiveIndex: number;
|
|
45
|
-
circular: boolean;
|
|
46
|
-
goTo(index: number): void;
|
|
47
|
-
nextSlide(): void;
|
|
48
|
-
previousSlide(): void;
|
|
49
|
-
announcement?: CarouselAnnouncerFunction;
|
|
50
|
-
}
|
|
51
|
-
export interface SharePointCarouselNavButtonElement extends HTMLElement {
|
|
52
|
-
index: number;
|
|
53
|
-
selected: boolean;
|
|
54
|
-
disabled: boolean;
|
|
55
|
-
}
|
|
56
|
-
export interface SharePointCarouselCardElement extends HTMLElement {
|
|
57
|
-
autoSize: boolean;
|
|
58
|
-
}
|
|
59
|
-
export interface SharePointCarouselButtonElement extends HTMLElement {
|
|
60
|
-
navType: "prev" | "next";
|
|
61
|
-
disabled: boolean;
|
|
62
|
-
}
|
|
63
|
-
export interface SharePointCarouselAutoplayButtonElement extends HTMLElement {
|
|
64
|
-
selected: boolean;
|
|
65
|
-
}
|
|
66
|
-
export interface SharePointCarouselSliderElement extends HTMLElement {
|
|
67
|
-
cardFocus: boolean;
|
|
68
|
-
}
|
|
69
|
-
declare global {
|
|
70
|
-
interface HTMLElementTagNameMap {
|
|
71
|
-
"spui-carousel": SharePointCarouselElement;
|
|
72
|
-
"spui-carousel-card": SharePointCarouselCardElement;
|
|
73
|
-
"spui-carousel-nav": HTMLElement;
|
|
74
|
-
"spui-carousel-nav-button": SharePointCarouselNavButtonElement;
|
|
75
|
-
"spui-carousel-nav-image-button": SharePointCarouselNavButtonElement;
|
|
76
|
-
"spui-carousel-button": SharePointCarouselButtonElement;
|
|
77
|
-
"spui-carousel-autoplay-button": SharePointCarouselAutoplayButtonElement;
|
|
78
|
-
"spui-carousel-slider": SharePointCarouselSliderElement;
|
|
79
|
-
"spui-carousel-viewport": HTMLElement;
|
|
80
|
-
"spui-carousel-nav-container": HTMLElement;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
export declare function defineCarouselCard(): void;
|
|
84
|
-
export declare function defineCarouselNav(): void;
|
|
85
|
-
export declare function defineCarouselNavButton(): void;
|
|
86
|
-
export declare function defineCarouselNavImageButton(): void;
|
|
87
|
-
export declare function defineCarouselButton(): void;
|
|
88
|
-
export declare function defineCarouselAutoplayButton(): void;
|
|
89
|
-
export declare function defineCarouselNavContainer(): void;
|
|
90
|
-
export declare function defineCarouselSlider(): void;
|
|
91
|
-
export declare function defineCarouselViewport(): void;
|
|
92
|
-
export declare function defineCarousel(): void;
|