@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,381 +0,0 @@
1
- import { buttonControlCss } from "./button.js";
2
- import { base } from "./shared.js";
3
- const itemSelector = "button:not(:disabled),a[href],input:not([type='hidden']):not(:disabled),select:not(:disabled),textarea:not(:disabled),[tabindex]:not([tabindex='-1']),[data-toolbar-focus]";
4
- export function defineToolbarGroup() {
5
- if (customElements.get("spui-toolbar-group"))
6
- return;
7
- class SpuiToolbarGroup extends HTMLElement {
8
- static observedAttributes = ["label", "orientation"];
9
- connectedCallback() { if (!this.shadowRoot)
10
- this.render(); this.sync(); }
11
- attributeChangedCallback() { if (this.isConnected)
12
- this.sync(); }
13
- sync() {
14
- this.setAttribute("role", "group");
15
- const label = this.getAttribute("aria-label") || this.getAttribute("label");
16
- if (label)
17
- this.setAttribute("aria-label", label);
18
- else
19
- this.removeAttribute("aria-label");
20
- }
21
- render() {
22
- const shadow = this.attachShadow({ mode: "open" });
23
- const style = document.createElement("style");
24
- style.textContent = `${base}:host{box-sizing:border-box;display:inline-flex;align-items:center;gap:var(--spui-toolbar-group-gap,4px);min-width:0}:host([orientation=vertical]){flex-direction:column;align-items:stretch;width:100%}`;
25
- shadow.append(style, document.createElement("slot"));
26
- }
27
- }
28
- customElements.define("spui-toolbar-group", SpuiToolbarGroup);
29
- }
30
- export function defineToolbarSeparator() {
31
- if (customElements.get("spui-toolbar-separator"))
32
- return;
33
- class SpuiToolbarSeparator extends HTMLElement {
34
- static observedAttributes = ["orientation", "vertical"];
35
- connectedCallback() { if (!this.shadowRoot)
36
- this.render(); this.sync(); }
37
- attributeChangedCallback() { if (this.isConnected)
38
- this.sync(); }
39
- sync() {
40
- this.setAttribute("role", "separator");
41
- const orientation = this.hasAttribute("vertical") ? (this.getAttribute("vertical") === "false" ? "horizontal" : "vertical") : this.getAttribute("orientation") === "horizontal" ? "horizontal" : "vertical";
42
- if (this.getAttribute("orientation") !== orientation)
43
- this.setAttribute("orientation", orientation);
44
- this.setAttribute("aria-orientation", orientation);
45
- }
46
- render() {
47
- const shadow = this.attachShadow({ mode: "open" });
48
- const style = document.createElement("style");
49
- style.textContent = `${base}:host{box-sizing:border-box;display:inline-flex;flex:0 0 auto;align-items:stretch;align-self:stretch;min-height:24px;padding-inline:var(--spui-toolbar-separator-inset,3px)}.line{width:1px;background:var(--spui-toolbar-separator,var(--spui-ui-stroke,var(--spui-semantic-body-divider,#d1d1d1)))}:host([orientation=horizontal]){align-self:center;min-height:0;width:100%;height:1px;padding-inline:0;padding-block:var(--spui-toolbar-separator-inset,3px)}:host([orientation=horizontal]) .line{width:100%;height:1px}@media(forced-colors:active){.line{background:CanvasText}}`;
50
- const line = document.createElement("span");
51
- line.className = "line";
52
- line.part.add("line");
53
- line.setAttribute("aria-hidden", "true");
54
- const wrapper = document.createElement("slot");
55
- wrapper.name = "wrapper";
56
- wrapper.append(line);
57
- shadow.append(style, wrapper);
58
- }
59
- }
60
- customElements.define("spui-toolbar-separator", SpuiToolbarSeparator);
61
- }
62
- export function defineToolbarRadioGroup() {
63
- if (customElements.get("spui-toolbar-radio-group"))
64
- return;
65
- class SpuiToolbarRadioGroup extends HTMLElement {
66
- static observedAttributes = ["label", "aria-label", "orientation"];
67
- connectedCallback() { if (!this.shadowRoot)
68
- this.render(); this.sync(); }
69
- attributeChangedCallback() { if (this.isConnected)
70
- this.sync(); }
71
- sync() {
72
- this.setAttribute("role", "radiogroup");
73
- if (!this.hasAttribute("aria-label") && this.hasAttribute("label"))
74
- this.setAttribute("aria-label", this.getAttribute("label") ?? "");
75
- }
76
- render() {
77
- const shadow = this.attachShadow({ mode: "open" });
78
- const style = document.createElement("style");
79
- style.textContent = `${base}:host{box-sizing:border-box;display:inline-flex;align-items:center;gap:var(--spui-toolbar-group-gap,4px);min-width:0}:host([orientation=vertical]){flex-direction:column;align-items:stretch;width:100%}`;
80
- shadow.append(style, document.createElement("slot"));
81
- }
82
- }
83
- customElements.define("spui-toolbar-radio-group", SpuiToolbarRadioGroup);
84
- }
85
- export function defineToolbarRadioButton() {
86
- if (customElements.get("spui-toolbar-radio-button"))
87
- return;
88
- class SpuiToolbarRadioButton extends HTMLElement {
89
- static observedAttributes = ["name", "value", "checked", "disabled", "appearance", "size", "aria-label", "aria-labelledby", "aria-describedby", "title"];
90
- get checked() { return this.hasAttribute("checked"); }
91
- set checked(value) { this.toggleAttribute("checked", Boolean(value)); }
92
- connectedCallback() { if (!this.shadowRoot)
93
- this.render(); this.sync(); }
94
- attributeChangedCallback() { if (this.isConnected)
95
- this.sync(); }
96
- sync() {
97
- const button = this.shadowRoot?.querySelector("button");
98
- if (!button)
99
- return;
100
- button.disabled = this.hasAttribute("disabled");
101
- button.setAttribute("aria-checked", String(this.checked));
102
- const label = this.getAttribute("aria-label");
103
- if (label)
104
- button.setAttribute("aria-label", label);
105
- else
106
- button.removeAttribute("aria-label");
107
- for (const name of ["aria-labelledby", "aria-describedby", "title"]) {
108
- const value = this.getAttribute(name);
109
- value === null ? button.removeAttribute(name) : button.setAttribute(name, value);
110
- }
111
- const appearance = this.getAttribute("appearance") ?? "subtle";
112
- button.className = appearance === "primary" ? "primary" : appearance === "transparent" ? "transparent" : "subtle";
113
- }
114
- render() {
115
- const shadow = this.attachShadow({ mode: "open" });
116
- const button = document.createElement("button");
117
- button.type = "button";
118
- button.setAttribute("role", "radio");
119
- button.setAttribute("aria-checked", "false");
120
- button.part.add("control");
121
- const icon = document.createElement("slot");
122
- icon.name = "icon";
123
- button.append(icon, document.createElement("slot"));
124
- button.addEventListener("click", event => {
125
- if (this.hasAttribute("disabled"))
126
- return;
127
- this.dispatchEvent(new CustomEvent("spui-toolbar-radio-select", { bubbles: true, composed: true, detail: { name: this.getAttribute("name") ?? "", value: this.getAttribute("value") ?? "", sourceEvent: event, currentTarget: event.currentTarget } }));
128
- });
129
- const style = document.createElement("style");
130
- style.textContent = `${buttonControlCss}:host{display:inline-block;vertical-align:middle}`;
131
- shadow.append(style, button);
132
- this.sync();
133
- }
134
- }
135
- customElements.define("spui-toolbar-radio-button", SpuiToolbarRadioButton);
136
- }
137
- export function defineToolbar() {
138
- if (customElements.get("spui-toolbar"))
139
- return;
140
- defineToolbarGroup();
141
- defineToolbarSeparator();
142
- defineToolbarRadioGroup();
143
- defineToolbarRadioButton();
144
- class SpuiToolbar extends HTMLElement {
145
- static observedAttributes = ["label", "orientation", "vertical", "loop", "size"];
146
- observer;
147
- events;
148
- observedShadowRoots = new WeakSet();
149
- syncFrame = 0;
150
- controlledCheckedValues;
151
- uncontrolledCheckedValues = {};
152
- get checkedValues() { return this.controlledCheckedValues; }
153
- set checkedValues(value) {
154
- if (value === undefined) {
155
- if (this.controlledCheckedValues)
156
- this.uncontrolledCheckedValues = this.controlledCheckedValues;
157
- this.controlledCheckedValues = undefined;
158
- }
159
- else
160
- this.controlledCheckedValues = value;
161
- this.syncRadioButtons();
162
- }
163
- get defaultCheckedValues() { return this.uncontrolledCheckedValues; }
164
- set defaultCheckedValues(value) { if (!this.controlledCheckedValues && value)
165
- this.uncontrolledCheckedValues = value; this.syncRadioButtons(); }
166
- get selectedValues() { return this.controlledCheckedValues ?? this.uncontrolledCheckedValues; }
167
- connectedCallback() {
168
- if (!this.shadowRoot)
169
- this.render();
170
- this.observer?.disconnect();
171
- this.observer = new MutationObserver(() => this.scheduleSync());
172
- const changes = { childList: true, subtree: true, attributes: true, attributeFilter: ["disabled", "hidden", "aria-disabled"] };
173
- this.observer.observe(this, changes);
174
- for (let parent = this.parentElement; parent; parent = parent.parentElement)
175
- this.observer.observe(parent, { attributes: true, attributeFilter: ["disabled"] });
176
- this.observeShadowRoots(this);
177
- this.events?.abort();
178
- this.events = new AbortController();
179
- this.addEventListener("keydown", this.onKeyDown, { signal: this.events.signal });
180
- this.addEventListener("focusin", this.onFocusIn, { signal: this.events.signal });
181
- this.addEventListener("spui-toolbar-radio-select", this.onRadioSelect, { signal: this.events.signal });
182
- this.addEventListener("spui-checked-change", this.onToggleChange, { signal: this.events.signal });
183
- this.sync();
184
- this.scheduleSync();
185
- }
186
- disconnectedCallback() { this.observer?.disconnect(); this.observedShadowRoots = new WeakSet(); this.events?.abort(); cancelAnimationFrame(this.syncFrame); this.syncFrame = 0; }
187
- attributeChangedCallback() { if (this.isConnected)
188
- this.sync(); }
189
- items() {
190
- const result = [];
191
- const visit = (nodes) => {
192
- for (const child of nodes) {
193
- if (child instanceof HTMLSlotElement) {
194
- const assigned = child.assignedNodes({ flatten: true });
195
- visit(assigned.length ? assigned : child.childNodes);
196
- continue;
197
- }
198
- if (!(child instanceof HTMLElement))
199
- continue;
200
- if (child.matches(itemSelector) && !child.matches(":disabled") && !child.closest("[hidden], [inert]") && child.getAttribute("aria-disabled") !== "true")
201
- result.push(child);
202
- visit(child.shadowRoot?.childNodes ?? child.childNodes);
203
- }
204
- };
205
- const slot = this.shadowRoot?.querySelector("slot");
206
- if (slot) {
207
- const assigned = slot.assignedNodes({ flatten: true });
208
- visit(assigned.length ? assigned : slot.childNodes);
209
- }
210
- else
211
- visit(this.childNodes);
212
- return result;
213
- }
214
- scheduleSync() {
215
- if (this.syncFrame)
216
- return;
217
- this.syncFrame = requestAnimationFrame(() => { this.syncFrame = 0; if (this.isConnected)
218
- this.sync(); });
219
- }
220
- syncItems() {
221
- const items = this.items();
222
- const active = items.find(item => item === this.shadowRoot?.activeElement || item === this.ownerDocument.activeElement || item.matches(":focus"));
223
- const remembered = items.find(item => item.dataset.toolbarFocus === "true");
224
- const initial = items[0];
225
- const current = active ?? remembered ?? initial;
226
- for (const item of items) {
227
- item.tabIndex = item === current ? 0 : -1;
228
- item.dataset.toolbarFocus = String(item === current);
229
- }
230
- }
231
- observeShadowRoots(root) {
232
- const visit = (node) => {
233
- if (node instanceof HTMLElement && node.shadowRoot) {
234
- const shadow = node.shadowRoot;
235
- if (!this.observedShadowRoots.has(shadow)) {
236
- this.observer?.observe(shadow, { childList: true, subtree: true, attributes: true, attributeFilter: ["disabled", "hidden", "aria-disabled"] });
237
- this.observedShadowRoots.add(shadow);
238
- }
239
- for (const child of shadow.childNodes)
240
- visit(child);
241
- }
242
- for (const child of node.childNodes)
243
- visit(child);
244
- };
245
- for (const child of root.childNodes)
246
- visit(child);
247
- }
248
- onFocusIn = (event) => {
249
- const items = this.items();
250
- const target = event.composedPath().find(node => node instanceof HTMLElement && items.includes(node));
251
- if (!target)
252
- return;
253
- for (const item of items) {
254
- item.tabIndex = item === target ? 0 : -1;
255
- item.dataset.toolbarFocus = String(item === target);
256
- }
257
- };
258
- onKeyDown = (event) => {
259
- if (event.altKey || event.ctrlKey || event.metaKey)
260
- return;
261
- const items = this.items();
262
- const current = event.composedPath().find(node => node instanceof HTMLElement && items.includes(node));
263
- if (!current)
264
- return;
265
- const vertical = this.getAttribute("orientation") === "vertical";
266
- const rtl = getComputedStyle(this).direction === "rtl";
267
- const nextKey = vertical ? "ArrowDown" : rtl ? "ArrowLeft" : "ArrowRight";
268
- const previousKey = vertical ? "ArrowUp" : rtl ? "ArrowRight" : "ArrowLeft";
269
- const index = items.indexOf(current);
270
- let next;
271
- const loop = this.getAttribute("loop") !== "false";
272
- if (event.key === nextKey)
273
- next = items[index + 1] ?? (loop ? items[0] : undefined);
274
- else if (event.key === previousKey)
275
- next = items[index - 1] ?? (loop ? items.at(-1) : undefined);
276
- else if (event.key === "Home")
277
- next = items[0];
278
- else if (event.key === "End")
279
- next = items.at(-1);
280
- if (!next)
281
- return;
282
- event.preventDefault();
283
- for (const item of items) {
284
- item.tabIndex = item === next ? 0 : -1;
285
- item.dataset.toolbarFocus = String(item === next);
286
- }
287
- next.focus();
288
- };
289
- sync() {
290
- this.observeShadowRoots(this);
291
- const toolbar = this.shadowRoot?.querySelector("[role=toolbar]");
292
- if (!toolbar)
293
- return;
294
- const orientation = this.hasAttribute("vertical") ? (this.getAttribute("vertical") === "false" ? "horizontal" : "vertical") : this.getAttribute("orientation") === "vertical" ? "vertical" : "horizontal";
295
- toolbar.setAttribute("aria-orientation", orientation);
296
- toolbar.setAttribute("aria-label", this.getAttribute("label") || this.getAttribute("aria-label") || "Toolbar");
297
- toolbar.dataset.size = this.getAttribute("size") || "medium";
298
- this.dataset.orientation = orientation;
299
- for (const group of this.querySelectorAll("spui-toolbar-group"))
300
- if (group.closest("spui-toolbar") === this)
301
- group.setAttribute("orientation", orientation);
302
- for (const group of this.querySelectorAll("spui-toolbar-radio-group"))
303
- if (group.closest("spui-toolbar") === this)
304
- group.setAttribute("orientation", orientation);
305
- for (const button of this.querySelectorAll("spui-button,spui-toggle-button,spui-toolbar-radio-button")) {
306
- if (button.closest("spui-toolbar") === this && !button.hasAttribute("size"))
307
- button.setAttribute("size", this.getAttribute("size") || "medium");
308
- }
309
- const separatorOrientation = orientation === "vertical" ? "horizontal" : "vertical";
310
- for (const separator of this.querySelectorAll("spui-toolbar-separator"))
311
- if (separator.closest("spui-toolbar") === this && !separator.hasAttribute("vertical"))
312
- separator.setAttribute("orientation", separatorOrientation);
313
- this.syncItems();
314
- this.syncRadioButtons();
315
- }
316
- syncRadioButtons() {
317
- for (const button of this.querySelectorAll("spui-toolbar-radio-button")) {
318
- if (button.closest("spui-toolbar") !== this)
319
- continue;
320
- const name = button.getAttribute("name") ?? "";
321
- const value = button.getAttribute("value") ?? "";
322
- const checked = Boolean(name && value && this.selectedValues[name]?.includes(value));
323
- button.toggleAttribute("checked", checked);
324
- if (!button.hasAttribute("size") && this.hasAttribute("size"))
325
- button.setAttribute("size", this.getAttribute("size") ?? "medium");
326
- }
327
- for (const button of this.querySelectorAll("spui-toggle-button[name][value]")) {
328
- if (button.closest("spui-toolbar") !== this)
329
- continue;
330
- const name = button.getAttribute("name") ?? "";
331
- const value = button.getAttribute("value") ?? "";
332
- button.toggleAttribute("checked", Boolean(name && value && this.selectedValues[name]?.includes(value)));
333
- if (!button.hasAttribute("size") && this.hasAttribute("size"))
334
- button.setAttribute("size", this.getAttribute("size") ?? "medium");
335
- }
336
- }
337
- onRadioSelect = (event) => {
338
- const { name, value, sourceEvent, currentTarget } = event.detail;
339
- if (!name || !value)
340
- return;
341
- const checkedItems = [value];
342
- if (!this.controlledCheckedValues)
343
- this.uncontrolledCheckedValues = { ...this.uncontrolledCheckedValues, [name]: checkedItems };
344
- this.syncRadioButtons();
345
- this.dispatchEvent(new CustomEvent("spui-checked-value-change", { bubbles: true, composed: true, detail: { name, checkedItems, sourceEvent, currentTarget } }));
346
- };
347
- onToggleChange = (event) => {
348
- const button = event.target;
349
- if (!(button instanceof HTMLElement) || button.tagName.toLowerCase() !== "spui-toggle-button" || button.closest("spui-toolbar") !== this)
350
- return;
351
- const name = button.getAttribute("name") ?? "";
352
- const value = button.getAttribute("value") ?? "";
353
- if (!name || !value)
354
- return;
355
- const checked = new Set(this.selectedValues[name] ?? []);
356
- if (event.detail.checked)
357
- checked.add(value);
358
- else
359
- checked.delete(value);
360
- const checkedItems = [...checked];
361
- if (!this.controlledCheckedValues)
362
- this.uncontrolledCheckedValues = { ...this.uncontrolledCheckedValues, [name]: checkedItems };
363
- this.syncRadioButtons();
364
- this.dispatchEvent(new CustomEvent("spui-checked-value-change", { bubbles: true, composed: true, detail: { name, checkedItems, sourceEvent: event.detail.sourceEvent, currentTarget: event.detail.currentTarget } }));
365
- };
366
- render() {
367
- const shadow = this.attachShadow({ mode: "open" });
368
- const style = document.createElement("style");
369
- style.textContent = `${base}:host{display:block;min-width:0}.toolbar{box-sizing:border-box;display:flex;align-items:center;gap:var(--spui-toolbar-gap,6px);min-width:0;max-width:100%;overflow:auto;overscroll-behavior-inline:contain;scrollbar-width:thin;padding:var(--spui-toolbar-padding,4px);border:1px solid var(--spui-toolbar-border,var(--spui-ui-stroke,var(--colorNeutralStroke2,#e1dfdd)));border-radius:var(--spui-toolbar-radius,var(--spui-control-radius,6px));background:var(--spui-toolbar-background,var(--spui-ui-surface,var(--colorNeutralBackground1,#fff)));color:var(--spui-ui-text,var(--colorNeutralForeground1,#242424));font:inherit}.toolbar:focus-within{outline:var(--spui-toolbar-focus-outline,none)}:host([orientation=vertical]) .toolbar{flex-direction:column;align-items:stretch;width:max-content;max-width:100%;max-height:100%;overflow:auto;overflow-x:hidden}@media(forced-colors:active){.toolbar{border-color:CanvasText;background:Canvas}::slotted(*){forced-color-adjust:auto}}`;
370
- const toolbar = document.createElement("div");
371
- toolbar.className = "toolbar";
372
- toolbar.setAttribute("role", "toolbar");
373
- toolbar.setAttribute("part", "control");
374
- toolbar.tabIndex = -1;
375
- toolbar.append(document.createElement("slot"));
376
- shadow.append(style, toolbar);
377
- this.sync();
378
- }
379
- }
380
- customElements.define("spui-toolbar", SpuiToolbar);
381
- }
@@ -1,76 +0,0 @@
1
- import { type FloatingAlign, type FloatingPlacement } from "./floating-position.js";
2
- export type TooltipRelationship = "label" | "description" | "inaccessible";
3
- export type TooltipAppearance = "normal" | "inverted";
4
- export type TooltipVisibleChangeData = {
5
- visible: boolean;
6
- documentKeyboardEvent?: KeyboardEvent;
7
- };
8
- export type TooltipPosition = FloatingPlacement | "above" | "below" | "before" | "after";
9
- export type TooltipPositioningShorthand = "above" | "above-start" | "above-end" | "below" | "below-start" | "below-end" | "before" | "before-top" | "before-bottom" | "after" | "after-top" | "after-bottom";
10
- export type TooltipPositioningRect = {
11
- x: number;
12
- y: number;
13
- width: number;
14
- height: number;
15
- };
16
- export type TooltipPositioningTargetRect = TooltipPositioningRect & Pick<DOMRectReadOnly, "top" | "left" | "bottom" | "right">;
17
- export type TooltipPositioningTarget = HTMLElement | {
18
- getBoundingClientRect: () => TooltipPositioningTargetRect;
19
- contextElement?: Element;
20
- };
21
- export type TooltipPositioningBoundary = TooltipPositioningRect | HTMLElement | HTMLElement[] | "clippingParents" | "scrollParent" | "window" | null;
22
- export type TooltipPositioningOffsetParams = {
23
- positionedRect: TooltipPositioningRect;
24
- targetRect: TooltipPositioningRect;
25
- position: "above" | "below" | "before" | "after";
26
- alignment?: FloatingAlign;
27
- };
28
- export type TooltipPositioningOffset = number | {
29
- mainAxis: number;
30
- crossAxis?: number;
31
- } | ((params: TooltipPositioningOffsetParams) => number | {
32
- mainAxis: number;
33
- crossAxis?: number;
34
- });
35
- export type TooltipPositioningPlacement = "top" | "top-start" | "top-end" | "right" | "right-start" | "right-end" | "bottom" | "bottom-start" | "bottom-end" | "left" | "left-start" | "left-end";
36
- export type TooltipPositioningEndData = {
37
- placement: TooltipPositioningPlacement;
38
- escaped: boolean;
39
- referenceHidden: boolean;
40
- };
41
- export type TooltipPositioningImperativeRef = {
42
- updatePosition: () => void;
43
- setTarget: (target: TooltipPositioningTarget | null) => void;
44
- };
45
- export type TooltipPositioningRef = {
46
- readonly current: TooltipPositioningImperativeRef | null;
47
- } | ((value: TooltipPositioningImperativeRef | null) => void) | null;
48
- export type TooltipPositioningOptions = {
49
- align?: FloatingAlign;
50
- arrowPadding?: number;
51
- autoSize?: boolean | "always" | "width" | "width-always" | "height" | "height-always";
52
- coverTarget?: boolean;
53
- fallbackPositions?: TooltipPositioningShorthand[];
54
- flipBoundary?: TooltipPositioningBoundary;
55
- matchTargetSize?: "width";
56
- offset?: TooltipPositioningOffset;
57
- onPositioningEnd?: (event: CustomEvent<TooltipPositioningEndData>) => void;
58
- overflowBoundary?: TooltipPositioningBoundary;
59
- overflowBoundaryPadding?: number | Partial<{
60
- top: number;
61
- end: number;
62
- bottom: number;
63
- start: number;
64
- }>;
65
- pinned?: boolean;
66
- position?: TooltipPosition;
67
- positionFixed?: boolean;
68
- positioningRef?: TooltipPositioningRef;
69
- shiftToCoverTarget?: boolean;
70
- strategy?: "absolute" | "fixed";
71
- target?: TooltipPositioningTarget | null;
72
- useTransform?: boolean;
73
- disableUpdateOnResize?: boolean;
74
- };
75
- export type TooltipPositioning = TooltipPosition | TooltipPositioningShorthand | TooltipPositioningOptions;
76
- export declare function defineTooltip(): void;