@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,409 +0,0 @@
1
- const rtlLanguages = new Set(["ar", "arc", "bal", "bcc", "bgn", "bqi", "ckb", "dv", "fa", "glk", "he", "khw", "ks", "lrc", "mzn", "nqo", "ps", "rhg", "sd", "ug", "ur", "yi"]);
2
- const rtlScripts = new Set(["arab", "armi", "avst", "hebr", "mand", "mani", "mend", "nkoo", "phli", "prti", "rohg", "samr", "syrc", "thaa"]);
3
- /** Resolve the normal text direction for a BCP 47 language tag; callers can still honor an explicit dir. */
4
- export function getDirectionFromLanguage(language) {
5
- const tags = language?.trim().replaceAll("_", "-").split("-").filter(Boolean);
6
- if (!tags?.length)
7
- return undefined;
8
- const script = tags.slice(1).find(tag => /^[a-z]{4}$/i.test(tag));
9
- return script ? rtlScripts.has(script.toLowerCase()) ? "rtl" : "ltr" : rtlLanguages.has(tags[0].toLowerCase()) ? "rtl" : "ltr";
10
- }
11
- const rtlLanguageTags = ["ar", "arc", "bal", "bcc", "bgn", "bqi", "ckb", "dv", "fa", "glk", "he", "khw", "ks", "lrc", "mzn", "nqo", "ps", "rhg", "sd", "ug", "ur", "yi", "az-Arab", "ku-Arab", "ms-Arab", "pa-Arab", "uz-Arab", "kk-Arab", "ky-Arab", "tt-Arab"];
12
- const ltrScriptTags = ["ar-Latn", "fa-Latn", "he-Latn", "ks-Deva", "sd-Deva", "ur-Latn", "ug-Latn", "yi-Latn"];
13
- export const directionByLanguage = `${rtlLanguageTags.map(tag => `:host(:lang(${tag}):not([dir]))`).join(",")}{direction:rtl}${ltrScriptTags.map(tag => `:host(:lang(${tag}):not([dir]))`).join(",")}{direction:ltr}`;
14
- export const base = `:host{font:inherit;font-family:var(--spui-font-family,inherit);color:var(--spui-ui-text,var(--spui-semantic-body-text,var(--colorNeutralForeground1,#323130)));color-scheme:var(--spui-color-scheme,light dark)}${directionByLanguage}button,input,textarea{font:inherit;font-family:var(--spui-font-family,inherit)}button:focus-visible,input:focus-visible,textarea:focus-visible{outline:2px solid var(--spui-focus-ring,var(--spui-semantic-focus-border,var(--colorStrokeFocus2,#005a9e)));outline-offset:2px}`;
15
- const accessibleNameSyncStates = new WeakMap();
16
- function stopHostAccessibleNameObserver(host, control) {
17
- const hostStates = accessibleNameSyncStates.get(host);
18
- const states = control ? [hostStates?.get(control)].filter((state) => Boolean(state)) : [...(hostStates?.values() ?? [])];
19
- for (const state of states) {
20
- state.observer?.disconnect();
21
- state.observer = undefined;
22
- }
23
- }
24
- function stopHostAccessibleDescriptionObserver(host, control) {
25
- const hostStates = accessibleNameSyncStates.get(host);
26
- const states = control ? [hostStates?.get(control)].filter((state) => Boolean(state)) : [...(hostStates?.values() ?? [])];
27
- for (const state of states) {
28
- state.descriptionObserver?.disconnect();
29
- state.descriptionObserver = undefined;
30
- }
31
- }
32
- export function stopHostAccessibleNameSync(host) {
33
- stopHostAccessibleNameObserver(host);
34
- stopHostAccessibleDescriptionObserver(host);
35
- for (const state of accessibleNameSyncStates.get(host)?.values() ?? []) {
36
- state.labelledBy = undefined;
37
- state.describedBy = undefined;
38
- }
39
- }
40
- function accessibleNameRoots(context) {
41
- const isDocument = context.nodeType === Node.DOCUMENT_NODE;
42
- const root = isDocument ? context : context.getRootNode();
43
- const document = isDocument ? context : context.ownerDocument;
44
- return [...new Set([root, document].filter((value) => value != null && (value.nodeType === Node.DOCUMENT_NODE || (value.nodeType === Node.DOCUMENT_FRAGMENT_NODE && "host" in value))))];
45
- }
46
- function accessibleNameHidden(element) {
47
- const view = element.ownerDocument.defaultView;
48
- let current = element;
49
- while (current) {
50
- if (current.hasAttribute("hidden") || current.getAttribute("aria-hidden") === "true")
51
- return true;
52
- if (view) {
53
- const style = view.getComputedStyle(current);
54
- if (style.display === "none" || style.visibility === "hidden" || style.visibility === "collapse" || style.contentVisibility === "hidden")
55
- return true;
56
- }
57
- if (current.parentElement)
58
- current = current.parentElement;
59
- else {
60
- const root = current.getRootNode();
61
- current = root.nodeType === Node.DOCUMENT_FRAGMENT_NODE && "host" in root ? root.host : null;
62
- }
63
- }
64
- return false;
65
- }
66
- function normalizeAccessibleText(value) {
67
- return value.replace(/\s+/g, " ").trim();
68
- }
69
- function resolveAccessibleText(context, labelledBy) {
70
- const roots = accessibleNameRoots(context);
71
- const targets = new Set();
72
- const contentPath = new Set();
73
- let unresolved = false;
74
- const find = (id) => {
75
- for (const root of roots) {
76
- const target = root.getElementById(id);
77
- if (target)
78
- return target;
79
- }
80
- return null;
81
- };
82
- const resolveIds = (ids, path) => ids.trim().split(/\s+/).filter(Boolean).map(id => {
83
- const target = find(id);
84
- if (!target) {
85
- unresolved = true;
86
- return "";
87
- }
88
- return nameOf(target, path, true);
89
- }).filter(Boolean).join(" ");
90
- const nameOf = (element, path, referenced) => {
91
- targets.add(element);
92
- const alreadyReferenced = path.has(element);
93
- const repeatedContent = contentPath.has(element);
94
- const addedReference = referenced && !alreadyReferenced;
95
- if (addedReference)
96
- path.add(element);
97
- const addedContent = !repeatedContent;
98
- if (addedContent)
99
- contentPath.add(element);
100
- try {
101
- const hidden = accessibleNameHidden(element);
102
- if (hidden && !referenced)
103
- return "";
104
- const includeHiddenDescendants = hidden && referenced;
105
- if (referenced && ["none", "presentation"].includes(element.getAttribute("role") ?? ""))
106
- return "";
107
- const labelledByValue = element.getAttribute("aria-labelledby");
108
- if (labelledByValue && !alreadyReferenced) {
109
- const name = resolveIds(labelledByValue, path);
110
- if (name)
111
- return name;
112
- }
113
- const embedded = referenced || element.closest("label") !== null;
114
- if (embedded) {
115
- const role = element.getAttribute("role");
116
- if (role === "textbox" && element.isContentEditable)
117
- return normalizeAccessibleText(element.textContent ?? "");
118
- if (["slider", "spinbutton", "scrollbar", "progressbar"].includes(role ?? "")) {
119
- const valueText = element.getAttribute("aria-valuetext");
120
- if (valueText !== null)
121
- return normalizeAccessibleText(valueText);
122
- const valueNow = element.getAttribute("aria-valuenow");
123
- if (valueNow !== null)
124
- return normalizeAccessibleText(valueNow);
125
- }
126
- if (element.localName === "input") {
127
- const input = element;
128
- if (["text", "search", "url", "tel", "email", "password", "number"].includes(input.type))
129
- return normalizeAccessibleText(input.value);
130
- if (input.type === "range")
131
- return normalizeAccessibleText(input.value);
132
- }
133
- if (element.localName === "textarea")
134
- return normalizeAccessibleText(element.value);
135
- if (element.localName === "select") {
136
- const selected = [...element.selectedOptions].map(option => normalizeAccessibleText(option.textContent ?? "")).filter(Boolean);
137
- return selected.join(" ");
138
- }
139
- }
140
- const ariaLabel = element.getAttribute("aria-label");
141
- if (ariaLabel?.trim())
142
- return normalizeAccessibleText(ariaLabel);
143
- if (element.localName === "img" && element.hasAttribute("alt"))
144
- return normalizeAccessibleText(element.getAttribute("alt") ?? "");
145
- if (element.localName === "input") {
146
- const input = element;
147
- if (input.type === "image" && element.hasAttribute("alt"))
148
- return normalizeAccessibleText(element.getAttribute("alt") ?? "");
149
- if (["button", "submit", "reset"].includes(input.type) && input.value)
150
- return normalizeAccessibleText(input.value);
151
- }
152
- if (element.namespaceURI === "http://www.w3.org/2000/svg" && element.localName === "svg") {
153
- const title = element.querySelector(":scope > title")?.textContent;
154
- if (title?.trim())
155
- return normalizeAccessibleText(title);
156
- }
157
- const text = [...element.childNodes].map(node => {
158
- if (node.nodeType === Node.TEXT_NODE)
159
- return normalizeAccessibleText(node.textContent ?? "");
160
- return node.nodeType === Node.ELEMENT_NODE && !repeatedContent ? nameOf(node, path, includeHiddenDescendants) : "";
161
- }).filter(Boolean).join(" ");
162
- return normalizeAccessibleText(text || element.getAttribute("title") || "");
163
- }
164
- finally {
165
- if (addedReference)
166
- path.delete(element);
167
- if (addedContent)
168
- contentPath.delete(element);
169
- }
170
- };
171
- return { text: resolveIds(labelledBy, new Set()), targets, unresolved };
172
- }
173
- export function observeAccessibleTextFromIdRefs(context, labelledBy, onText) {
174
- const view = context.ownerDocument.defaultView;
175
- const Observer = view?.MutationObserver ?? MutationObserver;
176
- const observer = new Observer(() => update());
177
- const roots = accessibleNameRoots(context);
178
- const valueListeners = new Map();
179
- const removeValueListeners = () => {
180
- for (const [target, listener] of valueListeners) {
181
- target.removeEventListener("input", listener);
182
- target.removeEventListener("change", listener);
183
- }
184
- valueListeners.clear();
185
- };
186
- const disconnectNative = observer.disconnect.bind(observer);
187
- const update = () => {
188
- const result = resolveAccessibleText(context, labelledBy);
189
- onText(result.text);
190
- disconnectNative();
191
- removeValueListeners();
192
- const subscriptions = new Map();
193
- const add = (node, options) => {
194
- const current = subscriptions.get(node) ?? {};
195
- const filters = new Set([...(current.attributeFilter ?? []), ...(options.attributeFilter ?? [])]);
196
- subscriptions.set(node, {
197
- childList: current.childList || options.childList,
198
- subtree: current.subtree || options.subtree,
199
- characterData: current.characterData || options.characterData,
200
- attributes: current.attributes || options.attributes,
201
- ...(filters.size ? { attributeFilter: [...filters] } : {}),
202
- });
203
- };
204
- for (const target of result.targets) {
205
- add(target, { subtree: true, childList: true, characterData: true, attributes: true, attributeFilter: ["aria-label", "aria-labelledby", "alt", "title", "hidden", "aria-hidden", "id", "value", "class", "style"] });
206
- if (target.parentNode)
207
- add(target.parentNode, { childList: true });
208
- for (let parent = target.parentElement; parent; parent = parent.parentElement) {
209
- add(parent, { attributes: true, attributeFilter: ["class", "style", "hidden", "aria-hidden"] });
210
- }
211
- }
212
- if (result.unresolved)
213
- for (const root of roots)
214
- add(root, { subtree: true, childList: true, attributes: true, attributeFilter: ["id"] });
215
- for (const [node, options] of subscriptions)
216
- observer.observe(node, options);
217
- for (const target of result.targets)
218
- if (["input", "textarea", "select"].includes(target.localName)) {
219
- const listener = () => update();
220
- target.addEventListener("input", listener);
221
- target.addEventListener("change", listener);
222
- valueListeners.set(target, listener);
223
- }
224
- };
225
- update();
226
- return { disconnect: () => { disconnectNative(); removeValueListeners(); } };
227
- }
228
- export function resolveAccessibleTextFromIdRefs(context, labelledBy) {
229
- return resolveAccessibleText(context, labelledBy).text;
230
- }
231
- function syncHostAccessibleDescription(host, control, state) {
232
- const description = host.getAttribute("aria-description");
233
- const describedBy = host.getAttribute("aria-describedby");
234
- const setResolvedDescription = (text) => {
235
- const value = host.hasAttribute("data-spui-field-description") ? [text, description].filter(Boolean).join(" ") : text;
236
- if (value) {
237
- if (control.getAttribute("aria-description") !== value)
238
- control.setAttribute("aria-description", value);
239
- }
240
- else if (control.hasAttribute("aria-description"))
241
- control.removeAttribute("aria-description");
242
- };
243
- if (describedBy !== null) {
244
- const ids = describedBy.trim().split(/\s+/).filter(Boolean);
245
- const localRoot = control.getRootNode();
246
- if (ids.length && ids.every(id => localRoot.getElementById(id))) {
247
- stopHostAccessibleDescriptionObserver(host, control);
248
- state.describedBy = describedBy;
249
- state.resolvedDescription = undefined;
250
- if (control.getAttribute("aria-describedby") !== describedBy)
251
- control.setAttribute("aria-describedby", describedBy);
252
- if (description === null)
253
- control.removeAttribute("aria-description");
254
- else if (control.getAttribute("aria-description") !== description)
255
- control.setAttribute("aria-description", description);
256
- return;
257
- }
258
- if (control.hasAttribute("aria-describedby"))
259
- control.removeAttribute("aria-describedby");
260
- if (state.describedBy !== describedBy || !state.descriptionObserver) {
261
- stopHostAccessibleDescriptionObserver(host, control);
262
- state.describedBy = describedBy;
263
- state.descriptionObserver = observeAccessibleTextFromIdRefs(host, describedBy, text => {
264
- state.resolvedDescription = text;
265
- setResolvedDescription(text);
266
- });
267
- }
268
- else {
269
- setResolvedDescription(state.resolvedDescription ?? "");
270
- }
271
- return;
272
- }
273
- stopHostAccessibleDescriptionObserver(host, control);
274
- state.describedBy = null;
275
- state.resolvedDescription = undefined;
276
- if (state.originalDescribedBy === null)
277
- control.removeAttribute("aria-describedby");
278
- else if (control.getAttribute("aria-describedby") !== state.originalDescribedBy)
279
- control.setAttribute("aria-describedby", state.originalDescribedBy);
280
- if (description === null) {
281
- if (state.originalDescription === null)
282
- control.removeAttribute("aria-description");
283
- else if (control.getAttribute("aria-description") !== state.originalDescription)
284
- control.setAttribute("aria-description", state.originalDescription);
285
- }
286
- else if (control.getAttribute("aria-description") !== description)
287
- control.setAttribute("aria-description", description);
288
- }
289
- export function syncHostAccessibleName(host, control) {
290
- const label = host.getAttribute("aria-label");
291
- const labelledBy = host.getAttribute("aria-labelledby");
292
- const description = host.getAttribute("aria-description");
293
- const describedBy = host.getAttribute("aria-describedby");
294
- const root = control.getRootNode();
295
- const inShadowRoot = host.shadowRoot?.contains(control) ?? false;
296
- // Most controls live inside the host's shadow root, but compound React adapters
297
- // can provide the active control as a slotted light-DOM child. In that case the
298
- // host and control share the same tree, so native ID references can be forwarded
299
- // directly instead of being ignored.
300
- if (!inShadowRoot && host.getRootNode() !== root)
301
- return;
302
- let hostStates = accessibleNameSyncStates.get(host);
303
- if (!hostStates) {
304
- hostStates = new Map();
305
- accessibleNameSyncStates.set(host, hostStates);
306
- }
307
- let state = hostStates.get(control);
308
- if (!state) {
309
- state = {
310
- control,
311
- originalLabel: control.getAttribute("aria-label") === label ? null : control.getAttribute("aria-label"),
312
- originalLabelledBy: control.getAttribute("aria-labelledby") === labelledBy ? null : control.getAttribute("aria-labelledby"),
313
- originalDescription: control.getAttribute("aria-description") === description ? null : control.getAttribute("aria-description"),
314
- originalDescribedBy: control.getAttribute("aria-describedby") === describedBy ? null : control.getAttribute("aria-describedby"),
315
- };
316
- hostStates.set(control, state);
317
- }
318
- if (label === null && labelledBy === null) {
319
- stopHostAccessibleNameObserver(host, control);
320
- if (state.originalLabel === null)
321
- control.removeAttribute("aria-label");
322
- else
323
- control.setAttribute("aria-label", state.originalLabel);
324
- if (state.originalLabelledBy === null)
325
- control.removeAttribute("aria-labelledby");
326
- else
327
- control.setAttribute("aria-labelledby", state.originalLabelledBy);
328
- syncHostAccessibleDescription(host, control, state);
329
- if (description === null && describedBy === null) {
330
- hostStates.delete(control);
331
- if (hostStates.size === 0)
332
- accessibleNameSyncStates.delete(host);
333
- }
334
- return;
335
- }
336
- if (labelledBy !== null && inShadowRoot) {
337
- const ids = labelledBy.trim().split(/\s+/).filter(Boolean);
338
- const localRoot = root;
339
- if (ids.length && ids.every(id => localRoot.getElementById(id))) {
340
- stopHostAccessibleNameObserver(host, control);
341
- state.labelledBy = labelledBy;
342
- control.removeAttribute("aria-label");
343
- control.setAttribute("aria-labelledby", labelledBy);
344
- syncHostAccessibleDescription(host, control, state);
345
- return;
346
- }
347
- control.removeAttribute("aria-labelledby");
348
- if (state.labelledBy !== labelledBy || !state.observer) {
349
- stopHostAccessibleNameObserver(host, control);
350
- state.labelledBy = labelledBy;
351
- state.observer = observeAccessibleTextFromIdRefs(host, labelledBy, resolved => {
352
- if (resolved) {
353
- if (control.getAttribute("aria-label") !== resolved)
354
- control.setAttribute("aria-label", resolved);
355
- }
356
- else if (control.hasAttribute("aria-label"))
357
- control.removeAttribute("aria-label");
358
- });
359
- }
360
- syncHostAccessibleDescription(host, control, state);
361
- return;
362
- }
363
- stopHostAccessibleNameObserver(host, control);
364
- state.labelledBy = labelledBy;
365
- if (labelledBy !== null)
366
- control.setAttribute("aria-labelledby", labelledBy);
367
- else
368
- control.removeAttribute("aria-labelledby");
369
- if (labelledBy === null && label !== null)
370
- control.setAttribute("aria-label", label);
371
- else
372
- control.removeAttribute("aria-label");
373
- syncHostAccessibleDescription(host, control, state);
374
- }
375
- export function rememberNativeFormControlDefaults(current, control) {
376
- if (current?.control === control)
377
- return current;
378
- return {
379
- control,
380
- disabled: control.disabled,
381
- required: control.required,
382
- readOnly: "readOnly" in control && control.readOnly,
383
- multiple: "multiple" in control && control.multiple,
384
- value: control.value,
385
- defaultValue: "defaultValue" in control ? control.defaultValue : control.value,
386
- checked: "checked" in control && control.checked,
387
- defaultChecked: "defaultChecked" in control && control.defaultChecked,
388
- };
389
- }
390
- export function findFocusable(root) {
391
- const selector = "button,a[href],input:not([type=hidden]),select,textarea,[tabindex],slot";
392
- const candidates = [...(root instanceof HTMLElement && root.matches(selector) ? [root] : []), ...root.querySelectorAll(selector)];
393
- for (const node of candidates) {
394
- if (!node.hasAttribute("disabled") && node.tabIndex >= 0 && node.getClientRects().length)
395
- return node;
396
- if (node.shadowRoot) {
397
- const nested = findFocusable(node.shadowRoot);
398
- if (nested)
399
- return nested;
400
- }
401
- if (node instanceof HTMLSlotElement)
402
- for (const assigned of node.assignedElements({ flatten: true })) {
403
- const nested = findFocusable(assigned);
404
- if (nested)
405
- return nested;
406
- }
407
- }
408
- return undefined;
409
- }
@@ -1 +0,0 @@
1
- export declare function defineSharePointFieldBasicControls(): void;
@@ -1,14 +0,0 @@
1
- import { defineButton } from "./button.js";
2
- import { defineInput } from "./input.js";
3
- import { defineTextArea } from "./textarea.js";
4
- import { defineSelect } from "./select.js";
5
- import { defineRadioGroup } from "./radio-group.js";
6
- import { defineCheckbox } from "./toggle.js";
7
- export function defineSharePointFieldBasicControls() {
8
- defineButton();
9
- defineInput();
10
- defineTextArea();
11
- defineSelect();
12
- defineRadioGroup();
13
- defineCheckbox();
14
- }
@@ -1,29 +0,0 @@
1
- import { type SharePointFieldMetadata, type SharePointFieldValue } from "../sharepoint-fields.js";
2
- export type SharePointFieldOption = {
3
- value: string | number;
4
- label: string;
5
- disabled?: boolean;
6
- };
7
- export type SharePointFieldValueChangeDetail = {
8
- field: SharePointFieldMetadata;
9
- value: SharePointFieldValue;
10
- };
11
- export type SharePointFieldElement = HTMLElement & {
12
- field: SharePointFieldMetadata | undefined;
13
- value: SharePointFieldValue | undefined;
14
- defaultValue: SharePointFieldValue | undefined;
15
- options: readonly SharePointFieldOption[];
16
- disabled: boolean;
17
- onValueChange?: (value: SharePointFieldValue, field: SharePointFieldMetadata) => void;
18
- renderUnsupported?: (field: SharePointFieldMetadata, reason: string) => Node | null;
19
- };
20
- declare global {
21
- interface HTMLElementTagNameMap {
22
- "spui-sharepoint-field": SharePointFieldElement;
23
- }
24
- interface HTMLElementEventMap {
25
- "spui-field-value-change": CustomEvent<SharePointFieldValueChangeDetail>;
26
- }
27
- }
28
- /** Render SharePoint field metadata as a framework-free, theme-aware form control. */
29
- export declare function defineSharePointField(): void;