@marianmeres/stuic 2.66.0 → 3.0.1

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 (208) hide show
  1. package/README.md +292 -4
  2. package/dist/README.md +41 -18
  3. package/dist/actions/index.d.ts +1 -0
  4. package/dist/actions/index.js +1 -0
  5. package/dist/actions/popover/README.md +19 -0
  6. package/dist/actions/popover/index.css +6 -9
  7. package/dist/actions/popover/popover.svelte.js +2 -2
  8. package/dist/actions/tooltip/README.md +18 -0
  9. package/dist/actions/tooltip/index.css +5 -8
  10. package/dist/actions/tooltip/tooltip.svelte.js +1 -1
  11. package/dist/actions/typeahead.svelte.d.ts +53 -0
  12. package/dist/actions/typeahead.svelte.js +328 -0
  13. package/dist/base.css +17 -0
  14. package/dist/components/AlertConfirmPrompt/AlertConfirmPrompt.svelte +10 -10
  15. package/dist/components/AlertConfirmPrompt/AlertConfirmPrompt.svelte.d.ts +4 -3
  16. package/dist/components/AlertConfirmPrompt/Current.svelte +15 -18
  17. package/dist/components/AlertConfirmPrompt/Current.svelte.d.ts +4 -3
  18. package/dist/components/AlertConfirmPrompt/acp-icons.js +5 -4
  19. package/dist/components/AlertConfirmPrompt/index.css +66 -0
  20. package/dist/components/AssetsPreview/AssetsPreview.svelte +91 -73
  21. package/dist/components/AssetsPreview/index.css +61 -0
  22. package/dist/components/Avatar/Avatar.svelte +31 -18
  23. package/dist/components/Avatar/README.md +166 -0
  24. package/dist/components/Avatar/index.css +130 -0
  25. package/dist/components/Backdrop/Backdrop.svelte +7 -2
  26. package/dist/components/Backdrop/README.md +71 -6
  27. package/dist/components/Backdrop/index.css +31 -0
  28. package/dist/components/Button/Button.svelte +116 -124
  29. package/dist/components/Button/Button.svelte.d.ts +35 -24
  30. package/dist/components/Button/README.md +87 -21
  31. package/dist/components/Button/index.css +475 -9
  32. package/dist/components/Button/index.d.ts +1 -1
  33. package/dist/components/Button/index.js +1 -1
  34. package/dist/components/ButtonGroupRadio/ButtonGroupRadio.svelte +7 -39
  35. package/dist/components/ButtonGroupRadio/ButtonGroupRadio.svelte.d.ts +0 -1
  36. package/dist/components/ButtonGroupRadio/README.md +82 -4
  37. package/dist/components/ButtonGroupRadio/index.css +158 -14
  38. package/dist/components/Collapsible/Collapsible.svelte +7 -7
  39. package/dist/components/Collapsible/Collapsible.svelte.d.ts +2 -2
  40. package/dist/components/Collapsible/README.md +34 -2
  41. package/dist/components/Collapsible/index.css +40 -0
  42. package/dist/components/CommandMenu/CommandMenu.svelte +18 -26
  43. package/dist/components/CommandMenu/CommandMenu.svelte.d.ts +0 -1
  44. package/dist/components/CommandMenu/README.md +39 -0
  45. package/dist/components/CommandMenu/index.css +47 -2
  46. package/dist/components/DismissibleMessage/DismissibleMessage.svelte +53 -51
  47. package/dist/components/DismissibleMessage/DismissibleMessage.svelte.d.ts +6 -6
  48. package/dist/components/DismissibleMessage/README.md +93 -11
  49. package/dist/components/DismissibleMessage/index.css +128 -8
  50. package/dist/components/DismissibleMessage/index.d.ts +1 -1
  51. package/dist/components/DropdownMenu/DropdownMenu.svelte +14 -51
  52. package/dist/components/DropdownMenu/DropdownMenu.svelte.d.ts +6 -7
  53. package/dist/components/DropdownMenu/README.md +132 -0
  54. package/dist/components/DropdownMenu/index.css +258 -52
  55. package/dist/components/Input/FieldAssets.svelte +8 -5
  56. package/dist/components/Input/FieldCheckbox.svelte +7 -44
  57. package/dist/components/Input/FieldFile.svelte +1 -6
  58. package/dist/components/Input/FieldInput.svelte +9 -1
  59. package/dist/components/Input/FieldInput.svelte.d.ts +2 -0
  60. package/dist/components/Input/FieldOptions.svelte +42 -39
  61. package/dist/components/Input/FieldRadios.svelte +7 -16
  62. package/dist/components/Input/FieldSelect.svelte +1 -1
  63. package/dist/components/Input/FieldSwitch.svelte +1 -5
  64. package/dist/components/Input/FieldTextarea.svelte +1 -1
  65. package/dist/components/Input/README.md +194 -0
  66. package/dist/components/Input/_internal/FieldRadioInternal.svelte +2 -40
  67. package/dist/components/Input/_internal/InputWrap.svelte +8 -48
  68. package/dist/components/Input/index.css +524 -116
  69. package/dist/components/KbdShortcut/KbdShortcut.svelte +4 -12
  70. package/dist/components/KbdShortcut/README.md +34 -0
  71. package/dist/components/KbdShortcut/index.css +55 -0
  72. package/dist/components/ListItemButton/ListItemButton.svelte +37 -74
  73. package/dist/components/ListItemButton/ListItemButton.svelte.d.ts +1 -10
  74. package/dist/components/ListItemButton/README.md +100 -45
  75. package/dist/components/ListItemButton/index.css +173 -52
  76. package/dist/components/ListItemButton/index.d.ts +1 -1
  77. package/dist/components/ListItemButton/index.js +1 -1
  78. package/dist/components/Modal/Modal.svelte +1 -8
  79. package/dist/components/Modal/README.md +29 -0
  80. package/dist/components/Modal/index.css +38 -0
  81. package/dist/components/ModalDialog/ModalDialog.svelte +2 -21
  82. package/dist/components/ModalDialog/README.md +35 -0
  83. package/dist/components/ModalDialog/index.css +59 -0
  84. package/dist/components/Nav/Nav.svelte +732 -0
  85. package/dist/components/Nav/Nav.svelte.d.ts +110 -0
  86. package/dist/components/Nav/README.md +334 -0
  87. package/dist/components/Nav/index.css +318 -0
  88. package/dist/components/Nav/index.d.ts +1 -0
  89. package/dist/components/Nav/index.js +1 -0
  90. package/dist/components/Notifications/Notifications.svelte +44 -129
  91. package/dist/components/Notifications/Notifications.svelte.d.ts +9 -18
  92. package/dist/components/Notifications/README.md +186 -70
  93. package/dist/components/Notifications/index.css +212 -15
  94. package/dist/components/Notifications/notifications-stack.svelte.d.ts +4 -0
  95. package/dist/components/Notifications/notifications-stack.svelte.js +8 -0
  96. package/dist/components/Progress/Progress.svelte +4 -2
  97. package/dist/components/Progress/Progress.svelte.d.ts +1 -0
  98. package/dist/components/Progress/README.md +97 -11
  99. package/dist/components/Progress/_internal/Bar.svelte +4 -15
  100. package/dist/components/Progress/_internal/Bar.svelte.d.ts +1 -1
  101. package/dist/components/Progress/_internal/Circle.svelte +30 -2
  102. package/dist/components/Progress/_internal/Circle.svelte.d.ts +1 -0
  103. package/dist/components/Progress/index.css +50 -4
  104. package/dist/components/Skeleton/README.md +152 -0
  105. package/dist/components/Skeleton/Skeleton.svelte +9 -9
  106. package/dist/components/Skeleton/Skeleton.svelte.d.ts +0 -1
  107. package/dist/components/Skeleton/index.css +72 -45
  108. package/dist/components/Spinner/README.md +149 -37
  109. package/dist/components/Spinner/Spinner.svelte +14 -38
  110. package/dist/components/Spinner/Spinner.svelte.d.ts +2 -1
  111. package/dist/components/Spinner/SpinnerCircle.svelte +6 -34
  112. package/dist/components/Spinner/SpinnerCircle.svelte.d.ts +1 -0
  113. package/dist/components/Spinner/SpinnerCircleOscillate.svelte +10 -5
  114. package/dist/components/Spinner/SpinnerUnicode.svelte +3 -1
  115. package/dist/components/Spinner/SpinnerUnicode.svelte.d.ts +1 -0
  116. package/dist/components/Spinner/index.css +104 -0
  117. package/dist/components/Switch/README.md +45 -14
  118. package/dist/components/Switch/Switch.svelte +23 -48
  119. package/dist/components/Switch/Switch.svelte.d.ts +4 -2
  120. package/dist/components/Switch/index.css +121 -4
  121. package/dist/components/Switch/index.d.ts +1 -2
  122. package/dist/components/Switch/index.js +1 -2
  123. package/dist/components/TabbedMenu/README.md +37 -21
  124. package/dist/components/TabbedMenu/TabbedMenu.svelte +5 -46
  125. package/dist/components/TabbedMenu/TabbedMenu.svelte.d.ts +0 -1
  126. package/dist/components/TabbedMenu/index.css +84 -17
  127. package/dist/components/ThemePreview/README.md +289 -0
  128. package/dist/components/ThemePreview/ThemePreview.svelte +394 -0
  129. package/dist/components/ThemePreview/ThemePreview.svelte.d.ts +35 -0
  130. package/dist/components/ThemePreview/index.css +509 -0
  131. package/dist/components/ThemePreview/index.d.ts +1 -0
  132. package/dist/components/ThemePreview/index.js +1 -0
  133. package/dist/components/TwCheck/README.md +32 -13
  134. package/dist/components/TwCheck/TwCheck.svelte +11 -9
  135. package/dist/components/TwCheck/TwCheck.svelte.d.ts +0 -1
  136. package/dist/components/TwCheck/index.css +17 -2
  137. package/dist/components/TypeaheadInput/TypeaheadInput.svelte +20 -188
  138. package/dist/components/TypeaheadInput/TypeaheadInput.svelte.d.ts +4 -2
  139. package/dist/components/X/X.svelte +12 -5
  140. package/dist/components/X/X.svelte.d.ts +1 -0
  141. package/dist/icons/index.d.ts +1 -0
  142. package/dist/icons/index.js +1 -0
  143. package/dist/index.css +46 -26
  144. package/dist/index.d.ts +2 -0
  145. package/dist/index.js +2 -0
  146. package/dist/themes/blue-orange.css +217 -0
  147. package/dist/themes/blue-orange.d.ts +6 -0
  148. package/dist/themes/blue-orange.js +175 -0
  149. package/dist/themes/cyan-red.css +217 -0
  150. package/dist/themes/cyan-red.d.ts +6 -0
  151. package/dist/themes/cyan-red.js +175 -0
  152. package/dist/themes/cyan-slate.css +217 -0
  153. package/dist/themes/cyan-slate.d.ts +6 -0
  154. package/dist/themes/cyan-slate.js +175 -0
  155. package/dist/themes/emerald-pink.css +217 -0
  156. package/dist/themes/emerald-pink.d.ts +6 -0
  157. package/dist/themes/emerald-pink.js +175 -0
  158. package/dist/themes/fuchsia-emerald.css +217 -0
  159. package/dist/themes/fuchsia-emerald.d.ts +6 -0
  160. package/dist/themes/fuchsia-emerald.js +175 -0
  161. package/dist/themes/gray.css +217 -0
  162. package/dist/themes/gray.d.ts +6 -0
  163. package/dist/themes/gray.js +175 -0
  164. package/dist/themes/indigo-amber.css +217 -0
  165. package/dist/themes/indigo-amber.d.ts +6 -0
  166. package/dist/themes/indigo-amber.js +175 -0
  167. package/dist/themes/neutral.css +217 -0
  168. package/dist/themes/neutral.d.ts +6 -0
  169. package/dist/themes/neutral.js +175 -0
  170. package/dist/themes/pink-emerald.css +217 -0
  171. package/dist/themes/pink-emerald.d.ts +6 -0
  172. package/dist/themes/pink-emerald.js +175 -0
  173. package/dist/themes/purple-yellow.css +217 -0
  174. package/dist/themes/purple-yellow.d.ts +6 -0
  175. package/dist/themes/purple-yellow.js +175 -0
  176. package/dist/themes/rainbow.css +217 -0
  177. package/dist/themes/rainbow.d.ts +6 -0
  178. package/dist/themes/rainbow.js +180 -0
  179. package/dist/themes/red-blue.css +217 -0
  180. package/dist/themes/red-blue.d.ts +6 -0
  181. package/dist/themes/red-blue.js +175 -0
  182. package/dist/themes/red-cyan.css +217 -0
  183. package/dist/themes/red-cyan.d.ts +6 -0
  184. package/dist/themes/red-cyan.js +175 -0
  185. package/dist/themes/rose-teal.css +217 -0
  186. package/dist/themes/rose-teal.d.ts +6 -0
  187. package/dist/themes/rose-teal.js +175 -0
  188. package/dist/themes/sky-amber.css +217 -0
  189. package/dist/themes/sky-amber.d.ts +6 -0
  190. package/dist/themes/sky-amber.js +175 -0
  191. package/dist/themes/slate-cyan.css +217 -0
  192. package/dist/themes/slate-cyan.d.ts +6 -0
  193. package/dist/themes/slate-cyan.js +175 -0
  194. package/dist/themes/tailwind-color-pairs.md +31 -0
  195. package/dist/themes/teal-rose.css +217 -0
  196. package/dist/themes/teal-rose.d.ts +6 -0
  197. package/dist/themes/teal-rose.js +175 -0
  198. package/dist/themes/violet-lime.css +217 -0
  199. package/dist/themes/violet-lime.d.ts +6 -0
  200. package/dist/themes/violet-lime.js +175 -0
  201. package/dist/utils/design-tokens.d.ts +43 -0
  202. package/dist/utils/design-tokens.js +127 -0
  203. package/dist/utils/index.d.ts +1 -0
  204. package/dist/utils/index.js +1 -0
  205. package/dist/utils/storage-abstraction.js +1 -1
  206. package/package.json +14 -11
  207. package/dist/components/Switch/SwitchButton.svelte +0 -135
  208. package/dist/components/Switch/SwitchButton.svelte.d.ts +0 -21
@@ -0,0 +1,127 @@
1
+ // ============================================================================
2
+ // Types
3
+ // ============================================================================
4
+ // ============================================================================
5
+ // Helpers
6
+ // ============================================================================
7
+ /** Check if a single color is an object with states or a plain string */
8
+ function isSingleColorObject(value) {
9
+ return typeof value === "object" && "DEFAULT" in value;
10
+ }
11
+ /** Generate color tokens for a paired color (with foreground) */
12
+ function generatePairedColorTokens(tokens, key, pair, prefix = "stuic-") {
13
+ // Main color
14
+ tokens[`${prefix}color-${key}`] = pair.DEFAULT;
15
+ tokens[`${prefix}color-${key}-hover`] = pair.hover ?? pair.DEFAULT;
16
+ tokens[`${prefix}color-${key}-active`] = pair.active ?? pair.DEFAULT;
17
+ // Foreground
18
+ tokens[`${prefix}color-${key}-foreground`] = pair.foreground;
19
+ tokens[`${prefix}color-${key}-foreground-hover`] =
20
+ pair.foregroundHover ?? pair.foreground;
21
+ tokens[`${prefix}color-${key}-foreground-active`] =
22
+ pair.foregroundActive ?? pair.foreground;
23
+ }
24
+ /** Generate color tokens for a single color */
25
+ function generateSingleColorTokens(tokens, key, color, prefix = "stuic-") {
26
+ if (isSingleColorObject(color)) {
27
+ tokens[`${prefix}color-${key}`] = color.DEFAULT;
28
+ tokens[`${prefix}color-${key}-hover`] = color.hover ?? color.DEFAULT;
29
+ tokens[`${prefix}color-${key}-active`] = color.active ?? color.DEFAULT;
30
+ }
31
+ else {
32
+ // Plain string: use same value for all states
33
+ tokens[`${prefix}color-${key}`] = color;
34
+ tokens[`${prefix}color-${key}-hover`] = color;
35
+ tokens[`${prefix}color-${key}-active`] = color;
36
+ }
37
+ }
38
+ // ============================================================================
39
+ // Generator
40
+ // ============================================================================
41
+ export function generateCssTokens(schema, prefix = "stuic-") {
42
+ const tokens = {};
43
+ // Intent colors
44
+ for (const [key, pair] of Object.entries(schema.colors.intent)) {
45
+ generatePairedColorTokens(tokens, key, pair, prefix);
46
+ }
47
+ // Role colors (paired)
48
+ for (const [key, pair] of Object.entries(schema.colors.role.paired)) {
49
+ generatePairedColorTokens(tokens, key, pair, prefix);
50
+ }
51
+ // Role colors (single)
52
+ for (const [key, color] of Object.entries(schema.colors.role.single)) {
53
+ generateSingleColorTokens(tokens, key, color, prefix);
54
+ }
55
+ return tokens;
56
+ }
57
+ // ============================================================================
58
+ // CSS Output Helpers
59
+ // ============================================================================
60
+ // Generic fallback for any Tailwind color variable
61
+ // This is a safety net for Vite HMR timing - rarely visible in practice
62
+ const GENERIC_COLOR_FALLBACK = "#737373"; // neutral-500 (mid-gray)
63
+ /**
64
+ * Add generic fallback to var(--color-X) references
65
+ * Input: "var(--color-neutral-800)"
66
+ * Output: "var(--color-neutral-800, #737373)"
67
+ *
68
+ * Works for ANY Tailwind color (neutral, blue, red, etc.)
69
+ */
70
+ function addColorFallback(value) {
71
+ // Match var(--color-X) pattern (but not if it already has a fallback)
72
+ const match = value.match(/^var\(--color-([^,)]+)\)$/);
73
+ if (match) {
74
+ const colorName = match[1];
75
+ // Special cases for obvious colors
76
+ if (colorName === "white")
77
+ return `var(--color-white, #ffffff)`;
78
+ if (colorName === "black")
79
+ return `var(--color-black, #000000)`;
80
+ // Generic fallback for all other colors
81
+ return `var(--color-${colorName}, ${GENERIC_COLOR_FALLBACK})`;
82
+ }
83
+ return value;
84
+ }
85
+ /** Convert tokens object to CSS :root declaration */
86
+ export function toCssString(tokens, selector = ":root") {
87
+ // Find max key length for padding
88
+ const maxLen = Math.max(...Object.keys(tokens).map((k) => `--${k}`.length));
89
+ // Helper to extract base color name from token key
90
+ const getBaseColor = (key) => {
91
+ // e.g., "stuic-color-primary-foreground-hover" → "primary"
92
+ // e.g., "stuic-color-surface-1-foreground" → "surface-1"
93
+ const match = key.match(/^stuic-color-([a-z]+-?\d*)/);
94
+ return match ? match[1] : key;
95
+ };
96
+ // Group tokens by base color name (preserving order)
97
+ const groups = new Map();
98
+ for (const [key, value] of Object.entries(tokens)) {
99
+ const base = getBaseColor(key);
100
+ if (!groups.has(base)) {
101
+ groups.set(base, []);
102
+ }
103
+ groups.get(base).push([key, value]);
104
+ }
105
+ // Format a token with padding (include colon in key)
106
+ const formatVar = ([key, value]) => {
107
+ const cssKey = `--${key}:`;
108
+ const valueWithFallback = addColorFallback(value);
109
+ return `\t${cssKey.padEnd(maxLen + 1)} ${valueWithFallback};`;
110
+ };
111
+ // Build output with empty lines between each color group
112
+ const parts = [];
113
+ for (const entries of groups.values()) {
114
+ parts.push(entries.map(formatVar).join("\n"));
115
+ }
116
+ return `${selector} {\n${parts.join("\n\n")}\n}\n`;
117
+ }
118
+ /** Create dark mode override tokens */
119
+ export function createDarkOverride(baseTokens, overrides) {
120
+ const darkTokens = {};
121
+ for (const [key, value] of Object.entries(overrides)) {
122
+ if (key in baseTokens && value !== undefined) {
123
+ darkTokens[key] = value;
124
+ }
125
+ }
126
+ return darkTokens;
127
+ }
@@ -3,6 +3,7 @@ export * from "./body-scroll-locker.js";
3
3
  export * from "./breakpoint.svelte.js";
4
4
  export * from "./colors.js";
5
5
  export * from "./debounce.js";
6
+ export * from "./design-tokens.js";
6
7
  export * from "./device-pointer.svelte.js";
7
8
  export * from "./escape-regex.js";
8
9
  export * from "./event-emitter.js";
@@ -3,6 +3,7 @@ export * from "./body-scroll-locker.js";
3
3
  export * from "./breakpoint.svelte.js";
4
4
  export * from "./colors.js";
5
5
  export * from "./debounce.js";
6
+ export * from "./design-tokens.js";
6
7
  export * from "./device-pointer.svelte.js";
7
8
  export * from "./escape-regex.js";
8
9
  export * from "./event-emitter.js";
@@ -131,7 +131,7 @@ export class StorageAbstraction {
131
131
  }
132
132
  function storage_value(type, key, initial) {
133
133
  const s = new StorageAbstraction(type);
134
- if (!s.has(key))
134
+ if (!s.has(key) && initial !== undefined)
135
135
  s.set(key, initial);
136
136
  return {
137
137
  get() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marianmeres/stuic",
3
- "version": "2.66.0",
3
+ "version": "3.0.1",
4
4
  "files": [
5
5
  "dist",
6
6
  "!dist/**/*.test.*",
@@ -26,30 +26,31 @@
26
26
  "@marianmeres/icons-fns": "^5.0.0",
27
27
  "@marianmeres/random-human-readable": "^1.6.1",
28
28
  "@sveltejs/adapter-auto": "^4.0.0",
29
- "@sveltejs/kit": "^2.49.5",
29
+ "@sveltejs/kit": "^2.50.1",
30
30
  "@sveltejs/package": "^2.5.7",
31
- "@sveltejs/vite-plugin-svelte": "^5.1.1",
31
+ "@sveltejs/vite-plugin-svelte": "^6.2.4",
32
32
  "@tailwindcss/cli": "^4.1.18",
33
33
  "@tailwindcss/forms": "^0.5.11",
34
34
  "@tailwindcss/typography": "^0.5.19",
35
35
  "@tailwindcss/vite": "^4.1.18",
36
- "@types/node": "^25.0.9",
36
+ "@types/node": "^25.0.10",
37
37
  "dotenv": "^16.6.1",
38
38
  "eslint": "^9.39.2",
39
39
  "globals": "^16.5.0",
40
- "prettier": "^3.8.0",
40
+ "prettier": "^3.8.1",
41
41
  "prettier-plugin-svelte": "^3.4.1",
42
- "publint": "^0.3.16",
43
- "svelte": "^5.46.4",
42
+ "publint": "^0.3.17",
43
+ "svelte": "^5.48.0",
44
44
  "svelte-check": "^4.3.5",
45
45
  "tailwindcss": "^4.1.18",
46
+ "tsx": "^4.21.0",
46
47
  "typescript": "^5.9.3",
47
- "typescript-eslint": "^8.53.0",
48
- "vite": "^6.4.1",
48
+ "typescript-eslint": "^8.53.1",
49
+ "vite": "^7.3.1",
49
50
  "vitest": "^3.2.4"
50
51
  },
51
52
  "dependencies": {
52
- "@marianmeres/clog": "^3.15.0",
53
+ "@marianmeres/clog": "^3.15.1",
53
54
  "@marianmeres/item-collection": "^1.3.5",
54
55
  "@marianmeres/parse-boolean": "^2.0.5",
55
56
  "@marianmeres/ticker": "^1.16.5",
@@ -71,6 +72,8 @@
71
72
  "svelte-check": "svelte-check",
72
73
  "svelte-package": "svelte-package",
73
74
  "rp": "pnpm run build && ./release.sh patch",
74
- "rpm": "pnpm run build && ./release.sh minor"
75
+ "rpm": "pnpm run build && ./release.sh minor",
76
+ "build:theme": "tsx scripts/generate-theme.ts",
77
+ "build:theme:all": "pnpm run build:theme --indir=src/lib/themes --outdir=src/lib/themes"
75
78
  }
76
79
  }
@@ -1,135 +0,0 @@
1
- <script lang="ts" module>
2
- import type { Snippet } from "svelte";
3
- import type { FormEventHandler, HTMLButtonAttributes } from "svelte/elements";
4
-
5
- export interface Props extends Omit<HTMLButtonAttributes, "children"> {
6
- button?: HTMLButtonElement;
7
- checked?: boolean;
8
- size?: "xs" | "sm" | "md" | "lg" | "xl" | string;
9
- class?: string;
10
- dotClass?: string;
11
- label?: string;
12
- disabled?: boolean;
13
- tabindex?: number;
14
- on?: Snippet;
15
- off?: Snippet;
16
- onclick?: (event: MouseEvent) => void;
17
- onchange?: FormEventHandler<HTMLButtonElement> | null | undefined;
18
- preHook?: (current: boolean) => Promise<false | any>;
19
- }
20
- </script>
21
-
22
- <script lang="ts">
23
- import { tick } from "svelte";
24
- import { twMerge } from "../../utils/tw-merge.js";
25
-
26
- import "./index.css";
27
-
28
- let {
29
- button = $bindable(),
30
- size = "md",
31
- class: classProp,
32
- dotClass,
33
- checked = $bindable(),
34
- disabled,
35
- tabindex = 0,
36
- label,
37
- on,
38
- off,
39
- onclick,
40
- preHook,
41
- ...rest
42
- }: Props = $props();
43
-
44
- const _preset: any = {
45
- size: {
46
- xs: `h-4 w-7`,
47
- sm: `h-5 w-9`,
48
- md: `h-6 w-11`,
49
- lg: `h-7 w-13`,
50
- xl: `h-8 w-15`,
51
- },
52
- dot: {
53
- size: {
54
- xs: `size-2 data-[checked=true]:translate-x-4`,
55
- sm: `size-3 data-[checked=true]:translate-x-5`,
56
- md: `size-4 data-[checked=true]:translate-x-6`,
57
- lg: `size-5 data-[checked=true]:translate-x-7`,
58
- xl: `size-6 data-[checked=true]:translate-x-8`,
59
- },
60
- },
61
- };
62
- </script>
63
-
64
- <!-- <div class="inline-block relative"> -->
65
- <button
66
- bind:this={button}
67
- class={twMerge(
68
- "stuic-switch",
69
- `m-2
70
- relative inline-flex flex-shrink-0 items-center
71
- rounded-full cursor-pointer
72
-
73
- transition-colors duration-100
74
-
75
- hover:brightness-105 active:brightness-95
76
- disabled:!cursor-not-allowed disabled:!opacity-50 disabled:hover:brightness-100
77
-
78
- bg-neutral-400 dark:bg-neutral-400
79
-
80
- aria-[checked=true]:bg-switch-accent
81
- dark:aria-[checked=true]:bg-switch-accent-dark
82
-
83
- focus:outline-0
84
- focus:ring-switch-accent/20 focus:dark:ring-switch-accent-dark/20
85
- focus:ring-4`,
86
- size,
87
- _preset.size[size],
88
- classProp
89
- )}
90
- type="button"
91
- role="switch"
92
- aria-checked={checked}
93
- value={`${!!checked}`}
94
- {tabindex}
95
- {disabled}
96
- onclick={async (e) => {
97
- if (typeof preHook === "function" && (await preHook(checked ?? false)) === false) {
98
- return false;
99
- }
100
- checked = !checked;
101
-
102
- await tick();
103
-
104
- if (typeof onclick === "function") onclick(e);
105
-
106
- button!.dispatchEvent(
107
- new CustomEvent("change", { bubbles: true, cancelable: true, detail: checked })
108
- );
109
- }}
110
- {...rest}
111
- >
112
- {#if label}<span class="sr-only">{@html label}</span>{/if}
113
- <span
114
- aria-hidden="true"
115
- data-checked={checked}
116
- class={twMerge(
117
- "dot",
118
- `flex items-center justify-center
119
- translate-x-1 rounded-full
120
- transition-all duration-100
121
- shadow
122
- bg-neutral-50 dark:bg-neutral-50
123
- text-neutral-950 dark:text-neutral-950`,
124
- size,
125
- _preset.dot.size[size],
126
- dotClass
127
- )}
128
- >
129
- {#if checked}
130
- {@render on?.()}
131
- {:else}
132
- {@render off?.()}
133
- {/if}
134
- </span>
135
- </button>
@@ -1,21 +0,0 @@
1
- import type { Snippet } from "svelte";
2
- import type { FormEventHandler, HTMLButtonAttributes } from "svelte/elements";
3
- export interface Props extends Omit<HTMLButtonAttributes, "children"> {
4
- button?: HTMLButtonElement;
5
- checked?: boolean;
6
- size?: "xs" | "sm" | "md" | "lg" | "xl" | string;
7
- class?: string;
8
- dotClass?: string;
9
- label?: string;
10
- disabled?: boolean;
11
- tabindex?: number;
12
- on?: Snippet;
13
- off?: Snippet;
14
- onclick?: (event: MouseEvent) => void;
15
- onchange?: FormEventHandler<HTMLButtonElement> | null | undefined;
16
- preHook?: (current: boolean) => Promise<false | any>;
17
- }
18
- import "./index.css";
19
- declare const SwitchButton: import("svelte").Component<Props, {}, "button" | "checked">;
20
- type SwitchButton = ReturnType<typeof SwitchButton>;
21
- export default SwitchButton;