@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,460 +0,0 @@
1
- import { getSharePointFieldAdapter, } from "../sharepoint-fields.js";
2
- import { createFormField } from "./field-composition.js";
3
- import { defineSharePointFieldBasicControls } from "./sharepoint-field-basic-controls.js";
4
- const textValue = (value) => {
5
- if (value == null)
6
- return "";
7
- if (value instanceof Date) {
8
- const pad = (part) => String(part).padStart(2, "0");
9
- return `${value.getFullYear()}-${pad(value.getMonth() + 1)}-${pad(value.getDate())}${value.getHours() || value.getMinutes() ? `T${pad(value.getHours())}:${pad(value.getMinutes())}` : ""}`;
10
- }
11
- if (typeof value === "object" && "url" in value)
12
- return value.url;
13
- return String(value);
14
- };
15
- function makeOption(tag, option) {
16
- const element = document.createElement(tag);
17
- element.setAttribute("value", String(option.value));
18
- element.setAttribute(tag === "option" ? "value" : "label", tag === "option" ? String(option.value) : option.label);
19
- if (tag === "option")
20
- element.textContent = option.label;
21
- else
22
- element.textContent = option.label;
23
- if (option.disabled)
24
- element.setAttribute("disabled", "");
25
- return element;
26
- }
27
- async function loadFieldControl(adapter) {
28
- switch (adapter.control) {
29
- case "input":
30
- case "read-only":
31
- case "textarea":
32
- case "radio-group":
33
- case "checkbox":
34
- case "multi-choice":
35
- case "select":
36
- if (adapter.control === "select" && adapter.allowFillIn && !customElements.get("spui-combobox")) {
37
- await import(/* webpackChunkName: "spui-sharepoint-field-freeform-choice" */ "./combobox.js").then(module => module.defineCombobox());
38
- }
39
- return;
40
- case "rich-text-editor":
41
- if (!customElements.get("spui-rich-text-editor"))
42
- (await import(/* webpackChunkName: "spui-sharepoint-field-rich-text" */ "./rich-text-editor.js")).defineRichTextEditor();
43
- break;
44
- case "date-picker":
45
- if (!customElements.get("spui-date-picker"))
46
- (await import(/* webpackChunkName: "spui-sharepoint-field-date" */ "./date-picker.js")).defineDatePicker();
47
- break;
48
- case "combobox":
49
- if (!customElements.get("spui-combobox"))
50
- (await import(/* webpackChunkName: "spui-sharepoint-field-lookup" */ "./combobox.js")).defineCombobox();
51
- break;
52
- }
53
- }
54
- /** Render SharePoint field metadata as a framework-free, theme-aware form control. */
55
- export function defineSharePointField() {
56
- if (customElements.get("spui-sharepoint-field"))
57
- return;
58
- defineSharePointFieldBasicControls();
59
- class SpuiSharePointField extends HTMLElement {
60
- static observedAttributes = ["field", "value", "disabled", "hint", "validation-message", "empty-option-label", "add-choice-label"];
61
- fieldValue;
62
- currentValue;
63
- initialValue;
64
- currentOptions = [];
65
- hasProvidedOptions = false;
66
- controlled = false;
67
- renderVersion = 0;
68
- valueChangeCallback;
69
- unsupportedRenderer;
70
- get field() { return this.fieldValue; }
71
- set field(value) { this.fieldValue = value; if (this.isConnected)
72
- this.render(); }
73
- get value() { return this.currentValue; }
74
- set value(value) {
75
- this.controlled = true;
76
- this.currentValue = value;
77
- this.syncControlValue();
78
- }
79
- get defaultValue() { return this.initialValue; }
80
- set defaultValue(value) {
81
- this.initialValue = value;
82
- if (!this.controlled)
83
- this.currentValue = value;
84
- if (this.isConnected)
85
- this.render();
86
- }
87
- get options() { return this.currentOptions; }
88
- set options(value) { this.currentOptions = [...(value ?? [])]; this.hasProvidedOptions = true; if (this.isConnected)
89
- this.render(); }
90
- get disabled() { return this.hasAttribute("disabled"); }
91
- set disabled(value) { this.toggleAttribute("disabled", Boolean(value)); }
92
- get onValueChange() { return this.valueChangeCallback; }
93
- set onValueChange(value) { this.valueChangeCallback = value; }
94
- get renderUnsupported() { return this.unsupportedRenderer; }
95
- set renderUnsupported(value) { this.unsupportedRenderer = value; }
96
- attributeChangedCallback(name, _oldValue, value) {
97
- if (!this.isConnected)
98
- return;
99
- if (name === "field") {
100
- try {
101
- this.fieldValue = value ? JSON.parse(value) : undefined;
102
- }
103
- catch {
104
- this.fieldValue = undefined;
105
- }
106
- this.render();
107
- }
108
- else if (name === "value") {
109
- if (!this.controlled) {
110
- this.currentValue = value;
111
- this.initialValue = value;
112
- }
113
- this.syncControlValue();
114
- }
115
- else
116
- this.render();
117
- }
118
- connectedCallback() {
119
- if (!this.fieldValue) {
120
- const encoded = this.getAttribute("field");
121
- if (encoded) {
122
- try {
123
- this.fieldValue = JSON.parse(encoded);
124
- }
125
- catch { /* Keep a useful fallback below. */ }
126
- }
127
- }
128
- if (this.currentValue === undefined && this.hasAttribute("value"))
129
- this.currentValue = this.getAttribute("value");
130
- if (this.initialValue === undefined && this.hasAttribute("value"))
131
- this.initialValue = this.getAttribute("value");
132
- this.render();
133
- }
134
- async render() {
135
- const renderVersion = ++this.renderVersion;
136
- const field = this.fieldValue;
137
- if (!field) {
138
- this.hidden = false;
139
- this.removeAttribute("aria-busy");
140
- this.replaceChildren();
141
- return;
142
- }
143
- const adapter = getSharePointFieldAdapter(field);
144
- this.setAttribute("aria-busy", "true");
145
- try {
146
- await loadFieldControl(adapter);
147
- if (!this.isConnected || renderVersion !== this.renderVersion)
148
- return;
149
- this.removeAttribute("aria-busy");
150
- const options = this.hasProvidedOptions ? this.currentOptions : (adapter.choices ?? []).map(value => ({ value, label: value }));
151
- const label = adapter.label || adapter.name || adapter.fieldType;
152
- const value = this.currentValue;
153
- const valueText = textValue(value);
154
- const defaultValueText = textValue(this.initialValue);
155
- const name = adapter.name || undefined;
156
- const disabled = this.hasAttribute("disabled");
157
- const controlDisabled = disabled || (adapter.readOnly && !["input", "textarea", "rich-text-editor"].includes(adapter.control));
158
- let control;
159
- const setBasics = (element) => {
160
- if (name)
161
- element.setAttribute("name", name);
162
- if (adapter.required)
163
- element.setAttribute("required", "");
164
- if (controlDisabled)
165
- element.setAttribute("disabled", "");
166
- return element;
167
- };
168
- const selectOptions = (element, tag) => {
169
- if (tag === "option") {
170
- const empty = document.createElement("option");
171
- empty.value = "";
172
- empty.textContent = this.getAttribute("empty-option-label") ?? "Select an option";
173
- empty.disabled = adapter.required;
174
- element.append(empty, ...options.map(option => makeOption(tag, option)));
175
- }
176
- else
177
- element.append(...options.map(option => makeOption(tag, option)));
178
- };
179
- switch (adapter.control) {
180
- case "input": {
181
- const input = setBasics(document.createElement("spui-input"));
182
- input.setAttribute("type", adapter.inputType ?? "text");
183
- if (this.initialValue !== undefined)
184
- input.setAttribute("value", defaultValueText);
185
- if (adapter.min !== undefined)
186
- input.setAttribute("min", String(adapter.min));
187
- if (adapter.max !== undefined)
188
- input.setAttribute("max", String(adapter.max));
189
- if (adapter.step !== undefined)
190
- input.setAttribute("step", String(adapter.step));
191
- if (adapter.maxLength !== undefined)
192
- input.setAttribute("maxlength", String(adapter.maxLength));
193
- if (adapter.readOnly)
194
- input.setAttribute("read-only", "");
195
- input.value = valueText;
196
- control = input;
197
- break;
198
- }
199
- case "textarea": {
200
- const textarea = setBasics(document.createElement("spui-textarea"));
201
- if (this.initialValue !== undefined)
202
- textarea.setAttribute("value", defaultValueText);
203
- if (adapter.maxLength !== undefined)
204
- textarea.setAttribute("maxlength", String(adapter.maxLength));
205
- if (adapter.readOnly)
206
- textarea.setAttribute("read-only", "");
207
- textarea.value = valueText;
208
- control = textarea;
209
- break;
210
- }
211
- case "rich-text-editor": {
212
- const editor = setBasics(document.createElement("spui-rich-text-editor"));
213
- if (this.initialValue !== undefined)
214
- editor.setAttribute("value", defaultValueText);
215
- editor.setAttribute("content-mode", adapter.richText?.contentMode ?? "rich");
216
- if (adapter.richText?.allowHyperlink === false)
217
- editor.setAttribute("allow-hyperlink", "false");
218
- if (adapter.readOnly)
219
- editor.setAttribute("read-only", "");
220
- editor.value = valueText;
221
- control = editor;
222
- break;
223
- }
224
- case "select": {
225
- if (adapter.allowFillIn) {
226
- const combo = setBasics(document.createElement("spui-combobox"));
227
- combo.setAttribute("allow-freeform", "");
228
- combo.setAttribute("placeholder", this.getAttribute("empty-option-label") ?? "Select an option");
229
- selectOptions(combo, "spui-combobox-option");
230
- combo.value = valueText;
231
- control = combo;
232
- }
233
- else {
234
- const select = setBasics(document.createElement("spui-select"));
235
- selectOptions(select, "option");
236
- if (this.initialValue !== undefined)
237
- select.setAttribute("default-value", defaultValueText);
238
- select.value = valueText;
239
- control = select;
240
- }
241
- break;
242
- }
243
- case "radio-group": {
244
- const radio = setBasics(document.createElement("spui-radio-group"));
245
- selectOptions(radio, "spui-radio-option");
246
- if (this.initialValue !== undefined)
247
- radio.setAttribute("default-value", defaultValueText);
248
- radio.value = valueText;
249
- control = radio;
250
- break;
251
- }
252
- case "checkbox": {
253
- const checkbox = setBasics(document.createElement("spui-checkbox"));
254
- checkbox.setAttribute("label", label);
255
- if (this.initialValue !== undefined)
256
- checkbox.defaultChecked = this.initialValue === true || this.initialValue === "true";
257
- checkbox.checked = value === true || value === "true";
258
- control = checkbox;
259
- break;
260
- }
261
- case "multi-choice": {
262
- const group = document.createElement("fieldset");
263
- group.style.minWidth = "0";
264
- group.style.margin = "0";
265
- group.style.padding = "0";
266
- group.style.border = "0";
267
- group.style.display = "grid";
268
- group.style.gap = "var(--spui-control-gap,6px)";
269
- const legend = document.createElement("legend");
270
- legend.textContent = label;
271
- group.append(legend);
272
- const selected = Array.isArray(value) ? value.map(String) : [];
273
- const visibleOptions = [...options];
274
- const initialSelected = Array.isArray(this.initialValue) ? this.initialValue.map(String) : [];
275
- for (const selectedValue of [...selected, ...initialSelected])
276
- if (!visibleOptions.some(option => String(option.value) === selectedValue))
277
- visibleOptions.push({ value: selectedValue, label: selectedValue });
278
- for (const option of visibleOptions) {
279
- const checkbox = document.createElement("spui-checkbox");
280
- checkbox.setAttribute("label", option.label);
281
- checkbox.setAttribute("value", String(option.value));
282
- if (option.disabled || controlDisabled)
283
- checkbox.setAttribute("disabled", "");
284
- if (Array.isArray(this.initialValue) && this.initialValue.map(String).includes(String(option.value)))
285
- checkbox.setAttribute("default-checked", "");
286
- checkbox.checked = selected.includes(String(option.value));
287
- group.append(checkbox);
288
- }
289
- if (adapter.allowFillIn) {
290
- const fillIn = document.createElement("spui-input");
291
- fillIn.setAttribute("type", "text");
292
- fillIn.setAttribute("aria-label", this.getAttribute("add-choice-label") ?? "Add another choice");
293
- const add = document.createElement("spui-button");
294
- add.setAttribute("appearance", "secondary");
295
- add.textContent = this.getAttribute("add-choice-label") ?? "Add another choice";
296
- if (controlDisabled)
297
- add.setAttribute("disabled", "");
298
- const addFillIn = () => {
299
- const choice = fillIn.value?.trim() ?? "";
300
- if (!choice || selected.includes(choice))
301
- return;
302
- this.acceptValue([...selected, choice]);
303
- fillIn.value = "";
304
- };
305
- fillIn.addEventListener("keydown", event => { if (event instanceof KeyboardEvent && event.key === "Enter") {
306
- event.preventDefault();
307
- addFillIn();
308
- } });
309
- add.addEventListener("click", addFillIn);
310
- const fillInRow = document.createElement("div");
311
- fillInRow.append(fillIn, add);
312
- group.append(fillInRow);
313
- fillInRow.style.display = "flex";
314
- fillInRow.style.alignItems = "end";
315
- fillInRow.style.gap = "var(--spui-control-gap,8px)";
316
- }
317
- control = group;
318
- break;
319
- }
320
- case "date-picker": {
321
- const datePicker = setBasics(document.createElement("spui-date-picker"));
322
- if (this.initialValue !== undefined)
323
- datePicker.setAttribute("value", textValue(this.initialValue));
324
- datePicker.value = valueText;
325
- control = datePicker;
326
- break;
327
- }
328
- case "combobox": {
329
- const combo = setBasics(document.createElement("spui-combobox"));
330
- if (adapter.multiple)
331
- combo.setAttribute("multiselect", "");
332
- combo.setAttribute("placeholder", this.getAttribute("empty-option-label") ?? "Select an option");
333
- selectOptions(combo, "spui-combobox-option");
334
- if (adapter.multiple) {
335
- if (Array.isArray(this.initialValue))
336
- combo.setAttribute("default-selected-options", JSON.stringify(this.initialValue.map(String)));
337
- combo.selectedOptions = Array.isArray(value) ? value.map(String) : [];
338
- }
339
- else {
340
- if (this.initialValue !== undefined) {
341
- combo.setAttribute("selected-value", defaultValueText);
342
- combo.setAttribute("value", options.find(option => String(option.value) === defaultValueText)?.label ?? defaultValueText);
343
- }
344
- combo.selectedValue = valueText;
345
- combo.value = options.find(option => String(option.value) === valueText)?.label ?? valueText;
346
- }
347
- control = combo;
348
- break;
349
- }
350
- case "read-only": {
351
- const readonly = setBasics(document.createElement("spui-input"));
352
- readonly.setAttribute("type", "text");
353
- readonly.setAttribute("read-only", "");
354
- readonly.value = valueText;
355
- control = readonly;
356
- break;
357
- }
358
- case "unsupported": {
359
- const custom = this.renderUnsupported?.(field, adapter.unsupportedReason ?? "No renderer is registered for this SharePoint field type.");
360
- const fallback = custom ?? Object.assign(document.createElement("div"), { textContent: `This SharePoint field type needs a custom renderer (${adapter.fieldType}).` });
361
- if (!custom && fallback instanceof HTMLElement)
362
- fallback.setAttribute("role", "note");
363
- control = fallback;
364
- break;
365
- }
366
- }
367
- const wrapper = createFormField(control, {
368
- id: this.id ? `${this.id}-field` : undefined,
369
- className: this.getAttribute("class") ?? undefined,
370
- label: adapter.control === "multi-choice" ? undefined : label,
371
- hint: this.getAttribute("hint") ?? adapter.description,
372
- validationMessage: this.getAttribute("validation-message") ?? undefined,
373
- required: adapter.required,
374
- disabled,
375
- });
376
- wrapper.dataset.sharePointField = adapter.name || adapter.fieldType;
377
- this.hidden = adapter.hidden;
378
- this.replaceChildren(wrapper);
379
- }
380
- catch {
381
- if (!this.isConnected || renderVersion !== this.renderVersion)
382
- return;
383
- this.removeAttribute("aria-busy");
384
- const error = document.createElement("div");
385
- error.setAttribute("role", "alert");
386
- error.textContent = "The field control could not be loaded.";
387
- this.replaceChildren(error);
388
- }
389
- }
390
- syncControlValue() {
391
- const wrapper = this.querySelector(".spui-form-field");
392
- const first = wrapper?.firstElementChild;
393
- const control = (first?.localName === "fieldset" ? first : first?.nextElementSibling);
394
- if (!control)
395
- return;
396
- if (control.localName === "fieldset") {
397
- const selected = new Set(Array.isArray(this.currentValue) ? this.currentValue.map(String) : []);
398
- control.querySelectorAll("spui-checkbox").forEach(checkbox => { checkbox.checked = selected.has(checkbox.getAttribute("value") ?? ""); });
399
- }
400
- else if (control.localName === "spui-checkbox")
401
- control.checked = this.currentValue === true || this.currentValue === "true";
402
- else if (control.localName === "spui-combobox" && control.hasAttribute("multiselect"))
403
- control.selectedOptions = Array.isArray(this.currentValue) ? this.currentValue.map(String) : [];
404
- else if ("value" in control)
405
- control.value = textValue(this.currentValue);
406
- }
407
- acceptValue(value) {
408
- this.currentValue = value;
409
- const field = this.fieldValue;
410
- if (!field)
411
- return;
412
- this.onValueChange?.(value, field);
413
- this.dispatchEvent(new CustomEvent("spui-field-value-change", { detail: { value, field }, bubbles: true, composed: true }));
414
- }
415
- constructor() {
416
- super();
417
- for (const key of ["field", "value", "defaultValue", "options", "disabled", "onValueChange", "renderUnsupported"]) {
418
- if (!Object.prototype.hasOwnProperty.call(this, key))
419
- continue;
420
- const pending = this[key];
421
- delete this[key];
422
- this[key] = pending;
423
- }
424
- this.addEventListener("spui-input", event => {
425
- const target = event.target;
426
- if ((target?.localName === "spui-combobox" && !target.hasAttribute("allow-freeform")) || (target?.localName === "spui-input" && target.closest("fieldset")))
427
- return;
428
- const value = event.detail?.value;
429
- if (value !== undefined)
430
- this.acceptValue(value);
431
- });
432
- this.addEventListener("spui-change", event => {
433
- const detail = event.detail;
434
- if (!detail)
435
- return;
436
- if (detail.checked !== undefined) {
437
- if (this.fieldValue && getSharePointFieldAdapter(this.fieldValue).control === "multi-choice") {
438
- const checkbox = event.target;
439
- const choice = checkbox.getAttribute("value") ?? "";
440
- const selected = new Set(Array.isArray(this.currentValue) ? this.currentValue.map(String) : []);
441
- if (detail.checked === true)
442
- selected.add(choice);
443
- else
444
- selected.delete(choice);
445
- this.acceptValue([...selected]);
446
- }
447
- else
448
- this.acceptValue(detail.checked === true);
449
- }
450
- else if (detail.selectedOptions)
451
- this.acceptValue(detail.selectedOptions);
452
- else if (detail.selectedValue !== undefined)
453
- this.acceptValue(detail.selectedValue || null);
454
- else if (detail.value !== undefined)
455
- this.acceptValue(detail.value || null);
456
- });
457
- }
458
- }
459
- customElements.define("spui-sharepoint-field", SpuiSharePointField);
460
- }
@@ -1,6 +0,0 @@
1
- export type SkeletonAnimation = "wave" | "pulse" | "none";
2
- export type SkeletonAppearance = "opaque" | "translucent";
3
- export type SkeletonShape = "text" | "rectangle" | "rounded" | "circle" | "square";
4
- export declare function defineSkeleton(): void;
5
- export type SkeletonItemSize = 8 | 12 | 14 | 16 | 20 | 22 | 24 | 28 | 32 | 36 | 40 | 48 | 52 | 56 | 64 | 72 | 92 | 96 | 120 | 128;
6
- export declare function defineSkeletonItem(): void;
@@ -1,91 +0,0 @@
1
- import { base } from "./shared.js";
2
- export function defineSkeleton() {
3
- if (customElements.get("spui-skeleton"))
4
- return;
5
- defineSkeletonItem();
6
- class SpuiSkeleton extends HTMLElement {
7
- static observedAttributes = ["shape", "width", "height", "animated", "animation", "appearance", "size"];
8
- connectedCallback() { if (!this.shadowRoot)
9
- this.render(); this.sync(); }
10
- attributeChangedCallback() { if (this.isConnected)
11
- this.sync(); }
12
- sync() {
13
- const shape = this.getAttribute("shape") ?? "text";
14
- this.dataset.shape = ["text", "rectangle", "circle", "rounded", "square"].includes(shape) ? shape : "text";
15
- const width = this.getAttribute("width");
16
- const height = this.getAttribute("height");
17
- if (width)
18
- this.style.setProperty("--spui-skeleton-width", this.cssLength(width));
19
- else
20
- this.style.removeProperty("--spui-skeleton-width");
21
- if (height)
22
- this.style.setProperty("--spui-skeleton-height", this.cssLength(height));
23
- else
24
- this.style.removeProperty("--spui-skeleton-height");
25
- const slot = this.shadowRoot?.querySelector("slot");
26
- const hasItems = Boolean(slot?.assignedElements().length);
27
- this.toggleAttribute("data-has-items", hasItems);
28
- if (!this.hasAttribute("role"))
29
- this.setAttribute("role", "progressbar");
30
- if (!this.hasAttribute("aria-busy"))
31
- this.setAttribute("aria-busy", "true");
32
- const animation = this.getAttribute("animated") === "false" ? "none" : this.getAttribute("animation") ?? "wave";
33
- this.dataset.animation = ["wave", "pulse", "none"].includes(animation) ? animation : "wave";
34
- this.dataset.appearance = this.getAttribute("appearance") === "translucent" ? "translucent" : "opaque";
35
- if (hasItems) {
36
- for (const item of this.querySelectorAll("spui-skeleton-item"))
37
- item.refresh?.();
38
- }
39
- else {
40
- this.removeAttribute("data-has-items");
41
- }
42
- }
43
- render() {
44
- const shadow = this.attachShadow({ mode: "open" });
45
- const block = document.createElement("span");
46
- block.part.add("shape");
47
- const children = document.createElement("slot");
48
- children.addEventListener("slotchange", () => this.sync());
49
- const style = document.createElement("style");
50
- style.textContent = `${base}:host{display:inline-block;vertical-align:middle;width:var(--spui-skeleton-width,100%);height:var(--spui-skeleton-height,1em);max-width:100%;overflow:hidden;border-radius:3px;background:var(--spui-skeleton-background,var(--spui-ui-stroke,#e5e5e5));color:transparent}:host([data-appearance=translucent]){background:var(--spui-skeleton-translucent,color-mix(in srgb,var(--spui-skeleton-background,var(--spui-ui-stroke,#e5e5e5)) 28%,transparent))}:host([data-shape=text]){height:var(--spui-skeleton-height,1em);width:var(--spui-skeleton-width,100%);border-radius:3px}:host([data-shape=rectangle]){height:var(--spui-skeleton-height,120px);border-radius:var(--spui-card-radius,8px)}:host([data-shape=rounded]){height:var(--spui-skeleton-height,40px);border-radius:999px}:host([data-shape=circle]){width:var(--spui-skeleton-width,40px);height:var(--spui-skeleton-height,40px);border-radius:50%}:host([data-shape=square]){width:var(--spui-skeleton-width,40px);height:var(--spui-skeleton-height,40px);border-radius:3px}:host([data-has-items]){display:block;width:auto;height:auto;overflow:visible;background:none}span{display:block;width:100%;height:100%;background:linear-gradient(100deg,transparent 20%,color-mix(in srgb,var(--spui-ui-surface,#fff) 55%,transparent) 50%,transparent 80%);background-size:200% 100%;animation:shimmer 1.5s ease-in-out infinite}:host([data-animation=pulse]) span{animation:spui-skeleton-pulse 1s ease-in-out infinite;background:none}slot{display:none}:host([data-has-items]) span{display:none}:host([data-has-items]) slot{display:block}:host([data-has-items]) slot::slotted(spui-skeleton-item){margin-inline-end:8px}@keyframes shimmer{to{background-position-x:-200%}}@keyframes spui-skeleton-pulse{50%{opacity:.4}}:host([animated=false]) span,:host([data-animation=none]) span{animation:none;background:none}@media(prefers-reduced-motion:reduce){span{animation:none;background:none}}@media(forced-colors:active){:host{forced-color-adjust:none;background:CanvasText;opacity:.25}span{display:none}}`;
51
- shadow.append(style, block, children);
52
- }
53
- cssLength(value) {
54
- return /^-?(?:\d+\.?\d*|\.\d+)$/.test(value.trim()) ? `${value.trim()}px` : value;
55
- }
56
- }
57
- customElements.define("spui-skeleton", SpuiSkeleton);
58
- }
59
- const skeletonItemSizes = new Set([8, 12, 14, 16, 20, 22, 24, 28, 32, 36, 40, 48, 52, 56, 64, 72, 92, 96, 120, 128]);
60
- export function defineSkeletonItem() {
61
- if (customElements.get("spui-skeleton-item"))
62
- return;
63
- class SpuiSkeletonItem extends HTMLElement {
64
- static observedAttributes = ["animation", "appearance", "size", "shape"];
65
- connectedCallback() { if (!this.shadowRoot)
66
- this.render(); this.sync(); }
67
- attributeChangedCallback() { if (this.isConnected)
68
- this.sync(); }
69
- refresh() { this.sync(); }
70
- sync() {
71
- const parent = this.closest("spui-skeleton");
72
- const animation = this.getAttribute("animation") ?? (parent?.getAttribute("animated") === "false" ? "none" : parent?.getAttribute("animation") ?? "wave");
73
- const appearance = this.getAttribute("appearance") ?? parent?.getAttribute("appearance") ?? "opaque";
74
- const requestedSize = Number(this.getAttribute("size") ?? parent?.getAttribute("size") ?? 16);
75
- const size = skeletonItemSizes.has(requestedSize) ? requestedSize : 16;
76
- const shape = this.getAttribute("shape") ?? parent?.getAttribute("shape") ?? "rectangle";
77
- this.dataset.animation = ["wave", "pulse", "none"].includes(animation) ? animation : "wave";
78
- this.dataset.appearance = appearance === "translucent" ? "translucent" : "opaque";
79
- this.dataset.size = String(size);
80
- this.dataset.shape = ["circle", "square", "rectangle"].includes(shape) ? shape : "rectangle";
81
- }
82
- render() {
83
- const shadow = this.attachShadow({ mode: "open" });
84
- const sizeRules = [...skeletonItemSizes].map(size => `:host([data-size="${size}"]){--spui-skeleton-size:${size}px}`).join("");
85
- const style = document.createElement("style");
86
- style.textContent = `${base}:host{position:relative;display:inline-block;vertical-align:middle;box-sizing:border-box;overflow:hidden;min-width:0;background:var(--spui-skeleton-background,var(--spui-ui-stroke,#e1e1e1));border-radius:4px}${sizeRules}:host([data-shape=rectangle]){display:block;width:100%;height:var(--spui-skeleton-size,16px)}:host([data-shape=square]){width:var(--spui-skeleton-size,16px);height:var(--spui-skeleton-size,16px)}:host([data-shape=circle]){width:var(--spui-skeleton-size,16px);height:var(--spui-skeleton-size,16px);border-radius:50%}:host([data-appearance=translucent]){background:var(--spui-skeleton-translucent,color-mix(in srgb,var(--spui-skeleton-background,var(--spui-ui-stroke,#e1e1e1)) 28%,transparent))}:host::after{content:"";position:absolute;inset:0;pointer-events:none;background:linear-gradient(90deg,transparent 0%,var(--spui-skeleton-highlight,color-mix(in srgb,var(--spui-ui-surface,#fff) 60%,transparent)) 50%,transparent 100%);transform:translateX(-100%);animation:spui-skeleton-wave 1.5s ease-in-out infinite}:host([data-animation=pulse]){animation:spui-skeleton-pulse 1s ease-in-out infinite}:host([data-animation=pulse])::after{display:none}:host([data-animation=none]){animation:none}:host([data-animation=none])::after{display:none}@keyframes spui-skeleton-wave{to{transform:translateX(100%)}}@keyframes spui-skeleton-pulse{50%{opacity:.4}}@media(prefers-reduced-motion:reduce){:host,:host::after{animation:none}}@media(forced-colors:active){:host{forced-color-adjust:none;background:CanvasText;opacity:.25}:host::after{display:none}}`;
87
- shadow.append(style);
88
- }
89
- }
90
- customElements.define("spui-skeleton-item", SpuiSkeletonItem);
91
- }
@@ -1 +0,0 @@
1
- export declare function defineSlider(): void;