@spfx-fast/sharepoint-ui 0.4.3 → 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 (282) hide show
  1. package/QUICKSTART.md +13 -128
  2. package/README.md +19 -26
  3. package/components.json +240 -5834
  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 -78
  55. package/dist/index.js +60 -68
  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 -4715
  89. package/dist/react.js +1 -7097
  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 -175
  117. package/dist/theme.js +36 -239
  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 +14 -46
  130. package/src/theme.css +125 -0
  131. package/AGENTS.md +0 -231
  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 -86
  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 -1115
  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 -120
  165. package/dist/elements/data-grid-model.js +0 -294
  166. package/dist/elements/data-grid.d.ts +0 -30
  167. package/dist/elements/data-grid.js +0 -1576
  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 -36
  183. package/dist/elements/floating-position.js +0 -92
  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 -327
  200. package/dist/elements/nav.d.ts +0 -32
  201. package/dist/elements/nav.js +0 -794
  202. package/dist/elements/overflow.d.ts +0 -10
  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 -32
  217. package/dist/elements/rich-text-editor.js +0 -1367
  218. package/dist/elements/search.d.ts +0 -3
  219. package/dist/elements/search.js +0 -200
  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 -22
  223. package/dist/elements/shared.js +0 -409
  224. package/dist/elements/sharepoint-field-basic-controls.d.ts +0 -1
  225. package/dist/elements/sharepoint-field-basic-controls.js +0 -14
  226. package/dist/elements/sharepoint-fields.d.ts +0 -29
  227. package/dist/elements/sharepoint-fields.js +0 -460
  228. package/dist/elements/skeleton.d.ts +0 -6
  229. package/dist/elements/skeleton.js +0 -91
  230. package/dist/elements/slider.d.ts +0 -1
  231. package/dist/elements/slider.js +0 -248
  232. package/dist/elements/spin-button.d.ts +0 -7
  233. package/dist/elements/spin-button.js +0 -499
  234. package/dist/elements/spinner.d.ts +0 -4
  235. package/dist/elements/spinner.js +0 -124
  236. package/dist/elements/swatch-picker.d.ts +0 -5
  237. package/dist/elements/swatch-picker.js +0 -363
  238. package/dist/elements/table.d.ts +0 -21
  239. package/dist/elements/table.js +0 -261
  240. package/dist/elements/tabs.d.ts +0 -1
  241. package/dist/elements/tabs.js +0 -276
  242. package/dist/elements/tag-picker.d.ts +0 -29
  243. package/dist/elements/tag-picker.js +0 -715
  244. package/dist/elements/tags.d.ts +0 -21
  245. package/dist/elements/tags.js +0 -421
  246. package/dist/elements/teaching-popover.d.ts +0 -32
  247. package/dist/elements/teaching-popover.js +0 -412
  248. package/dist/elements/text.d.ts +0 -9
  249. package/dist/elements/text.js +0 -75
  250. package/dist/elements/textarea.d.ts +0 -1
  251. package/dist/elements/textarea.js +0 -182
  252. package/dist/elements/toast.d.ts +0 -25
  253. package/dist/elements/toast.js +0 -337
  254. package/dist/elements/toaster.d.ts +0 -6
  255. package/dist/elements/toaster.js +0 -357
  256. package/dist/elements/toggle.d.ts +0 -2
  257. package/dist/elements/toggle.js +0 -246
  258. package/dist/elements/toolbar.d.ts +0 -12
  259. package/dist/elements/toolbar.js +0 -381
  260. package/dist/elements/tooltip.d.ts +0 -76
  261. package/dist/elements/tooltip.js +0 -527
  262. package/dist/elements/tree-model.d.ts +0 -19
  263. package/dist/elements/tree-model.js +0 -34
  264. package/dist/elements/tree.d.ts +0 -5
  265. package/dist/elements/tree.js +0 -273
  266. package/dist/elements/view-card.d.ts +0 -2
  267. package/dist/elements/view-card.js +0 -78
  268. package/dist/elements/virtual-list.d.ts +0 -41
  269. package/dist/elements/virtual-list.js +0 -369
  270. package/dist/elements.d.ts +0 -73
  271. package/dist/elements.js +0 -210
  272. package/dist/sharepoint-fields.d.ts +0 -135
  273. package/dist/sharepoint-fields.js +0 -402
  274. package/dist/virtualizer-hooks.d.ts +0 -80
  275. package/dist/virtualizer-hooks.js +0 -253
  276. package/scripts/generate-token-index.mjs +0 -43
  277. package/scripts/sync-component-catalog-signatures.mjs +0 -55
  278. package/scripts/validate-component-catalog.mjs +0 -44
  279. package/skills/sharepoint-ui/SKILL.md +0 -12
  280. package/skills/sharepoint-ui/references/choosing-components.md +0 -20
  281. package/skills/sharepoint-ui/references/sharepoint-patterns.md +0 -17
  282. package/tokens.json +0 -3777
@@ -1,297 +0,0 @@
1
- import { base } from "./shared.js";
2
- const parseValues = (value) => {
3
- if (!value)
4
- return [];
5
- try {
6
- const parsed = JSON.parse(value);
7
- return Array.isArray(parsed) ? parsed.filter((item) => typeof item === "string" || (typeof item === "number" && Number.isFinite(item))) : [];
8
- }
9
- catch {
10
- return [];
11
- }
12
- };
13
- export function defineListItem() {
14
- if (customElements.get("spui-list-item"))
15
- return;
16
- class SpuiListItem extends HTMLElement {
17
- static observedAttributes = ["value", "disabled-selection", "has-action"];
18
- generatedValue = `spui-list-item-${crypto.randomUUID()}`;
19
- itemValue;
20
- connectedCallback() { this.render(); this.closest("spui-list")?.dispatchEvent(new Event("spui-list-items-change")); }
21
- disconnectedCallback() { this.closest("spui-list")?.dispatchEvent(new Event("spui-list-items-change")); }
22
- attributeChangedCallback() { if (this.isConnected)
23
- this.closest("spui-list")?.dispatchEvent(new Event("spui-list-items-change")); }
24
- get value() { const attr = this.getAttribute("value"); return this.itemValue ?? attr ?? (this.id || this.generatedValue); }
25
- set value(value) { this.itemValue = value; this.setAttribute("value", String(value)); }
26
- get disabledSelection() { return this.hasAttribute("disabled-selection"); }
27
- set disabledSelection(value) { this.toggleAttribute("disabled-selection", value); }
28
- render() {
29
- const shadow = this.shadowRoot ?? this.attachShadow({ mode: "open" });
30
- const style = document.createElement("style");
31
- style.textContent = `${base}:host{box-sizing:border-box;position:relative;display:flex;align-items:center;gap:8px;min-width:0;min-height:36px;padding:6px 10px;border-radius:var(--spui-list-item-radius,var(--spui-control-radius,4px));outline:none;color:var(--spui-ui-text,var(--colorNeutralForeground1,#242424));cursor:default}:host(:focus-visible){outline:2px solid var(--spui-focus-ring,var(--spui-ui-accent,#0078d4));outline-offset:-2px}:host(:hover){background:var(--spui-list-row-hover,var(--spui-ui-surface-hover,#f5f5f5))}:host([aria-selected=true]){background:var(--spui-list-selected-background,color-mix(in srgb,var(--spui-ui-accent,#0078d4) 12%,var(--spui-ui-surface,#fff)))}:host([aria-selected=true]) .checkmark{opacity:1}:host([aria-disabled=true]){opacity:.55}.content{display:flex;align-items:center;gap:inherit;min-width:0;flex:1}.checkmark{display:inline-flex;align-items:center;justify-content:center;flex:none;width:16px;height:16px;opacity:0;color:var(--spui-ui-accent,#0078d4);font-size:14px}.checkmark::before{content:"✓"}@media(forced-colors:active){:host([aria-selected=true]){outline:1px solid Highlight;background:Canvas;color:CanvasText}.checkmark{color:Highlight}}`;
32
- const checkmark = document.createElement("span");
33
- checkmark.className = "checkmark";
34
- checkmark.part.add("checkmark");
35
- checkmark.setAttribute("aria-hidden", "true");
36
- checkmark.append(document.createElement("slot"));
37
- const customCheckmark = checkmark.querySelector("slot");
38
- customCheckmark.name = "checkmark";
39
- customCheckmark.textContent = "✓";
40
- const content = document.createElement("span");
41
- content.className = "content";
42
- content.part.add("content");
43
- content.append(document.createElement("slot"));
44
- shadow.replaceChildren(style, checkmark, content);
45
- }
46
- }
47
- customElements.define("spui-list-item", SpuiListItem);
48
- }
49
- export function defineList() {
50
- defineListItem();
51
- if (customElements.get("spui-list"))
52
- return;
53
- class SpuiList extends HTMLElement {
54
- static observedAttributes = ["selection-mode", "navigation-mode", "selected-items", "default-selected-items", "role"];
55
- selected = [];
56
- controlled;
57
- generatedRole;
58
- generatedItemRoles = new WeakMap();
59
- activeIndex = 0;
60
- onKeyDownBound = (event) => this.onKeyDown(event);
61
- onClickBound = (event) => this.onClick(event);
62
- onFocusBound = (event) => this.onFocus(event);
63
- onCheckmarkChangeBound = (event) => this.onCheckmarkChange(event);
64
- syncBound = () => this.syncItems();
65
- constructor() { super(); }
66
- connectedCallback() {
67
- this.setAttribute("data-spui-list", "");
68
- this.addEventListener("keydown", this.onKeyDownBound);
69
- this.addEventListener("click", this.onClickBound);
70
- this.addEventListener("focusin", this.onFocusBound);
71
- this.addEventListener("change", this.onCheckmarkChangeBound);
72
- this.addEventListener("spui-change", this.onCheckmarkChangeBound);
73
- this.addEventListener("spui-list-items-change", this.syncBound);
74
- if (this.hasAttribute("selected-items"))
75
- this.controlled = parseValues(this.getAttribute("selected-items"));
76
- else
77
- this.selected = parseValues(this.getAttribute("default-selected-items"));
78
- this.render();
79
- this.syncItems();
80
- }
81
- disconnectedCallback() {
82
- this.removeEventListener("keydown", this.onKeyDownBound);
83
- this.removeEventListener("click", this.onClickBound);
84
- this.removeEventListener("focusin", this.onFocusBound);
85
- this.removeEventListener("change", this.onCheckmarkChangeBound);
86
- this.removeEventListener("spui-change", this.onCheckmarkChangeBound);
87
- this.removeEventListener("spui-list-items-change", this.syncBound);
88
- }
89
- attributeChangedCallback(name) {
90
- if (!this.isConnected)
91
- return;
92
- if (name === "selected-items")
93
- this.controlled = this.hasAttribute("selected-items") ? parseValues(this.getAttribute("selected-items")) : undefined;
94
- if (name === "default-selected-items" && this.controlled === undefined)
95
- this.selected = parseValues(this.getAttribute("default-selected-items"));
96
- this.render();
97
- this.syncItems();
98
- }
99
- get selectionMode() { const mode = this.getAttribute("selection-mode"); return mode === "single" || mode === "multiselect" ? mode : undefined; }
100
- set selectionMode(value) { value ? this.setAttribute("selection-mode", value) : this.removeAttribute("selection-mode"); }
101
- get navigationMode() { const mode = this.getAttribute("navigation-mode"); return mode === "items" || mode === "composite" ? mode : undefined; }
102
- set navigationMode(value) { value ? this.setAttribute("navigation-mode", value) : this.removeAttribute("navigation-mode"); }
103
- get selectedItems() { return [...(this.controlled ?? this.selected)]; }
104
- set selectedItems(value) { this.controlled = value === undefined ? undefined : [...value]; this.syncItems(); }
105
- get defaultSelectedItems() { return parseValues(this.getAttribute("default-selected-items")); }
106
- set defaultSelectedItems(value) { this.setAttribute("default-selected-items", JSON.stringify([...value])); }
107
- items() { return [...this.children].filter((element) => element.localName === "spui-list-item"); }
108
- render() {
109
- const mode = this.navigationMode;
110
- const selection = this.selectionMode;
111
- const currentRole = this.getAttribute("role");
112
- const role = currentRole && currentRole !== this.generatedRole ? currentRole : (mode === "composite" ? "grid" : selection ? "listbox" : "list");
113
- this.generatedRole = role;
114
- if (this.getAttribute("role") !== role)
115
- this.setAttribute("role", role);
116
- if (selection === "multiselect")
117
- this.setAttribute("aria-multiselectable", "true");
118
- else
119
- this.removeAttribute("aria-multiselectable");
120
- const shadow = this.shadowRoot ?? this.attachShadow({ mode: "open" });
121
- const style = document.createElement("style");
122
- style.textContent = `${base}:host{box-sizing:border-box;display:flex;flex-direction:column;gap:var(--spui-list-gap,2px);min-width:0;margin:0;padding:var(--spui-list-padding,0);color:var(--spui-ui-text,var(--colorNeutralForeground1,#242424));font-family:var(--spui-font-family,inherit)}:host(:focus-visible){outline:2px solid var(--spui-focus-ring,var(--spui-ui-accent,#0078d4))}@media(forced-colors:active){:host{border-color:CanvasText}}`;
123
- const slot = document.createElement("slot");
124
- slot.addEventListener("slotchange", this.syncBound);
125
- shadow.replaceChildren(style, slot);
126
- }
127
- syncItems() {
128
- const items = this.items();
129
- const role = this.getAttribute("role") || "list";
130
- const selection = this.selectionMode;
131
- const focused = items.indexOf(this.shadowRoot?.activeElement);
132
- if (focused >= 0)
133
- this.activeIndex = focused;
134
- if (this.activeIndex >= items.length)
135
- this.activeIndex = Math.max(0, items.length - 1);
136
- items.forEach((item, index) => {
137
- const selectable = selection !== undefined;
138
- const itemRole = role === "grid" ? "row" : role === "listbox" ? "option" : "listitem";
139
- const currentRole = item.getAttribute("role");
140
- const effectiveRole = currentRole && currentRole !== this.generatedItemRoles.get(item) ? currentRole : itemRole;
141
- this.generatedItemRoles.set(item, effectiveRole);
142
- if (currentRole !== effectiveRole)
143
- item.setAttribute("role", effectiveRole);
144
- if (selectable) {
145
- const selected = this.selectedItems.includes(item.value ?? item.getAttribute("value") ?? "");
146
- item.setAttribute("aria-selected", String(selected));
147
- if (item.hasAttribute("disabled-selection") && !item.hasAttribute("has-action"))
148
- item.setAttribute("aria-disabled", "true");
149
- else
150
- item.removeAttribute("aria-disabled");
151
- const checkmarkSlot = item.shadowRoot?.querySelector('slot[name="checkmark"]');
152
- const assigned = checkmarkSlot?.assignedElements({ flatten: true }) ?? [];
153
- const controls = assigned.flatMap(element => [
154
- ...(element.matches('input[type="checkbox"],spui-checkbox') ? [element] : []),
155
- ...element.querySelectorAll('input[type="checkbox"],spui-checkbox')
156
- ]);
157
- for (const control of controls) {
158
- const checkbox = control;
159
- checkbox.checked = selected;
160
- checkbox.disabled = item.hasAttribute("disabled-selection");
161
- checkbox.tabIndex = -1;
162
- }
163
- }
164
- else {
165
- item.removeAttribute("aria-selected");
166
- item.removeAttribute("aria-disabled");
167
- }
168
- const managedTabOrder = this.navigationMode !== undefined || selectable;
169
- item.tabIndex = managedTabOrder ? (index === this.activeIndex ? 0 : -1) : item.hasAttribute("has-action") ? 0 : -1;
170
- });
171
- }
172
- onFocus(event) {
173
- const item = event.target.closest("spui-list-item");
174
- const index = item ? this.items().indexOf(item) : -1;
175
- if (index >= 0) {
176
- this.activeIndex = index;
177
- this.syncItems();
178
- }
179
- }
180
- onKeyDown(event) {
181
- const current = event.target.closest("spui-list-item");
182
- if (!current)
183
- return;
184
- const origin = event.composedPath()[0];
185
- const nestedTarget = origin !== current;
186
- const items = this.items();
187
- const index = items.indexOf(current);
188
- if (this.navigationMode === "composite" && (event.key === "ArrowLeft" || event.key === "ArrowRight")) {
189
- const rtl = getComputedStyle(this).direction === "rtl";
190
- const step = (event.key === "ArrowRight" ? 1 : -1) * (rtl ? -1 : 1);
191
- const focusable = [...current.querySelectorAll('a[href],button,input,select,textarea,[tabindex]:not([tabindex="-1"])')].filter(node => !node.hasAttribute("disabled") && !node.hasAttribute("hidden"));
192
- if (!nestedTarget) {
193
- if (step > 0 && focusable[0]) {
194
- event.preventDefault();
195
- focusable[0].focus();
196
- }
197
- else if (step < 0 && focusable.length) {
198
- event.preventDefault();
199
- focusable[focusable.length - 1].focus();
200
- }
201
- }
202
- else {
203
- const currentTarget = origin;
204
- const focusIndex = focusable.findIndex(node => node === currentTarget || node.contains(currentTarget));
205
- const next = focusable[focusIndex + step];
206
- if (next) {
207
- event.preventDefault();
208
- next.focus();
209
- }
210
- else if (step < 0 && focusIndex === 0) {
211
- event.preventDefault();
212
- current.focus();
213
- }
214
- }
215
- return;
216
- }
217
- if (event.key === "ArrowDown" || event.key === "ArrowUp" || event.key === "Home" || event.key === "End") {
218
- if (this.navigationMode === undefined && this.selectionMode === undefined)
219
- return;
220
- event.preventDefault();
221
- const direction = event.key === "ArrowDown" ? 1 : event.key === "ArrowUp" || event.key === "End" ? -1 : 1;
222
- let next = event.key === "Home" ? 0 : event.key === "End" ? items.length - 1 : Math.max(0, Math.min(items.length - 1, index + direction));
223
- while (items[next]?.getAttribute("aria-disabled") === "true" && next >= 0 && next < items.length)
224
- next += direction || 1;
225
- if (items[next]) {
226
- this.activeIndex = next;
227
- this.syncItems();
228
- items[next].focus();
229
- }
230
- return;
231
- }
232
- if (nestedTarget || (event.key !== "Enter" && event.key !== " "))
233
- return;
234
- const value = current.value ?? current.getAttribute("value") ?? "";
235
- if (event.key === " " && this.selectionMode) {
236
- event.preventDefault();
237
- if (!current.hasAttribute("disabled-selection"))
238
- this.toggleSelection(value, event);
239
- return;
240
- }
241
- this.activate(current, event, value);
242
- }
243
- onClick(event) {
244
- const current = event.target.closest("spui-list-item");
245
- if (!current)
246
- return;
247
- const path = event.composedPath();
248
- const itemIndex = path.indexOf(current);
249
- if (path.slice(0, itemIndex < 0 ? path.length : itemIndex).some(node => node instanceof Element && node.matches("a,button,input,select,textarea,[contenteditable=true]")))
250
- return;
251
- const value = current.value ?? current.getAttribute("value") ?? "";
252
- this.activate(current, event, value);
253
- }
254
- onCheckmarkChange(event) {
255
- const path = event.composedPath();
256
- const item = path.find((node) => node instanceof HTMLElement && node.localName === "spui-list-item");
257
- if (!item || !path.some(node => node instanceof Element && node.getAttribute("slot") === "checkmark"))
258
- return;
259
- if (event.type === "change" && path.some(node => node instanceof Element && node.localName === "spui-checkbox"))
260
- return;
261
- if (!this.selectionMode || item.hasAttribute("disabled-selection")) {
262
- this.syncItems();
263
- return;
264
- }
265
- const detail = event.detail;
266
- const target = event.target;
267
- const checked = detail?.checked ?? target.checked;
268
- if (checked === undefined)
269
- return;
270
- const value = item.value ?? item.getAttribute("value") ?? "";
271
- this.setItemSelected(value, checked === true, event);
272
- }
273
- activate(item, originalEvent, value) {
274
- const action = new CustomEvent("spui-list-item-action", { bubbles: true, composed: true, cancelable: true, detail: { originalEvent, value } });
275
- item.dispatchEvent(action);
276
- if (action.defaultPrevented)
277
- return;
278
- if (this.selectionMode && !item.hasAttribute("disabled-selection"))
279
- this.toggleSelection(value, originalEvent);
280
- }
281
- toggleSelection(value, originalEvent) {
282
- const selected = this.selectedItems;
283
- this.setItemSelected(value, !selected.includes(value), originalEvent);
284
- }
285
- setItemSelected(value, selected, originalEvent) {
286
- const current = this.selectedItems;
287
- const next = this.selectionMode === "single"
288
- ? (selected ? [value] : current.filter(item => item !== value))
289
- : (selected ? current.includes(value) ? current : [...current, value] : current.filter(item => item !== value));
290
- if (this.controlled === undefined)
291
- this.selected = next;
292
- this.syncItems();
293
- this.dispatchEvent(new CustomEvent("spui-selection-change", { bubbles: true, composed: true, detail: { event: originalEvent, type: "change", selectedItems: next } }));
294
- }
295
- }
296
- customElements.define("spui-list", SpuiList);
297
- }
@@ -1,33 +0,0 @@
1
- export type MenuOpenChangeType = "menuTriggerContextMenu" | "menuTriggerClick" | "menuTriggerMouseEnter" | "menuSafeZoneMouseEnter" | "menuSafeZoneTimeout" | "menuTriggerMouseLeave" | "menuTriggerMouseMove" | "menuTriggerKeyDown" | "menuItemClick" | "menuPopoverMouseEnter" | "menuPopoverKeyDown" | "clickOutside" | "scrollOutside" | "menuMouseEnter" | "programmatic";
2
- type MenuOpenChangeSourceData = {
3
- type: "menuTriggerContextMenu" | "menuTriggerClick" | "menuTriggerMouseEnter" | "menuSafeZoneMouseEnter" | "menuTriggerMouseLeave" | "menuTriggerMouseMove" | "menuItemClick" | "menuPopoverMouseEnter";
4
- event: MouseEvent;
5
- } | {
6
- type: "menuTriggerKeyDown" | "menuPopoverKeyDown";
7
- event: KeyboardEvent;
8
- keyboard?: boolean;
9
- } | {
10
- type: "menuSafeZoneTimeout" | "programmatic";
11
- event: Event;
12
- } | {
13
- type: "clickOutside" | "scrollOutside" | "menuMouseEnter";
14
- event: MouseEvent | TouchEvent;
15
- };
16
- export type MenuOpenChangeData = {
17
- bubble?: boolean;
18
- keyboard?: boolean;
19
- open: boolean;
20
- } & MenuOpenChangeSourceData;
21
- export declare function defineMenuItem(): void;
22
- export declare function defineMenuDivider(): void;
23
- export declare function defineMenuGroup(): void;
24
- export declare function defineMenuGroupHeader(): void;
25
- export declare function defineMenuItemLink(): void;
26
- export declare function defineMenuList(): void;
27
- export declare function defineMenuPopover(): void;
28
- export declare function defineMenuSplitGroup(): void;
29
- export declare function defineMenuTrigger(): void;
30
- export declare function defineMenu(): void;
31
- export declare function defineMenuBarItem(): void;
32
- export declare function defineMenuBar(): void;
33
- export {};