@spfx-fast/sharepoint-ui 0.4.2 → 0.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/AGENTS.md +23 -3
  2. package/QUICKSTART.md +133 -0
  3. package/README.md +3 -1
  4. package/components.json +168 -28
  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 +142 -10
  50. package/dist/react.js +306 -46
  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
@@ -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";
@@ -5,7 +5,7 @@ export function defineRating() {
5
5
  return;
6
6
  class SpuiRating extends HTMLElement {
7
7
  static formAssociated = true;
8
- static observedAttributes = ["value", "default-value", "max", "step", "size", "color", "label", "item-label", "name", "disabled", "readonly", "required", "aria-label", "aria-labelledby", "aria-description", "aria-describedby"];
8
+ static observedAttributes = ["value", "default-value", "max", "step", "size", "color", "label", "item-label", "name", "disabled", "readonly", "required", "required-message", "aria-label", "aria-labelledby", "aria-description", "aria-describedby"];
9
9
  internals;
10
10
  instanceName = `spui-rating-${crypto.randomUUID()}`;
11
11
  rating = 0;
@@ -96,7 +96,7 @@ export function defineRating() {
96
96
  this.internals?.setFormValue(this.rating > 0 ? String(this.rating) : null, String(this.rating));
97
97
  const missing = this.hasAttribute("required") && this.rating === 0;
98
98
  try {
99
- this.internals?.setValidity(missing ? { valueMissing: true } : {}, missing ? "Choose a rating." : "", this.queryInputs()[0]);
99
+ this.internals?.setValidity(missing ? { valueMissing: true } : {}, missing ? this.getAttribute("required-message") || "Choose a rating." : "", this.queryInputs()[0]);
100
100
  }
101
101
  catch { /* Keep the radio group functional if a browser rejects the validity anchor. */ }
102
102
  }
@@ -164,7 +164,7 @@ export function defineRating() {
164
164
  group.append(starItem);
165
165
  }
166
166
  const style = document.createElement("style");
167
- style.textContent = `${base}:host{display:inline-grid;gap:4px;min-width:0;color:var(--spui-ui-text,var(--spui-semantic-body-text,inherit));font-family:var(--spui-font-family,inherit)}.label{font-size:14px;font-weight:600;color:var(--spui-ui-muted,var(--spui-semantic-body-text,inherit))}.label[hidden]{display:none}.items{display:inline-flex;align-items:center;gap:2px;width:max-content}.star{position:relative;display:inline-block;flex:none;width:var(--spui-rating-size,28px);height:var(--spui-rating-size,28px)}.icon{position:relative;display:inline-block;font-size:var(--spui-rating-size,28px);line-height:1;color:var(--spui-rating-empty,color-mix(in srgb,var(--spui-ui-text,var(--spui-semantic-body-text,#242424)) 65%,var(--spui-ui-surface,var(--spui-semantic-body-background,#ffffff)) 35%));user-select:none}.fill{position:absolute;inset-block:0;inset-inline-start:0;overflow:hidden;width:0;color:var(--spui-rating-color,var(--spui-ui-accent,#0078d4));white-space:nowrap}:host([color=brand]){--spui-rating-color:color-mix(in srgb,var(--spui-ui-accent,#0078d4) 65%,var(--spui-ui-text,var(--spui-semantic-body-text,#242424)) 35%)}:host([color=marigold]){--spui-rating-color:color-mix(in srgb,var(--spui-rating-marigold,#c58b00) 65%,var(--spui-ui-text,var(--spui-semantic-body-text,#242424)) 35%)}:host(:not([color])),:host([color=neutral]){--spui-rating-color:var(--spui-ui-text,var(--spui-semantic-body-text,currentColor))}:host([size=small]){--spui-rating-size:18px}:host([size=medium]){--spui-rating-size:24px}:host([size=large]){--spui-rating-size:30px}:host([size=extra-large]),:host(:not([size])){--spui-rating-size:36px}.hit{position:absolute;z-index:1;inset-block:0;display:block;cursor:pointer}.hit.whole{inset-inline:0}.hit.half{inset-inline-start:0;width:50%}.hit.full{inset-inline-end:0;width:50%}.hit input{position:absolute;inset:0;width:100%;height:100%;margin:0;opacity:0;cursor:inherit}.hit:focus-within{outline:2px solid var(--spui-focus-ring,var(--spui-ui-accent,#0078d4));outline-offset:2px;border-radius:3px}:host([disabled]) .hit,:host([readonly]) .hit{cursor:default}@media(forced-colors:active){.icon{color:CanvasText}.fill{color:Highlight}.hit:focus-within{outline-color:Highlight}}`;
167
+ style.textContent = `${base}:host{display:inline-grid;gap:4px;min-width:0;color:var(--spui-ui-text,var(--spui-semantic-body-text,inherit));font-family:var(--spui-font-family,inherit)}.label{font-size:14px;font-weight:600;color:var(--spui-ui-muted,var(--spui-semantic-body-text,inherit))}.label[hidden]{display:none}.items{display:inline-flex;align-items:center;gap:2px;width:max-content}.star{position:relative;display:inline-block;flex:none;width:var(--spui-rating-size,28px);height:var(--spui-rating-size,28px)}.icon{position:relative;display:inline-block;font-size:var(--spui-rating-size,28px);line-height:1;color:var(--spui-rating-empty,color-mix(in srgb,var(--spui-ui-text,var(--spui-semantic-body-text,#242424)) 65%,var(--spui-ui-surface,var(--spui-semantic-body-background,#ffffff)) 35%));user-select:none}.fill{position:absolute;inset-block:0;inset-inline-start:0;overflow:hidden;width:0;color:var(--spui-rating-color,var(--spui-ui-accent,#0078d4));white-space:nowrap}:host([color=brand]){--spui-rating-color:color-mix(in srgb,var(--spui-ui-accent,#0078d4) 65%,var(--spui-ui-text,var(--spui-semantic-body-text,#242424)) 35%)}:host([color=marigold]){--spui-rating-color:color-mix(in srgb,var(--spui-rating-marigold,#c58b00) 65%,var(--spui-ui-text,var(--spui-semantic-body-text,#242424)) 35%)}:host(:not([color])),:host([color=neutral]){--spui-rating-color:var(--spui-ui-text,var(--spui-semantic-body-text,currentColor))}:host([size=small]){--spui-rating-size:18px}:host([size=medium]){--spui-rating-size:24px}:host([size=large]){--spui-rating-size:30px}:host([size=extra-large]),:host(:not([size])){--spui-rating-size:36px}.hit{position:absolute;z-index:1;inset-block:0;display:block;cursor:pointer}.hit.whole{inset-inline:0}.hit.half{inset-inline-start:0;width:50%}.hit.full{inset-inline-end:0;width:50%}.hit input{position:absolute;inset:0;width:100%;height:100%;margin:0;opacity:0;cursor:inherit}.hit input:focus-visible{outline:0}.hit:focus-within{outline:2px solid var(--spui-focus-ring,var(--spui-ui-accent,#0078d4));outline-offset:2px;border-radius:3px}:host([disabled]) .hit,:host([readonly]) .hit{cursor:default}@media(forced-colors:active){.icon{color:CanvasText}.fill{color:Highlight}.hit:focus-within{outline-color:Highlight}}`;
168
168
  const templates = document.createElement("div");
169
169
  templates.hidden = true;
170
170
  for (const slotName of ["icon-filled", "icon-outline", "full-value-input", "half-value-input"]) {
@@ -1,6 +1,20 @@
1
+ export { getRichTextEditorFieldOptions, type SharePointMultiLineField } from "../sharepoint-fields.js";
2
+ export type RichTextEditorLink = {
3
+ href: string;
4
+ text?: string;
5
+ title?: string;
6
+ openInNewTab?: boolean;
7
+ };
8
+ export type RichTextEditorLinkPicker = (currentLink: RichTextEditorLink | null) => Promise<RichTextEditorLink | null>;
9
+ export type RichTextEditorImageUploadResult = string | {
10
+ src: string;
11
+ alt: string;
12
+ };
13
+ export type RichTextEditorImageUploader = (file: File) => Promise<RichTextEditorImageUploadResult>;
1
14
  export interface SharePointRichTextEditorElement extends HTMLElement {
2
15
  value: string;
3
- uploadImage?: (file: File) => Promise<string>;
16
+ uploadImage?: RichTextEditorImageUploader;
17
+ linkPicker?: RichTextEditorLinkPicker;
4
18
  readonly form: HTMLFormElement | null;
5
19
  readonly validity: ValidityState | undefined;
6
20
  readonly validationMessage: string;