@spfx-fast/sharepoint-ui 0.4.2 → 0.4.3
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/AGENTS.md +23 -3
- package/QUICKSTART.md +133 -0
- package/README.md +3 -1
- package/components.json +168 -28
- package/dist/appearance.js +4 -4
- package/dist/elements/alert.js +26 -2
- package/dist/elements/avatar.js +1 -1
- package/dist/elements/button.js +1 -1
- package/dist/elements/carousel.js +5 -2
- package/dist/elements/color-picker.js +1 -1
- package/dist/elements/combobox.js +5 -5
- package/dist/elements/data-grid-model.d.ts +3 -0
- package/dist/elements/data-grid.d.ts +2 -1
- package/dist/elements/data-grid.js +19 -10
- package/dist/elements/date-picker.js +1 -1
- package/dist/elements/dialog.js +1 -1
- package/dist/elements/file-upload.js +1 -1
- package/dist/elements/floating-position.d.ts +10 -0
- package/dist/elements/floating-position.js +53 -0
- package/dist/elements/info.js +1 -1
- package/dist/elements/input.js +2 -2
- package/dist/elements/link.js +1 -1
- package/dist/elements/message-bar.js +33 -5
- package/dist/elements/nav.js +4 -1
- package/dist/elements/overflow.d.ts +1 -0
- package/dist/elements/overflow.js +2 -2
- package/dist/elements/popover.js +1 -1
- package/dist/elements/rating.js +3 -3
- package/dist/elements/rich-text-editor.d.ts +15 -1
- package/dist/elements/rich-text-editor.js +938 -79
- package/dist/elements/search.js +3 -10
- package/dist/elements/select.js +2 -2
- package/dist/elements/shared.d.ts +4 -1
- package/dist/elements/shared.js +14 -1
- package/dist/elements/sharepoint-field-basic-controls.d.ts +1 -0
- package/dist/elements/sharepoint-field-basic-controls.js +14 -0
- package/dist/elements/sharepoint-fields.d.ts +29 -0
- package/dist/elements/sharepoint-fields.js +460 -0
- package/dist/elements/spin-button.js +2 -2
- package/dist/elements/tag-picker.js +29 -11
- package/dist/elements/textarea.js +2 -2
- package/dist/elements/toaster.js +2 -1
- package/dist/elements/tooltip.js +18 -1
- package/dist/elements/tree.js +1 -1
- package/dist/elements.d.ts +3 -2
- package/dist/elements.js +4 -1
- package/dist/index.d.ts +6 -4
- package/dist/index.js +4 -2
- package/dist/react.d.ts +142 -10
- package/dist/react.js +306 -46
- package/dist/sharepoint-fields.d.ts +135 -0
- package/dist/sharepoint-fields.js +402 -0
- package/dist/theme.d.ts +9 -1
- package/dist/theme.js +78 -1
- package/package.json +11 -2
- package/skills/sharepoint-ui/SKILL.md +1 -1
- package/skills/sharepoint-ui/references/sharepoint-patterns.md +1 -1
package/dist/appearance.js
CHANGED
|
@@ -34,7 +34,7 @@ export function getSharePointUIStyleTokens(appearance = "fluent", overrides, bas
|
|
|
34
34
|
"--spui-ui-warning-surface": "var(--spui-semantic-warning-background, #fff4ce)",
|
|
35
35
|
"--spui-ui-danger": "var(--spui-semantic-error-text, #b10e1c)",
|
|
36
36
|
"--spui-ui-danger-surface": "var(--spui-semantic-error-background, #fde7e9)",
|
|
37
|
-
"--spui-focus-ring": "var(--spui-
|
|
37
|
+
"--spui-focus-ring": "var(--spui-semantic-focus-border, var(--colorStrokeFocus2, var(--spui-ui-accent)))"
|
|
38
38
|
});
|
|
39
39
|
else {
|
|
40
40
|
const presetText = String(tokens["--spui-ui-text"]);
|
|
@@ -61,7 +61,7 @@ export function getSharePointUIStyleTokens(appearance = "fluent", overrides, bas
|
|
|
61
61
|
"--spui-ui-warning-surface": `var(--spui-semantic-warning-background, ${tokens["--spui-ui-warning-surface"]})`,
|
|
62
62
|
"--spui-ui-danger": `var(--spui-semantic-error-text, ${tokens["--spui-ui-danger"]})`,
|
|
63
63
|
"--spui-ui-danger-surface": `var(--spui-semantic-error-background, ${tokens["--spui-ui-danger-surface"]})`,
|
|
64
|
-
"--spui-focus-ring": "var(--spui-
|
|
64
|
+
"--spui-focus-ring": "var(--spui-semantic-focus-border, var(--colorStrokeFocus2, var(--spui-ui-accent)))"
|
|
65
65
|
});
|
|
66
66
|
}
|
|
67
67
|
if (selectedBase === "ios") {
|
|
@@ -85,7 +85,7 @@ export function getSharePointUIStyleTokens(appearance = "fluent", overrides, bas
|
|
|
85
85
|
"--spui-ui-warning-surface": "light-dark(var(--spui-semantic-warning-background, #fff3d6), color-mix(in srgb, var(--spui-semantic-warning-background, #342900) 28%, black 72%))",
|
|
86
86
|
"--spui-ui-danger": "light-dark(var(--spui-semantic-error-text, #d70015), color-mix(in srgb, var(--spui-semantic-error-text, #d70015) 30%, white 70%))",
|
|
87
87
|
"--spui-ui-danger-surface": "light-dark(var(--spui-semantic-error-background, #ffe5e8), color-mix(in srgb, var(--spui-semantic-error-background, #3a1114) 28%, black 72%))",
|
|
88
|
-
"--spui-focus-ring": "var(--spui-
|
|
88
|
+
"--spui-focus-ring": "var(--spui-semantic-focus-border, var(--colorStrokeFocus2, var(--spui-ui-accent)))"
|
|
89
89
|
});
|
|
90
90
|
}
|
|
91
91
|
// Stable shared roles for applications that style slots or compose their own
|
|
@@ -202,7 +202,7 @@ export function getSharePointUIStyleTokens(appearance = "fluent", overrides, bas
|
|
|
202
202
|
"--spui-control-height": scalePresetLength(tokens["--spui-base-control-height"], 1.04),
|
|
203
203
|
"--spui-card-padding": scalePresetLength(tokens["--spui-base-card-padding"], 1.12),
|
|
204
204
|
"--spui-control-gap": scalePresetLength(tokens["--spui-base-control-gap"], 1.12),
|
|
205
|
-
"--spui-color-scheme": "light"
|
|
205
|
+
"--spui-color-scheme": tokens["--spui-color-scheme"] ?? "light"
|
|
206
206
|
});
|
|
207
207
|
if (appearance === "glass") {
|
|
208
208
|
// Directly specified finished values win; base values still flow through
|
package/dist/elements/alert.js
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import { base } from "./shared.js";
|
|
2
|
+
const alertIconPaths = {
|
|
3
|
+
info: "M10 2.5a7.5 7.5 0 1 0 0 15 7.5 7.5 0 0 0 0-15ZM10 9v5m0-7h.01",
|
|
4
|
+
success: "M10 2.5a7.5 7.5 0 1 0 0 15 7.5 7.5 0 0 0 0-15ZM6.5 10l2.3 2.3 4.7-5.1",
|
|
5
|
+
warning: "m10 2.5 8 14H2l8-14ZM10 7v4m0 3.5h.01",
|
|
6
|
+
error: "M10 2.5a7.5 7.5 0 1 0 0 15 7.5 7.5 0 0 0 0-15ZM7 7l6 6m0-6-6 6",
|
|
7
|
+
};
|
|
2
8
|
export function defineAlert() {
|
|
3
9
|
if (customElements.get("spui-alert"))
|
|
4
10
|
return;
|
|
@@ -23,6 +29,9 @@ export function defineAlert() {
|
|
|
23
29
|
const avatar = this.shadowRoot?.querySelector('slot[name="avatar"]');
|
|
24
30
|
if (icon && avatar)
|
|
25
31
|
icon.hidden = avatar.assignedElements().length > 0;
|
|
32
|
+
const iconPath = icon?.querySelector(".icon path");
|
|
33
|
+
if (iconPath)
|
|
34
|
+
iconPath.setAttribute("d", alertIconPaths[intent ?? "info"] ?? alertIconPaths.info);
|
|
26
35
|
}
|
|
27
36
|
render() {
|
|
28
37
|
const shadow = this.attachShadow({ mode: "open" });
|
|
@@ -37,6 +46,13 @@ export function defineAlert() {
|
|
|
37
46
|
defaultIcon.className = "icon";
|
|
38
47
|
defaultIcon.setAttribute("aria-hidden", "true");
|
|
39
48
|
icon.append(defaultIcon);
|
|
49
|
+
const iconSvg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
50
|
+
iconSvg.setAttribute("viewBox", "0 0 20 20");
|
|
51
|
+
iconSvg.setAttribute("focusable", "false");
|
|
52
|
+
const iconPath = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
53
|
+
iconPath.setAttribute("d", alertIconPaths.info);
|
|
54
|
+
iconSvg.append(iconPath);
|
|
55
|
+
defaultIcon.append(iconSvg);
|
|
40
56
|
const content = document.createElement("div");
|
|
41
57
|
content.className = "content";
|
|
42
58
|
content.part.add("content");
|
|
@@ -49,12 +65,20 @@ export function defineAlert() {
|
|
|
49
65
|
actions.part.add("actions");
|
|
50
66
|
const button = document.createElement("button");
|
|
51
67
|
button.type = "button";
|
|
52
|
-
button.textContent = "×";
|
|
53
68
|
button.hidden = !this.hasAttribute("dismissible");
|
|
54
69
|
button.part.add("dismiss");
|
|
70
|
+
const closeSvg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
71
|
+
closeSvg.classList.add("dismiss-icon");
|
|
72
|
+
closeSvg.setAttribute("viewBox", "0 0 20 20");
|
|
73
|
+
closeSvg.setAttribute("aria-hidden", "true");
|
|
74
|
+
closeSvg.setAttribute("focusable", "false");
|
|
75
|
+
const closePath = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
|
76
|
+
closePath.setAttribute("d", "m5 5 10 10M15 5 5 15");
|
|
77
|
+
closeSvg.append(closePath);
|
|
78
|
+
button.append(closeSvg);
|
|
55
79
|
button.addEventListener("click", () => { this.hidden = true; this.dispatchEvent(new CustomEvent("spui-dismiss", { bubbles: true, composed: true })); });
|
|
56
80
|
const style = document.createElement("style");
|
|
57
|
-
style.textContent = `${base}:host{display:flex;align-items:flex-start;gap:10px;padding:12px 14px;border:1px solid var(--spui-control-border,var(--spui-ui-stroke,#d1d1d1));border-inline-start:
|
|
81
|
+
style.textContent = `${base}:host{display:flex;align-items:flex-start;gap:10px;padding:12px 14px;border:1px solid var(--spui-control-border,var(--spui-ui-stroke,#d1d1d1));border-inline-start:2px solid var(--spui-ui-accent,#0f6cbd);border-radius:var(--spui-control-radius,6px);background:var(--spui-ui-canvas,#f5f5f5);line-height:1.45}:host([hidden]){display:none}.content{flex:1;min-width:0}.icon{display:inline-flex;flex:none;align-items:center;justify-content:center;color:var(--spui-ui-accent,#0f6cbd)}.icon svg,.dismiss-icon{display:block;width:1em;height:1em;fill:none;stroke:currentColor;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}.icon svg{width:18px;height:18px}slot[name=actions]::slotted(*){display:flex;align-items:center;gap:8px}slot[name=action]::slotted(button){border:0;border-radius:4px;background:transparent;color:inherit;font:inherit;cursor:pointer}slot[name=action]::slotted(button:focus-visible){outline:2px solid var(--spui-focus-ring,#005a9e);outline-offset:2px}:host([intent=success]){border-inline-start-color:var(--spui-ui-success,#107c10);background:var(--spui-success-surface,var(--spui-ui-success-surface,#dff6dd))}:host([intent=success]) .icon{color:var(--spui-ui-success,#107c10)}:host([intent=warning]){border-inline-start-color:var(--spui-ui-warning,#835b00);background:var(--spui-warning-surface,var(--spui-ui-warning-surface,#fff4ce))}:host([intent=warning]) .icon{color:var(--spui-ui-warning,#835b00)}:host([intent=error]){border-inline-start-color:var(--spui-ui-danger,#b10e1c);background:var(--spui-danger-surface,var(--spui-ui-danger-surface,#fde7e9))}:host([intent=error]) .icon{color:var(--spui-ui-danger,#b10e1c)}:host([appearance=inverted]){color:var(--colorNeutralForegroundInverted2,var(--spui-ui-surface,#fff));background:var(--colorNeutralBackgroundInverted,var(--spui-ui-text,#242424));border-color:var(--spui-alert-inverted-border,transparent)}:host([appearance=inverted]) .icon{color:currentColor}button{border:0;border-radius:4px;background:transparent;color:inherit;font:inherit;line-height:1;padding:2px 6px;cursor:pointer}button:hover{background:var(--spui-ui-surface-hover,#0001)}button:focus-visible{outline:2px solid var(--spui-focus-ring,#005a9e);outline-offset:2px}button[hidden]{display:none}:host([data-spui-appearance=glass]),:host-context([data-spui-appearance=glass]){backdrop-filter:var(--spui-card-backdrop,none);border-color:var(--spui-card-border,#ffffff80)}@media(forced-colors:active){:host{border-color:CanvasText;color:CanvasText;background:Canvas}.icon{color:CanvasText}}`;
|
|
58
82
|
shadow.append(style, avatar, icon, content, action, actions, button);
|
|
59
83
|
}
|
|
60
84
|
}
|
package/dist/elements/avatar.js
CHANGED
|
@@ -85,7 +85,7 @@ export function defineAvatar() {
|
|
|
85
85
|
this.fallback.innerHTML = '<svg viewBox="0 0 24 24" focusable="false"><path d="M12 12a4.5 4.5 0 1 0 0-9 4.5 4.5 0 0 0 0 9Zm0 2c-4.4 0-8 2.2-8 5v2h16v-2c0-2.8-3.6-5-8-5Z"/></svg>';
|
|
86
86
|
this.surface.append(this.image, this.initials, this.fallback);
|
|
87
87
|
const style = document.createElement("style");
|
|
88
|
-
style.textContent = `${base}:host{--spui-avatar-size:32px;display:inline-grid;flex:none;width:var(--spui-avatar-size);height:var(--spui-avatar-size);vertical-align:middle;line-height:1}:host([size]){width:var(--spui-avatar-size);height:var(--spui-avatar-size)}.surface{position:relative;box-sizing:border-box;display:grid;place-items:center;width:100%;height:100%;overflow:hidden;border:1px solid var(--spui-avatar-border,var(--spui-ui-stroke,var(--spui-semantic-body-divider,#d1d1d1)));border-radius:var(--spui-avatar-radius,50%);background:var(--spui-avatar-background,var(--spui-semantic-body-subtext,var(--colorNeutralBackground3,#f0f0f0)));color:var(--spui-avatar-foreground,var(--spui-semantic-body-text,var(--colorNeutralForeground1,#323130)));font:600 calc(var(--spui-avatar-size) * .36)/1 var(--spui-font-family,inherit);user-select:none}.image{position:absolute;inset:0;z-index:1;width:100%;height:100%;object-fit:cover}.initials{z-index:0;max-width:100%;overflow:hidden;padding:0 2px;text-
|
|
88
|
+
style.textContent = `${base}:host{--spui-avatar-size:32px;display:inline-grid;flex:none;width:var(--spui-avatar-size);height:var(--spui-avatar-size);vertical-align:middle;line-height:1}:host([size]){width:var(--spui-avatar-size);height:var(--spui-avatar-size)}.surface{position:relative;box-sizing:border-box;display:grid;place-items:center;width:100%;height:100%;overflow:hidden;border:1px solid var(--spui-avatar-border,var(--spui-ui-stroke,var(--spui-semantic-body-divider,#d1d1d1)));border-radius:var(--spui-avatar-radius,50%);background:var(--spui-avatar-background,var(--spui-semantic-body-subtext,var(--colorNeutralBackground3,#f0f0f0)));color:var(--spui-avatar-foreground,var(--spui-semantic-body-text,var(--colorNeutralForeground1,#323130)));font:600 calc(var(--spui-avatar-size) * .36)/1 var(--spui-font-family,inherit);user-select:none}.image{position:absolute;inset:0;z-index:1;width:100%;height:100%;object-fit:cover}.initials{position:absolute;inset:0;z-index:0;display:flex;align-items:center;justify-content:center;max-width:100%;overflow:hidden;padding:0 2px;text-align:center;line-height:1;white-space:nowrap}.fallback{z-index:0;display:grid;place-items:center;width:62%;height:62%;color:currentColor}.initials:not(:empty)~.fallback{display:none}.fallback svg{display:block;width:100%;height:100%;fill:currentColor}:host([data-image-state=loading]) .image,:host([data-image-state=error]) .image{visibility:hidden}:host([data-image-state=loaded]) .initials,:host([data-image-state=loaded]) .fallback{visibility:hidden}:host([shape=square]) .surface{border-radius:var(--spui-avatar-radius,var(--spui-control-radius,6px))}:host([color=brand]) .surface{background:var(--spui-avatar-brand-background,var(--spui-semantic-primary-button-background,var(--colorBrandBackground,var(--spui-avatar-active-color,var(--spui-ui-accent,#78716c)))));color:var(--spui-avatar-brand-foreground,var(--spui-semantic-primary-button-text,var(--colorNeutralForegroundOnBrand,#fff)))}:host([color=colorful]) .surface,:host([data-named-color]) .surface{background:var(--spui-avatar-colorful-background,var(--spui-semantic-primary-button-background,var(--colorBrandBackground,var(--spui-avatar-active-color,var(--spui-ui-accent,#78716c)))));color:var(--spui-avatar-colorful-foreground,var(--spui-semantic-primary-button-text,#fff))}:host([active=active]:not([active-appearance])) .surface,:host([active=active][active-appearance=ring]) .surface{box-shadow:0 0 0 2px var(--spui-ui-surface,#fff),0 0 0 4px var(--spui-avatar-active-color,var(--spui-ui-accent,#78716c))}:host([active=active][active-appearance=shadow]) .surface{box-shadow:var(--spui-avatar-active-shadow,var(--spui-card-shadow,0 2px 8px rgb(0 0 0 / 24%)))}:host([active=active][active-appearance=ring-shadow]) .surface{box-shadow:0 0 0 2px var(--spui-ui-surface,#fff),0 0 0 4px var(--spui-avatar-active-color,var(--spui-ui-accent,#78716c)),var(--spui-avatar-active-shadow,var(--spui-card-shadow,0 2px 8px rgb(0 0 0 / 24%)))}:host([active=inactive]){opacity:.56}:host([data-custom-icon=true]) .initials,:host([data-custom-icon=true]) .fallback{display:none}:host([data-custom-icon=true]) .icon{z-index:0;display:grid;place-items:center;width:70%;height:70%;color:inherit}:host([data-custom-badge=true]) .badge{position:absolute;z-index:2;inset-block-end:0;inset-inline-end:0;display:grid;place-items:center;min-width:var(--spui-avatar-badge-size,10px);min-height:var(--spui-avatar-badge-size,10px);border:2px solid var(--spui-avatar-badge-border,var(--spui-ui-surface,#fff));border-radius:50%;background:var(--spui-avatar-badge-background,var(--spui-semantic-success-background,#13a10e));color:var(--spui-avatar-badge-foreground,#fff);font:600 9px/1 var(--spui-font-family,inherit)}:host(:not([data-custom-badge=true])) .badge{display:none}@media(forced-colors:active){.surface{border-color:CanvasText;background:Canvas;color:CanvasText;forced-color-adjust:none}:host([data-named-color]) .surface{border-color:CanvasText;background:Canvas;color:CanvasText}.image{forced-color-adjust:auto}:host([active=active]) .surface{outline:2px solid Highlight;outline-offset:2px;box-shadow:none}}`;
|
|
89
89
|
style.textContent += `.surface{background:var(--spui-avatar-background,var(--spui-palette-neutral-light,var(--colorNeutralBackground3,#f0f0f0)));font-size:clamp(10px,calc(var(--spui-avatar-size) * .36),48px)}`;
|
|
90
90
|
style.textContent += `@media(forced-colors:active){.surface{border-color:CanvasText;background:Canvas;color:CanvasText}}`;
|
|
91
91
|
const icon = document.createElement("span");
|
package/dist/elements/button.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
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}}`;
|
|
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}:host([data-spui-appearance=glass]) button:not(.primary),:host-context([data-spui-appearance=glass]) button:not(.primary){backdrop-filter:var(--spui-card-backdrop,blur(16px) saturate(150%))}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
3
|
export const buttonControlCss = buttonCss.replace(/\bbutton(?=[.#:[\s,{])/g, ":is(button,a)");
|
|
4
4
|
const buttonSheets = new WeakMap();
|
|
5
5
|
const buttonSheetUnsupported = new WeakSet();
|
|
@@ -30,7 +30,7 @@ export function defineCarouselNav() {
|
|
|
30
30
|
return;
|
|
31
31
|
const root = this.attachShadow({ mode: "open" });
|
|
32
32
|
const style = document.createElement("style");
|
|
33
|
-
style.textContent = `${base}:host{display:flex;align-items:center;justify-content:center;gap:4px;min-width:0}:host([appearance=brand]){--spui-carousel-indicator:var(--spui-ui-accent,#0078d4)}slot{display:contents}`;
|
|
33
|
+
style.textContent = `${base}:host{display:flex;align-items:center;justify-content:center;gap:4px;min-width:0}:host([appearance=brand]){--spui-carousel-indicator:var(--spui-ui-accent,#0078d4)}:host([appearance=thumbnails]){justify-content:flex-start;max-width:100%;overflow-x:auto;overscroll-behavior-inline:contain;scroll-snap-type:inline mandatory;scrollbar-width:thin;padding-block:4px}:host([appearance=thumbnails]) div[role=group]{display:flex;align-items:center;gap:8px;width:max-content;min-width:100%}:host([appearance=thumbnails]) ::slotted(spui-carousel-nav-image-button){scroll-snap-align:start}slot{display:contents}`;
|
|
34
34
|
const group = document.createElement("div");
|
|
35
35
|
group.setAttribute("role", "group");
|
|
36
36
|
group.setAttribute("aria-label", this.getAttribute("aria-label") || "Slide navigation");
|
|
@@ -63,6 +63,9 @@ function defineCarouselNavControl(tag, image) {
|
|
|
63
63
|
this.button.type = "button";
|
|
64
64
|
if (image) {
|
|
65
65
|
this.picture = document.createElement("img");
|
|
66
|
+
this.picture.loading = "lazy";
|
|
67
|
+
this.picture.decoding = "async";
|
|
68
|
+
this.picture.draggable = false;
|
|
66
69
|
const imageSlot = document.createElement("slot");
|
|
67
70
|
imageSlot.name = "image";
|
|
68
71
|
imageSlot.append(this.picture);
|
|
@@ -460,7 +463,7 @@ export function defineCarousel() {
|
|
|
460
463
|
this.slides.forEach(slide => { this.restoreSlideState(slide); this.restoreSlideLayout(slide); });
|
|
461
464
|
}
|
|
462
465
|
attributeChangedCallback(name) {
|
|
463
|
-
if (!this.isConnected)
|
|
466
|
+
if (!this.isConnected || !this.controls)
|
|
464
467
|
return;
|
|
465
468
|
if ((name === "selected-index" || name === "active-index") && this.hasAttribute("controlled"))
|
|
466
469
|
this.setIndex(Number(this.getAttribute(name)), false);
|
|
@@ -136,7 +136,7 @@ export function defineColorArea() {
|
|
|
136
136
|
render() {
|
|
137
137
|
const shadow = this.attachShadow({ mode: "open" });
|
|
138
138
|
const style = document.createElement("style");
|
|
139
|
-
style.textContent = `${base}:host{display:block;min-width:0}.area{position:relative;width:min(260px,100%);height:160px;border:1px solid var(--spui-ui-stroke,var(--colorNeutralStroke1,#8a8886));border-radius:var(--picker-radius,var(--spui-control-radius,8px));background-image:linear-gradient(to top,#000,transparent),linear-gradient(to right,#fff,hsl(var(--picker-hue,0deg) 100% 50%));touch-action:none;cursor:crosshair}.thumb{position:absolute;inset-inline-start:var(--picker-saturation,0%);top:var(--picker-brightness,100%);width:14px;height:14px;border:2px solid #fff;border-radius:50%;box-shadow:0 0 0 1px #000;transform:translate(-50%,-50%);pointer-events:none}.area:focus-within{
|
|
139
|
+
style.textContent = `${base}:host{display:block;min-width:0}.area{box-sizing:border-box;position:relative;width:min(260px,100%);height:160px;border:1px solid var(--spui-ui-stroke,var(--colorNeutralStroke1,#8a8886));border-radius:var(--picker-radius,var(--spui-control-radius,8px));background-image:linear-gradient(to top,#000,transparent),linear-gradient(to right,#fff,hsl(var(--picker-hue,0deg) 100% 50%));touch-action:none;cursor:crosshair}.thumb{position:absolute;inset-inline-start:var(--picker-saturation,0%);top:var(--picker-brightness,100%);width:14px;height:14px;border:2px solid #fff;border-radius:50%;box-shadow:0 0 0 1px #000;transform:translate(-50%,-50%);pointer-events:none}.area:focus-within{border-width:2px;border-color:var(--spui-focus-ring,var(--spui-ui-accent,#0078d4));outline:0;box-shadow:none}.inputs{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}.inputs slot{display:contents}.inputs input{position:absolute;width:1px;height:1px}@media(forced-colors:active){.area{border-color:FieldText}.area:focus-within{border-color:Highlight;outline:0}.thumb{border-color:Canvas;box-shadow:0 0 0 1px CanvasText}}`;
|
|
140
140
|
this.area = document.createElement("div");
|
|
141
141
|
this.area.className = "area";
|
|
142
142
|
this.area.setAttribute("role", "group");
|
|
@@ -4,7 +4,7 @@ export function defineCombobox() {
|
|
|
4
4
|
return;
|
|
5
5
|
class SpuiCombobox extends HTMLElement {
|
|
6
6
|
static formAssociated = true;
|
|
7
|
-
static observedAttributes = ["label", "value", "selected-value", "selected-options", "default-selected-options", "multiselect", "disabled", "required", "name", "placeholder", "allow-freeform", "read-only", "button-trigger", "open", "default-open", "clearable", "clear-label", "disable-auto-focus", "appearance", "size", "positioning", "inline-popup", "no-results", "remove-selected-label", "selected-label", "aria-label", "aria-labelledby", "aria-description", "aria-describedby", "aria-invalid"];
|
|
7
|
+
static observedAttributes = ["label", "value", "selected-value", "selected-options", "default-selected-options", "multiselect", "disabled", "required", "required-message", "name", "placeholder", "allow-freeform", "read-only", "button-trigger", "open", "default-open", "clearable", "clear-label", "disable-auto-focus", "appearance", "size", "positioning", "inline-popup", "no-results", "remove-selected-label", "selected-label", "aria-label", "aria-labelledby", "aria-description", "aria-describedby", "aria-invalid"];
|
|
8
8
|
internals;
|
|
9
9
|
observer;
|
|
10
10
|
positionEvents;
|
|
@@ -304,7 +304,7 @@ export function defineCombobox() {
|
|
|
304
304
|
this.internals?.setFormValue(formValue || null, this.hasAttribute("multiselect") ? JSON.stringify(this.selectedOptionsState) : typeof formValue === "string" ? formValue : null);
|
|
305
305
|
const missing = this.hasAttribute("required") && (this.hasAttribute("multiselect") ? this.selectedOptionsState.length === 0 : !formValue);
|
|
306
306
|
try {
|
|
307
|
-
this.internals?.setValidity(missing ? { valueMissing: true } : {}, missing ? "Choose an option." : "", this.hasAttribute("button-trigger") ? undefined : this.getInput() ?? undefined);
|
|
307
|
+
this.internals?.setValidity(missing ? { valueMissing: true } : {}, missing ? this.getAttribute("required-message") || "Choose an option." : "", this.hasAttribute("button-trigger") ? undefined : this.getInput() ?? undefined);
|
|
308
308
|
}
|
|
309
309
|
catch { /* Keep native input semantics if an engine rejects the validity anchor. */ }
|
|
310
310
|
}
|
|
@@ -998,10 +998,10 @@ export function defineCombobox() {
|
|
|
998
998
|
empty.hidden = true;
|
|
999
999
|
wrapper.append(selected, triggerSlot, inputSlot, expand, clearSlot, listboxSlot, empty);
|
|
1000
1000
|
const style = document.createElement("style");
|
|
1001
|
-
style.textContent = `${base}:host{display:grid;gap:var(--spui-control-gap,6px)}label{font-size:14px;font-weight:600;color:var(--spui-ui-muted,var(--spui-semantic-body-text,inherit))}.control{position:relative;display:flex;flex-wrap:wrap;align-items:center;gap:4px;padding:4px;border:1px solid var(--spui-control-border,var(--spui-ui-stroke,var(--spui-semantic-input-border,var(--colorNeutralStroke1,#8a8886))));border-radius:var(--spui-control-radius,4px);background:var(--spui-control-background,var(--spui-ui-surface,var(--spui-semantic-input-background,var(--colorNeutralBackground1,#fff))));box-shadow:var(--spui-control-shadow,none)}.selected{display:flex;flex-wrap:wrap;gap:4px;min-width:0}.selected[hidden]{display:none}.tag{display:inline-flex;align-items:center;gap:4px;padding:2px 4px 2px 8px;border:1px solid var(--spui-tag-border,var(--spui-ui-stroke,#d1d1d1));border-radius:var(--spui-tag-radius,4px);background:var(--spui-tag-background,var(--spui-ui-surface-hover,#f5f5f5));color:var(--spui-ui-text,inherit);font-size:.9em}.remove,.clear{width:24px;height:24px;border:0;border-radius:3px;background:transparent;color:inherit;cursor:pointer}.remove:hover,.clear:hover{background:var(--spui-ui-surface-hover,#f5f5f5)}input{box-sizing:border-box;flex:1 1 120px;min-width:80px;min-height:calc(var(--spui-control-height,36px) - 10px);padding:4px 8px;border:0;outline:0;background:transparent;color:var(--spui-ui-text,var(--spui-semantic-body-text,inherit));font:inherit}input:focus-visible{outline:2px solid var(--spui-focus-ring,#005a9e);outline-offset:1px}input:disabled{opacity:.55}ul{position:absolute;z-index:var(--spui-layer-dropdown,20);top:calc(100% + 4px);inset-inline:0;box-sizing:border-box;max-height:240px;overflow:auto;margin:0;padding:4px;list-style:none;border:1px solid var(--spui-ui-stroke,#d1d1d1);border-radius:var(--spui-card-radius,8px);background:var(--spui-ui-surface,#fff);box-shadow:var(--spui-card-shadow,0 4px 14px #0002)}:host([positioning^=above]) ul{top:auto;bottom:calc(100% + 4px)}ul[hidden]{display:none}.option-group{display:grid;gap:2px;padding-block:2px}.group-label{padding:6px 10px;color:var(--spui-ui-muted,inherit);font-size:12px;font-weight:600}[role=option],li.empty{display:flex;align-items:center;gap:8px;padding:8px 10px;border-radius:var(--spui-control-radius,4px);color:var(--spui-ui-text,inherit);cursor:pointer}[role=option][data-active=true],[role=option][aria-selected=true]{background:var(--spui-ui-surface-hover,var(--spui-ui-canvas,#f5f5f5))}.check{display:inline-grid;place-items:center;width:16px;height:16px;flex:none;border:1px solid var(--spui-ui-stroke,#8a8886);border-radius:3px;color:var(--spui-ui-accent,#0f6cbd);font-size:12px}[role=option][aria-selected=true] .check{border-color:var(--spui-ui-accent,#0f6cbd);background:var(--spui-ui-canvas,#f5f5f5)}[role=option][aria-disabled=true]{opacity:.5;cursor:not-allowed}li.empty{color:var(--spui-ui-muted,inherit);cursor:default}:host([size=small]) input{min-height:30px}:host([size=large]) input{min-height:44px}:host([appearance=filled-darker]) input{background:var(--spui-ui-surface-sunken,#f0f0f0)}:host([appearance=filled-lighter]) input{background:var(--spui-ui-surface,#fff)}:host([appearance=underline]) input{border-radius:0;border-width:0 0 1px}@media(forced-colors:active){.control,ul{border-color:CanvasText;box-shadow:none}.tag{border-color:CanvasText}.check{border-color:CanvasText}li[role=option][data-active=true]{outline:1px solid Highlight}}:host(:not([multiselect])) .control{display:block;gap:0;padding:0;border:0;background:transparent;box-shadow:none}:host(:not([multiselect])) input{box-sizing:border-box;width:100%;min-height:var(--spui-control-height,36px);padding:8px 12px;border:1px solid var(--spui-control-border,var(--spui-ui-stroke,var(--spui-semantic-input-border,#8a8886)));border-radius:var(--spui-control-radius,4px);background:var(--spui-control-background,var(--spui-ui-surface,var(--spui-semantic-input-background,#fff)));box-shadow:var(--spui-control-shadow,none);color:var(--spui-ui-text,var(--spui-semantic-body-text,inherit));font:inherit}:host(:not([multiselect])) input:focus-visible{
|
|
1002
|
-
style.textContent += ".expand{display:inline-flex;align-items:center;justify-content:center;flex:none;color:inherit}.expand[hidden]{display:none}::slotted([slot=clear-button]){cursor:pointer}:host([read-only]) .expand,:host([button-trigger]) .expand{position:absolute;inset-inline-end:6px;top:6px}:host([read-only]) .clear,:host([read-only]) ::slotted([slot=clear-button]),:host([button-trigger]) .clear,:host([button-trigger]) ::slotted([slot=clear-button]){position:absolute;inset-inline-end:32px;top:6px}:host([read-only]) input{width:calc(100% - 56px)}:host([read-only]:not([clearable])) input{width:calc(100% - 28px)}.trigger,::slotted([slot=button]){box-sizing:border-box;display:flex;align-items:center;justify-content:space-between;gap:8px;width:100%;min-height:var(--spui-control-height,36px);padding:8px 12px;border:1px solid var(--spui-control-border,var(--spui-ui-stroke,var(--spui-semantic-input-border,#8a8886)));border-radius:var(--spui-control-radius,4px);background:var(--spui-control-background,var(--spui-ui-surface,var(--spui-semantic-input-background,#fff)));box-shadow:var(--spui-control-shadow,none);color:var(--spui-ui-text,var(--spui-semantic-body-text,inherit));font:inherit;text-align:start;cursor:pointer}.trigger:focus-visible
|
|
1001
|
+
style.textContent = `${base}:host{display:grid;gap:var(--spui-control-gap,6px)}label{font-size:14px;font-weight:600;color:var(--spui-ui-muted,var(--spui-semantic-body-text,inherit))}.control{position:relative;display:flex;flex-wrap:wrap;align-items:center;gap:4px;padding:4px;border:1px solid var(--spui-control-border,var(--spui-ui-stroke,var(--spui-semantic-input-border,var(--colorNeutralStroke1,#8a8886))));border-radius:var(--spui-control-radius,4px);background:var(--spui-control-background,var(--spui-ui-surface,var(--spui-semantic-input-background,var(--colorNeutralBackground1,#fff))));box-shadow:var(--spui-control-shadow,none)}.selected{display:flex;flex-wrap:wrap;gap:4px;min-width:0}.selected[hidden]{display:none}.tag{display:inline-flex;align-items:center;gap:4px;padding:2px 4px 2px 8px;border:1px solid var(--spui-tag-border,var(--spui-ui-stroke,#d1d1d1));border-radius:var(--spui-tag-radius,4px);background:var(--spui-tag-background,var(--spui-ui-surface-hover,#f5f5f5));color:var(--spui-ui-text,inherit);font-size:.9em}.remove,.clear{width:24px;height:24px;border:0;border-radius:3px;background:transparent;color:inherit;cursor:pointer}.remove:hover,.clear:hover{background:var(--spui-ui-surface-hover,#f5f5f5)}input{box-sizing:border-box;flex:1 1 120px;min-width:80px;min-height:calc(var(--spui-control-height,36px) - 10px);padding:4px 8px;border:0;outline:0;background:transparent;color:var(--spui-ui-text,var(--spui-semantic-body-text,inherit));font:inherit}input:focus-visible{outline:2px solid var(--spui-focus-ring,#005a9e);outline-offset:1px}input:disabled{opacity:.55}ul{position:absolute;z-index:var(--spui-layer-dropdown,20);top:calc(100% + 4px);inset-inline:0;box-sizing:border-box;max-height:240px;overflow:auto;margin:0;padding:4px;list-style:none;border:1px solid var(--spui-ui-stroke,#d1d1d1);border-radius:var(--spui-card-radius,8px);background:var(--spui-ui-surface,#fff);box-shadow:var(--spui-card-shadow,0 4px 14px #0002)}:host([positioning^=above]) ul{top:auto;bottom:calc(100% + 4px)}ul[hidden]{display:none}.option-group{display:grid;gap:2px;padding-block:2px}.group-label{padding:6px 10px;color:var(--spui-ui-muted,inherit);font-size:12px;font-weight:600}[role=option],li.empty{display:flex;align-items:center;gap:8px;padding:8px 10px;border-radius:var(--spui-control-radius,4px);color:var(--spui-ui-text,inherit);cursor:pointer}[role=option][data-active=true],[role=option][aria-selected=true]{background:var(--spui-ui-surface-hover,var(--spui-ui-canvas,#f5f5f5))}.check{display:inline-grid;place-items:center;width:16px;height:16px;flex:none;border:1px solid var(--spui-ui-stroke,#8a8886);border-radius:3px;color:var(--spui-ui-accent,#0f6cbd);font-size:12px}[role=option][aria-selected=true] .check{border-color:var(--spui-ui-accent,#0f6cbd);background:var(--spui-ui-canvas,#f5f5f5)}[role=option][aria-disabled=true]{opacity:.5;cursor:not-allowed}li.empty{color:var(--spui-ui-muted,inherit);cursor:default}:host([size=small]) input{min-height:30px}:host([size=large]) input{min-height:44px}:host([appearance=filled-darker]) input{background:var(--spui-ui-surface-sunken,#f0f0f0)}:host([appearance=filled-lighter]) input{background:var(--spui-ui-surface,#fff)}:host([appearance=underline]) input{border-radius:0;border-width:0 0 1px}@media(forced-colors:active){.control,ul{border-color:CanvasText;box-shadow:none}.tag{border-color:CanvasText}.check{border-color:CanvasText}li[role=option][data-active=true]{outline:1px solid Highlight}}:host(:not([multiselect])) .control{display:block;gap:0;padding:0;border:0;background:transparent;box-shadow:none}:host(:not([multiselect])) input{box-sizing:border-box;width:100%;min-height:var(--spui-control-height,36px);padding:8px 12px;border:1px solid var(--spui-control-border,var(--spui-ui-stroke,var(--spui-semantic-input-border,#8a8886)));border-radius:var(--spui-control-radius,4px);background:var(--spui-control-background,var(--spui-ui-surface,var(--spui-semantic-input-background,#fff)));box-shadow:var(--spui-control-shadow,none);color:var(--spui-ui-text,var(--spui-semantic-body-text,inherit));font:inherit}:host(:not([multiselect])) input:focus-visible{border-width:2px;border-color:var(--spui-focus-ring,var(--spui-ui-accent,#0078d4));outline:0}:host([appearance=underline]:not([multiselect])) input:focus-visible{border-width:0 0 2px}:host([multiselect]) .control:focus-within{border-width:2px;border-color:var(--spui-focus-ring,var(--spui-ui-accent,#0078d4));box-shadow:none}:host([multiselect]) .control input:focus-visible{outline:0}:host([aria-invalid]:not([aria-invalid=false])) .control,:host([aria-invalid]:not([aria-invalid=false])) input,:host([aria-invalid]:not([aria-invalid=false])) ::slotted([slot=input]),:host([aria-invalid]:not([aria-invalid=false])) .trigger,:host([aria-invalid]:not([aria-invalid=false])) ::slotted([slot=button]){border-color:var(--spui-input-invalid-border,var(--spui-ui-danger,var(--colorPaletteRedBorder2,#c50f1f)))}:host([aria-invalid]:not([aria-invalid=false])) input:focus-visible,:host([aria-invalid]:not([aria-invalid=false])) .trigger:focus-visible,:host([aria-invalid]:not([aria-invalid=false])) ::slotted([slot=input]:focus-visible),:host([aria-invalid]:not([aria-invalid=false])) ::slotted([slot=button]:focus-visible){border-color:var(--spui-input-invalid-border,var(--spui-ui-danger,var(--colorPaletteRedBorder2,#c50f1f)))}@media(forced-colors:active){:host(:not([multiselect])) input{border-color:FieldText;background:Field;color:FieldText}:host(:not([multiselect])) input:focus-visible{border-color:Highlight}:host([multiselect]) .control:focus-within{border-color:Highlight}:host([aria-invalid]:not([aria-invalid=false])) .control,:host([aria-invalid]:not([aria-invalid=false])) input,:host([aria-invalid]:not([aria-invalid=false])) ::slotted([slot=input]),:host([aria-invalid]:not([aria-invalid=false])) .trigger,:host([aria-invalid]:not([aria-invalid=false])) ::slotted([slot=button]){border-color:CanvasText}:host([aria-invalid]:not([aria-invalid=false])) input:focus-visible,:host([aria-invalid]:not([aria-invalid=false])) .trigger:focus-visible,:host([aria-invalid]:not([aria-invalid=false])) ::slotted([slot=input]:focus-visible),:host([aria-invalid]:not([aria-invalid=false])) ::slotted([slot=button]:focus-visible){border-color:Highlight!important}:host(:not([multiselect])) ::slotted([slot=input]:focus-visible){border-color:Highlight!important}:host([button-trigger]) ::slotted([slot=button]:focus-visible){border-color:Highlight!important}}`;
|
|
1002
|
+
style.textContent += ".expand{display:inline-flex;align-items:center;justify-content:center;flex:none;color:inherit}.expand[hidden]{display:none}::slotted([slot=clear-button]){cursor:pointer}:host([read-only]) .expand,:host([button-trigger]) .expand{position:absolute;inset-inline-end:6px;top:6px}:host([read-only]) .clear,:host([read-only]) ::slotted([slot=clear-button]),:host([button-trigger]) .clear,:host([button-trigger]) ::slotted([slot=clear-button]){position:absolute;inset-inline-end:32px;top:6px}:host([read-only]) input{width:calc(100% - 56px)}:host([read-only]:not([clearable])) input{width:calc(100% - 28px)}.trigger,::slotted([slot=button]){box-sizing:border-box;display:flex;align-items:center;justify-content:space-between;gap:8px;width:100%;min-height:var(--spui-control-height,36px);padding:8px 12px;border:1px solid var(--spui-control-border,var(--spui-ui-stroke,var(--spui-semantic-input-border,#8a8886)));border-radius:var(--spui-control-radius,4px);background:var(--spui-control-background,var(--spui-ui-surface,var(--spui-semantic-input-background,#fff)));box-shadow:var(--spui-control-shadow,none);color:var(--spui-ui-text,var(--spui-semantic-body-text,inherit));font:inherit;text-align:start;cursor:pointer}.trigger:focus-visible{border-width:2px;border-color:var(--spui-focus-ring,var(--spui-semantic-focus-border,#005a9e));outline:0;outline-offset:0;box-shadow:none}::slotted([slot=button]:focus-visible){border-width:2px!important;border-color:var(--spui-focus-ring,var(--spui-semantic-focus-border,#005a9e))!important;outline:0!important;outline-offset:0;box-shadow:none!important}:host([appearance=underline]) .trigger:focus-visible,:host([appearance=underline]) ::slotted([slot=button]:focus-visible){border-width:0 0 2px!important}.trigger:disabled,::slotted([slot=button][disabled]){opacity:.55;cursor:not-allowed}:host([button-trigger][size=small]) .trigger,:host([button-trigger][size=small]) ::slotted([slot=button]){min-height:30px}:host([button-trigger][size=large]) .trigger,:host([button-trigger][size=large]) ::slotted([slot=button]){min-height:44px}:host([button-trigger]) .trigger-value{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}@media(forced-colors:active){.trigger,:host([button-trigger]) ::slotted([slot=button]){border-color:ButtonText;background:ButtonFace;color:ButtonText}.trigger:focus-visible,:host([button-trigger]) ::slotted([slot=button]:focus-visible){border-color:Highlight!important;outline:0!important}}";
|
|
1003
1003
|
style.textContent = style.textContent?.replaceAll("li.empty", ".empty") ?? "";
|
|
1004
|
-
style.textContent += `::slotted([slot=input]){box-sizing:border-box;flex:1 1 120px;min-width:80px;min-height:calc(var(--spui-control-height,36px) - 10px);padding:4px 8px;border:0;outline:0;background:transparent;color:var(--spui-ui-text,var(--spui-semantic-body-text,inherit));font:inherit}::slotted([slot=input]:focus-visible){outline:
|
|
1004
|
+
style.textContent += `::slotted([slot=input]){box-sizing:border-box;flex:1 1 120px;min-width:80px;min-height:calc(var(--spui-control-height,36px) - 10px);padding:4px 8px;border:0;outline:0;background:transparent;color:var(--spui-ui-text,var(--spui-semantic-body-text,inherit));font:inherit}:host([multiselect]) ::slotted([slot=input]){border:0!important;outline:0!important;box-shadow:none!important}::slotted([slot=input]:focus-visible){border:0!important;outline:0!important;outline-offset:0;box-shadow:none!important}:host(:not([multiselect])) ::slotted([slot=input]:focus-visible){border-style:solid!important;border-width:2px!important;border-color:var(--spui-focus-ring,var(--spui-ui-accent,#0078d4))!important}:host([appearance=underline]:not([multiselect])) ::slotted([slot=input]:focus-visible){border-width:0 0 2px!important}:host(:not([multiselect])) ::slotted([slot=input]){box-sizing:border-box;width:100%;min-height:var(--spui-control-height,36px);padding:8px 12px;border:1px solid var(--spui-control-border,var(--spui-ui-stroke,var(--spui-semantic-input-border,#8a8886)));border-radius:var(--spui-control-radius,4px);background:var(--spui-control-background,var(--spui-ui-surface,var(--spui-semantic-input-background,#fff)));color:var(--spui-ui-text,var(--spui-semantic-body-text,inherit));font:inherit}`;
|
|
1005
1005
|
shadow.replaceChildren(style, label, wrapper);
|
|
1006
1006
|
this.bindInput();
|
|
1007
1007
|
this.syncExpandIcon();
|
|
@@ -93,6 +93,9 @@ export type DataGridCellEdit<T = unknown> = {
|
|
|
93
93
|
previousValue: unknown;
|
|
94
94
|
value: DataGridEditValue;
|
|
95
95
|
};
|
|
96
|
+
export type DataGridCellEditError<T = unknown> = DataGridCellEdit<T> & {
|
|
97
|
+
error: string;
|
|
98
|
+
};
|
|
96
99
|
/** Bound row sizes to keep a consumer callback from creating pathological virtual scroll extents. */
|
|
97
100
|
export declare function clampDataGridRowHeight(height: number | undefined, estimate: number): number;
|
|
98
101
|
export declare function getDataGridCellValue<T>(item: T, column: DataGridColumn<T>): unknown;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type DataGridCellEdit, type DataGridColumn, type DataGridDataSource, type DataGridColumnSizingOptions, type DataGridFocusMode, type DataGridSelectionAppearance, type DataGridSelectionModel } from "./data-grid-model.js";
|
|
1
|
+
import { type DataGridCellEdit, type DataGridCellEditError, type DataGridColumn, type DataGridDataSource, type DataGridColumnSizingOptions, type DataGridFocusMode, type DataGridSelectionAppearance, type DataGridSelectionModel } from "./data-grid-model.js";
|
|
2
2
|
export type DataGridCellRenderer<T = unknown> = (item: T, column: DataGridColumn<T>, rowIndex: number) => Node | string | number | null;
|
|
3
3
|
export type DataGridRowHeightGetter<T = unknown> = (item: T, rowIndex: number) => number;
|
|
4
4
|
export type DataGridCellsEditHandler = (edits: readonly DataGridCellEdit[]) => void | Promise<void>;
|
|
@@ -19,6 +19,7 @@ export interface SharePointDataGridElement extends HTMLElement {
|
|
|
19
19
|
onDataSourceSelectionChange?: DataGridSourceSelectionHandler;
|
|
20
20
|
getRowHeight?: DataGridRowHeightGetter;
|
|
21
21
|
onCellsEdit?: DataGridCellsEditHandler;
|
|
22
|
+
onCellEditError?: (error: DataGridCellEditError) => void;
|
|
22
23
|
}
|
|
23
24
|
declare global {
|
|
24
25
|
interface HTMLElementTagNameMap {
|
|
@@ -7,7 +7,7 @@ export function defineDataGrid() {
|
|
|
7
7
|
if (customElements.get("spui-data-grid"))
|
|
8
8
|
return;
|
|
9
9
|
class SpuiDataGrid extends HTMLElement {
|
|
10
|
-
static observedAttributes = ["aria-label", "label", "focus-mode", "selection-mode", "selection-appearance", "subtle-selection", "auto-fit-columns", "container-width-offset", "row-height", "overscan", "virtualize-columns", "select-label", "select-all-label", "empty-label", "no-results-label", "filterable", "filter-label", "sort-priority-label", "resizable-columns", "resize-label", "reorderable-columns", "reorder-label", "group-by", "empty-group-label", "expand-group-label", "collapse-group-label", "row-label", "edit-hint"];
|
|
10
|
+
static observedAttributes = ["aria-label", "label", "focus-mode", "selection-mode", "selection-appearance", "subtle-selection", "auto-fit-columns", "container-width-offset", "row-height", "overscan", "virtualize-columns", "select-label", "select-all-label", "empty-label", "no-results-label", "loading-label", "load-error-label", "edit-error-label", "filterable", "filter-label", "sort-priority-label", "resizable-columns", "resize-label", "reorderable-columns", "reorder-label", "reorder-hint-label", "group-by", "empty-group-label", "expand-group-label", "collapse-group-label", "row-label", "edit-hint", "selection-copied-label", "copy-failed-label", "paste-one-label", "paste-many-label", "paste-failed-label"];
|
|
11
11
|
data = [];
|
|
12
12
|
source;
|
|
13
13
|
sourceUnsubscribe;
|
|
@@ -85,6 +85,7 @@ export function defineDataGrid() {
|
|
|
85
85
|
editedValues = new Map();
|
|
86
86
|
editingCell;
|
|
87
87
|
editCallback;
|
|
88
|
+
editErrorCallback;
|
|
88
89
|
cellsEditCallback;
|
|
89
90
|
dataSourceGroupToggleCallback;
|
|
90
91
|
dataSourceSelectionCallback;
|
|
@@ -187,6 +188,8 @@ export function defineDataGrid() {
|
|
|
187
188
|
set collapsedGroupKeys(value) { this.collapsedGroups = new Set(value ?? []); this.paint(true); }
|
|
188
189
|
get onCellEdit() { return this.editCallback; }
|
|
189
190
|
set onCellEdit(value) { this.editCallback = value; }
|
|
191
|
+
get onCellEditError() { return this.editErrorCallback; }
|
|
192
|
+
set onCellEditError(value) { this.editErrorCallback = value; }
|
|
190
193
|
get validateCellEdit() { return this.editValidator; }
|
|
191
194
|
set validateCellEdit(value) { this.editValidator = value; }
|
|
192
195
|
get onCellsEdit() { return this.cellsEditCallback; }
|
|
@@ -210,6 +213,9 @@ export function defineDataGrid() {
|
|
|
210
213
|
}
|
|
211
214
|
disconnectedCallback() { cancelAnimationFrame(this.frame); this.frame = 0; this.resizeObserver?.disconnect(); this.sourceRequest?.controller.abort(); this.sourceRequest = undefined; this.clipboardController?.abort(); this.clipboardController = undefined; this.sourceUnsubscribe?.(); this.sourceUnsubscribe = undefined; }
|
|
212
215
|
attributeChangedCallback() { this.renderFilter(); this.renderHeader(); this.initializeColumnWidths(); this.paint(true); }
|
|
216
|
+
localizedMessage(attribute, fallback, values = {}) {
|
|
217
|
+
return Object.entries(values).reduce((message, [key, value]) => message.replaceAll(`{${key}}`, value), this.getAttribute(attribute) ?? fallback);
|
|
218
|
+
}
|
|
213
219
|
render() {
|
|
214
220
|
const shadow = this.attachShadow({ mode: "open" });
|
|
215
221
|
const style = document.createElement("style");
|
|
@@ -372,7 +378,7 @@ export function defineDataGrid() {
|
|
|
372
378
|
this.failedSourceRange = key;
|
|
373
379
|
const error = new Error("loadRange resolved before every requested row was available");
|
|
374
380
|
if (this.reorderStatus)
|
|
375
|
-
this.reorderStatus.textContent = error.
|
|
381
|
+
this.reorderStatus.textContent = this.localizedMessage("load-error-label", "Data could not be loaded.");
|
|
376
382
|
this.viewport?.setAttribute("aria-busy", "false");
|
|
377
383
|
this.dispatchEvent(new CustomEvent("spui-data-load-error", { detail: { error, start, end }, bubbles: true, composed: true }));
|
|
378
384
|
return;
|
|
@@ -389,7 +395,7 @@ export function defineDataGrid() {
|
|
|
389
395
|
this.sourceRequest = undefined;
|
|
390
396
|
this.failedSourceRange = key;
|
|
391
397
|
if (this.reorderStatus)
|
|
392
|
-
this.reorderStatus.textContent =
|
|
398
|
+
this.reorderStatus.textContent = this.localizedMessage("load-error-label", "Data could not be loaded.");
|
|
393
399
|
this.viewport?.setAttribute("aria-busy", "false");
|
|
394
400
|
this.dispatchEvent(new CustomEvent("spui-data-load-error", { detail: { error, start, end }, bubbles: true, composed: true }));
|
|
395
401
|
});
|
|
@@ -476,7 +482,7 @@ export function defineDataGrid() {
|
|
|
476
482
|
grip.dataset.reorderColumn = column.id;
|
|
477
483
|
grip.draggable = true;
|
|
478
484
|
grip.setAttribute("aria-label", `${this.getAttribute("reorder-label") || "Reorder column"} ${column.label}`);
|
|
479
|
-
grip.title =
|
|
485
|
+
grip.title = this.localizedMessage("reorder-hint-label", "Reorder {column}; use Alt+Shift+Arrow keys", { column: column.label });
|
|
480
486
|
grip.textContent = "⠿";
|
|
481
487
|
cell.append(grip);
|
|
482
488
|
}
|
|
@@ -1024,11 +1030,14 @@ export function defineDataGrid() {
|
|
|
1024
1030
|
}
|
|
1025
1031
|
catch (reason) {
|
|
1026
1032
|
editing.saving = false;
|
|
1027
|
-
|
|
1033
|
+
const message = reason instanceof Error ? reason.message : String(reason || "The value could not be saved.");
|
|
1034
|
+
editing.error = this.getAttribute("edit-error-label") || "The value could not be saved.";
|
|
1028
1035
|
if (input) {
|
|
1029
1036
|
input.disabled = false;
|
|
1030
1037
|
input.removeAttribute("aria-busy");
|
|
1031
1038
|
}
|
|
1039
|
+
this.editErrorCallback?.({ item: edit.item, rowId: edit.rowId, columnId: edit.columnId, previousValue: edit.previousValue, value: edit.value, error: message });
|
|
1040
|
+
this.dispatchEvent(new CustomEvent("spui-cell-edit-error", { detail: { item: edit.item, rowId: edit.rowId, columnId: edit.columnId, previousValue: edit.previousValue, value: edit.value, error: message }, bubbles: true, composed: true }));
|
|
1032
1041
|
this.showEditError(editing);
|
|
1033
1042
|
}
|
|
1034
1043
|
}
|
|
@@ -1049,7 +1058,7 @@ export function defineDataGrid() {
|
|
|
1049
1058
|
error.setAttribute("role", "alert");
|
|
1050
1059
|
cell.append(error);
|
|
1051
1060
|
}
|
|
1052
|
-
error.textContent = editing.error || "The value could not be saved.";
|
|
1061
|
+
error.textContent = editing.error || this.getAttribute("edit-error-label") || "The value could not be saved.";
|
|
1053
1062
|
requestAnimationFrame(() => input.focus());
|
|
1054
1063
|
}
|
|
1055
1064
|
currentEditValue(item, rowId, column) {
|
|
@@ -1101,13 +1110,13 @@ export function defineDataGrid() {
|
|
|
1101
1110
|
});
|
|
1102
1111
|
void writeDataGridClipboardText(text).then(() => {
|
|
1103
1112
|
if (this.clipboardController === controller && this.reorderStatus)
|
|
1104
|
-
this.reorderStatus.textContent = "Selection copied.";
|
|
1113
|
+
this.reorderStatus.textContent = this.localizedMessage("selection-copied-label", "Selection copied.");
|
|
1105
1114
|
}, reason => {
|
|
1106
1115
|
if (controller.signal.aborted)
|
|
1107
1116
|
return;
|
|
1108
1117
|
const message = reason instanceof Error ? reason.message : String(reason);
|
|
1109
1118
|
if (this.reorderStatus)
|
|
1110
|
-
this.reorderStatus.textContent =
|
|
1119
|
+
this.reorderStatus.textContent = this.localizedMessage("copy-failed-label", "Copy failed.");
|
|
1111
1120
|
this.dispatchEvent(new CustomEvent("spui-clipboard-error", { detail: { operation: "copy", message }, bubbles: true, composed: true }));
|
|
1112
1121
|
});
|
|
1113
1122
|
}
|
|
@@ -1194,7 +1203,7 @@ export function defineDataGrid() {
|
|
|
1194
1203
|
this.dispatchEvent(new CustomEvent("spui-cell-edit", { detail: edit, bubbles: true, composed: true }));
|
|
1195
1204
|
}
|
|
1196
1205
|
if (this.reorderStatus)
|
|
1197
|
-
this.reorderStatus.textContent =
|
|
1206
|
+
this.reorderStatus.textContent = this.localizedMessage(edits.length === 1 ? "paste-one-label" : "paste-many-label", edits.length === 1 ? "Pasted {count} cell." : "Pasted {count} cells.", { count: String(edits.length) });
|
|
1198
1207
|
this.paint(true);
|
|
1199
1208
|
}
|
|
1200
1209
|
catch (reason) {
|
|
@@ -1202,7 +1211,7 @@ export function defineDataGrid() {
|
|
|
1202
1211
|
return;
|
|
1203
1212
|
const message = reason instanceof Error ? reason.message : String(reason);
|
|
1204
1213
|
if (this.reorderStatus)
|
|
1205
|
-
this.reorderStatus.textContent =
|
|
1214
|
+
this.reorderStatus.textContent = this.localizedMessage("paste-failed-label", "Paste failed.");
|
|
1206
1215
|
this.dispatchEvent(new CustomEvent("spui-cells-edit-error", { detail: { message, edits }, bubbles: true, composed: true }));
|
|
1207
1216
|
}
|
|
1208
1217
|
}
|
|
@@ -191,7 +191,7 @@ export function defineDatePicker() {
|
|
|
191
191
|
control.append(input, calendarButton);
|
|
192
192
|
shadow.replaceChildren(document.createElement("style"), label, control, calendar);
|
|
193
193
|
const style = shadow.querySelector("style");
|
|
194
|
-
style.textContent = `${base}:host{position:relative;display:grid;gap:var(--spui-control-gap,6px);min-width:0;color:var(--spui-ui-text,var(--spui-semantic-body-text,inherit));font:inherit}.control{display:flex;position:relative;min-width:0}.control input{box-sizing:border-box;width:100%;min-width:0;min-height:var(--spui-control-height,36px);padding-inline:var(--spui-control-padding-inline,12px) 42px;border:1px solid var(--spui-control-border,var(--spui-ui-stroke,var(--spui-semantic-input-border,var(--colorNeutralStroke1,#8a8886))));border-radius:var(--spui-control-radius,4px);background:var(--spui-control-background,var(--spui-ui-surface,var(--spui-semantic-input-background,var(--colorNeutralBackground1,#fff))));box-shadow:var(--spui-control-shadow,none);color:inherit;font:inherit}.control input:focus-visible
|
|
194
|
+
style.textContent = `${base}:host{position:relative;display:grid;gap:var(--spui-control-gap,6px);min-width:0;color:var(--spui-ui-text,var(--spui-semantic-body-text,inherit));font:inherit}.control{display:flex;position:relative;min-width:0}.control input{box-sizing:border-box;width:100%;min-width:0;min-height:var(--spui-control-height,36px);padding-inline:var(--spui-control-padding-inline,12px) 42px;border:1px solid var(--spui-control-border,var(--spui-ui-stroke,var(--spui-semantic-input-border,var(--colorNeutralStroke1,#8a8886))));border-radius:var(--spui-control-radius,4px);background:var(--spui-control-background,var(--spui-ui-surface,var(--spui-semantic-input-background,var(--colorNeutralBackground1,#fff))));box-shadow:var(--spui-control-shadow,none);color:inherit;font:inherit}.control input:focus-visible{border-width:2px;border-color:var(--spui-focus-ring,var(--spui-ui-accent,#0078d4));outline:0;box-shadow:none}.calendar-button:focus-visible,.calendar button:focus-visible{outline:2px solid var(--spui-focus-ring,var(--spui-ui-accent,#0078d4));outline-offset:1px}.control input[aria-invalid]:not([aria-invalid=false]){border-color:var(--spui-input-invalid-border,var(--spui-ui-danger,var(--spui-semantic-danger,var(--colorPaletteRedBorderActive,#d13438))))}.control input[aria-invalid]:not([aria-invalid=false]):focus-visible{border-color:var(--spui-input-invalid-border,var(--spui-ui-danger,var(--spui-semantic-danger,var(--colorPaletteRedBorderActive,#d13438))))}.calendar-button{position:absolute;inset-block:2px;inset-inline-end:2px;display:grid;place-items:center;width:36px;border:0;border-radius:var(--spui-control-radius,4px);background:transparent;color:var(--spui-ui-muted,var(--colorNeutralForeground2,#616161));cursor:pointer}.calendar-button:hover{background:var(--spui-ui-surface-hover,var(--colorNeutralBackground1Hover,#f5f5f5));color:var(--spui-ui-text,inherit)}label{font-size:14px;font-weight:600;color:var(--spui-ui-muted,var(--spui-semantic-body-text,inherit))}.calendar{position:absolute;inset-block-start:calc(100% + 4px);inset-inline-start:0;z-index:var(--spui-layer-dropdown,20);width:min(320px,calc(100vw - 24px));padding:12px;border:1px solid var(--spui-ui-stroke,var(--colorNeutralStroke1,#d1d1d1));border-radius:var(--spui-card-radius,8px);background:var(--spui-ui-surface,var(--colorNeutralBackground1,#fff));box-shadow:var(--spui-card-shadow,0 4px 16px #0002);color:var(--spui-ui-text,var(--colorNeutralForeground1,#242424));direction:inherit}.calendar[hidden]{display:none}.calendar-header{display:grid;grid-template-columns:36px 1fr 36px;align-items:center;gap:4px;margin-block-end:8px}.month-label{text-align:center;font-weight:600}.calendar button{font:inherit}.month-nav{display:grid;place-items:center;width:36px;height:36px;border:0;border-radius:var(--spui-control-radius,4px);background:transparent;color:inherit;cursor:pointer}.month-nav:hover{background:var(--spui-ui-surface-hover,#f5f5f5)}.weekdays{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:2px}.days{display:grid;gap:2px}.days>[role=row]{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:2px}.weekday{display:grid;place-items:center;height:32px;color:var(--spui-ui-muted,var(--colorNeutralForeground2,#616161));font-size:12px;font-weight:600}.day{display:grid;place-items:center;min-width:0;aspect-ratio:1;border:0;border-radius:50%;background:transparent;color:inherit;cursor:pointer}.day:hover:not(:disabled){background:var(--spui-ui-surface-hover,var(--colorNeutralBackground1Hover,#f5f5f5))}.day[aria-selected=true]{background:var(--spui-ui-accent,var(--colorBrandBackground,#0f6cbd));color:var(--spui-ui-accent-text,var(--colorNeutralForegroundOnBrand,#fff))}.day[aria-current=date]{outline:1px solid var(--spui-ui-accent,var(--colorBrandForeground1,#0f6cbd));outline-offset:-2px}.day.outside-month{color:var(--spui-ui-muted,var(--colorNeutralForeground3,#a19f9d))}.day:disabled{opacity:.42;cursor:default}.calendar[dir=rtl]{direction:rtl}@media(prefers-reduced-motion:reduce){*{scroll-behavior:auto!important}}@media(forced-colors:active){.calendar,.control input{border-color:FieldText}.control input:focus-visible{border-color:Highlight;outline:0}.control input[aria-invalid]:not([aria-invalid=false]):focus-visible{border-color:Highlight}.day[aria-selected=true]{outline:2px solid Highlight}.calendar-button,.month-nav,.day{forced-color-adjust:auto}}`;
|
|
195
195
|
style.textContent += `.control input:disabled,.calendar-button:disabled,.month-nav:disabled{cursor:not-allowed;opacity:.5}.calendar-button:disabled:hover,.month-nav:disabled:hover{background:transparent}.day[aria-disabled=true]{opacity:.42;cursor:default}`;
|
|
196
196
|
this.syncInput();
|
|
197
197
|
this.syncInputAttributes();
|
package/dist/elements/dialog.js
CHANGED
|
@@ -364,7 +364,7 @@ export function defineDialog() {
|
|
|
364
364
|
this.closeDialog("backdropClick", event);
|
|
365
365
|
});
|
|
366
366
|
const style = document.createElement("style");
|
|
367
|
-
style.textContent = `${base}:host{display:contents}dialog{position:relative;z-index:2147483647;box-sizing:border-box;width:min(520px,calc(100vw - 32px));max-width:calc(100vw - 32px);max-height:calc(100dvh - 32px);overflow:auto;padding:0;border:1px solid var(--spui-ui-stroke,var(--spui-semantic-body-divider,#d1d1d1));border-radius:var(--spui-card-radius,12px);background:var(--spui-card-background,var(--spui-ui-surface,#fff));box-shadow:var(--spui-card-shadow,0 16px 48px #0004);color:var(--spui-ui-text,var(--spui-semantic-body-text,#242424))}dialog::backdrop{background:color-mix(in srgb,var(--spui-ui-text,#242424) 42%,transparent);backdrop-filter:blur(2px)}:host([backdrop-appearance=transparent]) dialog::backdrop{background:transparent;backdrop-filter:none}header{display:flex;align-items:start;justify-content:space-between;gap:16px;padding:20px 20px 0}h2{margin:0;font-size:20px;line-height:1.3;font-weight:650}.close{display:inline-grid;place-items:center;flex:none;width:var(--spui-control-height,32px);height:var(--spui-control-height,32px);margin:-5px
|
|
367
|
+
style.textContent = `${base}:host{display:contents}dialog{position:relative;z-index:2147483647;box-sizing:border-box;width:min(520px,calc(100vw - 32px));max-width:calc(100vw - 32px);max-height:calc(100dvh - 32px);overflow:auto;padding:0;border:1px solid var(--spui-ui-stroke,var(--spui-semantic-body-divider,#d1d1d1));border-radius:var(--spui-card-radius,12px);background:var(--spui-card-background,var(--spui-ui-surface,#fff));box-shadow:var(--spui-card-shadow,0 16px 48px #0004);color:var(--spui-ui-text,var(--spui-semantic-body-text,#242424))}dialog::backdrop{background:color-mix(in srgb,var(--spui-ui-text,#242424) 42%,transparent);backdrop-filter:blur(2px)}:host([backdrop-appearance=transparent]) dialog::backdrop{background:transparent;backdrop-filter:none}header{display:flex;align-items:start;justify-content:space-between;gap:16px;padding:20px 20px 0}h2{margin:0;font-size:20px;line-height:1.3;font-weight:650}.close{display:inline-grid;place-items:center;flex:none;width:var(--spui-control-height,32px);height:var(--spui-control-height,32px);margin:-5px 0 0;margin-inline-end:-6px;border:0;border-radius:var(--spui-control-radius,6px);background:transparent;color:inherit;font-size:24px;line-height:1;cursor:pointer}.close:hover{background:var(--spui-ui-surface-hover,#f5f5f5)}.close:focus-visible{outline:2px solid var(--spui-focus-ring,#005a9e);outline-offset:2px}.body{padding:16px 20px 20px;line-height:1.5}footer{display:flex;justify-content:flex-end;flex-wrap:wrap;gap:8px;padding:12px 20px 20px;border-top:1px solid var(--spui-ui-stroke,var(--spui-semantic-body-divider,#d1d1d1))}footer[hidden]{display:none}@media(forced-colors:active){dialog{border-color:CanvasText;box-shadow:none}dialog::backdrop{background:Canvas} .close:focus-visible{outline-color:Highlight}}`;
|
|
368
368
|
const overlayStyle = document.createElement("style");
|
|
369
369
|
overlayStyle.textContent = ".modal-backdrop{position:fixed;inset:0;z-index:2147483000;background:color-mix(in srgb,var(--spui-ui-text,#242424) 42%,transparent);backdrop-filter:blur(2px)}.modal-backdrop[hidden]{display:none}.modal-backdrop slot{position:absolute;inset:0}:host([data-has-custom-backdrop]) .modal-backdrop{background:transparent;backdrop-filter:none}:host([backdrop-appearance=transparent]) .modal-backdrop{background:transparent;backdrop-filter:none}::slotted([slot=backdrop]){position:absolute;inset:0;display:block;background:color-mix(in srgb,var(--spui-ui-text,#242424) 42%,transparent)}::slotted([slot=backdrop][data-appearance=transparent]){background:transparent}";
|
|
370
370
|
const backdrop = document.createElement("div");
|
|
@@ -33,7 +33,7 @@ export function defineFileUpload() {
|
|
|
33
33
|
render() {
|
|
34
34
|
const shadow = this.attachShadow({ mode: "open" });
|
|
35
35
|
const style = document.createElement("style");
|
|
36
|
-
style.textContent = `${base}:host{display:block;min-width:0;color:var(--spui-ui-text,var(--spui-semantic-body-text,#242424));font-family:var(--spui-font-family,inherit)}.label{display:block;margin-block-end:6px;font-size:14px;font-weight:600}.drop{box-sizing:border-box;display:grid;place-items:center;gap:6px;min-height:104px;padding:16px;border:1px dashed var(--spui-ui-stroke,var(--spui-semantic-input-border,#8a8886));border-radius:var(--spui-control-radius,6px);background:var(--spui-ui-surface,var(--spui-semantic-input-background,#fff));text-align:center;transition:border-color var(--spui-motion-duration-fast,120ms) var(--spui-motion-easing-standard,cubic-bezier(.2,0,0,1)),background-color var(--spui-motion-duration-fast,120ms) var(--spui-motion-easing-standard,cubic-bezier(.2,0,0,1))}.drop[data-dragging=true]{border-color:var(--spui-focus-ring,var(--spui-ui-accent,#0078d4));background:var(--spui-ui-surface-hover,var(--spui-ui-canvas,#f5f5f5))}.hint{color:var(--spui-ui-muted,var(--spui-semantic-body-subtext,#616161));font-size:12px}.browse{min-height:32px;padding:4px 12px;border:1px solid var(--spui-control-border,var(--spui-ui-stroke,#8a8886));border-radius:var(--spui-control-radius,4px);background:var(--spui-ui-surface,#fff);color:inherit;font:inherit;cursor:pointer}.browse:hover:not(:disabled){background:var(--spui-ui-surface-hover,var(--spui-ui-canvas,#f5f5f5))}.browse:focus-visible,.remove:focus-visible{outline:2px solid var(--spui-focus-ring,var(--spui-ui-accent,#0078d4));outline-offset:2px}.browse:disabled,.remove:disabled{opacity:.55;cursor:not-allowed}.input{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.files{display:grid;gap:4px;margin:8px 0 0;padding:0;list-style:none}.files:empty{display:none}.file{display:flex;align-items:center;gap:8px;min-width:0;padding:6px 8px;border:1px solid var(--spui-ui-stroke,#d1d1d1);border-radius:var(--spui-control-radius,4px)}.filename{min-width:0;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.size{flex:none;color:var(--spui-ui-muted,#616161);font-size:12px;font-variant-numeric:tabular-nums}.remove{min-width:32px;min-height:32px;border:0;border-radius:var(--spui-control-radius,4px);background:transparent;color:inherit;font:inherit;cursor:pointer}.status{margin-block-start:6px;color:var(--spui-semantic-error-text,var(--spui-ui-danger,#b10e1c));font-size:12px}.status:empty{display:none}:host([data-spui-appearance=glass]) .drop{backdrop-filter:var(--spui-card-backdrop,blur(12px) saturate(1.2))}@media(prefers-reduced-motion:reduce){.drop{transition:none}}@media(forced-colors:active){.drop,.file{border-color:CanvasText;background:Canvas;color:CanvasText}.drop[data-dragging=true]{outline:2px solid Highlight}.browse{border-color:ButtonText;background:ButtonFace;color:ButtonText}}`;
|
|
36
|
+
style.textContent = `${base}:host{display:block;min-width:0;color:var(--spui-ui-text,var(--spui-semantic-body-text,#242424));font-family:var(--spui-font-family,inherit)}.label{display:block;margin-block-end:6px;font-size:14px;font-weight:600}.drop{box-sizing:border-box;display:grid;place-items:center;gap:6px;min-height:104px;padding:16px;border:1px dashed var(--spui-ui-stroke,var(--spui-semantic-input-border,#8a8886));border-radius:var(--spui-control-radius,6px);background:var(--spui-ui-surface,var(--spui-semantic-input-background,#fff));text-align:center;transition:border-color var(--spui-motion-duration-fast,120ms) var(--spui-motion-easing-standard,cubic-bezier(.2,0,0,1)),background-color var(--spui-motion-duration-fast,120ms) var(--spui-motion-easing-standard,cubic-bezier(.2,0,0,1))}.drop[data-dragging=true]{border-color:var(--spui-focus-ring,var(--spui-ui-accent,#0078d4));background:var(--spui-ui-surface-hover,var(--spui-ui-canvas,#f5f5f5))}.hint{color:var(--spui-ui-muted,var(--spui-semantic-body-subtext,#616161));font-size:12px}.browse{min-height:32px;padding:4px 12px;border:1px solid var(--spui-control-border,var(--spui-ui-stroke,#8a8886));border-radius:var(--spui-control-radius,4px);background:var(--spui-ui-surface,#fff);color:inherit;font:inherit;cursor:pointer}.browse:hover:not(:disabled){background:var(--spui-ui-surface-hover,var(--spui-ui-canvas,#f5f5f5))}.browse:focus-visible,.remove:focus-visible{outline:2px solid var(--spui-focus-ring,var(--spui-ui-accent,#0078d4));outline-offset:2px}.browse:disabled,.remove:disabled{opacity:.55;cursor:not-allowed}.input{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}.files{display:grid;gap:4px;margin:8px 0 0;padding:0;list-style:none}.files:empty{display:none}.file{display:flex;align-items:center;gap:8px;min-width:0;padding:6px 8px;border:1px solid var(--spui-ui-stroke,#d1d1d1);border-radius:var(--spui-control-radius,4px)}.filename{min-width:0;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.size{flex:none;color:var(--spui-ui-muted,#616161);font-size:12px;font-variant-numeric:tabular-nums}.remove{min-width:32px;min-height:32px;border:0;border-radius:var(--spui-control-radius,4px);background:transparent;color:inherit;font:inherit;cursor:pointer}.status{margin-block-start:6px;color:var(--spui-semantic-error-text,var(--spui-ui-danger,#b10e1c));font-size:12px}.status:empty{display:none}:host([data-spui-appearance=glass]) .drop,:host-context([data-spui-appearance=glass]) .drop{backdrop-filter:var(--spui-card-backdrop,blur(12px) saturate(1.2))}@media(prefers-reduced-motion:reduce){.drop{transition:none}}@media(forced-colors:active){.drop,.file{border-color:CanvasText;background:Canvas;color:CanvasText}.drop[data-dragging=true]{outline:2px solid Highlight}.browse{border-color:ButtonText;background:ButtonFace;color:ButtonText}}`;
|
|
37
37
|
const label = document.createElement("label");
|
|
38
38
|
label.className = "label";
|
|
39
39
|
label.part.add("label");
|
|
@@ -17,6 +17,16 @@ export type FloatingModifiers = {
|
|
|
17
17
|
};
|
|
18
18
|
};
|
|
19
19
|
export type FloatingAnchorRect = Pick<DOMRectReadOnly, "left" | "top" | "right" | "bottom" | "width" | "height">;
|
|
20
|
+
export type FloatingBoundary = Element | {
|
|
21
|
+
x: number;
|
|
22
|
+
y: number;
|
|
23
|
+
width: number;
|
|
24
|
+
height: number;
|
|
25
|
+
} | readonly Element[] | "clippingParents" | "scrollParent" | "window" | null;
|
|
26
|
+
export declare function getFloatingBoundary(boundary: FloatingBoundary | undefined, context: Element, viewport?: {
|
|
27
|
+
width: number;
|
|
28
|
+
height: number;
|
|
29
|
+
}): Pick<DOMRectReadOnly, "left" | "top" | "right" | "bottom"> | undefined;
|
|
20
30
|
export declare function getFloatingPosition(anchor: FloatingAnchorRect, surface: Pick<DOMRectReadOnly, "width" | "height">, placement: FloatingPlacement, direction: "ltr" | "rtl", gap?: number, viewport?: {
|
|
21
31
|
width: number;
|
|
22
32
|
height: number;
|
|
@@ -1,3 +1,56 @@
|
|
|
1
|
+
export function getFloatingBoundary(boundary, context, viewport = { width: innerWidth, height: innerHeight }) {
|
|
2
|
+
if (boundary === undefined || boundary === null || boundary === "window")
|
|
3
|
+
return undefined;
|
|
4
|
+
const rectEdges = (rect) => {
|
|
5
|
+
const left = rect.left ?? rect.x ?? 0;
|
|
6
|
+
const top = rect.top ?? rect.y ?? 0;
|
|
7
|
+
return { left, top, right: left + rect.width, bottom: top + rect.height };
|
|
8
|
+
};
|
|
9
|
+
const isElement = (value) => Boolean(value && typeof value === "object" && value.nodeType === 1 && typeof value.getBoundingClientRect === "function");
|
|
10
|
+
if (Array.isArray(boundary)) {
|
|
11
|
+
const rects = boundary.map(element => rectEdges(element.getBoundingClientRect()));
|
|
12
|
+
if (!rects.length)
|
|
13
|
+
return undefined;
|
|
14
|
+
const left = Math.max(...rects.map(rect => rect.left));
|
|
15
|
+
const top = Math.max(...rects.map(rect => rect.top));
|
|
16
|
+
return { left, top, right: Math.max(left, Math.min(...rects.map(rect => rect.right))), bottom: Math.max(top, Math.min(...rects.map(rect => rect.bottom))) };
|
|
17
|
+
}
|
|
18
|
+
if (isElement(boundary))
|
|
19
|
+
return rectEdges(boundary.getBoundingClientRect());
|
|
20
|
+
if (typeof boundary === "object" && "width" in boundary && "height" in boundary)
|
|
21
|
+
return rectEdges(boundary);
|
|
22
|
+
if (boundary !== "clippingParents" && boundary !== "scrollParent")
|
|
23
|
+
return undefined;
|
|
24
|
+
const bounds = { left: 0, top: 0, right: viewport.width, bottom: viewport.height };
|
|
25
|
+
const view = context.ownerDocument.defaultView;
|
|
26
|
+
const parent = (current) => current.parentElement ?? (current.getRootNode() instanceof ShadowRoot ? current.getRootNode().host : null);
|
|
27
|
+
for (let current = parent(context); current; current = parent(current)) {
|
|
28
|
+
const style = view?.getComputedStyle(current);
|
|
29
|
+
if (!style)
|
|
30
|
+
continue;
|
|
31
|
+
const clipsX = /^(auto|scroll|hidden|clip|overlay)$/.test(style.overflowX);
|
|
32
|
+
const clipsY = /^(auto|scroll|hidden|clip|overlay)$/.test(style.overflowY);
|
|
33
|
+
const scrolls = /^(auto|scroll|hidden|overlay)$/.test(style.overflowX) || /^(auto|scroll|hidden|overlay)$/.test(style.overflowY);
|
|
34
|
+
if (boundary === "scrollParent" && !scrolls)
|
|
35
|
+
continue;
|
|
36
|
+
if (!clipsX && !clipsY)
|
|
37
|
+
continue;
|
|
38
|
+
const rect = current.getBoundingClientRect();
|
|
39
|
+
const left = rect.left + current.clientLeft;
|
|
40
|
+
const top = rect.top + current.clientTop;
|
|
41
|
+
if (boundary === "scrollParent")
|
|
42
|
+
return { left, top, right: left + current.clientWidth, bottom: top + current.clientHeight };
|
|
43
|
+
if (clipsX) {
|
|
44
|
+
bounds.left = Math.max(bounds.left, left);
|
|
45
|
+
bounds.right = Math.min(bounds.right, left + current.clientWidth);
|
|
46
|
+
}
|
|
47
|
+
if (clipsY) {
|
|
48
|
+
bounds.top = Math.max(bounds.top, top);
|
|
49
|
+
bounds.bottom = Math.min(bounds.bottom, top + current.clientHeight);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return { left: bounds.left, top: bounds.top, right: Math.max(bounds.left, bounds.right), bottom: Math.max(bounds.top, bounds.bottom) };
|
|
53
|
+
}
|
|
1
54
|
export function getFloatingPosition(anchor, surface, placement, direction, gap = 8, viewport = { width: innerWidth, height: innerHeight }, align = "center", fallbackPlacements = [], pinned = false, flipBoundary, overflowBoundary, modifiers = {}) {
|
|
2
55
|
const viewportBoundary = { left: 0, top: 0, right: viewport.width, bottom: viewport.height };
|
|
3
56
|
const flipBounds = flipBoundary ?? viewportBoundary;
|
package/dist/elements/info.js
CHANGED
|
@@ -29,7 +29,7 @@ export function defineInfoButton() {
|
|
|
29
29
|
render() {
|
|
30
30
|
const shadow = this.attachShadow({ mode: "open" });
|
|
31
31
|
const style = document.createElement("style");
|
|
32
|
-
style.textContent = `:host{display:inline-flex;vertical-align:middle;line-height:1}:host([hidden]){display:none}button{display:inline-grid;place-items:center;box-sizing:border-box;width:var(--spui-info-button-size,20px);height:var(--spui-info-button-size,20px);padding:2px;border:1px solid transparent;border-radius:50%;background:transparent;color:var(--spui-info-button-color,var(--spui-ui-muted,var(--spui-semantic-body-text,#484644)));cursor:pointer;font:inherit}button:hover:not(:disabled){background:var(--spui-info-button-hover,var(--spui-ui-surface-hover,#f3f2f1));color:var(--spui-ui-accent,var(--spui-semantic-link,#0f6cbd))}button:focus-visible{outline:2px solid var(--spui-focus-ring,var(--spui-ui-accent,#005a9e));outline-offset:2px}button:disabled{opacity:.55;cursor:not-allowed}svg{width:calc(var(--spui-info-button-size,20px) * .8);height:calc(var(--spui-info-button-size,20px) * .8);fill:none;stroke:currentColor;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round;pointer-events:none}:host([size=small]){--spui-info-button-size:16px}:host([size=large]){--spui-info-button-size:24px}:host([data-spui-appearance=glass]) button{backdrop-filter:blur(8px)}@media(forced-colors:active){button{border-color:ButtonText;color:ButtonText}button:focus-visible{outline-color:Highlight}}`;
|
|
32
|
+
style.textContent = `:host{display:inline-flex;vertical-align:middle;line-height:1}:host([hidden]){display:none}button{display:inline-grid;place-items:center;box-sizing:border-box;width:var(--spui-info-button-size,20px);height:var(--spui-info-button-size,20px);padding:2px;border:1px solid transparent;border-radius:50%;background:transparent;color:var(--spui-info-button-color,var(--spui-ui-muted,var(--spui-semantic-body-text,#484644)));cursor:pointer;font:inherit}button:hover:not(:disabled){background:var(--spui-info-button-hover,var(--spui-ui-surface-hover,#f3f2f1));color:var(--spui-ui-accent,var(--spui-semantic-link,#0f6cbd))}button:focus-visible{outline:2px solid var(--spui-focus-ring,var(--spui-ui-accent,#005a9e));outline-offset:2px}button:disabled{opacity:.55;cursor:not-allowed}svg{width:calc(var(--spui-info-button-size,20px) * .8);height:calc(var(--spui-info-button-size,20px) * .8);fill:none;stroke:currentColor;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round;pointer-events:none}:host([size=small]){--spui-info-button-size:16px}:host([size=large]){--spui-info-button-size:24px}:host([data-spui-appearance=glass]) button,:host-context([data-spui-appearance=glass]) button{backdrop-filter:blur(8px)}@media(forced-colors:active){button{border-color:ButtonText;color:ButtonText}button:focus-visible{outline-color:Highlight}}`;
|
|
33
33
|
const popover = document.createElement("spui-popover");
|
|
34
34
|
this.popoverElement = popover;
|
|
35
35
|
const trigger = document.createElement("button");
|