@spfx-fast/sharepoint-ui 0.4.1 → 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.
Files changed (57) hide show
  1. package/AGENTS.md +23 -3
  2. package/QUICKSTART.md +133 -0
  3. package/README.md +21 -878
  4. package/components.json +178 -33
  5. package/dist/appearance.js +4 -4
  6. package/dist/elements/alert.js +26 -2
  7. package/dist/elements/avatar.js +1 -1
  8. package/dist/elements/button.js +1 -1
  9. package/dist/elements/carousel.js +5 -2
  10. package/dist/elements/color-picker.js +1 -1
  11. package/dist/elements/combobox.js +5 -5
  12. package/dist/elements/data-grid-model.d.ts +3 -0
  13. package/dist/elements/data-grid.d.ts +2 -1
  14. package/dist/elements/data-grid.js +19 -10
  15. package/dist/elements/date-picker.js +1 -1
  16. package/dist/elements/dialog.js +1 -1
  17. package/dist/elements/file-upload.js +1 -1
  18. package/dist/elements/floating-position.d.ts +10 -0
  19. package/dist/elements/floating-position.js +53 -0
  20. package/dist/elements/info.js +1 -1
  21. package/dist/elements/input.js +2 -2
  22. package/dist/elements/link.js +1 -1
  23. package/dist/elements/message-bar.js +33 -5
  24. package/dist/elements/nav.js +4 -1
  25. package/dist/elements/overflow.d.ts +1 -0
  26. package/dist/elements/overflow.js +2 -2
  27. package/dist/elements/popover.js +1 -1
  28. package/dist/elements/rating.js +3 -3
  29. package/dist/elements/rich-text-editor.d.ts +15 -1
  30. package/dist/elements/rich-text-editor.js +938 -79
  31. package/dist/elements/search.js +3 -10
  32. package/dist/elements/select.js +2 -2
  33. package/dist/elements/shared.d.ts +4 -1
  34. package/dist/elements/shared.js +14 -1
  35. package/dist/elements/sharepoint-field-basic-controls.d.ts +1 -0
  36. package/dist/elements/sharepoint-field-basic-controls.js +14 -0
  37. package/dist/elements/sharepoint-fields.d.ts +29 -0
  38. package/dist/elements/sharepoint-fields.js +460 -0
  39. package/dist/elements/spin-button.js +2 -2
  40. package/dist/elements/tag-picker.js +29 -11
  41. package/dist/elements/textarea.js +2 -2
  42. package/dist/elements/toaster.js +2 -1
  43. package/dist/elements/tooltip.js +18 -1
  44. package/dist/elements/tree.js +1 -1
  45. package/dist/elements.d.ts +3 -2
  46. package/dist/elements.js +4 -1
  47. package/dist/index.d.ts +6 -4
  48. package/dist/index.js +4 -2
  49. package/dist/react.d.ts +188 -19
  50. package/dist/react.js +321 -61
  51. package/dist/sharepoint-fields.d.ts +135 -0
  52. package/dist/sharepoint-fields.js +402 -0
  53. package/dist/theme.d.ts +9 -1
  54. package/dist/theme.js +78 -1
  55. package/package.json +11 -2
  56. package/skills/sharepoint-ui/SKILL.md +1 -1
  57. package/skills/sharepoint-ui/references/sharepoint-patterns.md +1 -1
@@ -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{outline:2px solid var(--spui-focus-ring,var(--spui-ui-accent,#0078d4));outline-offset:3px}.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{outline-color:Highlight}.thumb{border-color:Canvas;box-shadow:0 0 0 1px CanvasText}}`;
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{outline:2px solid var(--spui-focus-ring,#005a9e);outline-offset:2px}:host([multiselect]) .control:focus-within{border-color:var(--spui-focus-ring,var(--spui-ui-accent,#0078d4));box-shadow:0 0 0 1px var(--spui-focus-ring,var(--spui-ui-accent,#0078d4))}@media(forced-colors:active){:host(:not([multiselect])) input{border-color:FieldText;background:Field;color:FieldText}}`;
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,::slotted([slot=button]:focus-visible){outline:2px solid var(--spui-focus-ring,var(--spui-semantic-focus-border,#005a9e));outline-offset:2px}.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){outline-color:Highlight}}";
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:2px solid var(--spui-focus-ring,#005a9e);outline-offset:1px}: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}`;
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.message;
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 = `Data could not be loaded: ${error instanceof Error ? error.message : String(error)}`;
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 = `${this.getAttribute("reorder-label") || "Reorder column"} ${column.label}; use Alt+Shift+Arrow keys`;
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
- editing.error = reason instanceof Error ? reason.message : String(reason || "The value could not be saved.");
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 = `Copy failed. ${message}`;
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 = `Pasted ${edits.length} cell${edits.length === 1 ? "" : "s"}.`;
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 = `Paste failed. ${message}`;
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,.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=true]{border-color: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}.day[aria-selected=true]{outline:2px solid Highlight}.calendar-button,.month-nav,.day{forced-color-adjust:auto}}`;
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();
@@ -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 -6px 0 0;margin-left:auto;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}}`;
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;
@@ -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");
@@ -209,8 +209,8 @@ export function defineInput() {
209
209
  render() {
210
210
  const shadow = this.attachShadow({ mode: "open" });
211
211
  const style = document.createElement("style");
212
- style.textContent = `${base}:host{display:inline-block;min-width:0;vertical-align:middle}.control{box-sizing:border-box;display:flex;align-items:center;gap:var(--spui-input-content-gap,8px);min-width:0;width:100%;border:1px solid var(--spui-input-border,var(--spui-control-border,var(--spui-ui-stroke,var(--spui-semantic-input-border,#8a8886))));border-radius:var(--spui-input-radius,var(--spui-control-radius,4px));background:var(--spui-input-background,var(--spui-control-background,var(--spui-ui-surface,var(--spui-semantic-input-background,#fff))));box-shadow:var(--spui-input-shadow,var(--spui-control-shadow,none));color:var(--spui-ui-text,var(--spui-semantic-body-text,inherit));font-family:var(--spui-font-family,inherit);font-size:var(--fontSizeBase200,14px);transition:border-color var(--spui-motion-duration-fast,120ms) var(--spui-motion-easing-standard,cubic-bezier(.2,0,0,1)),box-shadow var(--spui-motion-duration-fast,120ms) var(--spui-motion-easing-standard,cubic-bezier(.2,0,0,1))}.control:focus-within{border-color:var(--spui-focus-ring,var(--spui-ui-accent,#0078d4));box-shadow:0 0 0 1px var(--spui-focus-ring,var(--spui-ui-accent,#0078d4))}.control[data-size=small]{min-height:24px;font-size:var(--fontSizeBase100,12px)}.control[data-size=medium]{min-height:32px}.control[data-size=large]{min-height:40px;font-size:var(--fontSizeBase200,14px)}.control[data-appearance=underline]{border-width:0 0 1px;border-radius:0;box-shadow:none}.control[data-appearance=filled-darker],.control[data-appearance=filled-darker-shadow]{background:var(--spui-input-filled-darker,var(--spui-ui-surface-hover,var(--colorNeutralBackground3,#f0f0f0)));border-color:transparent}.control[data-appearance=filled-lighter],.control[data-appearance=filled-lighter-shadow]{background:var(--spui-input-filled-lighter,var(--spui-ui-canvas,var(--colorNeutralBackground1,#fafafa)));border-color:transparent}.control[data-appearance=filled-darker-shadow],.control[data-appearance=filled-lighter-shadow]{box-shadow:var(--spui-input-filled-shadow,var(--shadow2,0 1px 2px rgb(0 0 0 / 20%)))}input{box-sizing:border-box;flex:1;min-width:0;width:100%;height:100%;padding-inline:var(--spui-input-padding-inline,var(--spui-control-padding-inline,12px));border:0;outline:0;background:transparent;color:inherit;font:var(--spui-input-font,var(--spui-font-family,inherit));font-size:inherit}input::placeholder{color:var(--spui-ui-muted,var(--spui-semantic-body-subtext,#616161));opacity:1}input:disabled{cursor:not-allowed;opacity:.55}.control:has(input:disabled){opacity:.65}slot[name=before],slot[name=after]{display:inline-flex;align-items:center;flex:none;color:var(--spui-input-content-color,var(--spui-ui-muted,var(--spui-semantic-body-subtext,#616161)))}slot[name=before]{padding-inline-start:12px}slot[name=after]{padding-inline-end:12px}:host([data-spui-appearance=glass]) .control{backdrop-filter:blur(12px) saturate(1.2)}@media(prefers-reduced-motion:reduce){.control{transition:none}}@media(forced-colors:active){.control{border-color:FieldText;background:Field;color:FieldText}.control:focus-within{outline:2px solid Highlight;outline-offset:2px}input::placeholder{color:GrayText}}`;
213
- style.textContent += `slot[name=input]{display:contents}slot[name=input]::slotted(input){box-sizing:border-box;flex:1;min-width:0;width:100%;height:100%;padding-inline:var(--spui-input-padding-inline,var(--spui-control-padding-inline,12px));border:0;outline:0;background:transparent;color:inherit;font:var(--spui-input-font,var(--spui-font-family,inherit));font-size:inherit}slot[name=input]::slotted(input:disabled){cursor:not-allowed;opacity:.55}`;
212
+ style.textContent = `${base}:host{display:inline-block;min-width:0;vertical-align:middle}.control{box-sizing:border-box;display:flex;align-items:center;gap:var(--spui-input-content-gap,8px);min-width:0;width:100%;border:1px solid var(--spui-input-border,var(--spui-control-border,var(--spui-ui-stroke,var(--spui-semantic-input-border,#8a8886))));border-radius:var(--spui-input-radius,var(--spui-control-radius,4px));background:var(--spui-input-background,var(--spui-control-background,var(--spui-ui-surface,var(--spui-semantic-input-background,#fff))));box-shadow:var(--spui-input-shadow,var(--spui-control-shadow,none));color:var(--spui-ui-text,var(--spui-semantic-body-text,inherit));font-family:var(--spui-font-family,inherit);font-size:var(--fontSizeBase200,14px);transition:border-color var(--spui-motion-duration-fast,120ms) var(--spui-motion-easing-standard,cubic-bezier(.2,0,0,1)),box-shadow var(--spui-motion-duration-fast,120ms) var(--spui-motion-easing-standard,cubic-bezier(.2,0,0,1))}.control:focus-within{border-color:var(--spui-focus-ring,var(--spui-ui-accent,#0078d4));box-shadow:none}.control:has(input[aria-invalid]:not([aria-invalid=false])){border-color:var(--spui-input-invalid-border,var(--spui-ui-danger,var(--colorPaletteRedBorder2,#c50f1f)))}.control[data-size=small]{min-height:24px;font-size:var(--fontSizeBase100,12px)}.control[data-size=medium]{min-height:32px}.control[data-size=large]{min-height:40px;font-size:var(--fontSizeBase200,14px)}.control[data-appearance=underline]{border-width:0 0 1px;border-radius:0;box-shadow:none}.control[data-appearance=underline]:focus-within{border-width:0 0 1px}.control[data-appearance=filled-darker],.control[data-appearance=filled-darker-shadow]{background:var(--spui-input-filled-darker,var(--spui-ui-surface-hover,var(--colorNeutralBackground3,#f0f0f0)));border-color:transparent}.control[data-appearance=filled-lighter],.control[data-appearance=filled-lighter-shadow]{background:var(--spui-input-filled-lighter,var(--spui-ui-canvas,var(--colorNeutralBackground1,#fafafa)));border-color:transparent}.control[data-appearance=filled-darker-shadow],.control[data-appearance=filled-lighter-shadow]{box-shadow:var(--spui-input-filled-shadow,var(--shadow2,0 1px 2px rgb(0 0 0 / 20%)))}input{box-sizing:border-box;flex:1;min-width:0;width:100%;height:100%;padding-inline:var(--spui-input-padding-inline,var(--spui-control-padding-inline,12px));border:0!important;outline:0!important;box-shadow:none!important;background:transparent;color:inherit;font:var(--spui-input-font,var(--spui-font-family,inherit));font-size:inherit}input:focus-visible{outline:0!important;outline-offset:0;box-shadow:none!important}input::placeholder{color:var(--spui-ui-muted,var(--spui-semantic-body-subtext,#616161));opacity:1}input:disabled{cursor:not-allowed;opacity:.55}.control:has(input:disabled){opacity:.65}slot[name=before],slot[name=after]{display:inline-flex;align-items:center;flex:none;color:var(--spui-input-content-color,var(--spui-ui-muted,var(--spui-semantic-body-subtext,#616161)))}slot[name=before]{padding-inline-start:12px}slot[name=after]{padding-inline-end:12px}:host([data-spui-appearance=glass]) .control,:host-context([data-spui-appearance=glass]) .control{backdrop-filter:blur(12px) saturate(1.2)}@media(prefers-reduced-motion:reduce){.control{transition:none}}@media(forced-colors:active){.control{border-color:FieldText;background:Field;color:FieldText}.control:focus-within{border:1px solid Highlight;outline:0;box-shadow:none}.control:has(input[aria-invalid]:not([aria-invalid=false])){border-color:CanvasText}.control:has(input[aria-invalid]:not([aria-invalid=false])):focus-within{border-color:Highlight}.control[data-appearance=underline]:focus-within{border-width:0 0 1px}input::placeholder{color:GrayText}}`;
213
+ style.textContent += `slot[name=input]{display:contents}slot[name=input]::slotted(input){box-sizing:border-box;flex:1;min-width:0;width:100%;height:100%;padding-inline:var(--spui-input-padding-inline,var(--spui-control-padding-inline,12px));border:0!important;outline:0!important;box-shadow:none!important;background:transparent;color:inherit;font:var(--spui-input-font,var(--spui-font-family,inherit));font-size:inherit}slot[name=input]::slotted(input:focus-visible){border:0!important;outline:0!important;outline-offset:0;box-shadow:none!important}slot[name=input]::slotted(input:disabled){cursor:not-allowed;opacity:.55}`;
214
214
  style.textContent += `input[type=checkbox],input[type=radio],slot[name=input]::slotted(input[type=checkbox]),slot[name=input]::slotted(input[type=radio]){box-sizing:border-box;flex:none;width:16px;height:16px;padding:0}`;
215
215
  const control = document.createElement("div");
216
216
  control.className = "control";
@@ -61,7 +61,7 @@ export function defineLink() {
61
61
  render() {
62
62
  const shadow = this.attachShadow({ mode: "open" });
63
63
  const style = document.createElement("style");
64
- style.textContent = `${base}:host{display:inline;color:var(--spui-link-color,var(--spui-semantic-link,var(--colorBrandForeground1,#115ea3)))}a,button,span{box-sizing:border-box;background:transparent;border:0;color:inherit;font:inherit;text-align:inherit;text-decoration:none;cursor:pointer;padding:0;margin:0}a,span{display:inline}button{display:inline}a:visited{color:var(--spui-link-visited,var(--spui-semantic-link-visited,var(--colorBrandForeground2,#4f52b2))))}a:hover,button:hover,span:hover{text-decoration:underline}a:focus-visible,button:focus-visible,span:focus-visible{outline:2px solid var(--spui-focus-ring,var(--spui-semantic-focus-border,#005a9e));outline-offset:2px} [aria-disabled=true]{color:var(--spui-ui-foreground-disabled,var(--spui-ui-muted,#777));cursor:not-allowed;text-decoration:none}[aria-disabled=true]:hover,[aria-disabled=true]:active{text-decoration:none}@media(forced-colors:active){[aria-disabled=true]{color:GrayText}}:host([underline=always]) a,:host([underline=always]) button,:host([underline=always]) span{text-decoration:underline;text-decoration-thickness:from-font;text-underline-offset:2px}:host([underline=hover]) a,:host([underline=hover]) button,:host([underline=hover]) span{text-decoration:none}:host([underline=hover]) a:hover,:host([underline=hover]) button:hover,:host([underline=hover]) span:hover,:host([underline=hover]) a:focus-visible,:host([underline=hover]) button:focus-visible,:host([underline=hover]) span:focus-visible,:host([inline]) a,:host([inline]) button,:host([inline]) span{text-decoration:underline}:host([appearance=subtle]){color:var(--spui-ui-text,var(--spui-semantic-body-text,#323130))}:host([appearance=subtle]) a:visited{color:inherit}`;
64
+ style.textContent = `${base}:host{display:inline;color:var(--spui-link-color,var(--spui-semantic-link,var(--colorBrandForeground1,#115ea3)))}a,button,span{box-sizing:border-box;background:transparent;border:0;color:inherit;font:inherit;text-align:inherit;text-decoration:none;cursor:pointer;padding:0;margin:0}a,span{display:inline}button{display:inline}a:visited{color:var(--spui-link-visited,var(--spui-semantic-link-visited,var(--colorBrandForeground2,#4f52b2)))}a:hover,button:hover,span:hover{text-decoration:underline}a:focus-visible,button:focus-visible,span:focus-visible{outline:2px solid var(--spui-focus-ring,var(--spui-semantic-focus-border,#005a9e));outline-offset:2px} [aria-disabled=true]{color:var(--spui-ui-foreground-disabled,var(--spui-ui-muted,#777));cursor:not-allowed;text-decoration:none}[aria-disabled=true]:hover,[aria-disabled=true]:active{text-decoration:none}@media(forced-colors:active){[aria-disabled=true]{color:GrayText}}:host([underline=always]) a,:host([underline=always]) button,:host([underline=always]) span{text-decoration:underline;text-decoration-thickness:from-font;text-underline-offset:2px}:host([underline=hover]) a,:host([underline=hover]) button,:host([underline=hover]) span{text-decoration:none}:host([underline=hover]) a:hover,:host([underline=hover]) button:hover,:host([underline=hover]) span:hover,:host([underline=hover]) a:focus-visible,:host([underline=hover]) button:focus-visible,:host([underline=hover]) span:focus-visible,:host([inline]) a,:host([inline]) button,:host([inline]) span{text-decoration:underline}:host([appearance=subtle]){color:var(--spui-ui-text,var(--spui-semantic-body-text,#323130))}:host([appearance=subtle]) a:visited{color:inherit}`;
65
65
  shadow.append(style);
66
66
  this.renderRoot(this.getAttribute("as") || (this.getAttribute("href") ? "a" : "button"));
67
67
  this.addEventListener("click", event => { if (this.isDisabled()) {
@@ -66,8 +66,10 @@ function definePart(tag, content, css, observed = []) {
66
66
  }
67
67
  }
68
68
  for (const node of record.removedNodes)
69
- if (node instanceof HTMLElement && node.localName === "spui-message-bar" && !node.hasAttribute("data-spui-exiting"))
69
+ if (node instanceof HTMLElement && node.localName === "spui-message-bar" && !node.hasAttribute("data-spui-exiting")) {
70
+ this.resizeObserver?.unobserve(node);
70
71
  this.animateExit(node);
72
+ }
71
73
  }
72
74
  });
73
75
  this.childObserver.observe(this, { childList: true });
@@ -78,12 +80,32 @@ function definePart(tag, content, css, observed = []) {
78
80
  animateExit(bar) {
79
81
  const view = this.ownerDocument.defaultView;
80
82
  const rect = this.childRects.get(bar);
81
- if (!view || !rect || this.getAttribute("animate") === "none")
83
+ if (!view || !rect || this.getAttribute("animate") === "none" || view.matchMedia("(prefers-reduced-motion: reduce)").matches)
82
84
  return;
83
85
  const groupRect = this.getBoundingClientRect();
86
+ for (const sibling of this.querySelectorAll(":scope > spui-message-bar:not([data-spui-exiting])")) {
87
+ const previous = this.childRects.get(sibling);
88
+ const current = sibling.getBoundingClientRect();
89
+ this.childRects.set(sibling, current);
90
+ const offset = previous ? previous.top - current.top : 0;
91
+ if (Math.abs(offset) < 1)
92
+ continue;
93
+ sibling.style.setProperty("--spui-message-shift", `${offset}px`);
94
+ sibling.setAttribute("data-spui-shifting", "");
95
+ const clearShift = () => {
96
+ sibling.removeAttribute("data-spui-shifting");
97
+ sibling.style.removeProperty("--spui-message-shift");
98
+ sibling.removeEventListener("animationend", clearShift);
99
+ sibling.removeEventListener("animationcancel", clearShift);
100
+ };
101
+ sibling.addEventListener("animationend", clearShift);
102
+ sibling.addEventListener("animationcancel", clearShift);
103
+ }
84
104
  const clone = bar.cloneNode(true);
85
105
  clone.setAttribute("data-spui-exiting", "");
86
106
  clone.setAttribute("aria-hidden", "true");
107
+ clone.removeAttribute("data-spui-shifting");
108
+ clone.style.removeProperty("--spui-message-shift");
87
109
  clone.inert = true;
88
110
  clone.removeAttribute("id");
89
111
  clone.querySelectorAll("[id], [data-testid]").forEach(node => { node.removeAttribute("id"); node.removeAttribute("data-testid"); });
@@ -97,9 +119,15 @@ function definePart(tag, content, css, observed = []) {
97
119
  pointerEvents: "none",
98
120
  zIndex: "1",
99
121
  });
100
- clone.addEventListener("animationend", () => clone.remove(), { once: true });
122
+ const removeClone = () => {
123
+ clone.removeEventListener("animationend", removeClone);
124
+ clone.removeEventListener("animationcancel", removeClone);
125
+ clone.remove();
126
+ };
127
+ clone.addEventListener("animationend", removeClone);
128
+ clone.addEventListener("animationcancel", removeClone);
101
129
  this.append(clone);
102
- view.setTimeout(() => clone.remove(), 300);
130
+ view.setTimeout(removeClone, 300);
103
131
  }
104
132
  }
105
133
  customElements.define(tag, SpuiMessageBarPart);
@@ -114,7 +142,7 @@ export function defineMessageBarTitle() {
114
142
  definePart("spui-message-bar-title", "<slot></slot>", ":host{display:inline;font-weight:600}");
115
143
  }
116
144
  export function defineMessageBarGroup() {
117
- definePart("spui-message-bar-group", "<slot></slot>", ":host{position:relative;display:grid;gap:8px}:host([data-animate=both]) ::slotted(spui-message-bar:not([data-spui-exiting])){animation:spui-message-enter 160ms cubic-bezier(.2,0,0,1) both}::slotted(spui-message-bar[data-spui-exiting]){animation:spui-message-exit 250ms ease-in both}@keyframes spui-message-enter{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}@keyframes spui-message-exit{to{opacity:0}}@media(prefers-reduced-motion:reduce){:host([data-animate=both]) ::slotted(spui-message-bar:not([data-spui-exiting])),::slotted(spui-message-bar[data-spui-exiting]){animation:none}}", ["animate"]);
145
+ definePart("spui-message-bar-group", "<slot></slot>", ":host{position:relative;display:grid;gap:8px}:host([data-animate=both]) ::slotted(spui-message-bar:not([data-spui-exiting])){animation:spui-message-enter 160ms cubic-bezier(.2,0,0,1) both}::slotted(spui-message-bar[data-spui-exiting]){animation:spui-message-exit 250ms ease-in both}:host([data-animate]) ::slotted(spui-message-bar[data-spui-shifting]){animation:spui-message-shift 180ms cubic-bezier(.2,0,0,1) both}@keyframes spui-message-enter{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}@keyframes spui-message-exit{to{opacity:0}}@keyframes spui-message-shift{from{transform:translateY(var(--spui-message-shift,0px))}to{transform:translateY(0)}}@media(prefers-reduced-motion:reduce){:host([data-animate=both]) ::slotted(spui-message-bar:not([data-spui-exiting])),::slotted(spui-message-bar[data-spui-exiting]),:host([data-animate]) ::slotted(spui-message-bar[data-spui-shifting]){animation:none}}", ["animate"]);
118
146
  }
119
147
  export function defineMessageBar() {
120
148
  if (customElements.get("spui-message-bar"))
@@ -20,7 +20,7 @@ export function defineNav() {
20
20
  if (customElements.get("spui-nav"))
21
21
  return;
22
22
  class SpuiNav extends HTMLElement {
23
- static observedAttributes = ["label", "aria-label", "density", "multiple", "tabbable", "open", "open-label", "close-label", "collapsible", "collapsed", "expand-label", "collapse-label"];
23
+ static observedAttributes = ["label", "aria-label", "density", "multiple", "tabbable", "open", "open-label", "close-label", "collapsible", "collapsed", "full-width", "expand-label", "collapse-label"];
24
24
  observer;
25
25
  events;
26
26
  breakpoint;
@@ -46,6 +46,8 @@ export function defineNav() {
46
46
  get defaultCollapsed() { return this.collapsed; }
47
47
  set defaultCollapsed(value) { if (!this.collapsedControlled)
48
48
  this.setCollapsed(Boolean(value)); }
49
+ get fullWidth() { return this.hasAttribute("full-width"); }
50
+ set fullWidth(value) { this.toggleAttribute("full-width", Boolean(value)); }
49
51
  connectedCallback() {
50
52
  if (!this.shadowRoot)
51
53
  this.render();
@@ -432,6 +434,7 @@ export function defineNav() {
432
434
  const style = document.createElement("style");
433
435
  style.textContent = `${base}
434
436
  :host{display:block;width:var(--spui-nav-width,260px);max-width:100%;min-width:0;color:var(--spui-ui-text,var(--spui-semantic-body-text,#242424));font:inherit}:host([data-collapsed]){width:var(--spui-nav-collapsed-width,64px)}
437
+ @media(min-width:641px){:host([full-width]:not([data-collapsed])){width:100%}}
435
438
  nav{display:grid;grid-template-columns:minmax(0,1fr);gap:2px;width:100%;min-width:0;font-family:var(--spui-font-family,inherit);font-size:var(--spui-nav-font-size,14px);color:inherit}nav[hidden]{display:none}nav slot{min-width:0}
436
439
  :host([density=small]) nav{--spui-nav-item-block:5px;--spui-nav-font-size:13px}
437
440
  :host([density=large]) nav{--spui-nav-item-block:10px;--spui-nav-font-size:15px}
@@ -4,6 +4,7 @@ export type OverflowState = {
4
4
  groupVisibility: Record<string, "visible" | "hidden" | "overflow">;
5
5
  };
6
6
  export type OverflowAxis = "horizontal" | "vertical";
7
+ export type OverflowDensity = "comfortable" | "compact";
7
8
  export declare function defineOverflowItem(): void;
8
9
  export declare function defineOverflowDivider(): void;
9
10
  export declare function defineOverflow(): void;
@@ -34,7 +34,7 @@ export function defineOverflow() {
34
34
  defineOverflowItem();
35
35
  defineOverflowDivider();
36
36
  class SpuiOverflow extends HTMLElement {
37
- static observedAttributes = ["aria-label", "minimum-visible", "overflow-direction", "overflow-axis", "has-hidden-items", "padding"];
37
+ static observedAttributes = ["aria-label", "minimum-visible", "overflow-direction", "overflow-axis", "has-hidden-items", "padding", "density"];
38
38
  itemSlot;
39
39
  triggerSlot;
40
40
  row;
@@ -84,7 +84,7 @@ export function defineOverflow() {
84
84
  render() {
85
85
  const shadow = this.attachShadow({ mode: "open" });
86
86
  const style = document.createElement("style");
87
- style.textContent = `${base}:host{display:block;min-width:0;max-width:100%}.row{display:flex;align-items:center;flex-wrap:nowrap;gap:var(--spui-overflow-gap,var(--spui-toolbar-gap,6px));min-width:0;max-width:100%;overflow:hidden}.row:dir(rtl){direction:rtl}:host([overflow-axis=vertical]) .row{height:100%;flex-direction:column;align-items:stretch}:host([overflow-axis=vertical]) ::slotted([slot=overflow-trigger]){margin-inline-start:0;margin-block-start:auto;align-self:flex-end}::slotted([slot=overflow-trigger]){display:inline-flex;flex:none;margin-inline-start:auto}::slotted([slot=overflow-trigger][hidden]){display:none!important}::slotted(spui-overflow-divider[hidden]){display:none!important}@media(forced-colors:active){.row{forced-color-adjust:auto}}`;
87
+ style.textContent = `${base}:host{display:block;min-width:0;max-width:100%}:host([density=compact]){--spui-control-height:28px;--spui-control-padding-inline:10px;--spui-overflow-gap:4px}.row{display:flex;align-items:center;flex-wrap:nowrap;gap:var(--spui-overflow-gap,var(--spui-toolbar-gap,6px));min-width:0;max-width:100%;overflow:hidden}.row:dir(rtl){direction:rtl}:host([overflow-axis=vertical]) .row{height:100%;flex-direction:column;align-items:stretch}:host([overflow-axis=vertical]) ::slotted([slot=overflow-trigger]){margin-inline-start:0;margin-block-start:auto;align-self:flex-end}::slotted([slot=overflow-trigger]){display:inline-flex;flex:none;margin-inline-start:auto}::slotted([slot=overflow-trigger][hidden]){display:none!important}::slotted(spui-overflow-divider[hidden]){display:none!important}@media(pointer:coarse){:host([density=compact]){--spui-control-height:max(44px,var(--spui-touch-target-min,44px))}}@media(forced-colors:active){.row{forced-color-adjust:auto}}`;
88
88
  this.row = document.createElement("div");
89
89
  this.row.className = "row";
90
90
  this.row.setAttribute("part", "control");
@@ -289,7 +289,7 @@ export function definePopover() {
289
289
  render() {
290
290
  const shadow = this.attachShadow({ mode: "open" });
291
291
  const style = document.createElement("style");
292
- style.textContent = `${base}:host{display:contents}.trigger{display:contents}.surface{position:fixed;inset:auto;margin:0;z-index:var(--spui-layer-popover,10000);box-sizing:border-box;width:max-content;max-width:var(--spui-popover-max-width,min(360px,calc(100vw - 16px)));max-height:var(--spui-popover-max-height,min(70vh,calc(100dvh - 24px)));overflow:auto;padding:16px;border:1px solid var(--spui-popover-border,var(--spui-ui-stroke,var(--spui-semantic-body-divider,#d1d1d1)));border-radius:var(--spui-popover-radius,var(--spui-card-radius,8px));background:var(--spui-popover-background,var(--spui-ui-surface,var(--colorNeutralBackground1,#fff)));color:var(--spui-popover-color,var(--spui-ui-text,var(--colorNeutralForeground1,#242424)));box-shadow:var(--spui-popover-shadow,0 8px 24px rgb(0 0 0 / 18%));font-family:var(--spui-font-family,inherit);font-size:14px;line-height:1.45;opacity:1;transform:scale(1);transform-origin:center;transition:opacity var(--spui-motion-duration-normal,140ms) cubic-bezier(.16,1,.3,1),transform var(--spui-motion-duration-normal,140ms) cubic-bezier(.16,1,.3,1)}@starting-style{.surface:popover-open{opacity:0;transform:scale(.97)}}.surface:not(:popover-open){display:none}.surface[hidden]{display:none}h2{margin:0 0 8px;font:600 16px/1.35 var(--spui-font-family,inherit)}h2:empty{display:none}slot[name=trigger]{display:contents}slot[name=title]:not(:defined){display:none}:host([data-spui-appearance=glass]) .surface{backdrop-filter:blur(18px) saturate(1.35)}:host([appearance=brand]){--spui-popover-background:var(--spui-ui-accent,var(--colorBrandBackground,#0078d4));--spui-popover-color:var(--spui-ui-accent-text,var(--spui-semantic-primary-button-text,#fff));--spui-popover-border:var(--spui-ui-accent,var(--colorBrandBackground,#0078d4))}:host([appearance=inverted]){--spui-popover-background:var(--spui-ui-text,var(--spui-semantic-body-text,#242424));--spui-popover-color:var(--spui-ui-surface,var(--spui-semantic-body-background,#fff));--spui-popover-border:var(--spui-ui-text,var(--spui-semantic-body-text,#242424))}:host([size=small]) .surface{padding:8px;font-size:12px}:host([size=large]) .surface{padding:20px;font-size:16px}@media(prefers-reduced-motion:reduce){.surface{transition:none}}@media(forced-colors:active){.surface{border-color:CanvasText;box-shadow:none}.surface:popover-open{outline:1px solid CanvasText}}`;
292
+ style.textContent = `${base}:host{display:contents}.trigger{display:contents}.surface{position:fixed;inset:auto;margin:0;z-index:var(--spui-layer-popover,10000);box-sizing:border-box;width:max-content;max-width:var(--spui-popover-max-width,min(360px,calc(100vw - 16px)));max-height:var(--spui-popover-max-height,min(70vh,calc(100dvh - 24px)));overflow:auto;padding:16px;border:1px solid var(--spui-popover-border,var(--spui-ui-stroke,var(--spui-semantic-body-divider,#d1d1d1)));border-radius:var(--spui-popover-radius,var(--spui-card-radius,8px));background:var(--spui-popover-background,var(--spui-ui-surface,var(--colorNeutralBackground1,#fff)));color:var(--spui-popover-color,var(--spui-ui-text,var(--colorNeutralForeground1,#242424)));box-shadow:var(--spui-popover-shadow,0 8px 24px rgb(0 0 0 / 18%));font-family:var(--spui-font-family,inherit);font-size:14px;line-height:1.45;opacity:1;transform:scale(1);transform-origin:center;transition:opacity var(--spui-motion-duration-normal,140ms) cubic-bezier(.16,1,.3,1),transform var(--spui-motion-duration-normal,140ms) cubic-bezier(.16,1,.3,1)}@starting-style{.surface:popover-open{opacity:0;transform:scale(.97)}}.surface:not(:popover-open){display:none}.surface[hidden]{display:none}h2{margin:0 0 8px;font:600 16px/1.35 var(--spui-font-family,inherit)}h2:empty{display:none}slot[name=trigger]{display:contents}slot[name=title]:not(:defined){display:none}:host([data-spui-appearance=glass]) .surface,:host-context([data-spui-appearance=glass]) .surface{backdrop-filter:blur(18px) saturate(1.35)}:host([appearance=brand]){--spui-popover-background:var(--spui-ui-accent,var(--colorBrandBackground,#0078d4));--spui-popover-color:var(--spui-ui-accent-text,var(--spui-semantic-primary-button-text,#fff));--spui-popover-border:var(--spui-ui-accent,var(--colorBrandBackground,#0078d4))}:host([appearance=inverted]){--spui-popover-background:var(--spui-ui-text,var(--spui-semantic-body-text,#242424));--spui-popover-color:var(--spui-ui-surface,var(--spui-semantic-body-background,#fff));--spui-popover-border:var(--spui-ui-text,var(--spui-semantic-body-text,#242424))}:host([size=small]) .surface{padding:8px;font-size:12px}:host([size=large]) .surface{padding:20px;font-size:16px}@media(prefers-reduced-motion:reduce){.surface{transition:none}}@media(forced-colors:active){.surface{border-color:CanvasText;box-shadow:none}.surface:popover-open{outline:1px solid CanvasText}}`;
293
293
  style.textContent += `:host([arrow]) .surface:before{content:"";position:absolute;z-index:1;width:8px;height:8px;border:1px solid var(--spui-popover-border,var(--spui-ui-stroke,#d1d1d1));background:var(--spui-popover-background,var(--spui-ui-surface,#fff));transform:rotate(45deg)}:host([arrow]) .surface[data-placement=bottom]:before{inset-block-start:-5px;inset-inline-start:var(--spui-popover-arrow-inline-offset,calc(50% - 5px));border-inline-end:0;border-block-end:0}:host([arrow]) .surface[data-placement=top]:before{inset-block-end:-5px;inset-inline-start:var(--spui-popover-arrow-inline-offset,calc(50% - 5px));border-inline-start:0;border-block-start:0}:host([arrow]) .surface[data-placement=left]:before{inset-inline-end:-5px;inset-block-start:var(--spui-popover-arrow-block-offset,calc(50% - 5px));border-inline-start:0;border-block-end:0}:host([arrow]) .surface[data-placement=right]:before{inset-inline-start:-5px;inset-block-start:var(--spui-popover-arrow-block-offset,calc(50% - 5px));border-inline-end:0;border-block-start:0}`;
294
294
  const panel = document.createElement("div");
295
295
  panel.className = "surface";