@sondor-technology/sondor-components 1.0.1-develop.13 → 1.0.1-develop.14

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 (226) hide show
  1. package/dist/components/alert/alert.constants.d.ts +3 -0
  2. package/dist/components/alert/alert.constants.d.ts.map +1 -0
  3. package/dist/components/alert/alert.constants.js +2 -0
  4. package/dist/components/alert/alert.constants.js.map +1 -0
  5. package/dist/components/alert/alert.d.ts +4 -3
  6. package/dist/components/alert/alert.d.ts.map +1 -1
  7. package/dist/components/alert/alert.js +21 -11
  8. package/dist/components/alert/alert.js.map +1 -0
  9. package/dist/components/badge/badge.constants.d.ts +3 -0
  10. package/dist/components/badge/badge.constants.d.ts.map +1 -0
  11. package/dist/components/badge/badge.constants.js +2 -0
  12. package/dist/components/badge/badge.constants.js.map +1 -0
  13. package/dist/components/badge/badge.d.ts +1 -1
  14. package/dist/components/badge/badge.d.ts.map +1 -1
  15. package/dist/components/badge/badge.js +3 -2
  16. package/dist/components/badge/badge.js.map +1 -0
  17. package/dist/components/breadcrumb/breadcrumb.d.ts.map +1 -1
  18. package/dist/components/breadcrumb/breadcrumb.js +2 -1
  19. package/dist/components/breadcrumb/breadcrumb.js.map +1 -0
  20. package/dist/components/button/button.constants.d.ts +7 -0
  21. package/dist/components/button/button.constants.d.ts.map +1 -0
  22. package/dist/components/button/button.constants.js +4 -0
  23. package/dist/components/button/button.constants.js.map +1 -0
  24. package/dist/components/button/button.d.ts +8 -4
  25. package/dist/components/button/button.d.ts.map +1 -1
  26. package/dist/components/button/button.js +181 -137
  27. package/dist/components/button/button.js.map +1 -0
  28. package/dist/components/button-group/button-group.d.ts +1 -0
  29. package/dist/components/button-group/button-group.d.ts.map +1 -1
  30. package/dist/components/button-group/button-group.js +17 -21
  31. package/dist/components/button-group/button-group.js.map +1 -0
  32. package/dist/components/checkbox/checkbox.constants.d.ts +3 -0
  33. package/dist/components/checkbox/checkbox.constants.d.ts.map +1 -0
  34. package/dist/components/checkbox/checkbox.constants.js +2 -0
  35. package/dist/components/checkbox/checkbox.constants.js.map +1 -0
  36. package/dist/components/checkbox/checkbox.d.ts +5 -1
  37. package/dist/components/checkbox/checkbox.d.ts.map +1 -1
  38. package/dist/components/checkbox/checkbox.js +21 -5
  39. package/dist/components/checkbox/checkbox.js.map +1 -0
  40. package/dist/components/code-block/code-block.d.ts +7 -7
  41. package/dist/components/code-block/code-block.d.ts.map +1 -1
  42. package/dist/components/code-block/code-block.js +130 -66
  43. package/dist/components/code-block/code-block.js.map +1 -0
  44. package/dist/components/content-card/content-card.d.ts.map +1 -1
  45. package/dist/components/content-card/content-card.js +10 -15
  46. package/dist/components/content-card/content-card.js.map +1 -0
  47. package/dist/components/divider/divider.constants.d.ts +5 -0
  48. package/dist/components/divider/divider.constants.d.ts.map +1 -0
  49. package/dist/components/divider/divider.constants.js +3 -0
  50. package/dist/components/divider/divider.constants.js.map +1 -0
  51. package/dist/components/divider/divider.d.ts +4 -2
  52. package/dist/components/divider/divider.d.ts.map +1 -1
  53. package/dist/components/divider/divider.js +18 -9
  54. package/dist/components/divider/divider.js.map +1 -0
  55. package/dist/components/drawer/drawer.d.ts +7 -4
  56. package/dist/components/drawer/drawer.d.ts.map +1 -1
  57. package/dist/components/drawer/drawer.js +73 -30
  58. package/dist/components/drawer/drawer.js.map +1 -0
  59. package/dist/components/field/field.d.ts +2 -2
  60. package/dist/components/field/field.d.ts.map +1 -1
  61. package/dist/components/field/field.js +8 -9
  62. package/dist/components/field/field.js.map +1 -0
  63. package/dist/components/footer/footer.d.ts +8 -1
  64. package/dist/components/footer/footer.d.ts.map +1 -1
  65. package/dist/components/footer/footer.js +42 -12
  66. package/dist/components/footer/footer.js.map +1 -0
  67. package/dist/components/form/form-step.js +1 -0
  68. package/dist/components/form/form-step.js.map +1 -0
  69. package/dist/components/form/form.d.ts +3 -0
  70. package/dist/components/form/form.d.ts.map +1 -1
  71. package/dist/components/form/form.js +109 -69
  72. package/dist/components/form/form.js.map +1 -0
  73. package/dist/components/grid/grid-row.d.ts +3 -3
  74. package/dist/components/grid/grid-row.d.ts.map +1 -1
  75. package/dist/components/grid/grid-row.js +36 -22
  76. package/dist/components/grid/grid-row.js.map +1 -0
  77. package/dist/components/grid/grid.d.ts +2 -2
  78. package/dist/components/grid/grid.d.ts.map +1 -1
  79. package/dist/components/grid/grid.js +5 -2
  80. package/dist/components/grid/grid.js.map +1 -0
  81. package/dist/components/icon/icon-paths.d.ts +161 -86
  82. package/dist/components/icon/icon-paths.d.ts.map +1 -1
  83. package/dist/components/icon/icon-paths.js +176 -106
  84. package/dist/components/icon/icon-paths.js.map +1 -0
  85. package/dist/components/icon/icon.d.ts +1 -1
  86. package/dist/components/icon/icon.d.ts.map +1 -1
  87. package/dist/components/icon/icon.js +6 -5
  88. package/dist/components/icon/icon.js.map +1 -0
  89. package/dist/components/input/input.d.ts +9 -0
  90. package/dist/components/input/input.d.ts.map +1 -1
  91. package/dist/components/input/input.js +30 -37
  92. package/dist/components/input/input.js.map +1 -0
  93. package/dist/components/link/link.d.ts +6 -6
  94. package/dist/components/link/link.d.ts.map +1 -1
  95. package/dist/components/link/link.js +42 -19
  96. package/dist/components/link/link.js.map +1 -0
  97. package/dist/components/metadata/metadata.d.ts +3 -3
  98. package/dist/components/metadata/metadata.d.ts.map +1 -1
  99. package/dist/components/metadata/metadata.js +23 -20
  100. package/dist/components/metadata/metadata.js.map +1 -0
  101. package/dist/components/modal/modal.d.ts +4 -16
  102. package/dist/components/modal/modal.d.ts.map +1 -1
  103. package/dist/components/modal/modal.js +99 -62
  104. package/dist/components/modal/modal.js.map +1 -0
  105. package/dist/components/page-layout/page-layout.d.ts +4 -3
  106. package/dist/components/page-layout/page-layout.d.ts.map +1 -1
  107. package/dist/components/page-layout/page-layout.js +95 -68
  108. package/dist/components/page-layout/page-layout.js.map +1 -0
  109. package/dist/components/radio/radio.d.ts +8 -0
  110. package/dist/components/radio/radio.d.ts.map +1 -1
  111. package/dist/components/radio/radio.js +8 -12
  112. package/dist/components/radio/radio.js.map +1 -0
  113. package/dist/components/radio-group/radio-group.d.ts +6 -1
  114. package/dist/components/radio-group/radio-group.d.ts.map +1 -1
  115. package/dist/components/radio-group/radio-group.js +44 -18
  116. package/dist/components/radio-group/radio-group.js.map +1 -0
  117. package/dist/components/router/router.d.ts +5 -7
  118. package/dist/components/router/router.d.ts.map +1 -1
  119. package/dist/components/router/router.js +54 -38
  120. package/dist/components/router/router.js.map +1 -0
  121. package/dist/components/select/select.d.ts +1 -3
  122. package/dist/components/select/select.d.ts.map +1 -1
  123. package/dist/components/select/select.js +14 -5
  124. package/dist/components/select/select.js.map +1 -0
  125. package/dist/components/skeleton/skeleton.d.ts +3 -2
  126. package/dist/components/skeleton/skeleton.d.ts.map +1 -1
  127. package/dist/components/skeleton/skeleton.js +10 -13
  128. package/dist/components/skeleton/skeleton.js.map +1 -0
  129. package/dist/components/switch/switch.d.ts +12 -0
  130. package/dist/components/switch/switch.d.ts.map +1 -1
  131. package/dist/components/switch/switch.js +28 -22
  132. package/dist/components/switch/switch.js.map +1 -0
  133. package/dist/components/table/data-table.d.ts +3 -25
  134. package/dist/components/table/data-table.d.ts.map +1 -1
  135. package/dist/components/table/data-table.js +211 -146
  136. package/dist/components/table/data-table.js.map +1 -0
  137. package/dist/components/table/table.d.ts +3 -3
  138. package/dist/components/table/table.d.ts.map +1 -1
  139. package/dist/components/table/table.js +39 -20
  140. package/dist/components/table/table.js.map +1 -0
  141. package/dist/components/tabs/tab-panel.d.ts +3 -1
  142. package/dist/components/tabs/tab-panel.d.ts.map +1 -1
  143. package/dist/components/tabs/tab-panel.js +21 -11
  144. package/dist/components/tabs/tab-panel.js.map +1 -0
  145. package/dist/components/tabs/tab.d.ts +5 -1
  146. package/dist/components/tabs/tab.d.ts.map +1 -1
  147. package/dist/components/tabs/tab.js +46 -28
  148. package/dist/components/tabs/tab.js.map +1 -0
  149. package/dist/components/tabs/tabs.d.ts +4 -0
  150. package/dist/components/tabs/tabs.d.ts.map +1 -1
  151. package/dist/components/tabs/tabs.js +76 -13
  152. package/dist/components/tabs/tabs.js.map +1 -0
  153. package/dist/components/textarea/textarea.d.ts +13 -0
  154. package/dist/components/textarea/textarea.d.ts.map +1 -1
  155. package/dist/components/textarea/textarea.js +59 -13
  156. package/dist/components/textarea/textarea.js.map +1 -0
  157. package/dist/components/theme-toggle/theme-toggle.constants.d.ts +3 -0
  158. package/dist/components/theme-toggle/theme-toggle.constants.d.ts.map +1 -0
  159. package/dist/components/theme-toggle/theme-toggle.constants.js +2 -0
  160. package/dist/components/theme-toggle/theme-toggle.constants.js.map +1 -0
  161. package/dist/components/theme-toggle/theme-toggle.d.ts +3 -2
  162. package/dist/components/theme-toggle/theme-toggle.d.ts.map +1 -1
  163. package/dist/components/theme-toggle/theme-toggle.js +46 -19
  164. package/dist/components/theme-toggle/theme-toggle.js.map +1 -0
  165. package/dist/components/vertical-nav/vertical-nav-group.d.ts +5 -2
  166. package/dist/components/vertical-nav/vertical-nav-group.d.ts.map +1 -1
  167. package/dist/components/vertical-nav/vertical-nav-group.js +50 -14
  168. package/dist/components/vertical-nav/vertical-nav-group.js.map +1 -0
  169. package/dist/components/vertical-nav/vertical-nav-item.d.ts +3 -2
  170. package/dist/components/vertical-nav/vertical-nav-item.d.ts.map +1 -1
  171. package/dist/components/vertical-nav/vertical-nav-item.js +30 -8
  172. package/dist/components/vertical-nav/vertical-nav-item.js.map +1 -0
  173. package/dist/styles/index.css +48 -17
  174. package/dist/styles/reset.js +1 -0
  175. package/dist/styles/reset.js.map +1 -0
  176. package/package.json +2 -1
  177. package/src/components/alert/alert.constants.ts +2 -0
  178. package/src/components/alert/alert.ts +24 -15
  179. package/src/components/badge/badge.constants.ts +2 -0
  180. package/src/components/badge/badge.ts +3 -4
  181. package/src/components/breadcrumb/breadcrumb.ts +2 -2
  182. package/src/components/button/button.constants.ts +8 -0
  183. package/src/components/button/button.ts +184 -144
  184. package/src/components/button-group/button-group.ts +18 -22
  185. package/src/components/checkbox/checkbox.constants.ts +2 -0
  186. package/src/components/checkbox/checkbox.ts +33 -18
  187. package/src/components/code-block/code-block.ts +151 -84
  188. package/src/components/content-card/content-card.ts +10 -16
  189. package/src/components/divider/divider.constants.ts +5 -0
  190. package/src/components/divider/divider.ts +22 -11
  191. package/src/components/drawer/drawer.ts +79 -34
  192. package/src/components/field/field.ts +9 -11
  193. package/src/components/footer/footer.ts +43 -12
  194. package/src/components/form/form.ts +121 -84
  195. package/src/components/grid/grid-row.ts +45 -32
  196. package/src/components/grid/grid.ts +7 -4
  197. package/src/components/icon/icon-paths.ts +175 -106
  198. package/src/components/icon/icon.ts +6 -6
  199. package/src/components/input/input.ts +32 -42
  200. package/src/components/link/link.ts +45 -21
  201. package/src/components/metadata/metadata.ts +26 -24
  202. package/src/components/modal/modal.ts +108 -74
  203. package/src/components/page-layout/page-layout.ts +97 -72
  204. package/src/components/radio/radio.ts +8 -13
  205. package/src/components/radio-group/radio-group.ts +45 -21
  206. package/src/components/router/router.ts +73 -50
  207. package/src/components/select/select.ts +18 -19
  208. package/src/components/skeleton/skeleton.ts +14 -14
  209. package/src/components/switch/switch.ts +31 -25
  210. package/src/components/table/data-table.ts +248 -177
  211. package/src/components/table/table.ts +52 -29
  212. package/src/components/tabs/tab-panel.ts +25 -13
  213. package/src/components/tabs/tab.ts +58 -33
  214. package/src/components/tabs/tabs.ts +77 -15
  215. package/src/components/textarea/textarea.ts +63 -15
  216. package/src/components/theme-toggle/theme-toggle.constants.ts +2 -0
  217. package/src/components/theme-toggle/theme-toggle.ts +47 -22
  218. package/src/components/vertical-nav/vertical-nav-group.ts +57 -18
  219. package/src/components/vertical-nav/vertical-nav-item.ts +35 -12
  220. package/src/styles/globals.css +27 -4
  221. package/src/styles/theme.css +38 -32
  222. package/tsconfig.json +2 -1
  223. package/dist/components/card/card.d.ts +0 -11
  224. package/dist/components/card/card.d.ts.map +0 -1
  225. package/dist/components/card/card.js +0 -54
  226. package/src/components/card/card.ts +0 -53
@@ -1,6 +1,6 @@
1
1
  export interface RouteDefinition {
2
2
  component: string;
3
- [key: string]: unknown; // Allows consuming apps to attach custom metadata (e.g., titles, auth roles)
3
+ [key: string]: unknown;
4
4
  }
5
5
 
6
6
  export type RouteConfig = Record<string, RouteDefinition>;
@@ -13,85 +13,105 @@ export interface RouteMatch {
13
13
  }
14
14
 
15
15
  function getRouteWeight(pattern: string): number {
16
- const segments = pattern.split('/').filter(Boolean);
16
+ const segments = pattern.split("/").filter(Boolean);
17
17
  return segments.reduce((weight, seg) => {
18
- return weight + (seg.startsWith(':') ? 1 : 10);
18
+ return weight + (seg.startsWith(":") ? 1 : 10);
19
19
  }, 0);
20
20
  }
21
21
 
22
22
  export class AppRouter {
23
23
  private _routes: RouteConfig = {};
24
24
  private _initialized = false;
25
+ private _boundNotify: () => void;
26
+ private _boundClick: (e: MouseEvent) => void;
25
27
 
26
28
  constructor(routes?: RouteConfig) {
29
+ this._boundNotify = () => this._notify();
30
+ this._boundClick = (e: MouseEvent) => this._handleClick(e);
31
+
27
32
  if (routes) {
28
33
  this.setRoutes(routes);
29
34
  }
30
35
 
31
- window.addEventListener('popstate', () => this._notify());
32
-
33
- document.addEventListener('click', (e) => {
34
- if (e.defaultPrevented || e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) {
35
- return;
36
- }
37
-
38
- const path = e.composedPath();
39
- const link = path.find((el: any) =>
40
- el && typeof el.hasAttribute === 'function' && el.hasAttribute('href')
41
- ) as HTMLElement | undefined;
36
+ // 🚀 FIX: SSR Safety check. Prevents crashes during Node.js CI test imports.
37
+ if (typeof window !== "undefined") {
38
+ window.addEventListener("popstate", this._boundNotify);
39
+ document.addEventListener("click", this._boundClick as EventListener);
40
+ }
41
+ }
42
42
 
43
- if (!link) return;
43
+ /**
44
+ * 🚀 FIX: Removes global listeners to prevent memory leaks during testing/teardown.
45
+ */
46
+ public destroy() {
47
+ if (typeof window !== "undefined") {
48
+ window.removeEventListener("popstate", this._boundNotify);
49
+ document.removeEventListener("click", this._boundClick as EventListener);
50
+ }
51
+ }
44
52
 
45
- const href = link.getAttribute('href');
46
- const target = link.getAttribute('target');
53
+ private _handleClick(e: MouseEvent) {
54
+ if (e.defaultPrevented || e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) {
55
+ return;
56
+ }
47
57
 
48
- if (!href || href.startsWith('http') || href.startsWith('mailto:') || target === '_blank') {
49
- return;
50
- }
58
+ const path = e.composedPath();
59
+ const link = path.find(
60
+ (el: any) => el && typeof el.hasAttribute === "function" && el.hasAttribute("href"),
61
+ ) as HTMLElement | undefined;
62
+
63
+ if (!link) return;
64
+
65
+ const href = link.getAttribute("href");
66
+ const target = link.getAttribute("target");
67
+
68
+ // 🚀 FIX: Ignore links with the 'download' attribute so file downloads aren't hijacked
69
+ if (
70
+ !href ||
71
+ href.startsWith("http") ||
72
+ href.startsWith("mailto:") ||
73
+ target === "_blank" ||
74
+ link.hasAttribute("download")
75
+ ) {
76
+ return;
77
+ }
51
78
 
52
- if (href.startsWith('/')) {
53
- e.preventDefault();
54
- this.navigate(href);
55
- }
56
- });
79
+ if (href.startsWith("/")) {
80
+ e.preventDefault();
81
+ this.navigate(href);
82
+ }
57
83
  }
58
84
 
59
- /**
60
- * Register or update the route configuration for this application.
61
- */
62
85
  public setRoutes(routes: RouteConfig) {
63
86
  this._routes = routes;
64
87
 
65
- // Trigger initial route resolution once routes are registered
66
88
  if (!this._initialized) {
67
89
  this._initialized = true;
68
- setTimeout(() => this._notify(), 0);
90
+ if (typeof window !== "undefined") {
91
+ setTimeout(() => this._notify(), 0);
92
+ }
69
93
  } else {
70
94
  this._notify();
71
95
  }
72
96
  }
73
97
 
74
- /**
75
- * Programmatically navigate to an internal path.
76
- */
77
98
  public navigate(path: string) {
78
- window.history.pushState(null, '', path);
99
+ if (typeof window !== "undefined") {
100
+ window.history.pushState(null, "", path);
101
+ }
79
102
  this._notify();
80
103
  }
81
104
 
82
- /**
83
- * Matches a URL path against the registered routes.
84
- */
85
105
  public matchRoute(currentPath: string): RouteMatch | null {
86
106
  const sortedRoutes = Object.entries(this._routes).sort(
87
- ([patternA], [patternB]) => getRouteWeight(patternB) - getRouteWeight(patternA)
107
+ ([patternA], [patternB]) => getRouteWeight(patternB) - getRouteWeight(patternA),
88
108
  );
89
109
 
90
110
  for (const [pattern, routeDef] of sortedRoutes) {
91
111
  const paramNames: string[] = [];
92
112
  const regexPath = pattern.replace(/:([a-zA-Z0-9_]+)/g, (_, paramName) => {
93
113
  paramNames.push(paramName);
94
- return '([^/]+)';
114
+ return "([^/]+)";
95
115
  });
96
116
 
97
117
  const regex = new RegExp(`^${regexPath}$`);
@@ -107,7 +127,7 @@ export class AppRouter {
107
127
  path: currentPath,
108
128
  component: routeDef.component,
109
129
  params,
110
- definition: routeDef
130
+ definition: routeDef,
111
131
  };
112
132
  }
113
133
  }
@@ -116,19 +136,22 @@ export class AppRouter {
116
136
  }
117
137
 
118
138
  private _notify() {
139
+ if (typeof window === "undefined") return;
140
+
119
141
  const currentPath = window.location.pathname;
120
142
  const match = this.matchRoute(currentPath);
121
143
 
122
- window.dispatchEvent(new CustomEvent('route-changed', {
123
- detail: {
124
- path: currentPath,
125
- component: match ? match.component : 'not-found-page',
126
- params: match ? match.params : {},
127
- definition: match ? match.definition : null
128
- }
129
- }));
144
+ window.dispatchEvent(
145
+ new CustomEvent("route-changed", {
146
+ detail: {
147
+ path: currentPath,
148
+ component: match ? match.component : "not-found-page",
149
+ params: match ? match.params : {},
150
+ definition: match ? match.definition : null,
151
+ },
152
+ }),
153
+ );
130
154
  }
131
155
  }
132
156
 
133
- // Export a singleton instance for standard app-wide use
134
- export const router = new AppRouter();
157
+ export const router = new AppRouter();
@@ -7,13 +7,9 @@ export interface SelectOption {
7
7
  value: string;
8
8
  }
9
9
 
10
- /**
11
- * Standard WHATWG Autocomplete tokens.
12
- */
13
10
  export type SelectAutocomplete =
14
11
  | "on"
15
12
  | "off"
16
- // Names
17
13
  | "name"
18
14
  | "honorific-prefix"
19
15
  | "given-name"
@@ -21,7 +17,6 @@ export type SelectAutocomplete =
21
17
  | "family-name"
22
18
  | "honorific-suffix"
23
19
  | "nickname"
24
- // Authentication & Identity
25
20
  | "email"
26
21
  | "username"
27
22
  | "new-password"
@@ -32,19 +27,17 @@ export type SelectAutocomplete =
32
27
  | "url"
33
28
  | "photo"
34
29
  | "webauthn"
35
- // Addresses
36
30
  | "street-address"
37
31
  | "address-line1"
38
32
  | "address-line2"
39
33
  | "address-line3"
40
- | "address-level1" // State / Province
41
- | "address-level2" // City
34
+ | "address-level1"
35
+ | "address-level2"
42
36
  | "address-level3"
43
37
  | "address-level4"
44
38
  | "country"
45
39
  | "country-name"
46
40
  | "postal-code"
47
- // Payment
48
41
  | "cc-name"
49
42
  | "cc-given-name"
50
43
  | "cc-additional-name"
@@ -57,14 +50,12 @@ export type SelectAutocomplete =
57
50
  | "cc-type"
58
51
  | "transaction-currency"
59
52
  | "transaction-amount"
60
- // Personal
61
53
  | "language"
62
54
  | "bday"
63
55
  | "bday-day"
64
56
  | "bday-month"
65
57
  | "bday-year"
66
58
  | "sex"
67
- // Telephone & Messaging
68
59
  | "tel"
69
60
  | "tel-country-code"
70
61
  | "tel-national"
@@ -74,7 +65,6 @@ export type SelectAutocomplete =
74
65
  | "tel-local-suffix"
75
66
  | "tel-extension"
76
67
  | "impp"
77
- // Preserves IDE autocomplete while allowing space-separated modifiers (e.g., "shipping postal-code")
78
68
  | (string & {});
79
69
 
80
70
  @customElement("st-select")
@@ -184,7 +174,7 @@ export class StSelect extends LitElement {
184
174
  top: calc(100% + 4px);
185
175
  left: 0;
186
176
  right: 0;
187
- z-index: 1;
177
+ z-index: 10;
188
178
  background: var(--st-color-surface);
189
179
  border: 1px solid var(--st-color-border);
190
180
  border-radius: var(--st-radius-md);
@@ -264,19 +254,17 @@ export class StSelect extends LitElement {
264
254
  this.handleClickOutside = this.handleClickOutside.bind(this);
265
255
  }
266
256
 
267
- // 2. Public API methods expected by st-form
268
257
  public checkValidity(): boolean {
269
258
  return this.internals.checkValidity();
270
259
  }
271
260
 
272
261
  public reportValidity(): boolean {
273
262
  const isValid = this.checkValidity();
274
- this.touched = true; // Force UI to reveal the error
263
+ this.touched = true;
275
264
  this.invalid = !isValid;
276
265
  return isValid;
277
266
  }
278
267
 
279
- // 3. Override native focus to target the internal combobox button
280
268
  public override focus(options?: FocusOptions) {
281
269
  this.buttonElement?.focus(options);
282
270
  }
@@ -297,6 +285,7 @@ export class StSelect extends LitElement {
297
285
  }
298
286
 
299
287
  override willUpdate(changedProperties: PropertyValues) {
288
+ super.willUpdate(changedProperties);
300
289
  if (
301
290
  changedProperties.has("value") ||
302
291
  changedProperties.has("required") ||
@@ -333,6 +322,13 @@ export class StSelect extends LitElement {
333
322
  }
334
323
  }
335
324
 
325
+ formResetCallback() {
326
+ const initialValue = this.getAttribute("value") || "";
327
+ this.value = initialValue;
328
+ this.touched = false;
329
+ this.validate();
330
+ }
331
+
336
332
  private handleClickOutside(e: Event) {
337
333
  const path = e.composedPath();
338
334
  if (!path.includes(this)) {
@@ -406,7 +402,6 @@ export class StSelect extends LitElement {
406
402
  const currentValues = this.selectedValues;
407
403
  const selectedOptions = this.options.filter((opt) => currentValues.includes(opt.value));
408
404
 
409
- // 4. Update isInvalid to also respect the new property fallback
410
405
  const isInvalid =
411
406
  this.invalid || (this.touched && !this.internals.validity.valid) || !!this.error;
412
407
  const displayError = isInvalid ? this.error || this.nativeError : "";
@@ -465,6 +460,8 @@ export class StSelect extends LitElement {
465
460
  class="search-input"
466
461
  placeholder="Search options..."
467
462
  autocomplete="off"
463
+ spellcheck="false"
464
+ autocapitalize="none"
468
465
  .value=${this.filterText}
469
466
  @input=${this.handleSearchInput}
470
467
  />
@@ -495,6 +492,8 @@ export class StSelect extends LitElement {
495
492
  })
496
493
  : html`<li
497
494
  class="option"
495
+ role="option"
496
+ aria-disabled="true"
498
497
  style="color:var(--st-color-text-muted); cursor:default;"
499
498
  >
500
499
  No options found
@@ -508,7 +507,7 @@ export class StSelect extends LitElement {
508
507
  <select
509
508
  class="hidden-native"
510
509
  name="${this.name}"
511
- .autocomplete="${this.autocomplete}"
510
+ .autocomplete="${this.autocomplete as any}"
512
511
  ?multiple=${this.multiple}
513
512
  tabindex="-1"
514
513
  aria-hidden="true"
@@ -531,4 +530,4 @@ declare global {
531
530
  interface HTMLElementTagNameMap {
532
531
  "st-select": StSelect;
533
532
  }
534
- }
533
+ }
@@ -1,4 +1,4 @@
1
- import { LitElement, html, css } from 'lit';
1
+ import { LitElement, html, css, PropertyValues } from 'lit';
2
2
  import { customElement, property } from 'lit/decorators.js';
3
3
  import { resetStyles } from '../../styles/reset.js';
4
4
 
@@ -9,8 +9,14 @@ export class StSkeleton extends LitElement {
9
9
  @property({ type: String }) width = '';
10
10
  @property({ type: String }) height = '';
11
11
 
12
- // Apply properties directly to the :host as CSS variables when they change
13
- updated(changedProperties: Map<string | number | symbol, unknown>) {
12
+ constructor() {
13
+ super();
14
+ this.setAttribute('role', 'status');
15
+ this.setAttribute('aria-label', 'Loading');
16
+ this.setAttribute('aria-busy', 'true');
17
+ }
18
+
19
+ override updated(changedProperties: PropertyValues<this>) {
14
20
  super.updated(changedProperties);
15
21
 
16
22
  if (changedProperties.has('width')) {
@@ -36,22 +42,20 @@ export class StSkeleton extends LitElement {
36
42
  :host {
37
43
  display: block;
38
44
 
39
- /* Define base sizing variables that can be overridden by props */
40
45
  --_width: var(--st-skeleton-width, 100%);
41
46
  --_height: var(--st-skeleton-height, 1em);
42
47
 
43
- /*
44
- CRITICAL FIX: Apply sizing directly to the host.
45
- This allows external classes and styles (like margin: auto) to work perfectly.
46
- */
47
48
  width: var(--_width);
48
49
  height: var(--_height);
49
50
 
50
- /* Expose radius as a token for external theme overrides */
51
51
  --st-skeleton-radius: var(--st-radius-sm, 0.25rem);
52
52
  }
53
53
 
54
- /* Shape Variants adjust the host's sizing variables */
54
+ :host([variant="text"]) {
55
+ display: inline-block;
56
+ vertical-align: middle;
57
+ }
58
+
55
59
  :host([variant="circular"]) {
56
60
  --_width: var(--st-skeleton-width, 2.5rem);
57
61
  --_height: var(--st-skeleton-height, 2.5rem);
@@ -62,7 +66,6 @@ export class StSkeleton extends LitElement {
62
66
  }
63
67
 
64
68
  .skeleton {
65
- /* The inner element simply fills the host */
66
69
  display: block;
67
70
  width: 100%;
68
71
  height: 100%;
@@ -76,7 +79,6 @@ export class StSkeleton extends LitElement {
76
79
  background-size: 400% 100%;
77
80
  border-radius: var(--st-skeleton-radius);
78
81
 
79
- /* Prevent accidental selection */
80
82
  user-select: none;
81
83
  pointer-events: none;
82
84
  }
@@ -85,7 +87,6 @@ export class StSkeleton extends LitElement {
85
87
  border-radius: 50%;
86
88
  }
87
89
 
88
- /* Animations */
89
90
  :host([animation="shimmer"]) .skeleton {
90
91
  animation: st-shimmer 1.4s ease infinite;
91
92
  }
@@ -100,7 +101,6 @@ export class StSkeleton extends LitElement {
100
101
  animation: none;
101
102
  }
102
103
 
103
- /* Accessibility: Respect OS reduced motion settings */
104
104
  @media (prefers-reduced-motion: reduce) {
105
105
  .skeleton {
106
106
  animation: none !important;
@@ -1,23 +1,25 @@
1
1
  import {LitElement, html, css, PropertyValues} from "lit";
2
2
  import {customElement, property, query} from "lit/decorators.js";
3
+ import {ifDefined} from "lit/directives/if-defined.js";
3
4
  import {resetStyles} from "../../styles/reset.js";
4
5
 
5
6
  @customElement("st-switch")
6
7
  export class StSwitch extends LitElement {
7
8
  static formAssociated = true;
8
9
  private _internals: ElementInternals;
10
+ static shadowRootOptions = {...LitElement.shadowRootOptions, delegatesFocus: true};
9
11
 
10
12
  @query("input") private _inputEl!: HTMLInputElement;
11
13
 
12
14
  @property({type: String, reflect: true}) name = "";
13
15
  @property({type: String}) value = "on";
14
-
15
16
  @property({type: Boolean, reflect: true}) checked = false;
16
17
  @property({type: Boolean, reflect: true}) disabled = false;
17
18
  @property({type: Boolean, reflect: true}) required = false;
18
-
19
19
  @property({attribute: "aria-label"}) ariaLabel = "";
20
20
 
21
+ private _defaultChecked = false;
22
+
21
23
  constructor() {
22
24
  super();
23
25
  this._internals = this.attachInternals();
@@ -41,7 +43,6 @@ export class StSwitch extends LitElement {
41
43
  font-size: var(--st-font-size-base);
42
44
  }
43
45
 
44
- /* Visually hide the native input */
45
46
  input {
46
47
  position: absolute;
47
48
  width: 1px;
@@ -54,12 +55,11 @@ export class StSwitch extends LitElement {
54
55
  border-width: 0;
55
56
  }
56
57
 
57
- /* The Switch Track (Pill) */
58
58
  .track {
59
59
  display: flex;
60
60
  align-items: center;
61
- width: 2.25rem; /* 36px */
62
- height: 1.25rem; /* 20px */
61
+ width: 2.25rem;
62
+ height: 1.25rem;
63
63
  background-color: var(--st-color-border);
64
64
  border-radius: 999px;
65
65
  padding: 2px;
@@ -69,40 +69,34 @@ export class StSwitch extends LitElement {
69
69
  flex-shrink: 0;
70
70
  }
71
71
 
72
- /* The Switch Thumb (Circle) */
73
72
  .thumb {
74
- width: 1rem; /* 16px */
75
- height: 1rem; /* 16px */
76
- background-color: var(--st-white);
73
+ width: 1rem;
74
+ height: 1rem;
75
+ background-color: #ffffff; /* Explicitly white for contrast */
77
76
  border-radius: 50%;
78
77
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
79
78
  transform: translateX(0);
80
79
  transition: transform 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
81
80
  }
82
81
 
83
- /* Focus State */
82
+ label:hover input:not(:checked):not(:disabled) + .track {
83
+ background-color: var(--st-color-text-muted);
84
+ }
85
+
84
86
  input:focus-visible + .track {
85
87
  box-shadow:
86
88
  0 0 0 2px var(--st-color-bg),
87
89
  0 0 0 4px var(--st-color-primary);
88
90
  }
89
91
 
90
- /* Checked State */
91
92
  :host([checked]) .track {
92
93
  background-color: var(--st-color-primary);
93
94
  }
94
95
 
95
96
  :host([checked]) .thumb {
96
- /* Move thumb to the right: Track width (36px) - Padding (4px) - Thumb width (16px) = 16px */
97
97
  transform: translateX(16px);
98
98
  }
99
99
 
100
- /* Hover State (Subtle darkening of the track if unchecked) */
101
- label:hover input:not(:checked) + .track {
102
- background-color: var(--st-color-text-muted);
103
- }
104
-
105
- /* Disabled State */
106
100
  :host([disabled]) {
107
101
  pointer-events: none;
108
102
  }
@@ -114,16 +108,21 @@ export class StSwitch extends LitElement {
114
108
  `,
115
109
  ];
116
110
 
111
+ override firstUpdated(changedProperties: PropertyValues) {
112
+ super.firstUpdated(changedProperties);
113
+ this._defaultChecked = this.checked;
114
+ }
115
+
117
116
  override updated(changedProperties: PropertyValues<this>) {
118
117
  super.updated(changedProperties);
119
118
 
120
119
  if (changedProperties.has("checked") || changedProperties.has("value")) {
121
120
  this._internals.setFormValue(this.checked ? this.value : null);
122
- this._syncValidity();
121
+ this.updateComplete.then(() => this._syncValidity());
123
122
  }
124
123
 
125
124
  if (changedProperties.has("required")) {
126
- this._syncValidity();
125
+ this.updateComplete.then(() => this._syncValidity());
127
126
  }
128
127
  }
129
128
 
@@ -136,15 +135,22 @@ export class StSwitch extends LitElement {
136
135
  );
137
136
  }
138
137
 
138
+ public checkValidity() {
139
+ return this._internals.checkValidity();
140
+ }
141
+
142
+ public reportValidity() {
143
+ return this._internals.reportValidity();
144
+ }
145
+
139
146
  formResetCallback() {
140
- this.checked = false;
141
- this._internals.setFormValue(null);
147
+ this.checked = this._defaultChecked;
148
+ this._internals.setFormValue(this.checked ? this.value : null);
142
149
  this.updateComplete.then(() => this._syncValidity());
143
150
  }
144
151
 
145
152
  private _handleChange(e: Event) {
146
153
  e.stopPropagation();
147
-
148
154
  if (this.disabled) return;
149
155
 
150
156
  this.checked = this._inputEl.checked;
@@ -157,7 +163,7 @@ export class StSwitch extends LitElement {
157
163
  <input
158
164
  type="checkbox"
159
165
  role="switch"
160
- aria-label=${this.ariaLabel || ""}
166
+ aria-label=${ifDefined(this.ariaLabel || undefined)}
161
167
  .name=${this.name}
162
168
  .value=${this.value}
163
169
  .checked=${this.checked}