@spfx-fast/sharepoint-ui 0.4.2 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (276) hide show
  1. package/QUICKSTART.md +18 -0
  2. package/README.md +19 -24
  3. package/components.json +240 -5694
  4. package/dist/accordion.d.ts +11 -0
  5. package/dist/accordion.js +4 -0
  6. package/dist/alert.d.ts +3 -0
  7. package/dist/alert.js +4 -0
  8. package/dist/attachment-list.d.ts +15 -0
  9. package/dist/attachment-list.js +14 -0
  10. package/dist/avatar-group.d.ts +12 -0
  11. package/dist/avatar-group.js +7 -0
  12. package/dist/avatar.d.ts +6 -0
  13. package/dist/avatar.js +5 -0
  14. package/dist/badge.d.ts +3 -0
  15. package/dist/badge.js +4 -0
  16. package/dist/breadcrumb.d.ts +10 -0
  17. package/dist/breadcrumb.js +9 -0
  18. package/dist/button-group.d.ts +6 -0
  19. package/dist/button-group.js +4 -0
  20. package/dist/button.d.ts +3 -0
  21. package/dist/button.js +4 -0
  22. package/dist/card.d.ts +3 -0
  23. package/dist/card.js +4 -0
  24. package/dist/carousel.d.ts +11 -0
  25. package/dist/carousel.js +6 -0
  26. package/dist/checkbox.d.ts +3 -0
  27. package/dist/checkbox.js +4 -0
  28. package/dist/combobox.d.ts +9 -0
  29. package/dist/combobox.js +6 -0
  30. package/dist/command-bar.d.ts +6 -0
  31. package/dist/command-bar.js +4 -0
  32. package/dist/copy-button.d.ts +7 -0
  33. package/dist/copy-button.js +19 -0
  34. package/dist/data-grid.d.ts +25 -0
  35. package/dist/data-grid.js +39 -0
  36. package/dist/date-range-picker.d.ts +12 -0
  37. package/dist/date-range-picker.js +4 -0
  38. package/dist/dialog.d.ts +9 -0
  39. package/dist/dialog.js +21 -0
  40. package/dist/divider.d.ts +3 -0
  41. package/dist/divider.js +4 -0
  42. package/dist/drawer.d.ts +6 -0
  43. package/dist/drawer.js +5 -0
  44. package/dist/empty-state.d.ts +7 -0
  45. package/dist/empty-state.js +5 -0
  46. package/dist/field.d.ts +15 -0
  47. package/dist/field.js +11 -0
  48. package/dist/file-dropzone.d.ts +15 -0
  49. package/dist/file-dropzone.js +21 -0
  50. package/dist/filter-bar.d.ts +9 -0
  51. package/dist/filter-bar.js +9 -0
  52. package/dist/image.d.ts +5 -0
  53. package/dist/image.js +4 -0
  54. package/dist/index.d.ts +68 -76
  55. package/dist/index.js +60 -66
  56. package/dist/input.d.ts +3 -0
  57. package/dist/input.js +4 -0
  58. package/dist/label.d.ts +3 -0
  59. package/dist/label.js +4 -0
  60. package/dist/link.d.ts +3 -0
  61. package/dist/link.js +9 -0
  62. package/dist/list-view.d.ts +29 -0
  63. package/dist/list-view.js +14 -0
  64. package/dist/list.d.ts +6 -0
  65. package/dist/list.js +5 -0
  66. package/dist/lookup-picker.d.ts +12 -0
  67. package/dist/lookup-picker.js +4 -0
  68. package/dist/menu.d.ts +6 -0
  69. package/dist/menu.js +4 -0
  70. package/dist/nav.d.ts +12 -0
  71. package/dist/nav.js +4 -0
  72. package/dist/pagination.d.ts +11 -0
  73. package/dist/pagination.js +5 -0
  74. package/dist/person-picker.d.ts +13 -0
  75. package/dist/person-picker.js +4 -0
  76. package/dist/persona.d.ts +7 -0
  77. package/dist/persona.js +5 -0
  78. package/dist/popover.d.ts +6 -0
  79. package/dist/popover.js +4 -0
  80. package/dist/progress-bar.d.ts +5 -0
  81. package/dist/progress-bar.js +5 -0
  82. package/dist/radio-group.d.ts +6 -0
  83. package/dist/radio-group.js +4 -0
  84. package/dist/radio.d.ts +3 -0
  85. package/dist/radio.js +4 -0
  86. package/dist/rating.d.ts +8 -0
  87. package/dist/rating.js +5 -0
  88. package/dist/react.d.ts +1 -4583
  89. package/dist/react.js +1 -6837
  90. package/dist/select.d.ts +3 -0
  91. package/dist/select.js +4 -0
  92. package/dist/sharepoint-field.d.ts +18 -0
  93. package/dist/sharepoint-field.js +54 -0
  94. package/dist/skeleton.d.ts +6 -0
  95. package/dist/skeleton.js +9 -0
  96. package/dist/spinner.d.ts +5 -0
  97. package/dist/spinner.js +4 -0
  98. package/dist/swatch-picker.d.ts +17 -0
  99. package/dist/swatch-picker.js +11 -0
  100. package/dist/switch.d.ts +3 -0
  101. package/dist/switch.js +4 -0
  102. package/dist/table.d.ts +6 -0
  103. package/dist/table.js +4 -0
  104. package/dist/tabs.d.ts +14 -0
  105. package/dist/tabs.js +30 -0
  106. package/dist/tag-group.d.ts +6 -0
  107. package/dist/tag-group.js +4 -0
  108. package/dist/tag-picker.d.ts +12 -0
  109. package/dist/tag-picker.js +4 -0
  110. package/dist/tag.d.ts +7 -0
  111. package/dist/tag.js +5 -0
  112. package/dist/text.d.ts +5 -0
  113. package/dist/text.js +4 -0
  114. package/dist/textarea.d.ts +3 -0
  115. package/dist/textarea.js +4 -0
  116. package/dist/theme.d.ts +15 -167
  117. package/dist/theme.js +36 -162
  118. package/dist/toast.d.ts +9 -0
  119. package/dist/toast.js +12 -0
  120. package/dist/tree.d.ts +13 -0
  121. package/dist/tree.js +9 -0
  122. package/dist/view-card.d.ts +8 -0
  123. package/dist/view-card.js +4 -0
  124. package/dist/view-switcher.d.ts +13 -0
  125. package/dist/view-switcher.js +7 -0
  126. package/dist/virtual-list.d.ts +11 -0
  127. package/dist/virtual-list.js +25 -0
  128. package/measurements.json +365 -0
  129. package/package.json +19 -42
  130. package/src/theme.css +125 -0
  131. package/AGENTS.md +0 -211
  132. package/dist/appearance.d.ts +0 -6
  133. package/dist/appearance.js +0 -217
  134. package/dist/elements/accordion.d.ts +0 -9
  135. package/dist/elements/accordion.js +0 -338
  136. package/dist/elements/alert.d.ts +0 -2
  137. package/dist/elements/alert.js +0 -62
  138. package/dist/elements/avatar-group-primitives.d.ts +0 -3
  139. package/dist/elements/avatar-group-primitives.js +0 -189
  140. package/dist/elements/avatar-group.d.ts +0 -2
  141. package/dist/elements/avatar-group.js +0 -110
  142. package/dist/elements/avatar.d.ts +0 -4
  143. package/dist/elements/avatar.js +0 -251
  144. package/dist/elements/badge.d.ts +0 -8
  145. package/dist/elements/badge.js +0 -182
  146. package/dist/elements/breadcrumb.d.ts +0 -4
  147. package/dist/elements/breadcrumb.js +0 -233
  148. package/dist/elements/button-group.d.ts +0 -1
  149. package/dist/elements/button-group.js +0 -20
  150. package/dist/elements/button-variants.d.ts +0 -6
  151. package/dist/elements/button-variants.js +0 -339
  152. package/dist/elements/button.d.ts +0 -5
  153. package/dist/elements/button.js +0 -233
  154. package/dist/elements/card-primitives.d.ts +0 -3
  155. package/dist/elements/card-primitives.js +0 -83
  156. package/dist/elements/card.d.ts +0 -5
  157. package/dist/elements/card.js +0 -213
  158. package/dist/elements/carousel.d.ts +0 -92
  159. package/dist/elements/carousel.js +0 -1112
  160. package/dist/elements/color-picker.d.ts +0 -24
  161. package/dist/elements/color-picker.js +0 -1004
  162. package/dist/elements/combobox.d.ts +0 -1
  163. package/dist/elements/combobox.js +0 -1012
  164. package/dist/elements/data-grid-model.d.ts +0 -117
  165. package/dist/elements/data-grid-model.js +0 -294
  166. package/dist/elements/data-grid.d.ts +0 -29
  167. package/dist/elements/data-grid.js +0 -1567
  168. package/dist/elements/date-picker.d.ts +0 -1
  169. package/dist/elements/date-picker.js +0 -486
  170. package/dist/elements/dialog.d.ts +0 -23
  171. package/dist/elements/dialog.js +0 -409
  172. package/dist/elements/divider.d.ts +0 -2
  173. package/dist/elements/divider.js +0 -66
  174. package/dist/elements/drawer.d.ts +0 -3
  175. package/dist/elements/drawer.js +0 -308
  176. package/dist/elements/field-composition.d.ts +0 -26
  177. package/dist/elements/field-composition.js +0 -133
  178. package/dist/elements/field.d.ts +0 -1
  179. package/dist/elements/field.js +0 -67
  180. package/dist/elements/file-upload.d.ts +0 -6
  181. package/dist/elements/file-upload.js +0 -211
  182. package/dist/elements/floating-position.d.ts +0 -26
  183. package/dist/elements/floating-position.js +0 -39
  184. package/dist/elements/image.d.ts +0 -28
  185. package/dist/elements/image.js +0 -38
  186. package/dist/elements/info.d.ts +0 -9
  187. package/dist/elements/info.js +0 -102
  188. package/dist/elements/input.d.ts +0 -5
  189. package/dist/elements/input.js +0 -255
  190. package/dist/elements/label.d.ts +0 -15
  191. package/dist/elements/label.js +0 -56
  192. package/dist/elements/link.d.ts +0 -1
  193. package/dist/elements/link.js +0 -92
  194. package/dist/elements/list.d.ts +0 -19
  195. package/dist/elements/list.js +0 -297
  196. package/dist/elements/menu.d.ts +0 -33
  197. package/dist/elements/menu.js +0 -1103
  198. package/dist/elements/message-bar.d.ts +0 -10
  199. package/dist/elements/message-bar.js +0 -299
  200. package/dist/elements/nav.d.ts +0 -32
  201. package/dist/elements/nav.js +0 -791
  202. package/dist/elements/overflow.d.ts +0 -9
  203. package/dist/elements/overflow.js +0 -218
  204. package/dist/elements/persona.d.ts +0 -3
  205. package/dist/elements/persona.js +0 -125
  206. package/dist/elements/popover.d.ts +0 -77
  207. package/dist/elements/popover.js +0 -840
  208. package/dist/elements/progress-bar.d.ts +0 -4
  209. package/dist/elements/progress-bar.js +0 -82
  210. package/dist/elements/radio-group.d.ts +0 -1
  211. package/dist/elements/radio-group.js +0 -303
  212. package/dist/elements/rating-display.d.ts +0 -2
  213. package/dist/elements/rating-display.js +0 -125
  214. package/dist/elements/rating.d.ts +0 -2
  215. package/dist/elements/rating.js +0 -206
  216. package/dist/elements/rich-text-editor.d.ts +0 -18
  217. package/dist/elements/rich-text-editor.js +0 -508
  218. package/dist/elements/search.d.ts +0 -3
  219. package/dist/elements/search.js +0 -207
  220. package/dist/elements/select.d.ts +0 -6
  221. package/dist/elements/select.js +0 -291
  222. package/dist/elements/shared.d.ts +0 -19
  223. package/dist/elements/shared.js +0 -396
  224. package/dist/elements/skeleton.d.ts +0 -6
  225. package/dist/elements/skeleton.js +0 -91
  226. package/dist/elements/slider.d.ts +0 -1
  227. package/dist/elements/slider.js +0 -248
  228. package/dist/elements/spin-button.d.ts +0 -7
  229. package/dist/elements/spin-button.js +0 -499
  230. package/dist/elements/spinner.d.ts +0 -4
  231. package/dist/elements/spinner.js +0 -124
  232. package/dist/elements/swatch-picker.d.ts +0 -5
  233. package/dist/elements/swatch-picker.js +0 -363
  234. package/dist/elements/table.d.ts +0 -21
  235. package/dist/elements/table.js +0 -261
  236. package/dist/elements/tabs.d.ts +0 -1
  237. package/dist/elements/tabs.js +0 -276
  238. package/dist/elements/tag-picker.d.ts +0 -29
  239. package/dist/elements/tag-picker.js +0 -697
  240. package/dist/elements/tags.d.ts +0 -21
  241. package/dist/elements/tags.js +0 -421
  242. package/dist/elements/teaching-popover.d.ts +0 -32
  243. package/dist/elements/teaching-popover.js +0 -412
  244. package/dist/elements/text.d.ts +0 -9
  245. package/dist/elements/text.js +0 -75
  246. package/dist/elements/textarea.d.ts +0 -1
  247. package/dist/elements/textarea.js +0 -182
  248. package/dist/elements/toast.d.ts +0 -25
  249. package/dist/elements/toast.js +0 -337
  250. package/dist/elements/toaster.d.ts +0 -6
  251. package/dist/elements/toaster.js +0 -356
  252. package/dist/elements/toggle.d.ts +0 -2
  253. package/dist/elements/toggle.js +0 -246
  254. package/dist/elements/toolbar.d.ts +0 -12
  255. package/dist/elements/toolbar.js +0 -381
  256. package/dist/elements/tooltip.d.ts +0 -76
  257. package/dist/elements/tooltip.js +0 -510
  258. package/dist/elements/tree-model.d.ts +0 -19
  259. package/dist/elements/tree-model.js +0 -34
  260. package/dist/elements/tree.d.ts +0 -5
  261. package/dist/elements/tree.js +0 -273
  262. package/dist/elements/view-card.d.ts +0 -2
  263. package/dist/elements/view-card.js +0 -78
  264. package/dist/elements/virtual-list.d.ts +0 -41
  265. package/dist/elements/virtual-list.js +0 -369
  266. package/dist/elements.d.ts +0 -72
  267. package/dist/elements.js +0 -207
  268. package/dist/virtualizer-hooks.d.ts +0 -80
  269. package/dist/virtualizer-hooks.js +0 -253
  270. package/scripts/generate-token-index.mjs +0 -43
  271. package/scripts/sync-component-catalog-signatures.mjs +0 -55
  272. package/scripts/validate-component-catalog.mjs +0 -44
  273. package/skills/sharepoint-ui/SKILL.md +0 -12
  274. package/skills/sharepoint-ui/references/choosing-components.md +0 -20
  275. package/skills/sharepoint-ui/references/sharepoint-patterns.md +0 -17
  276. package/tokens.json +0 -3777
@@ -1,4 +0,0 @@
1
- export type ProgressBarColor = "brand" | "success" | "warning" | "error";
2
- export type ProgressBarShape = "rounded" | "square";
3
- export type ProgressBarThickness = "medium" | "large";
4
- export declare function defineProgressBar(): void;
@@ -1,82 +0,0 @@
1
- import { base } from "./shared.js";
2
- export function defineProgressBar() {
3
- if (customElements.get("spui-progress-bar"))
4
- return;
5
- class SpuiProgressBar extends HTMLElement {
6
- static observedAttributes = ["value", "max", "label", "aria-label", "aria-labelledby", "aria-describedby", "aria-valuetext", "color", "shape", "thickness"];
7
- generatedLabel;
8
- connectedCallback() {
9
- if (!this.shadowRoot) {
10
- const shadow = this.attachShadow({ mode: "open" });
11
- const progress = document.createElement("div");
12
- progress.className = "track";
13
- progress.setAttribute("aria-hidden", "true");
14
- progress.part.add("track");
15
- const bar = document.createElement("slot");
16
- bar.name = "bar";
17
- bar.append(Object.assign(document.createElement("span"), { className: "indicator" }));
18
- progress.append(bar);
19
- const motion = document.createElement("slot");
20
- motion.name = "indeterminateMotion";
21
- motion.setAttribute("aria-hidden", "true");
22
- progress.append(motion);
23
- const style = document.createElement("style");
24
- style.textContent = `${base}:host{display:block;min-width:0}.track{position:relative;display:block;width:100%;height:2px;overflow:hidden;border-radius:var(--spui-progress-radius,999px);background:var(--spui-progress-track,color-mix(in srgb,currentColor 10%,transparent))}.indicator{position:absolute;inset-block:0;inset-inline-start:0;width:100%;border-radius:inherit;background:var(--spui-progress-color,var(--spui-ui-accent,var(--spui-semantic-focus-border,#0f6cbd)));transform-origin:left center}:host([dir=rtl]) .indicator{transform-origin:right center}:host([data-determinate-transition]) .indicator,:host([data-determinate-transition]) slot[name=bar]::slotted([slot=bar]){transition:transform 300ms ease,width 300ms ease}:host([thickness=large]) .track{height:4px}:host([shape=square]){--spui-progress-radius:0px}:host([color=success]){--spui-progress-color:var(--spui-ui-success,#107c10)}:host([color=warning]){--spui-progress-color:var(--spui-ui-warning,#835b00)}:host([color=error]){--spui-progress-color:var(--spui-ui-danger,#b10e1c)}:host([data-indeterminate]) .indicator{width:33%;animation:spui-progress-indeterminate 3s linear infinite}:host([dir=rtl][data-indeterminate]) .indicator{animation-name:spui-progress-indeterminate-rtl}:host([data-indeterminate][data-custom-motion]) .indicator{display:none}slot[name=bar]::slotted([slot=bar]){width:var(--spui-progress-value,100%);height:100%;border-radius:inherit;background:var(--spui-progress-color,var(--spui-ui-accent,var(--spui-semantic-focus-border,#0f6cbd)))}:host([data-indeterminate]) slot[name=bar]::slotted([slot=bar]){width:33%;animation:spui-progress-indeterminate 3s linear infinite}:host([dir=rtl][data-indeterminate]) slot[name=bar]::slotted([slot=bar]){animation-name:spui-progress-indeterminate-rtl}slot[name=indeterminateMotion]::slotted(*){position:absolute;inset-block:0;inset-inline-start:0;width:33%;height:100%}:host([dir=rtl]) slot[name=indeterminateMotion]::slotted(*){inset-inline-start:auto;inset-inline-end:0}@keyframes spui-progress-indeterminate{from{transform:translateX(-100%)}to{transform:translateX(300%)}}@keyframes spui-progress-indeterminate-rtl{from{transform:translateX(100%)}to{transform:translateX(-300%)}}@media(prefers-reduced-motion:reduce){.indicator{transition:none}:host([data-indeterminate]) .indicator,:host([dir=rtl][data-indeterminate]) .indicator{width:100%;animation:spui-progress-pulse 3s linear infinite}:host([data-indeterminate]) slot[name=bar]::slotted([slot=bar]),:host([dir=rtl][data-indeterminate]) slot[name=bar]::slotted([slot=bar]){width:100%;animation:spui-progress-pulse 3s linear infinite}}@keyframes spui-progress-pulse{0%,100%{opacity:.2}50%{opacity:1}}@media(forced-colors:active){.track{forced-color-adjust:none;background:Canvas;border:1px solid CanvasText}.indicator,slot[name=bar]::slotted([slot=bar]){background:Highlight}}`;
25
- style.textContent += `:host(:not([color])),:host([color=brand]){--spui-progress-color:color-mix(in srgb,var(--spui-ui-accent,#0f6cbd) 45%,currentColor 55%)}:host([color=success]){--spui-progress-color:color-mix(in srgb,var(--spui-ui-success,#107c10) 45%,currentColor 55%)}:host([color=warning]){--spui-progress-color:color-mix(in srgb,var(--spui-ui-warning,#835b00) 45%,currentColor 55%)}:host([color=error]){--spui-progress-color:color-mix(in srgb,var(--spui-ui-danger,#b10e1c) 45%,currentColor 55%)}`;
26
- shadow.append(style, progress);
27
- progress.querySelectorAll("slot").forEach(slot => slot.addEventListener("slotchange", () => this.sync()));
28
- }
29
- this.sync();
30
- }
31
- attributeChangedCallback() { if (this.isConnected)
32
- this.sync(); }
33
- sync() {
34
- const progress = this.shadowRoot?.querySelector(".track");
35
- if (!progress)
36
- return;
37
- this.toggleAttribute("data-custom-motion", (this.shadowRoot?.querySelector('slot[name="indeterminateMotion"]')?.assignedElements().length ?? 0) > 0);
38
- this.setAttribute("role", "progressbar");
39
- const max = Number(this.getAttribute("max"));
40
- const normalizedMax = Number.isFinite(max) && max > 0 ? max : 1;
41
- const raw = this.getAttribute("value");
42
- const value = raw === null ? null : Number(raw);
43
- this.setAttribute("aria-valuemin", "0");
44
- this.setAttribute("aria-valuemax", String(normalizedMax));
45
- if (value === null || !Number.isFinite(value)) {
46
- this.setAttribute("data-indeterminate", "");
47
- this.removeAttribute("data-determinate-transition");
48
- this.removeAttribute("aria-valuenow");
49
- const indicator = this.shadowRoot?.querySelector(".indicator");
50
- if (indicator)
51
- indicator.style.removeProperty("transform");
52
- const slottedBar = this.shadowRoot?.querySelector("slot[name=bar]")?.assignedElements()[0];
53
- slottedBar?.style.removeProperty("--spui-progress-value");
54
- }
55
- else {
56
- this.removeAttribute("data-indeterminate");
57
- const bounded = Math.min(normalizedMax, Math.max(0, value));
58
- this.toggleAttribute("data-determinate-transition", bounded / normalizedMax > 0.01);
59
- this.setAttribute("aria-valuenow", String(bounded));
60
- const indicator = this.shadowRoot?.querySelector(".indicator");
61
- if (indicator)
62
- indicator.style.transform = `scaleX(${bounded / normalizedMax})`;
63
- const slottedBar = this.shadowRoot?.querySelector("slot[name=bar]")?.assignedElements()[0];
64
- slottedBar?.style.setProperty("--spui-progress-value", `${bounded / normalizedMax * 100}%`);
65
- }
66
- if (this.hasAttribute("aria-labelledby")) {
67
- if (this.generatedLabel !== undefined && this.getAttribute("aria-label") === this.generatedLabel)
68
- this.removeAttribute("aria-label");
69
- this.generatedLabel = undefined;
70
- }
71
- else if (this.getAttribute("aria-label") === null || this.getAttribute("aria-label") === this.generatedLabel) {
72
- const label = this.getAttribute("label") ?? "Loading";
73
- this.generatedLabel = label;
74
- if (this.getAttribute("aria-label") !== label)
75
- this.setAttribute("aria-label", label);
76
- }
77
- else
78
- this.generatedLabel = undefined;
79
- }
80
- }
81
- customElements.define("spui-progress-bar", SpuiProgressBar);
82
- }
@@ -1 +0,0 @@
1
- export declare function defineRadioGroup(): void;
@@ -1,303 +0,0 @@
1
- import { base, stopHostAccessibleNameSync, syncHostAccessibleName } from "./shared.js";
2
- function radioOptionLabel(option, fallback) {
3
- const text = [...option.childNodes].filter(node => !(node instanceof Element && ["input", "indicator", "label"].includes(node.getAttribute("slot") ?? ""))).map(node => node.textContent ?? "").join("").trim();
4
- return option.getAttribute("label") ?? (text || fallback);
5
- }
6
- const radioRootInputAttributes = new WeakMap();
7
- const radioManagedInputAttributes = new Set(["checked", "disabled", "hidden", "label", "label-position", "name", "required", "slot", "type", "value"]);
8
- function isForwardableRadioInputAttribute(name) {
9
- return !radioManagedInputAttributes.has(name) && !name.startsWith("on");
10
- }
11
- function syncRadioRootProps(option, input, label) {
12
- label.className = option.getAttribute("class") ?? option.getAttribute("classname") ?? "";
13
- label.style.cssText = option.getAttribute("style") ?? "";
14
- for (const name of radioRootInputAttributes.get(input) ?? [])
15
- input.removeAttribute(name);
16
- const applied = new Set();
17
- for (const attribute of [...option.attributes]) {
18
- if (attribute.name !== "class" && attribute.name !== "style" && isForwardableRadioInputAttribute(attribute.name)) {
19
- input.setAttribute(attribute.name, attribute.value);
20
- applied.add(attribute.name);
21
- }
22
- }
23
- radioRootInputAttributes.set(input, applied);
24
- }
25
- const radioInputSlotAttributes = new WeakMap();
26
- function syncRadioInputSlot(source, input) {
27
- for (const name of radioInputSlotAttributes.get(input) ?? [])
28
- input.removeAttribute(name);
29
- const applied = new Set();
30
- if (!source) {
31
- radioInputSlotAttributes.set(input, applied);
32
- return;
33
- }
34
- for (const attribute of [...source.attributes]) {
35
- if (isForwardableRadioInputAttribute(attribute.name)) {
36
- input.setAttribute(attribute.name, attribute.value);
37
- applied.add(attribute.name);
38
- }
39
- }
40
- radioInputSlotAttributes.set(input, applied);
41
- }
42
- function createRadioIndicator(source) {
43
- const indicator = source?.cloneNode(true) ?? document.createElement("span");
44
- indicator.removeAttribute("slot");
45
- indicator.removeAttribute("hidden");
46
- indicator.setAttribute("aria-hidden", "true");
47
- indicator.classList.add("radio-indicator");
48
- indicator.part.add("indicator");
49
- return indicator;
50
- }
51
- function createRadioLabel(source, text) {
52
- const label = document.createElement("span");
53
- label.dataset.radioLabel = "";
54
- if (source) {
55
- const content = source.cloneNode(true);
56
- content.removeAttribute("slot");
57
- content.removeAttribute("hidden");
58
- label.append(content);
59
- }
60
- else
61
- label.textContent = text;
62
- return label;
63
- }
64
- export function defineRadioGroup() {
65
- if (customElements.get("spui-radio-group"))
66
- return;
67
- class SpuiRadioGroup extends HTMLElement {
68
- static formAssociated = true;
69
- static observedAttributes = ["label", "value", "default-value", "disabled", "required", "name", "orientation", "layout", "aria-label", "aria-labelledby", "aria-description", "aria-describedby", "aria-invalid"];
70
- internals;
71
- observer;
72
- currentValue;
73
- formDisabledValue = false;
74
- constructor() {
75
- super();
76
- try {
77
- this.internals = this.attachInternals();
78
- }
79
- catch { /* Keep the controls usable where custom form association is unavailable. */ }
80
- }
81
- get form() { return this.internals?.form ?? null; }
82
- get validity() { return this.internals?.validity; }
83
- get validationMessage() { return this.internals?.validationMessage ?? ""; }
84
- get willValidate() { return this.internals?.willValidate ?? false; }
85
- checkValidity() { return this.internals?.checkValidity() ?? true; }
86
- reportValidity() { return this.internals?.reportValidity() ?? true; }
87
- connectedCallback() {
88
- this.render();
89
- this.observer = new MutationObserver(records => {
90
- let optionsChanged = false;
91
- const textChanged = new Set();
92
- for (const record of records) {
93
- if (record.type === "attributes") {
94
- const option = record.target instanceof Element ? record.target.closest("spui-radio-option") : null;
95
- if (option?.parentElement === this && record.target === option && ["value", "disabled", "checked"].includes(record.attributeName ?? ""))
96
- optionsChanged = true;
97
- else if (option?.parentElement === this)
98
- textChanged.add(option);
99
- else if (record.target === this)
100
- optionsChanged = true;
101
- continue;
102
- }
103
- const target = record.target instanceof Element ? record.target : record.target.parentElement;
104
- const option = target?.closest("spui-radio-option");
105
- if (option?.parentElement === this)
106
- textChanged.add(option);
107
- else if (record.target === this)
108
- optionsChanged = true;
109
- }
110
- if (optionsChanged)
111
- this.syncOptions();
112
- else
113
- for (const option of textChanged)
114
- this.syncOptionLabel(option);
115
- });
116
- this.observer.observe(this, { childList: true, subtree: true, characterData: true, attributes: true });
117
- }
118
- disconnectedCallback() { this.observer?.disconnect(); stopHostAccessibleNameSync(this); }
119
- attributeChangedCallback(name, _oldValue, value) {
120
- if (!this.isConnected)
121
- return;
122
- const fieldset = this.shadowRoot?.querySelector("fieldset");
123
- if (!fieldset)
124
- return;
125
- if (name === "label") {
126
- const legend = this.shadowRoot?.querySelector("legend");
127
- if (legend)
128
- legend.textContent = value ?? "";
129
- }
130
- if (name === "disabled")
131
- fieldset.disabled = this.formDisabledValue || this.hasAttribute("disabled");
132
- if (name === "orientation" || name === "layout")
133
- fieldset.dataset.layout = this.getLayout();
134
- if (name === "aria-label" || name === "aria-labelledby" || name === "aria-description" || name === "aria-describedby" || name === "aria-invalid") {
135
- const value = this.getAttribute(name);
136
- if (value === null)
137
- fieldset.removeAttribute(name);
138
- else
139
- fieldset.setAttribute(name, value);
140
- syncHostAccessibleName(this, fieldset);
141
- }
142
- if (name === "value")
143
- this.currentValue = value ?? "";
144
- for (const radio of fieldset.querySelectorAll('input[type="radio"]')) {
145
- if (name === "name")
146
- radio.name = value ?? (this.id || "spui-radio-group");
147
- if (name === "required")
148
- radio.required = this.hasAttribute("required");
149
- if (name === "value")
150
- radio.checked = radio.value === (this.currentValue ?? "");
151
- if (name === "disabled")
152
- radio.disabled = this.hasAttribute("disabled") || radio.dataset.optionDisabled === "true";
153
- }
154
- this.syncFormValue();
155
- }
156
- get value() { return this.currentValue ?? this.getAttribute("value") ?? this.shadowRoot?.querySelector('input[type="radio"]:checked')?.value ?? ""; }
157
- set value(value) {
158
- this.currentValue = value;
159
- const fieldset = this.shadowRoot?.querySelector("fieldset");
160
- if (fieldset) {
161
- for (const radio of fieldset.querySelectorAll('input[type="radio"]'))
162
- radio.checked = radio.value === value;
163
- this.syncFormValue();
164
- }
165
- }
166
- get defaultValue() { return this.getAttribute("default-value") ?? this.querySelector(':scope > spui-radio-option[checked]')?.getAttribute("value") ?? ""; }
167
- set defaultValue(value) { this.setAttribute("default-value", value); }
168
- formDisabledCallback(disabled) {
169
- this.formDisabledValue = disabled;
170
- for (const radio of this.shadowRoot?.querySelectorAll('input[type="radio"]') ?? [])
171
- radio.disabled = disabled || this.hasAttribute("disabled") || radio.dataset.optionDisabled === "true";
172
- this.syncFormValue();
173
- }
174
- formResetCallback() {
175
- const options = [...this.querySelectorAll(":scope > spui-radio-option")];
176
- const initial = options.find(option => option.hasAttribute("checked"))?.getAttribute("value") ?? "";
177
- this.value = this.getAttribute("value") ?? this.getAttribute("default-value") ?? initial;
178
- }
179
- formStateRestoreCallback(state) { if (typeof state === "string")
180
- this.value = state; }
181
- syncFormValue() {
182
- const checked = this.shadowRoot?.querySelector('input[type="radio"]:checked');
183
- const disabled = this.formDisabledValue || this.hasAttribute("disabled");
184
- const value = checked?.value ?? "";
185
- for (const label of this.shadowRoot?.querySelectorAll("fieldset > label") ?? [])
186
- label.dataset.checked = String(Boolean(label.querySelector("input")?.checked));
187
- this.internals?.setFormValue(checked && !disabled ? value : null);
188
- try {
189
- const anchor = checked ?? this.shadowRoot?.querySelector('input[type="radio"]');
190
- const missing = !disabled && this.hasAttribute("required") && !checked;
191
- this.internals?.setValidity(missing ? { valueMissing: true } : {}, missing ? anchor?.validationMessage ?? "" : "", missing ? anchor ?? undefined : undefined);
192
- }
193
- catch { /* Some engines do not accept shadow descendants as validity anchors. */ }
194
- }
195
- syncOptionLabel(option) {
196
- const index = [...this.querySelectorAll(":scope > spui-radio-option")].indexOf(option);
197
- const label = this.shadowRoot?.querySelectorAll("fieldset > label")[index];
198
- const input = label?.querySelector("input");
199
- const text = label?.querySelector(":scope > [data-radio-label]");
200
- if (input) {
201
- syncRadioRootProps(option, input, label);
202
- syncRadioInputSlot(option.querySelector(":scope > input[slot=input]"), input);
203
- const sourceIndicator = option.querySelector(":scope > [slot=indicator]");
204
- const currentIndicator = label?.querySelector(".radio-indicator");
205
- if (currentIndicator && sourceIndicator)
206
- currentIndicator.replaceWith(createRadioIndicator(sourceIndicator));
207
- else if (currentIndicator && !sourceIndicator)
208
- currentIndicator.remove();
209
- else if (label && sourceIndicator)
210
- label.insertBefore(createRadioIndicator(sourceIndicator), text ?? null);
211
- label?.toggleAttribute("data-custom-indicator", Boolean(sourceIndicator));
212
- input.dataset.customIndicator = String(Boolean(sourceIndicator));
213
- if (label)
214
- label.dataset.labelPosition = option.getAttribute("label-position") ?? (this.getLayout() === "horizontal-stacked" ? "below" : "after");
215
- }
216
- if (label && input) {
217
- const nextText = createRadioLabel(option.querySelector(":scope > [slot=label]"), radioOptionLabel(option, input.value));
218
- if (text)
219
- text.replaceWith(nextText);
220
- else
221
- label.append(nextText);
222
- }
223
- }
224
- syncOptions() {
225
- const fieldset = this.shadowRoot?.querySelector("fieldset");
226
- if (!fieldset)
227
- return;
228
- const current = this.currentValue ?? this.getAttribute("value") ?? this.getAttribute("default-value") ?? fieldset.querySelector('input[type="radio"]:checked')?.value ?? "";
229
- const options = [...this.querySelectorAll(":scope > spui-radio-option")];
230
- const radios = options.map((option, index) => this.createRadio(option, index));
231
- fieldset.replaceChildren(fieldset.querySelector("legend"), ...radios);
232
- const checked = fieldset.querySelector(`input[type="radio"][value="${CSS.escape(current)}"]`);
233
- if (checked)
234
- checked.checked = true;
235
- this.syncFormValue();
236
- }
237
- createRadio(option, index) {
238
- const label = document.createElement("label");
239
- label.part.add("option");
240
- label.dataset.labelPosition = option.getAttribute("label-position") ?? (this.getLayout() === "horizontal-stacked" ? "below" : "after");
241
- const inputSource = option.querySelector(":scope > input[slot=input]");
242
- const input = (inputSource?.cloneNode(false) ?? document.createElement("input"));
243
- input.removeAttribute("slot");
244
- input.removeAttribute("hidden");
245
- input.type = "radio";
246
- input.name = this.getAttribute("name") ?? (this.id || "spui-radio-group");
247
- input.value = option.getAttribute("value") ?? String(index);
248
- input.disabled = this.formDisabledValue || this.hasAttribute("disabled") || option.hasAttribute("disabled");
249
- input.required = this.hasAttribute("required");
250
- input.dataset.optionDisabled = String(option.hasAttribute("disabled"));
251
- input.part.add("control");
252
- syncRadioRootProps(option, input, label);
253
- syncRadioInputSlot(inputSource, input);
254
- const text = createRadioLabel(option.querySelector(":scope > [slot=label]"), radioOptionLabel(option, input.value));
255
- const indicatorSource = option.querySelector(":scope > [slot=indicator]");
256
- label.toggleAttribute("data-custom-indicator", Boolean(indicatorSource));
257
- input.dataset.customIndicator = String(Boolean(indicatorSource));
258
- label.append(input);
259
- if (indicatorSource)
260
- label.append(createRadioIndicator(indicatorSource));
261
- label.append(text);
262
- input.addEventListener("change", event => {
263
- if (!input.checked)
264
- return;
265
- this.currentValue = input.value;
266
- this.syncFormValue();
267
- option.dispatchEvent(new CustomEvent("spui-radio-change", { detail: { value: input.value, sourceEvent: event }, bubbles: true, composed: true }));
268
- this.dispatchEvent(new CustomEvent("spui-change", { detail: { value: input.value, sourceEvent: event }, bubbles: true, composed: true }));
269
- });
270
- return label;
271
- }
272
- render() {
273
- const shadow = this.shadowRoot ?? this.attachShadow({ mode: "open" });
274
- const fieldset = document.createElement("fieldset");
275
- fieldset.disabled = this.formDisabledValue || this.hasAttribute("disabled");
276
- fieldset.dataset.layout = this.getLayout();
277
- for (const name of ["aria-label", "aria-labelledby", "aria-description", "aria-describedby", "aria-invalid"]) {
278
- const value = this.getAttribute(name);
279
- if (value !== null)
280
- fieldset.setAttribute(name, value);
281
- }
282
- const legend = document.createElement("legend");
283
- legend.textContent = this.getAttribute("label") ?? "";
284
- legend.part.add("label");
285
- const options = [...this.querySelectorAll(":scope > spui-radio-option")];
286
- const radios = options.map((option, index) => this.createRadio(option, index));
287
- const initial = this.currentValue ?? this.getAttribute("value") ?? this.getAttribute("default-value") ?? options.find(option => option.hasAttribute("checked"))?.getAttribute("value") ?? "";
288
- const selected = radios.find(label => label.querySelector("input")?.value === initial)?.querySelector("input");
289
- if (selected)
290
- selected.checked = true;
291
- const style = document.createElement("style");
292
- style.textContent = `${base}:host{display:block}fieldset{display:flex;flex-direction:column;gap:var(--spui-control-gap,8px);min-width:0;margin:0;padding:0;border:0}fieldset[data-layout="horizontal"],fieldset[data-layout="horizontal-stacked"]{flex-direction:row;flex-wrap:wrap;column-gap:var(--spui-control-gap,16px)}label[data-label-position="below"]{flex-direction:column;align-items:flex-start;justify-content:center}legend{margin-bottom:var(--spui-control-gap,8px);padding:0;color:var(--spui-ui-muted,var(--spui-semantic-body-text,inherit));font-size:14px;font-weight:600}label{display:inline-flex;align-items:center;gap:8px;min-height:var(--spui-control-height,32px);color:var(--spui-ui-text,var(--spui-semantic-body-text,inherit));cursor:pointer}input{width:18px;height:18px;margin:0;accent-color:var(--spui-ui-accent,var(--spui-semantic-input-background-checked,var(--colorBrandBackground,#0f6cbd)));cursor:pointer}input:focus-visible{outline:2px solid var(--spui-focus-ring,#005a9e);outline-offset:2px}input:disabled{cursor:not-allowed}label:has(input:disabled){opacity:.55;cursor:not-allowed}@media(forced-colors:active){input{accent-color:Highlight}input:focus-visible{outline-color:Highlight}}`;
293
- style.textContent += `.radio-indicator[hidden]{display:none!important}.radio-indicator{box-sizing:border-box;display:inline-grid;place-items:center;flex:none;width:18px;height:18px;border:1px solid var(--spui-ui-stroke,var(--spui-semantic-body-divider,#8a8886));border-radius:50%;color:var(--spui-ui-accent,var(--spui-semantic-accent,#0f6cbd));background:var(--spui-ui-surface,var(--spui-semantic-body-background,#fff))}.radio-indicator::after{content:"";width:10px;height:10px;border-radius:50%;background:currentColor;transform:scale(0);transition:transform var(--spui-motion-duration-fast,120ms) var(--spui-motion-easing-standard,ease)}label[data-checked=true] .radio-indicator{border-color:currentColor}label[data-checked=true] .radio-indicator::after{transform:scale(1)}input[data-custom-indicator=true]{position:absolute;inset-inline-start:0;inset-block-start:calc(50% - 9px);z-index:1;opacity:0}input[data-custom-indicator=true]:focus-visible{outline:0}input[data-custom-indicator=true]:focus-visible+.radio-indicator{outline:2px solid var(--spui-focus-ring,#005a9e);outline-offset:2px}@media(prefers-reduced-motion:reduce){.radio-indicator::after{transition:none}}@media(forced-colors:active){.radio-indicator{border-color:ButtonText;background:Canvas;color:Highlight}.radio-indicator::after{background:Highlight}}`;
294
- fieldset.append(legend, ...radios);
295
- fieldset.addEventListener("change", () => this.syncFormValue());
296
- shadow.replaceChildren(style, fieldset);
297
- syncHostAccessibleName(this, fieldset);
298
- this.syncFormValue();
299
- }
300
- getLayout() { return this.getAttribute("layout") ?? this.getAttribute("orientation") ?? "vertical"; }
301
- }
302
- customElements.define("spui-radio-group", SpuiRadioGroup);
303
- }
@@ -1,2 +0,0 @@
1
- export declare function defineRatingItem(): void;
2
- export declare function defineRatingDisplay(): void;
@@ -1,125 +0,0 @@
1
- import { base } from "./shared.js";
2
- function ratingValue(element) {
3
- const parent = element.closest("spui-rating-display");
4
- const maxRaw = Number(parent?.getAttribute("max") ?? element.getAttribute("max") ?? 5);
5
- const max = Number.isInteger(maxRaw) && maxRaw > 1 ? Math.min(20, maxRaw) : 5;
6
- const valueRaw = Number(parent?.getAttribute("value") ?? element.getAttribute("rating") ?? 0);
7
- return { value: Number.isFinite(valueRaw) ? Math.max(0, Math.min(max, valueRaw)) : 0, max };
8
- }
9
- export function defineRatingItem() {
10
- if (customElements.get("spui-rating-item"))
11
- return;
12
- class SpuiRatingItem extends HTMLElement {
13
- static observedAttributes = ["value", "rating", "max", "size", "color"];
14
- connectedCallback() { this.render(); }
15
- attributeChangedCallback() { if (this.isConnected)
16
- this.render(); }
17
- render() {
18
- const { value: rating } = ratingValue(this);
19
- const raw = Number(this.getAttribute("value") ?? 1);
20
- const itemValue = Number.isInteger(raw) && raw > 0 ? raw : 1;
21
- const amount = Math.max(0, Math.min(1, rating - itemValue + 1));
22
- this.setAttribute("aria-hidden", "true");
23
- const shadow = this.shadowRoot ?? this.attachShadow({ mode: "open" });
24
- const style = document.createElement("style");
25
- style.textContent = `${base}:host{position:relative;display:inline-block;flex:none;width:var(--spui-rating-size,24px);height:var(--spui-rating-size,24px);font-size:var(--spui-rating-size,24px);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}.outline,.filled{position:absolute;inset:0;display:block;overflow:hidden;white-space:nowrap}.outline slot::slotted(*),.filled slot::slotted(*){font:inherit}.outline slot::slotted(*){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%))}.filled{inset-inline-start:0;width:${amount * 100}%;color:var(--spui-rating-color,var(--spui-ui-accent,#0078d4))}.filled slot::slotted(*){color:var(--spui-rating-color,var(--spui-ui-accent,#0078d4))}:host(:not([color])),:host([color=neutral]){--spui-rating-color:var(--spui-ui-text,var(--spui-semantic-body-text,currentColor))}: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([size=small]){--spui-rating-size:18px}:host([size=medium]){--spui-rating-size:24px}:host([size=large]){--spui-rating-size:30px}:host([size=extra-large]){--spui-rating-size:36px}@media(forced-colors:active){:host{color:CanvasText}.filled{color:Highlight}}`;
26
- const outline = document.createElement("span");
27
- outline.className = "outline";
28
- outline.part.add("unselected-icon");
29
- const outlineSlot = document.createElement("slot");
30
- outlineSlot.name = "unselected-icon";
31
- outlineSlot.textContent = "☆";
32
- outline.append(outlineSlot);
33
- const filled = document.createElement("span");
34
- filled.className = "filled";
35
- filled.part.add("selected-icon");
36
- const filledSlot = document.createElement("slot");
37
- filledSlot.name = "selected-icon";
38
- filledSlot.textContent = "★";
39
- filled.append(filledSlot);
40
- shadow.replaceChildren(style, outline, filled);
41
- }
42
- }
43
- customElements.define("spui-rating-item", SpuiRatingItem);
44
- }
45
- export function defineRatingDisplay() {
46
- defineRatingItem();
47
- if (customElements.get("spui-rating-display"))
48
- return;
49
- class SpuiRatingDisplay extends HTMLElement {
50
- static observedAttributes = ["value", "max", "count", "compact", "size", "color", "aria-label", "lang"];
51
- connectedCallback() { this.render(); }
52
- attributeChangedCallback() { if (this.isConnected)
53
- this.render(); }
54
- render() {
55
- const maxRaw = Number(this.getAttribute("max") ?? 5);
56
- const max = Number.isInteger(maxRaw) && maxRaw > 1 ? Math.min(20, maxRaw) : 5;
57
- const hasValue = this.hasAttribute("value");
58
- const valueRaw = Number(this.getAttribute("value") ?? 0);
59
- const value = Number.isFinite(valueRaw) ? Math.max(0, Math.min(max, valueRaw)) : 0;
60
- const countRaw = this.getAttribute("count");
61
- const explicitLabel = this.getAttribute("aria-label");
62
- const shadow = this.shadowRoot ?? this.attachShadow({ mode: "open" });
63
- const style = document.createElement("style");
64
- style.textContent = `${base}:host{display:inline-flex;align-items:center;gap:6px;min-width:0;color:var(--spui-ui-text,var(--spui-semantic-body-text,inherit));font-family:var(--spui-font-family,inherit)}.root{display:inline-flex;align-items:center;gap:6px}.items{display:inline-flex;align-items:center;gap:2px}.value-text,.count-text{color:var(--spui-ui-muted,var(--spui-semantic-body-subtext,#616161));font-size:var(--spui-rating-label-size,14px);font-variant-numeric:tabular-nums}.count-text:before{content:"("}.count-text:after{content:")"}:host([compact]) .items{gap:0}@media(forced-colors:active){:host{color:CanvasText}}`;
65
- const root = document.createElement("span");
66
- root.className = "root";
67
- root.setAttribute("role", "img");
68
- root.setAttribute("aria-label", explicitLabel || `${value} of ${max}${countRaw === null ? "" : `, ${Number(countRaw).toLocaleString(this.lang || undefined)} ratings`}`);
69
- const items = document.createElement("span");
70
- items.className = "items";
71
- items.part.add("items");
72
- const slot = document.createElement("slot");
73
- const hasItems = [...this.children].some(child => child.localName === "spui-rating-item");
74
- if (!hasItems) {
75
- const itemCount = this.hasAttribute("compact") ? 1 : max;
76
- for (let index = 1; index <= itemCount; index++) {
77
- const item = document.createElement("spui-rating-item");
78
- item.setAttribute("value", String(index));
79
- item.setAttribute("rating", String(value));
80
- item.setAttribute("max", String(max));
81
- if (this.hasAttribute("size"))
82
- item.setAttribute("size", this.getAttribute("size"));
83
- if (this.hasAttribute("color"))
84
- item.setAttribute("color", this.getAttribute("color"));
85
- items.append(item);
86
- }
87
- }
88
- else {
89
- slot.addEventListener("slotchange", () => this.syncItems(slot, value, max));
90
- items.append(slot);
91
- }
92
- const valueText = document.createElement("span");
93
- valueText.className = "value-text";
94
- valueText.part.add("value-text");
95
- const valueSlot = document.createElement("slot");
96
- valueSlot.name = "value-text";
97
- valueSlot.textContent = String(value);
98
- valueText.append(valueSlot);
99
- const countText = document.createElement("span");
100
- countText.className = "count-text";
101
- countText.part.add("count-text");
102
- const countSlot = document.createElement("slot");
103
- countSlot.name = "count-text";
104
- countSlot.textContent = countRaw === null ? "" : Number(countRaw).toLocaleString(this.lang || undefined);
105
- countText.append(countSlot);
106
- if (!hasValue)
107
- valueText.hidden = true;
108
- if (countRaw === null)
109
- countText.hidden = true;
110
- root.append(items, valueText, countText);
111
- shadow.replaceChildren(style, root);
112
- if (hasItems)
113
- this.syncItems(slot, value, max);
114
- }
115
- syncItems(slot, value, max) {
116
- for (const item of slot.assignedElements().filter((node) => node.localName === "spui-rating-item")) {
117
- item.setAttribute("rating", String(value));
118
- item.setAttribute("max", String(max));
119
- for (const name of ["size", "color"])
120
- this.hasAttribute(name) ? item.setAttribute(name, this.getAttribute(name)) : item.removeAttribute(name);
121
- }
122
- }
123
- }
124
- customElements.define("spui-rating-display", SpuiRatingDisplay);
125
- }
@@ -1,2 +0,0 @@
1
- /** Selectable, form-associated star rating with optional half steps. */
2
- export declare function defineRating(): void;