@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,10 +0,0 @@
1
- export type OverflowState = {
2
- hasOverflow: boolean;
3
- itemVisibility: Record<string, boolean>;
4
- groupVisibility: Record<string, "visible" | "hidden" | "overflow">;
5
- };
6
- export type OverflowAxis = "horizontal" | "vertical";
7
- export type OverflowDensity = "comfortable" | "compact";
8
- export declare function defineOverflowItem(): void;
9
- export declare function defineOverflowDivider(): void;
10
- export declare function defineOverflow(): void;
@@ -1,218 +0,0 @@
1
- import { base } from "./shared.js";
2
- export function defineOverflowItem() {
3
- if (customElements.get("spui-overflow-item"))
4
- return;
5
- class SpuiOverflowItem extends HTMLElement {
6
- static observedAttributes = ["priority", "pinned", "group-id", "id"];
7
- connectedCallback() { if (!this.shadowRoot) {
8
- const shadow = this.attachShadow({ mode: "open" });
9
- const style = document.createElement("style");
10
- style.textContent = `${base}:host{display:inline-flex;flex:none;min-width:0;max-width:100%}:host([hidden]){display:none!important}slot{display:contents}::slotted(*){flex:none}@media(forced-colors:active){:host{forced-color-adjust:auto}}`;
11
- shadow.append(style, document.createElement("slot"));
12
- } }
13
- }
14
- customElements.define("spui-overflow-item", SpuiOverflowItem);
15
- }
16
- export function defineOverflowDivider() {
17
- if (customElements.get("spui-overflow-divider"))
18
- return;
19
- class SpuiOverflowDivider extends HTMLElement {
20
- connectedCallback() { if (!this.shadowRoot) {
21
- const shadow = this.attachShadow({ mode: "open" });
22
- const style = document.createElement("style");
23
- style.textContent = `${base}:host{display:block;align-self:stretch;flex:none;inline-size:1px;min-block-size:24px;background:var(--spui-ui-stroke,var(--colorNeutralStroke2,#e1dfdd))}:host([has-child]){inline-size:auto;min-block-size:0;background:transparent}:host([hidden]){display:none!important}slot{display:contents}`;
24
- const slot = document.createElement("slot");
25
- slot.addEventListener("slotchange", () => this.toggleAttribute("has-child", slot.assignedNodes({ flatten: true }).length > 0));
26
- shadow.append(style, slot);
27
- } }
28
- }
29
- customElements.define("spui-overflow-divider", SpuiOverflowDivider);
30
- }
31
- export function defineOverflow() {
32
- if (customElements.get("spui-overflow"))
33
- return;
34
- defineOverflowItem();
35
- defineOverflowDivider();
36
- class SpuiOverflow extends HTMLElement {
37
- static observedAttributes = ["aria-label", "minimum-visible", "overflow-direction", "overflow-axis", "has-hidden-items", "padding", "density"];
38
- itemSlot;
39
- triggerSlot;
40
- row;
41
- resizeObserver;
42
- mutationObserver;
43
- events;
44
- state;
45
- frame = 0;
46
- transaction = false;
47
- refresh() { this.schedule(); }
48
- forceRefresh() { if (this.frame)
49
- cancelAnimationFrame(this.frame); this.frame = 0; this.recompute(); }
50
- connectedCallback() {
51
- if (!this.shadowRoot)
52
- this.render();
53
- this.events?.abort();
54
- this.events = new AbortController();
55
- this.itemSlot.addEventListener("slotchange", this.schedule, { signal: this.events.signal });
56
- this.triggerSlot.addEventListener("slotchange", this.schedule, { signal: this.events.signal });
57
- this.resizeObserver?.disconnect();
58
- this.resizeObserver = new ResizeObserver(this.schedule);
59
- this.resizeObserver.observe(this);
60
- this.mutationObserver?.disconnect();
61
- this.mutationObserver = new MutationObserver(this.schedule);
62
- this.mutationObserver.observe(this, { childList: true, subtree: true, attributes: true, attributeFilter: ["id", "priority", "pinned", "group-id", "data-overflow-id", "data-overflow-item", "data-overflow-divider", "style", "class"] });
63
- window.addEventListener("resize", this.schedule, { signal: this.events.signal, passive: true });
64
- document.fonts?.addEventListener("loadingdone", this.schedule, { signal: this.events.signal });
65
- this.syncLabel();
66
- this.schedule();
67
- }
68
- disconnectedCallback() {
69
- this.events?.abort();
70
- this.events = undefined;
71
- this.resizeObserver?.disconnect();
72
- this.resizeObserver = undefined;
73
- this.mutationObserver?.disconnect();
74
- this.mutationObserver = undefined;
75
- if (this.frame)
76
- cancelAnimationFrame(this.frame);
77
- this.frame = 0;
78
- this.transaction = false;
79
- }
80
- attributeChangedCallback() { if (this.isConnected) {
81
- this.syncLabel();
82
- this.schedule();
83
- } }
84
- render() {
85
- const shadow = this.attachShadow({ mode: "open" });
86
- const style = document.createElement("style");
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
- this.row = document.createElement("div");
89
- this.row.className = "row";
90
- this.row.setAttribute("part", "control");
91
- this.itemSlot = document.createElement("slot");
92
- this.triggerSlot = document.createElement("slot");
93
- this.triggerSlot.name = "overflow-trigger";
94
- this.row.append(this.itemSlot, this.triggerSlot);
95
- shadow.append(style, this.row);
96
- this.syncLabel();
97
- }
98
- syncLabel() {
99
- if (!this.hasAttribute("role"))
100
- this.setAttribute("role", "group");
101
- if (!this.hasAttribute("aria-label"))
102
- this.setAttribute("aria-label", "Overflow actions");
103
- }
104
- schedule = () => {
105
- if (!this.isConnected || this.frame)
106
- return;
107
- this.frame = requestAnimationFrame(() => { this.frame = 0; this.recompute(); });
108
- };
109
- recompute() {
110
- if (this.transaction || !this.row)
111
- return;
112
- const assigned = this.itemSlot.assignedElements({ flatten: true }).filter((item) => item instanceof HTMLElement);
113
- const items = assigned.flatMap(root => [root, ...root.querySelectorAll("[data-overflow-item], [data-overflow-divider]")]).filter(item => item.localName === "spui-overflow-item" || item.localName === "spui-overflow-divider" || item.hasAttribute("data-overflow-item") || item.hasAttribute("data-overflow-divider"));
114
- const overflowItems = items.filter(item => item.localName === "spui-overflow-item" || item.hasAttribute("data-overflow-item"));
115
- const dividers = items.filter(item => item.localName === "spui-overflow-divider" || item.hasAttribute("data-overflow-divider"));
116
- const trigger = this.triggerSlot.assignedElements({ flatten: true }).find((item) => item instanceof HTMLElement);
117
- const vertical = this.getAttribute("overflow-axis") === "vertical";
118
- const available = vertical ? this.row.clientHeight : this.row.clientWidth;
119
- if (!overflowItems.length || available <= 0)
120
- return;
121
- this.transaction = true;
122
- try {
123
- for (const item of [...overflowItems, ...dividers, ...(trigger ? [trigger] : [])])
124
- item.hidden = false;
125
- const sizes = new Map([...overflowItems, ...dividers].map(item => [item, vertical ? item.getBoundingClientRect().height : item.getBoundingClientRect().width]));
126
- const triggerSize = trigger ? (vertical ? trigger.getBoundingClientRect().height : trigger.getBoundingClientRect().width) : 0;
127
- const gap = parseFloat(getComputedStyle(this.row)[vertical ? "rowGap" : "columnGap"]) || 0;
128
- const minVisible = Math.max(0, Math.min(overflowItems.length, Number(this.getAttribute("minimum-visible")) || 0));
129
- const direction = this.getAttribute("overflow-direction") === "start" ? "start" : "end";
130
- const candidates = overflowItems.filter(item => !item.hasAttribute("pinned")).sort((a, b) => {
131
- const priority = (Number(a.getAttribute("priority")) || 0) - (Number(b.getAttribute("priority")) || 0);
132
- return priority || (direction === "end" ? overflowItems.indexOf(b) - overflowItems.indexOf(a) : overflowItems.indexOf(a) - overflowItems.indexOf(b));
133
- });
134
- const hidden = new Set();
135
- let visible = overflowItems.slice();
136
- const visibleDividers = () => dividers.filter(divider => visible.some(item => item.getAttribute("group-id") === divider.getAttribute("group-id")));
137
- const rowWidth = () => {
138
- const shown = items.filter(item => overflowItems.includes(item) ? !hidden.has(item) : visibleDividers().includes(item));
139
- const parent = shown[0]?.parentElement;
140
- const itemGap = parent === this ? gap : parent ? (parseFloat(getComputedStyle(parent)[vertical ? "rowGap" : "columnGap"]) || 0) : gap;
141
- return shown.reduce((sum, item) => sum + (sizes.get(item) ?? 0), 0) + itemGap * Math.max(0, shown.length - 1);
142
- };
143
- const reserveMenu = hidden.size > 0 || this.hasAttribute("has-hidden-items");
144
- const needsSpace = () => rowWidth() + (reserveMenu ? gap + triggerSize + Math.max(0, Number(this.getAttribute("padding")) || 0) : 0) > available;
145
- for (const candidate of candidates) {
146
- if (!needsSpace() || visible.length <= minVisible)
147
- break;
148
- hidden.add(candidate);
149
- visible = visible.filter(item => item !== candidate);
150
- }
151
- for (const item of overflowItems) {
152
- item.hidden = hidden.has(item);
153
- if (hidden.has(item))
154
- item.setAttribute("aria-hidden", "true");
155
- else
156
- item.removeAttribute("aria-hidden");
157
- item.dataset.overflowed = String(hidden.has(item));
158
- }
159
- const visibleGroups = new Set(visible.map(item => item.getAttribute("group-id")).filter((id) => Boolean(id)));
160
- const hiddenGroups = new Set([...hidden].map(item => item.getAttribute("group-id")).filter((id) => Boolean(id)));
161
- for (const divider of dividers) {
162
- const group = divider.getAttribute("group-id");
163
- divider.hidden = !group || !visibleGroups.has(group);
164
- }
165
- if (trigger)
166
- trigger.hidden = !reserveMenu;
167
- const groupVisibility = {};
168
- for (const group of new Set([...visibleGroups, ...hiddenGroups])) {
169
- const groupItems = overflowItems.filter(item => item.getAttribute("group-id") === group);
170
- const visibleCount = groupItems.filter(item => !hidden.has(item)).length;
171
- groupVisibility[group] = visibleCount === 0 ? "hidden" : visibleCount === groupItems.length ? "visible" : "overflow";
172
- }
173
- const itemId = (item) => item.getAttribute("data-overflow-id") || item.id || "";
174
- const itemVisibility = Object.fromEntries(overflowItems.map(item => [itemId(item), !hidden.has(item)]).filter(([id]) => Boolean(id)));
175
- const state = {
176
- visibleIds: visible.map(itemId).filter(Boolean),
177
- overflowIds: [...hidden].map(itemId).filter(Boolean),
178
- hasOverflow: hidden.size > 0 || this.hasAttribute("has-hidden-items"),
179
- itemVisibility,
180
- groupVisibility
181
- };
182
- const changed = !this.state || JSON.stringify(this.state) !== JSON.stringify(state);
183
- this.state = state;
184
- this.dataset.visibleCount = String(state.visibleIds.length);
185
- this.dataset.overflowCount = String(state.overflowIds.length);
186
- this.dataset.overflowIds = state.overflowIds.join(",");
187
- if (changed) {
188
- let active = this.ownerDocument.activeElement;
189
- while (active?.shadowRoot?.activeElement)
190
- active = active.shadowRoot.activeElement;
191
- if (trigger && active instanceof HTMLElement && [...hidden].some(item => item === active || item.contains(active)))
192
- this.focusTrigger(trigger);
193
- this.dispatchEvent(new CustomEvent("spui-overflow-change", { bubbles: true, composed: true, detail: state }));
194
- }
195
- }
196
- finally {
197
- this.transaction = false;
198
- }
199
- }
200
- focusTrigger(trigger) {
201
- const visit = (node) => {
202
- if (node instanceof HTMLSlotElement)
203
- return node.assignedNodes({ flatten: true }).map(visit).find(Boolean);
204
- if (node instanceof HTMLElement) {
205
- if (node.matches("button:not(:disabled),a[href],[tabindex]:not([tabindex='-1'])"))
206
- return node;
207
- const root = node.shadowRoot;
208
- const target = root ? [...root.childNodes].map(visit).find(Boolean) : undefined;
209
- if (target)
210
- return target;
211
- }
212
- return [...node.childNodes].map(visit).find(Boolean);
213
- };
214
- visit(trigger)?.focus();
215
- }
216
- }
217
- customElements.define("spui-overflow", SpuiOverflow);
218
- }
@@ -1,3 +0,0 @@
1
- export type PersonaSize = "extra-small" | "small" | "medium" | "large" | "extra-large" | "huge";
2
- export type PersonaPresence = "available" | "busy" | "do-not-disturb" | "away" | "offline" | "unknown";
3
- export declare function definePersona(): void;
@@ -1,125 +0,0 @@
1
- import { base } from "./shared.js";
2
- import { defineAvatar } from "./avatar.js";
3
- const avatarSizes = { "extra-small": 20, small: 28, medium: 32, large: 36, "extra-large": 40, huge: 56 };
4
- const presenceNames = {
5
- available: "Available", busy: "Busy", "do-not-disturb": "Do not disturb", away: "Away", offline: "Offline", unknown: "Presence unknown"
6
- };
7
- export function definePersona() {
8
- if (customElements.get("spui-persona"))
9
- return;
10
- defineAvatar();
11
- class SpuiPersona extends HTMLElement {
12
- static observedAttributes = ["name", "image", "initials", "color", "size", "text-position", "text-alignment", "presence-only", "secondary-text", "tertiary-text", "presence", "presence-label"];
13
- connectedCallback() { if (!this.shadowRoot)
14
- this.render(); this.sync(); }
15
- attributeChangedCallback() { if (this.isConnected)
16
- this.sync(); }
17
- sync() {
18
- const name = this.getAttribute("name") ?? "";
19
- const avatar = this.shadowRoot?.querySelector("spui-avatar");
20
- if (avatar) {
21
- avatar.setAttribute("name", name);
22
- avatar.setAttribute("size", String(avatarSizes[this.getAttribute("size")] ?? avatarSizes.medium));
23
- avatar.setAttribute("color", this.getAttribute("color") || "neutral");
24
- avatar.setAttribute("decorative", "");
25
- for (const attribute of ["image", "initials"]) {
26
- const value = this.getAttribute(attribute);
27
- if (value)
28
- avatar.setAttribute(attribute, value);
29
- else
30
- avatar.removeAttribute(attribute);
31
- }
32
- }
33
- if (avatar)
34
- avatar.hidden = this.hasAttribute("presence-only");
35
- const primary = this.shadowRoot?.querySelector(".primary");
36
- if (primary)
37
- primary.textContent = name;
38
- const secondary = this.shadowRoot?.querySelector(".secondary");
39
- if (secondary) {
40
- secondary.textContent = this.getAttribute("secondary-text") ?? "";
41
- secondary.hidden = !secondary.textContent;
42
- }
43
- const tertiary = this.shadowRoot?.querySelector(".tertiary");
44
- if (tertiary) {
45
- tertiary.textContent = this.getAttribute("tertiary-text") ?? "";
46
- tertiary.hidden = !tertiary.textContent;
47
- }
48
- const quaternary = this.shadowRoot?.querySelector(".quaternary");
49
- if (quaternary)
50
- quaternary.hidden = !quaternary.textContent;
51
- const presence = this.getAttribute("presence");
52
- const marker = this.shadowRoot?.querySelector(".presence");
53
- const validPresence = presence && Object.hasOwn(presenceNames, presence) ? presence : undefined;
54
- if (marker) {
55
- marker.hidden = !validPresence;
56
- if (validPresence) {
57
- marker.dataset.presence = validPresence;
58
- marker.setAttribute("aria-label", this.getAttribute("presence-label") || presenceNames[validPresence]);
59
- marker.title = this.getAttribute("presence-label") || presenceNames[validPresence];
60
- }
61
- else {
62
- marker.removeAttribute("aria-label");
63
- marker.removeAttribute("title");
64
- }
65
- }
66
- }
67
- render() {
68
- const shadow = this.attachShadow({ mode: "open" });
69
- const style = document.createElement("style");
70
- style.textContent = `${base}:host{--spui-persona-avatar-size:32px;--spui-persona-gap:10px;display:inline-flex;max-width:100%;min-width:0;color:var(--spui-ui-text,var(--spui-semantic-body-text,var(--colorNeutralForeground1,#242424)));font:inherit;vertical-align:middle}.layout{display:flex;align-items:center;gap:var(--spui-persona-gap);min-width:0;max-width:100%}.avatar-wrap{position:relative;display:grid;place-items:center;flex:none;width:var(--spui-persona-avatar-size);height:var(--spui-persona-avatar-size)}.avatar-fallback{display:grid;width:100%;height:100%}.presence{position:absolute;inset-inline-end:-1px;bottom:-1px;box-sizing:border-box;width:12px;height:12px;border:2px solid var(--spui-base-surface,var(--spui-ui-surface,var(--colorNeutralBackground1,#fff)));border-radius:50%;background:var(--spui-persona-presence-color,#808080)}.presence[data-presence=available]{--spui-persona-presence-color:var(--spui-persona-presence-available,var(--spui-presence-available,var(--spui-semantic-success-text,var(--colorPaletteGreenForeground1,var(--spui-ui-success,#13a10e)))))}.presence[data-presence=busy],.presence[data-presence=do-not-disturb]{--spui-persona-presence-color:var(--spui-persona-presence-busy,var(--spui-presence-busy,var(--spui-semantic-error-text,var(--colorPaletteRedForeground1,var(--spui-ui-danger,#c50f1f)))))}.presence[data-presence=away]{--spui-persona-presence-color:var(--spui-persona-presence-away,var(--spui-presence-away,var(--spui-semantic-warning-text,var(--colorPaletteMarigoldForeground1,var(--spui-ui-warning,#835b00)))))}.presence[data-presence=offline],.presence[data-presence=unknown]{--spui-persona-presence-color:var(--spui-persona-presence-offline,var(--spui-presence-offline,var(--spui-semantic-body-subtext,var(--colorNeutralForeground3,var(--spui-ui-muted,#8a8886)))))}.presence[data-presence=do-not-disturb]{box-shadow:inset 0 0 0 2px var(--spui-base-surface,var(--spui-ui-surface,#fff))}.details{display:flex;flex-direction:column;justify-content:flex-start;min-width:0;max-width:100%;line-height:1.3}.primary,.secondary,.tertiary{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.primary{font-size:14px;font-weight:600;color:var(--spui-ui-text,var(--colorNeutralForeground1,#242424))}.secondary,.tertiary{font-size:12px;color:var(--spui-ui-muted,var(--colorNeutralForeground2,#616161))}.tertiary{font-size:11px}:host([size=extra-small]){--spui-persona-avatar-size:20px;--spui-persona-gap:6px}:host([size=small]){--spui-persona-avatar-size:28px;--spui-persona-gap:8px}:host([size=large]){--spui-persona-avatar-size:36px}:host([size=extra-large]){--spui-persona-avatar-size:40px;--spui-persona-gap:12px}:host([size=huge]){--spui-persona-avatar-size:56px;--spui-persona-gap:14px}:host([size=huge]) .primary{font-size:var(--spui-persona-huge-primary-size,20px)}:host([size=huge]) .secondary{font-size:var(--spui-persona-huge-secondary-size,16px)}:host([text-position=before]) .layout{flex-direction:row-reverse}:host([text-position=below]) .layout{flex-direction:column;align-items:center;text-align:center}:host([text-position=below]) .details{align-items:center}:host([text-position=below]){max-width:12rem}:host([text-alignment=center]) .details{justify-content:center}:host([presence-only]) .avatar-wrap{width:auto;height:auto}:host([presence-only]) .avatar-fallback, :host([presence-only]) slot[name=avatar]{display:none}:host([presence-only]) .presence{position:static;inset:auto;width:16px;height:16px;border-width:0}::slotted([slot=avatar]){display:block;max-width:100%;max-height:100%}::slotted([slot=details]){min-width:0}@media(forced-colors:active){.presence{border-color:Canvas;background:Highlight}.presence[data-presence=offline],.presence[data-presence=unknown]{background:GrayText}}`;
71
- style.textContent += `::slotted([slot=primary-text]),::slotted([slot=secondary-text]),::slotted([slot=tertiary-text]),::slotted([slot=quaternary-text]){display:block;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}::slotted([slot=primary-text]){font-size:14px;font-weight:600;color:var(--spui-ui-text,var(--colorNeutralForeground1,#242424))}::slotted([slot=secondary-text]),::slotted([slot=quaternary-text]){font-size:12px;color:var(--spui-ui-muted,var(--colorNeutralForeground2,#616161))}::slotted([slot=tertiary-text]){font-size:11px;color:var(--spui-ui-muted,var(--colorNeutralForeground2,#616161))}:host([size=huge])::slotted([slot=primary-text]){font-size:var(--spui-persona-huge-primary-size,20px)}`;
72
- const layout = document.createElement("div");
73
- layout.className = "layout";
74
- layout.part.add("root");
75
- const avatarWrap = document.createElement("span");
76
- avatarWrap.className = "avatar-wrap";
77
- avatarWrap.part.add("avatar-wrap");
78
- const avatarSlot = document.createElement("slot");
79
- avatarSlot.name = "avatar";
80
- const fallback = document.createElement("spui-avatar");
81
- fallback.className = "avatar-fallback";
82
- fallback.part.add("avatar");
83
- avatarSlot.append(fallback);
84
- const presence = document.createElement("span");
85
- presence.className = "presence";
86
- presence.part.add("presence");
87
- presence.setAttribute("role", "img");
88
- avatarWrap.append(avatarSlot, presence);
89
- const details = document.createElement("span");
90
- details.className = "details";
91
- details.part.add("details");
92
- const primary = document.createElement("span");
93
- primary.className = "primary";
94
- primary.part.add("primary");
95
- const secondary = document.createElement("span");
96
- secondary.className = "secondary";
97
- secondary.part.add("secondary");
98
- const tertiary = document.createElement("span");
99
- tertiary.className = "tertiary";
100
- tertiary.part.add("tertiary");
101
- const primarySlot = document.createElement("slot");
102
- primarySlot.name = "primary-text";
103
- primarySlot.append(primary);
104
- const secondarySlot = document.createElement("slot");
105
- secondarySlot.name = "secondary-text";
106
- secondarySlot.append(secondary);
107
- const tertiarySlot = document.createElement("slot");
108
- tertiarySlot.name = "tertiary-text";
109
- tertiarySlot.append(tertiary);
110
- const quaternary = document.createElement("span");
111
- quaternary.className = "quaternary";
112
- quaternary.part.add("quaternary");
113
- quaternary.hidden = true;
114
- const quaternarySlot = document.createElement("slot");
115
- quaternarySlot.name = "quaternary-text";
116
- quaternarySlot.append(quaternary);
117
- const detailsSlot = document.createElement("slot");
118
- detailsSlot.name = "details";
119
- details.append(primarySlot, secondarySlot, tertiarySlot, quaternarySlot, detailsSlot);
120
- layout.append(avatarWrap, details);
121
- shadow.append(style, layout);
122
- }
123
- }
124
- customElements.define("spui-persona", SpuiPersona);
125
- }
@@ -1,77 +0,0 @@
1
- import { type FloatingAlign, type FloatingPlacement } from "./floating-position.js";
2
- export type PopoverPosition = FloatingPlacement | "above" | "below" | "before" | "after";
3
- export type PopoverOpenChangeData = {
4
- open: boolean;
5
- };
6
- export type PopoverAlignment = FloatingAlign;
7
- export type PopoverAutoSize = boolean | "always" | "width" | "width-always" | "height" | "height-always";
8
- export type PopoverBoundaryRect = {
9
- x: number;
10
- y: number;
11
- width: number;
12
- height: number;
13
- };
14
- export type PopoverBoundary = Element | DOMRectReadOnly | PopoverBoundaryRect | readonly Element[] | "clippingParents" | "scrollParent" | "window" | null;
15
- export type PopoverPositioningTargetRect = PopoverBoundaryRect & Pick<DOMRectReadOnly, "top" | "left" | "bottom" | "right">;
16
- export type PopoverOffsetParams = {
17
- positionedRect: PopoverBoundaryRect;
18
- targetRect: PopoverBoundaryRect;
19
- position: "above" | "below" | "before" | "after";
20
- alignment?: PopoverAlignment;
21
- };
22
- export type PopoverOffset = number | {
23
- mainAxis: number;
24
- crossAxis?: number;
25
- } | ((params: PopoverOffsetParams) => number | {
26
- mainAxis: number;
27
- crossAxis?: number;
28
- });
29
- export type PopoverBoundaryPadding = number | Partial<Record<"top" | "end" | "bottom" | "start", number>>;
30
- export type PopoverTarget = Element | {
31
- getBoundingClientRect: () => PopoverPositioningTargetRect;
32
- contextElement?: Element;
33
- } | null;
34
- export type PopoverPositioningPlacement = "top" | "top-start" | "top-end" | "right" | "right-start" | "right-end" | "bottom" | "bottom-start" | "bottom-end" | "left" | "left-start" | "left-end";
35
- export type PopoverPositioningEndData = {
36
- placement: PopoverPositioningPlacement;
37
- escaped: boolean;
38
- referenceHidden: boolean;
39
- };
40
- export type PopoverPositioningImperativeRef = {
41
- updatePosition: () => void;
42
- setTarget: (target: PopoverTarget) => void;
43
- };
44
- export type PopoverPositioningRef = {
45
- readonly current: PopoverPositioningImperativeRef | null;
46
- } | ((value: PopoverPositioningImperativeRef | null) => void) | null;
47
- export type PopoverPositioningOptions = {
48
- position?: PopoverPosition;
49
- align?: PopoverAlignment;
50
- offset?: PopoverOffset;
51
- fallbackPositions?: Array<PopoverPosition | `${"above" | "below" | "before" | "after"}-${"start" | "end" | "top" | "bottom"}`>;
52
- autoSize?: PopoverAutoSize;
53
- matchTargetSize?: boolean | "width";
54
- pinned?: boolean;
55
- flipBoundary?: PopoverBoundary;
56
- overflowBoundary?: PopoverBoundary;
57
- overflowBoundaryPadding?: PopoverBoundaryPadding;
58
- positionFixed?: boolean;
59
- strategy?: "absolute" | "fixed";
60
- target?: PopoverTarget;
61
- coverTarget?: boolean;
62
- arrowPadding?: number;
63
- positioningRef?: PopoverPositioningRef;
64
- onPositioningEnd?: (event: CustomEvent<PopoverPositioningEndData>) => void;
65
- disableUpdateOnResize?: boolean;
66
- shiftToCoverTarget?: boolean;
67
- useTransform?: boolean;
68
- };
69
- export type PopoverPositioning = PopoverPosition | `${"above" | "below" | "before" | "after"}-${"start" | "end" | "top" | "bottom"}` | PopoverPositioningOptions;
70
- export declare function definePopoverTrigger(): void;
71
- export declare function definePopoverSurface(): void;
72
- export declare function definePopover(): void;
73
- export declare function definePopoverVariant(tagName: string, defaults?: {
74
- label?: string;
75
- trapFocus?: boolean;
76
- arrow?: boolean;
77
- }): void;