@spfx-fast/sharepoint-ui 0.4.2 → 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 (276) hide show
  1. package/QUICKSTART.md +18 -0
  2. package/README.md +19 -24
  3. package/components.json +240 -5694
  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 -76
  55. package/dist/index.js +60 -66
  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 -4583
  89. package/dist/react.js +1 -6837
  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 -167
  117. package/dist/theme.js +36 -162
  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 +19 -42
  130. package/src/theme.css +125 -0
  131. package/AGENTS.md +0 -211
  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 -62
  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 -1112
  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 -117
  165. package/dist/elements/data-grid-model.js +0 -294
  166. package/dist/elements/data-grid.d.ts +0 -29
  167. package/dist/elements/data-grid.js +0 -1567
  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 -26
  183. package/dist/elements/floating-position.js +0 -39
  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 -299
  200. package/dist/elements/nav.d.ts +0 -32
  201. package/dist/elements/nav.js +0 -791
  202. package/dist/elements/overflow.d.ts +0 -9
  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 -18
  217. package/dist/elements/rich-text-editor.js +0 -508
  218. package/dist/elements/search.d.ts +0 -3
  219. package/dist/elements/search.js +0 -207
  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 -19
  223. package/dist/elements/shared.js +0 -396
  224. package/dist/elements/skeleton.d.ts +0 -6
  225. package/dist/elements/skeleton.js +0 -91
  226. package/dist/elements/slider.d.ts +0 -1
  227. package/dist/elements/slider.js +0 -248
  228. package/dist/elements/spin-button.d.ts +0 -7
  229. package/dist/elements/spin-button.js +0 -499
  230. package/dist/elements/spinner.d.ts +0 -4
  231. package/dist/elements/spinner.js +0 -124
  232. package/dist/elements/swatch-picker.d.ts +0 -5
  233. package/dist/elements/swatch-picker.js +0 -363
  234. package/dist/elements/table.d.ts +0 -21
  235. package/dist/elements/table.js +0 -261
  236. package/dist/elements/tabs.d.ts +0 -1
  237. package/dist/elements/tabs.js +0 -276
  238. package/dist/elements/tag-picker.d.ts +0 -29
  239. package/dist/elements/tag-picker.js +0 -697
  240. package/dist/elements/tags.d.ts +0 -21
  241. package/dist/elements/tags.js +0 -421
  242. package/dist/elements/teaching-popover.d.ts +0 -32
  243. package/dist/elements/teaching-popover.js +0 -412
  244. package/dist/elements/text.d.ts +0 -9
  245. package/dist/elements/text.js +0 -75
  246. package/dist/elements/textarea.d.ts +0 -1
  247. package/dist/elements/textarea.js +0 -182
  248. package/dist/elements/toast.d.ts +0 -25
  249. package/dist/elements/toast.js +0 -337
  250. package/dist/elements/toaster.d.ts +0 -6
  251. package/dist/elements/toaster.js +0 -356
  252. package/dist/elements/toggle.d.ts +0 -2
  253. package/dist/elements/toggle.js +0 -246
  254. package/dist/elements/toolbar.d.ts +0 -12
  255. package/dist/elements/toolbar.js +0 -381
  256. package/dist/elements/tooltip.d.ts +0 -76
  257. package/dist/elements/tooltip.js +0 -510
  258. package/dist/elements/tree-model.d.ts +0 -19
  259. package/dist/elements/tree-model.js +0 -34
  260. package/dist/elements/tree.d.ts +0 -5
  261. package/dist/elements/tree.js +0 -273
  262. package/dist/elements/view-card.d.ts +0 -2
  263. package/dist/elements/view-card.js +0 -78
  264. package/dist/elements/virtual-list.d.ts +0 -41
  265. package/dist/elements/virtual-list.js +0 -369
  266. package/dist/elements.d.ts +0 -72
  267. package/dist/elements.js +0 -207
  268. package/dist/virtualizer-hooks.d.ts +0 -80
  269. package/dist/virtualizer-hooks.js +0 -253
  270. package/scripts/generate-token-index.mjs +0 -43
  271. package/scripts/sync-component-catalog-signatures.mjs +0 -55
  272. package/scripts/validate-component-catalog.mjs +0 -44
  273. package/skills/sharepoint-ui/SKILL.md +0 -12
  274. package/skills/sharepoint-ui/references/choosing-components.md +0 -20
  275. package/skills/sharepoint-ui/references/sharepoint-patterns.md +0 -17
  276. package/tokens.json +0 -3777
@@ -1,412 +0,0 @@
1
- import { buttonControlCss, defineButton } from "./button.js";
2
- import { definePopoverVariant } from "./popover.js";
3
- import { base } from "./shared.js";
4
- const pageCountTag = "spui-teaching-popover-carousel-page-count";
5
- const cardTag = "spui-teaching-popover-carousel-card";
6
- const navButtonTag = "spui-teaching-popover-carousel-nav-button";
7
- const footerButtonTag = "spui-teaching-popover-carousel-footer-button";
8
- const carouselTag = "spui-teaching-popover-carousel";
9
- const partTag = (name) => `spui-teaching-popover-${name}`;
10
- function languageOf(element) {
11
- return element.closest("[lang]")?.lang || document.documentElement.lang || "en";
12
- }
13
- function localize(template, current, total) {
14
- return template.replaceAll("{current}", String(current)).replaceAll("{totalPages}", String(total)).replaceAll("{total}", String(total));
15
- }
16
- function definePart(tag, elementName, css, namedSlots = [], fallbacks = {}, closeSlots = namedSlots) {
17
- if (customElements.get(tag))
18
- return;
19
- class SpuiTeachingPart extends HTMLElement {
20
- connectedCallback() {
21
- if (this.shadowRoot)
22
- return;
23
- const shadow = this.attachShadow({ mode: "open" });
24
- const style = document.createElement("style");
25
- style.textContent = `${base}:host{box-sizing:border-box;display:block}${css}`;
26
- const element = document.createElement(elementName);
27
- element.part.add("root");
28
- for (const name of namedSlots) {
29
- const slot = document.createElement("slot");
30
- slot.name = name;
31
- if (name === "icon")
32
- slot.setAttribute("aria-hidden", "true");
33
- const fallback = fallbacks[name]?.(this);
34
- if (fallback)
35
- slot.append(fallback);
36
- element.append(slot);
37
- }
38
- element.append(document.createElement("slot"));
39
- if (closeSlots.length)
40
- this.addEventListener("click", event => {
41
- const path = event.composedPath();
42
- if (event.defaultPrevented || path.some(node => node instanceof HTMLElement && node.hasAttribute("data-spui-react-action")) || !path.some(node => node instanceof HTMLElement && closeSlots.includes(node.slot)))
43
- return;
44
- this.dispatchEvent(new CustomEvent("spui-popover-request-close", { bubbles: true, composed: true, detail: { sourceEvent: event } }));
45
- });
46
- shadow.append(style, element);
47
- }
48
- }
49
- customElements.define(tag, SpuiTeachingPart);
50
- }
51
- function defineTeachingButton(tag, kind) {
52
- if (customElements.get(tag))
53
- return;
54
- class SpuiTeachingButton extends HTMLElement {
55
- static observedAttributes = ["nav-type", "value", "alt-text", "aria-label", "aria-current", "tabindex", "disabled", "size", "appearance", "shape", "icon-only", "data-edge"];
56
- button;
57
- fallback;
58
- alternate;
59
- connectedCallback() {
60
- if (!this.shadowRoot)
61
- this.render();
62
- this.style.display ||= "inline-flex";
63
- this.sync();
64
- }
65
- attributeChangedCallback() { this.sync(); }
66
- render() {
67
- const shadow = this.attachShadow({ mode: "open", delegatesFocus: true });
68
- const style = document.createElement("style");
69
- style.textContent = buttonControlCss;
70
- const button = document.createElement("button");
71
- button.type = "button";
72
- button.part.add("control");
73
- const fallback = document.createElement("span");
74
- fallback.className = "fallback";
75
- fallback.append(document.createElement("slot"));
76
- button.append(fallback);
77
- this.button = button;
78
- this.fallback = fallback;
79
- if (kind === "footer") {
80
- const alternate = document.createElement("span");
81
- alternate.className = "alternate";
82
- alternate.hidden = true;
83
- button.append(alternate);
84
- this.alternate = alternate;
85
- style.textContent += `.fallback[hidden],.alternate[hidden]{display:none}.alternate{white-space:nowrap}`;
86
- }
87
- shadow.append(style, button);
88
- }
89
- sync() {
90
- const button = this.button;
91
- if (!button)
92
- return;
93
- const navType = this.getAttribute("nav-type") ?? (kind === "nav" ? "step" : "next");
94
- const appearance = this.getAttribute("appearance") ?? (kind === "nav" ? "subtle" : navType === "next" ? "primary" : navType === "dismiss" ? "subtle" : "secondary");
95
- const size = this.getAttribute("size") ?? (kind === "nav" ? "small" : "medium");
96
- const shape = this.getAttribute("shape") ?? (kind === "nav" ? "circular" : "rounded");
97
- const setIfChanged = (name, value) => { if (this.getAttribute(name) !== value)
98
- this.setAttribute(name, value); };
99
- button.className = appearance === "primary" ? "primary" : ["outline", "subtle", "transparent"].includes(appearance) ? appearance : "secondary";
100
- this.toggleAttribute("data-spui-popover-close", kind === "footer" && navType === "dismiss");
101
- if (kind === "nav" && !this.hasAttribute("icon-only"))
102
- this.setAttribute("icon-only", "");
103
- button.disabled = this.hasAttribute("disabled");
104
- button.setAttribute("part", "control");
105
- button.setAttribute("aria-label", this.getAttribute("aria-label") || this.textContent?.trim() || (kind === "nav" ? "Tour step" : navType));
106
- if (this.hasAttribute("aria-current"))
107
- button.setAttribute("aria-current", this.getAttribute("aria-current"));
108
- else
109
- button.removeAttribute("aria-current");
110
- button.tabIndex = this.hasAttribute("tabindex") ? Number(this.getAttribute("tabindex")) : kind === "nav" ? -1 : 0;
111
- setIfChanged("appearance", appearance);
112
- setIfChanged("size", size);
113
- setIfChanged("shape", shape);
114
- if (kind === "footer") {
115
- const edge = this.getAttribute("data-edge");
116
- const isEdge = (navType === "previous" || navType === "prev") ? edge === "first" : navType === "next" && edge === "last";
117
- const altText = this.getAttribute("alt-text");
118
- const alternate = this.alternate;
119
- if (this.fallback)
120
- this.fallback.hidden = Boolean(isEdge && altText);
121
- if (alternate) {
122
- alternate.hidden = !(isEdge && altText);
123
- alternate.textContent = isEdge ? altText ?? "" : "";
124
- }
125
- const label = isEdge && altText ? altText : this.getAttribute("aria-label") || this.textContent?.trim() || (navType === "dismiss" ? "Finish tour" : navType === "previous" || navType === "prev" ? "Previous step" : "Next step");
126
- button.setAttribute("aria-label", label);
127
- setIfChanged("aria-label", label);
128
- }
129
- }
130
- }
131
- customElements.define(tag, SpuiTeachingButton);
132
- }
133
- function defineCarousel() {
134
- if (customElements.get(carouselTag))
135
- return;
136
- class SpuiTeachingPopoverCarousel extends HTMLElement {
137
- static observedAttributes = ["value", "default-value", "aria-label", "page-count-template", "page-label-template"];
138
- currentValue = "";
139
- events;
140
- observer;
141
- slotNode;
142
- liveRegion;
143
- announcement;
144
- get value() { return this.getAttribute("value") ?? this.currentValue; }
145
- set value(value) { this.setAttribute("value", value); }
146
- get defaultValue() { return this.getAttribute("default-value") ?? ""; }
147
- set defaultValue(value) { this.setAttribute("default-value", value); }
148
- connectedCallback() {
149
- this.style.display ||= "grid";
150
- if (!this.shadowRoot)
151
- this.render();
152
- this.events?.abort();
153
- this.events = new AbortController();
154
- this.addEventListener("click", this.onClick, { signal: this.events.signal });
155
- this.addEventListener("keydown", this.onKeyDown, { signal: this.events.signal });
156
- this.slotNode?.addEventListener("slotchange", this.sync, { signal: this.events.signal });
157
- this.observer?.disconnect();
158
- this.observer = new MutationObserver(this.sync);
159
- this.observer.observe(this, { childList: true, subtree: true, attributes: true, attributeFilter: ["value", "nav-type", "alt-text"] });
160
- this.setAttribute("role", "region");
161
- this.setAttribute("aria-roledescription", "carousel");
162
- if (!this.hasAttribute("aria-label"))
163
- this.setAttribute("aria-label", languageOf(this).startsWith("ar") ? "خطوات الجولة" : "Tour steps");
164
- this.currentValue = this.defaultValue || this.cards()[0]?.getAttribute("value") || "";
165
- this.sync();
166
- }
167
- disconnectedCallback() { this.events?.abort(); this.observer?.disconnect(); }
168
- attributeChangedCallback() { if (this.isConnected)
169
- this.sync(); }
170
- render() {
171
- const shadow = this.attachShadow({ mode: "open" });
172
- const style = document.createElement("style");
173
- style.textContent = `${base}:host{display:grid;gap:8px;min-width:0}slot{display:contents}`;
174
- this.slotNode = document.createElement("slot");
175
- this.liveRegion = document.createElement("span");
176
- this.liveRegion.setAttribute("aria-live", "polite");
177
- this.liveRegion.setAttribute("aria-atomic", "true");
178
- this.liveRegion.setAttribute("part", "announcement");
179
- style.textContent += `span[part=announcement]{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}`;
180
- shadow.append(style, this.slotNode, this.liveRegion);
181
- }
182
- cards() { return [...this.querySelectorAll(cardTag)]; }
183
- sync = () => {
184
- const cards = this.cards();
185
- if (!cards.length)
186
- return;
187
- const current = this.getAttribute("value") ?? this.currentValue ?? cards[0].getAttribute("value") ?? "";
188
- const selectedIndex = Math.max(0, cards.findIndex(card => card.getAttribute("value") === current));
189
- const selected = cards[selectedIndex];
190
- if (!this.hasAttribute("value"))
191
- this.currentValue = selected.getAttribute("value") ?? "";
192
- const language = languageOf(this);
193
- const pageTemplate = this.getAttribute("page-label-template") ?? (language.startsWith("ar") ? "الخطوة {current} من {total}" : "Step {current} of {total}");
194
- cards.forEach((card, index) => {
195
- const active = index === selectedIndex;
196
- card.hidden = !active;
197
- card.setAttribute("role", "group");
198
- card.setAttribute("aria-roledescription", language.startsWith("ar") ? "شريحة" : "slide");
199
- if (!card.hasAttribute("aria-label"))
200
- card.setAttribute("aria-label", localize(pageTemplate, index + 1, cards.length));
201
- card.toggleAttribute("data-active", active);
202
- });
203
- this.querySelectorAll(navButtonTag).forEach(button => {
204
- const active = button.getAttribute("value") === selected.getAttribute("value");
205
- if (active)
206
- button.setAttribute("aria-current", "step");
207
- else
208
- button.removeAttribute("aria-current");
209
- button.setAttribute("tabindex", active ? "0" : "-1");
210
- });
211
- const edge = selectedIndex === 0 ? "first" : selectedIndex === cards.length - 1 ? "last" : "";
212
- this.querySelectorAll(footerButtonTag).forEach(button => edge ? button.setAttribute("data-edge", edge) : button.removeAttribute("data-edge"));
213
- const countTemplate = this.getAttribute("page-count-template") ?? (language.startsWith("ar") ? "{current} من {total}" : "{current} of {total}");
214
- const count = localize(countTemplate, selectedIndex + 1, cards.length);
215
- this.querySelectorAll(pageCountTag).forEach(pageCount => {
216
- const value = pageCount.shadowRoot?.querySelector("[aria-live]");
217
- if (value)
218
- value.textContent = count;
219
- });
220
- this.setAttribute("data-value", selected.getAttribute("value") ?? "");
221
- this.setAttribute("data-current-page", String(selectedIndex + 1));
222
- this.setAttribute("data-total-pages", String(cards.length));
223
- };
224
- changeTo(index, event) {
225
- const cards = this.cards();
226
- const next = cards[Math.max(0, Math.min(cards.length - 1, index))]?.getAttribute("value");
227
- if (!next || next === this.value)
228
- return;
229
- const type = (event?.type ?? "programmatic");
230
- if (this.hasAttribute("value")) {
231
- this.dispatchEvent(new CustomEvent("spui-value-change", { bubbles: true, composed: true, detail: { value: next, event, type } }));
232
- this.announceAfterUpdate(next, cards.length);
233
- return;
234
- }
235
- this.currentValue = next;
236
- this.sync();
237
- const currentPage = cards.findIndex(card => card.getAttribute("value") === next) + 1;
238
- const detail = { value: next, currentPage, totalPages: cards.length, event, type };
239
- this.dispatchEvent(new CustomEvent("spui-value-change", { bubbles: true, composed: true, detail }));
240
- this.dispatchEvent(new CustomEvent("spui-carousel-change", { bubbles: true, composed: true, detail }));
241
- this.announceAfterUpdate(next, cards.length);
242
- }
243
- announceAfterUpdate(value, totalPages) {
244
- if (!this.announcement)
245
- return;
246
- requestAnimationFrame(() => {
247
- if (this.value !== value)
248
- return;
249
- const message = this.announcement?.(value) ?? "";
250
- if (this.liveRegion)
251
- this.liveRegion.textContent = message;
252
- if (!message)
253
- return;
254
- const currentPage = this.cards().findIndex(card => card.getAttribute("value") === value) + 1;
255
- this.dispatchEvent(new CustomEvent("spui-announcement", { bubbles: true, composed: true, detail: { value, message, currentPage, totalPages } }));
256
- });
257
- }
258
- onClick = (event) => {
259
- if (event.defaultPrevented)
260
- return;
261
- const path = event.composedPath().filter((node) => node instanceof HTMLElement);
262
- const nav = path.find(node => node.localName === navButtonTag);
263
- if (nav) {
264
- const index = this.cards().findIndex(card => card.getAttribute("value") === nav.getAttribute("value"));
265
- if (index >= 0)
266
- this.changeTo(index, event);
267
- return;
268
- }
269
- const button = path.find(node => node.localName === footerButtonTag);
270
- if (!button)
271
- return;
272
- const type = button.getAttribute("nav-type");
273
- const index = this.cards().findIndex(card => card.getAttribute("value") === this.value);
274
- if (type === "prev" || type === "previous")
275
- this.changeTo(index - 1, event);
276
- else if (type === "next" && index === this.cards().length - 1)
277
- this.dispatchEvent(new CustomEvent("spui-finish", { bubbles: true, composed: true, detail: { value: this.value, event, type: "click" } }));
278
- else if (type === "next")
279
- this.changeTo(index + 1, event);
280
- };
281
- onKeyDown = (event) => {
282
- if (event.defaultPrevented || event.altKey || event.ctrlKey || event.metaKey)
283
- return;
284
- const cards = this.cards();
285
- const index = cards.findIndex(card => card.getAttribute("value") === this.value);
286
- const rtl = getComputedStyle(this).direction === "rtl";
287
- const delta = event.key === "ArrowRight" ? (rtl ? -1 : 1) : event.key === "ArrowLeft" ? (rtl ? 1 : -1) : 0;
288
- const next = event.key === "Home" ? 0 : event.key === "End" ? cards.length - 1 : delta ? Math.max(0, Math.min(cards.length - 1, index + delta)) : -1;
289
- if (next < 0 || next === index)
290
- return;
291
- event.preventDefault();
292
- this.changeTo(next, event);
293
- const value = cards[next]?.getAttribute("value");
294
- requestAnimationFrame(() => {
295
- const control = [...this.querySelectorAll(navButtonTag)].find(item => item.getAttribute("value") === value);
296
- (control?.shadowRoot?.querySelector("button") ?? control)?.focus();
297
- });
298
- };
299
- }
300
- customElements.define(carouselTag, SpuiTeachingPopoverCarousel);
301
- }
302
- function defineCard() {
303
- if (customElements.get(cardTag))
304
- return;
305
- class SpuiTeachingPopoverCarouselCard extends HTMLElement {
306
- static observedAttributes = ["value", "aria-label", "hidden"];
307
- connectedCallback() {
308
- this.style.display ||= "grid";
309
- this.style.minWidth ||= "0";
310
- if (!this.shadowRoot) {
311
- const shadow = this.attachShadow({ mode: "open" });
312
- const style = document.createElement("style");
313
- style.textContent = `${base}:host([hidden]){display:none!important}slot{display:contents}`;
314
- const slide = document.createElement("div");
315
- slide.part.add("slide");
316
- slide.append(document.createElement("slot"));
317
- shadow.append(style, slide);
318
- }
319
- }
320
- }
321
- customElements.define(cardTag, SpuiTeachingPopoverCarouselCard);
322
- }
323
- function definePageCount() {
324
- if (customElements.get(pageCountTag))
325
- return;
326
- class SpuiTeachingPopoverPageCount extends HTMLElement {
327
- connectedCallback() {
328
- if (this.shadowRoot)
329
- return;
330
- const shadow = this.attachShadow({ mode: "open" });
331
- const style = document.createElement("style");
332
- style.textContent = `${base}:host{display:inline-flex;align-items:center;color:var(--spui-ui-text-muted,var(--colorNeutralForeground3,#616161));font-size:var(--spui-font-size-200,12px);white-space:nowrap}[aria-live]{display:inline}`;
333
- const value = document.createElement("span");
334
- value.setAttribute("aria-live", "polite");
335
- value.setAttribute("part", "count");
336
- shadow.append(style, value);
337
- }
338
- }
339
- customElements.define(pageCountTag, SpuiTeachingPopoverPageCount);
340
- }
341
- function defineCarouselFooter() {
342
- const tag = partTag("carousel-footer");
343
- if (customElements.get(tag))
344
- return;
345
- class SpuiTeachingPopoverCarouselFooter extends HTMLElement {
346
- static observedAttributes = ["layout", "initial-step-text", "final-step-text"];
347
- slotNode;
348
- footer;
349
- connectedCallback() {
350
- if (this.shadowRoot)
351
- return;
352
- this.style.display ||= "block";
353
- const shadow = this.attachShadow({ mode: "open" });
354
- const style = document.createElement("style");
355
- style.textContent = `${base}:host{box-sizing:border-box}footer{display:flex;align-items:center;justify-content:center;flex-wrap:wrap;gap:8px}slot{display:contents}`;
356
- this.footer = document.createElement("footer");
357
- this.footer.part.add("root");
358
- const previous = document.createElement("slot");
359
- previous.name = "previous";
360
- const next = document.createElement("slot");
361
- next.name = "next";
362
- this.slotNode = document.createElement("slot");
363
- this.slotNode.addEventListener("slotchange", this.sync);
364
- this.footer.append(previous, this.slotNode, next);
365
- shadow.append(style, this.footer);
366
- this.sync();
367
- }
368
- attributeChangedCallback() { this.sync(); }
369
- sync = () => {
370
- if (this.footer)
371
- this.footer.style.justifyContent = this.getAttribute("layout") === "offset" ? "space-between" : "center";
372
- for (const [type, attr] of [["previous", "initial-step-text"], ["prev", "initial-step-text"], ["next", "final-step-text"]]) {
373
- const text = this.getAttribute(attr);
374
- for (const button of this.querySelectorAll(`${footerButtonTag}[nav-type="${type}"]`)) {
375
- const previousGenerated = button.getAttribute("data-spui-footer-alt-text");
376
- const existingAlt = button.getAttribute("alt-text");
377
- if ((previousGenerated && existingAlt !== previousGenerated) || (!previousGenerated && existingAlt))
378
- continue;
379
- if (text) {
380
- button.setAttribute("alt-text", text);
381
- button.setAttribute("data-spui-footer-alt-text", text);
382
- }
383
- else if (previousGenerated) {
384
- button.removeAttribute("alt-text");
385
- button.removeAttribute("data-spui-footer-alt-text");
386
- }
387
- }
388
- }
389
- };
390
- }
391
- customElements.define(tag, SpuiTeachingPopoverCarouselFooter);
392
- }
393
- /** Register the framework-neutral TeachingPopover and its composable guided-tour parts. */
394
- export function defineTeachingPopover() {
395
- defineButton();
396
- definePopoverVariant("spui-teaching-popover", { label: "Guided tour", trapFocus: true, arrow: true });
397
- definePart(partTag("trigger"), "span", ":host{display:contents!important}");
398
- definePart(partTag("surface"), "div", ":host{display:grid;gap:12px;min-width:min(320px,calc(100vw - 64px));max-width:100%;box-sizing:border-box}");
399
- const iconFallback = () => { const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); svg.setAttribute("viewBox", "0 0 16 16"); svg.setAttribute("width", "16"); svg.setAttribute("height", "16"); svg.setAttribute("fill", "none"); svg.setAttribute("stroke", "currentColor"); svg.setAttribute("stroke-width", "1.25"); const path = document.createElementNS(svg.namespaceURI, "path"); path.setAttribute("d", "M5.1 10.6c-.3-.8-.7-1.3-1.2-2A4.3 4.3 0 1 1 12.1 8c-.5.7-.9 1.2-1.2 2.6H5.2l-.1 0Zm.4 1.3h5m-4.5 1.4h4m-3.4 1.2h2.8"); svg.append(path); return svg; };
400
- const dismissFallback = (host) => { const button = document.createElement("button"); button.type = "button"; button.setAttribute("aria-label", languageOf(host).startsWith("ar") ? "إغلاق" : "Dismiss"); button.setAttribute("data-spui-popover-close", ""); button.textContent = "×"; return button; };
401
- definePart(partTag("header"), "header", "header{display:flex;align-items:center;gap:8px;padding-block-end:4px;color:var(--spui-ui-text-muted,var(--colorNeutralForeground3,#616161));font-size:var(--spui-font-size-200,12px);font-weight:600}slot[name=icon]{display:inline-flex;align-items:center;flex:none;color:var(--spui-ui-accent,var(--colorBrandForeground1,#0f6cbd))}slot[name=dismiss-button]{margin-inline-start:auto}slot[name=dismiss-button] button,slot[name=dismiss-button]::slotted(button){box-sizing:border-box;display:grid;place-items:center;width:28px;height:28px;padding:0;border:0;border-radius:var(--spui-control-radius,4px);background:transparent;color:inherit;font:inherit;cursor:pointer}slot[name=dismiss-button] button:hover,slot[name=dismiss-button]::slotted(button):hover{background:var(--spui-ui-surface-hover,var(--colorNeutralBackground1Hover,#f5f5f5))}slot[name=dismiss-button] button:focus-visible,slot[name=dismiss-button]::slotted(button):focus-visible{outline:2px solid var(--spui-ui-border-focus,var(--spui-ui-accent,#0f6cbd));outline-offset:1px}", ["icon", "dismiss-button"], { icon: iconFallback, "dismiss-button": dismissFallback }, ["dismiss-button"]);
402
- definePart(partTag("title"), "h2", "h2{display:flex;align-items:center;gap:8px;margin:0;color:var(--spui-ui-text,var(--colorNeutralForeground1,#242424));font:600 20px/1.3 var(--spui-font-family,inherit)}slot[name=dismiss-button]{margin-inline-start:auto}", ["dismiss-button"]);
403
- definePart(partTag("body"), "div", "div{display:grid;gap:8px;padding-block-end:8px;color:var(--spui-ui-text,var(--colorNeutralForeground1,#242424));font:var(--spui-font-family,inherit);line-height:1.5}");
404
- definePart(partTag("footer"), "footer", "footer{display:flex;align-items:center;justify-content:flex-end;flex-wrap:wrap;gap:8px}slot[name=primary],slot[name=secondary]{display:inline-flex}slot:not([name]){display:contents}", ["primary", "secondary"]);
405
- defineCarouselFooter();
406
- definePart(partTag("carousel-nav"), "nav", "nav{display:flex;align-items:center;gap:4px}");
407
- defineCard();
408
- definePageCount();
409
- defineCarousel();
410
- defineTeachingButton(navButtonTag, "nav");
411
- defineTeachingButton(footerButtonTag, "footer");
412
- }
@@ -1,9 +0,0 @@
1
- export type TextSize = 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 1000 | 1100 | 1200;
2
- export type TextWeight = "regular" | "medium" | "semibold" | "bold";
3
- export type TextFont = "base" | "monospace" | "numeric";
4
- export type TextTag = "span" | "p" | "div" | "strong" | "b" | "em" | "i" | "small" | "code" | "pre" | "blockquote" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
5
- export declare function getTextSizeStyles(size: TextSize | string): {
6
- fontSize: string;
7
- lineHeight: string;
8
- };
9
- export declare function defineText(): void;
@@ -1,75 +0,0 @@
1
- import { base } from "./shared.js";
2
- const sizes = {
3
- "100": ["10px", "14px"], "200": ["12px", "16px"], "300": ["14px", "20px"], "400": ["16px", "22px"],
4
- "500": ["20px", "28px"], "600": ["24px", "32px"], "700": ["28px", "36px"], "800": ["32px", "40px"],
5
- "900": ["40px", "52px"], "1000": ["68px", "92px"], "1100": ["80px", "104px"], "1200": ["96px", "128px"],
6
- };
7
- const fluentSizeTokens = {
8
- "100": ["fontSizeBase100", "lineHeightBase100"], "200": ["fontSizeBase200", "lineHeightBase200"], "300": ["fontSizeBase300", "lineHeightBase300"],
9
- "400": ["fontSizeBase400", "lineHeightBase400"], "500": ["fontSizeBase500", "lineHeightBase500"], "600": ["fontSizeBase600", "lineHeightBase600"],
10
- "700": ["fontSizeHero700", "lineHeightHero700"], "800": ["fontSizeHero800", "lineHeightHero800"], "900": ["fontSizeHero900", "lineHeightHero900"], "1000": ["fontSizeHero1000", "lineHeightHero1000"],
11
- };
12
- const extendedSizeTokens = {
13
- "1100": ["--spui-text-font-size-1100", "--spui-text-line-height-1100"],
14
- "1200": ["--spui-text-font-size-1200", "--spui-text-line-height-1200"],
15
- };
16
- const tags = new Set(["span", "p", "div", "strong", "b", "em", "i", "small", "code", "pre", "blockquote", "h1", "h2", "h3", "h4", "h5", "h6"]);
17
- export function getTextSizeStyles(size) {
18
- const [fallbackSize, fallbackLine] = sizes[size] ?? sizes["300"];
19
- const fluentTokens = fluentSizeTokens[size];
20
- const [fontToken, lineToken] = extendedSizeTokens[size] ?? (fluentTokens ? [`--${fluentTokens[0]}`, `--${fluentTokens[1]}`] : [`--${fluentSizeTokens["300"][0]}`, `--${fluentSizeTokens["300"][1]}`]);
21
- return {
22
- fontSize: `var(--spui-text-font-size,var(${fontToken},${fallbackSize}))`,
23
- lineHeight: `var(--spui-text-line-height,var(${lineToken},${fallbackLine}))`,
24
- };
25
- }
26
- export function defineText() {
27
- if (customElements.get("spui-text"))
28
- return;
29
- class SpuiText extends HTMLElement {
30
- static observedAttributes = ["as", "size", "weight", "font", "align", "italic", "underline", "strikethrough", "truncate", "wrap", "block"];
31
- connectedCallback() { if (!this.shadowRoot)
32
- this.render();
33
- else {
34
- this.syncTag();
35
- this.syncSize();
36
- } }
37
- attributeChangedCallback(name) {
38
- if (!this.isConnected)
39
- return;
40
- if (name === "as")
41
- this.syncTag();
42
- if (name === "size")
43
- this.syncSize();
44
- }
45
- tag() { const tag = this.getAttribute("as") ?? "span"; return tags.has(tag) ? tag : "span"; }
46
- content() {
47
- const content = document.createElement(this.tag());
48
- content.className = "text";
49
- content.part.add("content");
50
- content.append(document.createElement("slot"));
51
- return content;
52
- }
53
- render() {
54
- const shadow = this.attachShadow({ mode: "open" });
55
- const style = document.createElement("style");
56
- style.textContent = `${base}:host{display:inline;vertical-align:baseline}:host([block]),:host([as=p]),:host([as=div]),:host([as=pre]),:host([as=blockquote]),:host([as=h1]),:host([as=h2]),:host([as=h3]),:host([as=h4]),:host([as=h5]),:host([as=h6]){display:block}.text{box-sizing:border-box;margin:0;color:inherit;font-family:var(--spui-font-family,var(--fontFamilyBase,inherit));font-size:var(--spui-text-font-size,var(--fontSizeBase300,14px));font-weight:var(--spui-text-font-weight,var(--fontWeightRegular,400));line-height:var(--spui-text-line-height,var(--lineHeightBase300,20px));text-align:var(--spui-text-align,start);font-style:normal;text-decoration:none;white-space:normal;overflow-wrap:anywhere}:host([as=strong]) .text,:host([as=b]) .text{font-weight:var(--fontWeightBold,700)}:host([as=em]) .text,:host([as=i]) .text{font-style:italic}:host([weight=regular]) .text{font-weight:var(--fontWeightRegular,400)}:host([weight=medium]) .text{font-weight:var(--fontWeightMedium,500)}:host([weight=semibold]) .text{font-weight:var(--fontWeightSemibold,600)}:host([weight=bold]) .text{font-weight:var(--fontWeightBold,700)}:host([font=monospace]) .text{font-family:var(--spui-font-family-mono,var(--fontFamilyMonospace,ui-monospace,monospace))}:host([font=numeric]) .text{font-family:var(--fontFamilyNumeric,var(--fontFamilyBase,inherit));font-variant-numeric:tabular-nums}:host([align=center]) .text{text-align:center}:host([align=end]) .text{text-align:end}:host([align=justify]) .text{text-align:justify}:host([italic]) .text{font-style:italic}:host([underline]) .text{text-decoration:underline;text-underline-offset:.15em}:host([strikethrough]) .text{text-decoration:line-through}:host([underline][strikethrough]) .text{text-decoration-line:underline line-through}:host([truncate]){display:inline-block;max-width:100%;vertical-align:bottom}:host([truncate]) .text{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;overflow-wrap:normal}:host([wrap=false]) .text{white-space:nowrap;overflow-wrap:normal}:host([as=code]) .text,:host([as=pre]) .text{font-family:var(--spui-font-family-mono,var(--fontFamilyMonospace,ui-monospace,monospace))}:host([as=pre]) .text{white-space:pre-wrap;overflow-wrap:anywhere}@media(forced-colors:active){.text{color:CanvasText}}`;
57
- shadow.replaceChildren(style, this.content());
58
- this.syncSize();
59
- }
60
- syncTag() {
61
- const content = this.shadowRoot?.querySelector(".text");
62
- if (content && content.localName !== this.tag())
63
- content.replaceWith(this.content());
64
- }
65
- syncSize() {
66
- const content = this.shadowRoot?.querySelector(".text");
67
- if (!content)
68
- return;
69
- const sizeStyles = getTextSizeStyles(this.getAttribute("size") ?? "300");
70
- content.style.fontSize = sizeStyles.fontSize;
71
- content.style.lineHeight = sizeStyles.lineHeight;
72
- }
73
- }
74
- customElements.define("spui-text", SpuiText);
75
- }
@@ -1 +0,0 @@
1
- export declare function defineTextArea(): void;