@marianmeres/stuic 3.0.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 (144) hide show
  1. package/dist/actions/index.d.ts +1 -0
  2. package/dist/actions/index.js +1 -0
  3. package/dist/actions/typeahead.svelte.d.ts +53 -0
  4. package/dist/actions/typeahead.svelte.js +328 -0
  5. package/dist/base.css +17 -0
  6. package/dist/components/AlertConfirmPrompt/AlertConfirmPrompt.svelte +4 -3
  7. package/dist/components/AlertConfirmPrompt/AlertConfirmPrompt.svelte.d.ts +4 -3
  8. package/dist/components/AlertConfirmPrompt/Current.svelte +1 -2
  9. package/dist/components/AlertConfirmPrompt/Current.svelte.d.ts +0 -1
  10. package/dist/components/AlertConfirmPrompt/index.css +47 -43
  11. package/dist/components/AssetsPreview/AssetsPreview.svelte +0 -1
  12. package/dist/components/AssetsPreview/AssetsPreview.svelte.d.ts +0 -1
  13. package/dist/components/AssetsPreview/index.css +31 -29
  14. package/dist/components/Avatar/Avatar.svelte +0 -1
  15. package/dist/components/Avatar/Avatar.svelte.d.ts +0 -1
  16. package/dist/components/Avatar/index.css +87 -85
  17. package/dist/components/Backdrop/Backdrop.svelte +0 -1
  18. package/dist/components/Backdrop/Backdrop.svelte.d.ts +0 -1
  19. package/dist/components/Backdrop/index.css +15 -13
  20. package/dist/components/Button/Button.svelte +0 -1
  21. package/dist/components/Button/Button.svelte.d.ts +0 -1
  22. package/dist/components/Button/index.css +431 -429
  23. package/dist/components/ButtonGroupRadio/ButtonGroupRadio.svelte +0 -1
  24. package/dist/components/ButtonGroupRadio/ButtonGroupRadio.svelte.d.ts +0 -1
  25. package/dist/components/ButtonGroupRadio/index.css +123 -117
  26. package/dist/components/Collapsible/index.css +17 -15
  27. package/dist/components/CommandMenu/CommandMenu.svelte +7 -4
  28. package/dist/components/CommandMenu/CommandMenu.svelte.d.ts +0 -1
  29. package/dist/components/CommandMenu/index.css +27 -25
  30. package/dist/components/DismissibleMessage/DismissibleMessage.svelte +0 -1
  31. package/dist/components/DismissibleMessage/DismissibleMessage.svelte.d.ts +0 -1
  32. package/dist/components/DismissibleMessage/index.css +116 -110
  33. package/dist/components/DropdownMenu/DropdownMenu.svelte +0 -1
  34. package/dist/components/DropdownMenu/DropdownMenu.svelte.d.ts +0 -1
  35. package/dist/components/DropdownMenu/index.css +179 -177
  36. package/dist/components/Input/FieldInput.svelte +8 -0
  37. package/dist/components/Input/FieldInput.svelte.d.ts +2 -0
  38. package/dist/components/Input/FieldOptions.svelte +1 -1
  39. package/dist/components/Input/index.css +411 -398
  40. package/dist/components/KbdShortcut/KbdShortcut.svelte +4 -12
  41. package/dist/components/KbdShortcut/README.md +34 -0
  42. package/dist/components/KbdShortcut/index.css +55 -0
  43. package/dist/components/ListItemButton/ListItemButton.svelte +0 -1
  44. package/dist/components/ListItemButton/ListItemButton.svelte.d.ts +0 -1
  45. package/dist/components/ListItemButton/index.css +118 -116
  46. package/dist/components/Modal/Modal.svelte +0 -1
  47. package/dist/components/Modal/Modal.svelte.d.ts +0 -1
  48. package/dist/components/Modal/index.css +18 -16
  49. package/dist/components/ModalDialog/index.css +29 -27
  50. package/dist/components/Nav/Nav.svelte +732 -0
  51. package/dist/components/Nav/Nav.svelte.d.ts +110 -0
  52. package/dist/components/Nav/README.md +334 -0
  53. package/dist/components/Nav/index.css +318 -0
  54. package/dist/components/Nav/index.d.ts +1 -0
  55. package/dist/components/Nav/index.js +1 -0
  56. package/dist/components/Notifications/Notifications.svelte +2 -3
  57. package/dist/components/Notifications/Notifications.svelte.d.ts +0 -1
  58. package/dist/components/Notifications/index.css +158 -158
  59. package/dist/components/Notifications/notifications-stack.svelte.d.ts +4 -0
  60. package/dist/components/Notifications/notifications-stack.svelte.js +8 -0
  61. package/dist/components/Progress/Progress.svelte +4 -2
  62. package/dist/components/Progress/Progress.svelte.d.ts +1 -0
  63. package/dist/components/Progress/README.md +86 -15
  64. package/dist/components/Progress/_internal/Bar.svelte +4 -15
  65. package/dist/components/Progress/_internal/Bar.svelte.d.ts +1 -1
  66. package/dist/components/Progress/_internal/Circle.svelte +30 -2
  67. package/dist/components/Progress/_internal/Circle.svelte.d.ts +1 -0
  68. package/dist/components/Progress/index.css +47 -1
  69. package/dist/components/Skeleton/README.md +152 -0
  70. package/dist/components/Skeleton/Skeleton.svelte +6 -7
  71. package/dist/components/Skeleton/Skeleton.svelte.d.ts +0 -1
  72. package/dist/components/Skeleton/index.css +73 -43
  73. package/dist/components/Spinner/README.md +149 -37
  74. package/dist/components/Spinner/Spinner.svelte +14 -38
  75. package/dist/components/Spinner/Spinner.svelte.d.ts +2 -1
  76. package/dist/components/Spinner/SpinnerCircle.svelte +6 -34
  77. package/dist/components/Spinner/SpinnerCircle.svelte.d.ts +1 -0
  78. package/dist/components/Spinner/SpinnerCircleOscillate.svelte +10 -5
  79. package/dist/components/Spinner/SpinnerUnicode.svelte +3 -1
  80. package/dist/components/Spinner/SpinnerUnicode.svelte.d.ts +1 -0
  81. package/dist/components/Spinner/index.css +104 -0
  82. package/dist/components/Switch/README.md +34 -18
  83. package/dist/components/Switch/Switch.svelte +24 -46
  84. package/dist/components/Switch/Switch.svelte.d.ts +4 -2
  85. package/dist/components/Switch/index.css +120 -2
  86. package/dist/components/Switch/index.d.ts +1 -2
  87. package/dist/components/Switch/index.js +1 -2
  88. package/dist/components/TabbedMenu/README.md +28 -17
  89. package/dist/components/TabbedMenu/TabbedMenu.svelte +5 -46
  90. package/dist/components/TabbedMenu/TabbedMenu.svelte.d.ts +0 -1
  91. package/dist/components/TabbedMenu/index.css +85 -3
  92. package/dist/components/ThemePreview/ThemePreview.svelte +76 -23
  93. package/dist/components/ThemePreview/ThemePreview.svelte.d.ts +3 -1
  94. package/dist/components/ThemePreview/index.css +17 -1
  95. package/dist/components/TwCheck/README.md +32 -13
  96. package/dist/components/TwCheck/TwCheck.svelte +11 -9
  97. package/dist/components/TwCheck/TwCheck.svelte.d.ts +0 -1
  98. package/dist/components/TwCheck/index.css +14 -0
  99. package/dist/components/TypeaheadInput/TypeaheadInput.svelte +19 -187
  100. package/dist/components/TypeaheadInput/TypeaheadInput.svelte.d.ts +4 -2
  101. package/dist/index.css +44 -39
  102. package/dist/index.d.ts +1 -0
  103. package/dist/index.js +1 -0
  104. package/dist/themes/blue-orange.css +202 -148
  105. package/dist/themes/blue-orange.js +24 -0
  106. package/dist/themes/cyan-red.css +202 -148
  107. package/dist/themes/cyan-red.js +24 -0
  108. package/dist/themes/cyan-slate.css +202 -148
  109. package/dist/themes/cyan-slate.js +25 -1
  110. package/dist/themes/emerald-pink.css +202 -148
  111. package/dist/themes/emerald-pink.js +25 -1
  112. package/dist/themes/fuchsia-emerald.css +202 -148
  113. package/dist/themes/fuchsia-emerald.js +25 -1
  114. package/dist/themes/gray.css +202 -148
  115. package/dist/themes/gray.js +24 -0
  116. package/dist/themes/indigo-amber.css +202 -148
  117. package/dist/themes/indigo-amber.js +26 -2
  118. package/dist/themes/neutral.css +202 -148
  119. package/dist/themes/neutral.js +24 -0
  120. package/dist/themes/pink-emerald.css +202 -148
  121. package/dist/themes/pink-emerald.js +25 -1
  122. package/dist/themes/purple-yellow.css +202 -148
  123. package/dist/themes/purple-yellow.js +24 -0
  124. package/dist/themes/rainbow.css +202 -148
  125. package/dist/themes/rainbow.js +25 -1
  126. package/dist/themes/red-blue.css +202 -148
  127. package/dist/themes/red-blue.js +24 -0
  128. package/dist/themes/red-cyan.css +202 -148
  129. package/dist/themes/red-cyan.js +24 -0
  130. package/dist/themes/rose-teal.css +202 -148
  131. package/dist/themes/rose-teal.js +24 -0
  132. package/dist/themes/sky-amber.css +202 -148
  133. package/dist/themes/sky-amber.js +26 -2
  134. package/dist/themes/slate-cyan.css +202 -148
  135. package/dist/themes/slate-cyan.js +25 -1
  136. package/dist/themes/teal-rose.css +202 -148
  137. package/dist/themes/teal-rose.js +24 -0
  138. package/dist/themes/violet-lime.css +202 -148
  139. package/dist/themes/violet-lime.js +27 -3
  140. package/dist/utils/design-tokens.js +29 -2
  141. package/dist/utils/storage-abstraction.js +1 -1
  142. package/package.json +11 -28
  143. package/dist/components/Switch/SwitchButton.svelte +0 -134
  144. package/dist/components/Switch/SwitchButton.svelte.d.ts +0 -21
@@ -1,59 +1,89 @@
1
+ /* ============================================================================
2
+ SKELETON COMPONENT TOKENS
3
+ Override globally: :root { --stuic-skeleton-radius: 0; }
4
+ Override locally: <Skeleton style="--stuic-skeleton-duration: 2s;">
5
+ ============================================================================ */
6
+
1
7
  /* prettier-ignore */
2
- @theme inline {
3
- /* Skeleton component tokens */
4
- --stuic-skeleton-bg: var(--stuic-skeleton-bg, var(--stuic-surface-interactive));
5
- --stuic-skeleton-bg-highlight: var(--stuic-skeleton-bg-highlight, var(--stuic-surface-interactive-hover));
6
- }
8
+ :root {
9
+ /* Colors */
10
+ --stuic-skeleton-bg: var(--stuic-color-muted);
11
+ --stuic-skeleton-bg-highlight: var(--stuic-color-muted-hover);
7
12
 
8
- .stuic-skeleton-circle {
9
- border-radius: 50%;
10
- }
13
+ /* Dimensions */
14
+ --stuic-skeleton-height: 1rem;
15
+ --stuic-skeleton-gap: 0.5rem;
16
+ --stuic-skeleton-radius: var(--radius-sm);
11
17
 
12
- .stuic-skeleton-text-container {
13
- display: flex;
14
- flex-direction: column;
18
+ /* Animation */
19
+ --stuic-skeleton-duration: 1.5s;
20
+ --stuic-skeleton-timing: ease-in-out;
21
+ --stuic-skeleton-pulse-opacity: 0.4;
15
22
  }
16
23
 
17
- /* Shimmer animation */
18
- @keyframes skeleton-shimmer {
19
- 0% {
20
- background-position: -200% 0;
24
+ @layer components {
25
+ .stuic-skeleton-circle {
26
+ border-radius: 50%;
21
27
  }
22
- 100% {
23
- background-position: 200% 0;
28
+
29
+ .stuic-skeleton-rounded {
30
+ border-radius: var(--stuic-skeleton-radius);
24
31
  }
25
- }
26
32
 
27
- .stuic-skeleton-shimmer {
28
- background: linear-gradient(
29
- 90deg,
30
- var(--stuic-skeleton-bg) 25%,
31
- var(--stuic-skeleton-bg-highlight) 50%,
32
- var(--stuic-skeleton-bg) 75%
33
- );
34
- background-size: 200% 100%;
35
- animation: skeleton-shimmer var(--stuic-skeleton-duration, 1.5s) ease-in-out infinite;
36
- }
33
+ .stuic-skeleton-text-container {
34
+ display: flex;
35
+ flex-direction: column;
36
+ gap: var(--stuic-skeleton-gap);
37
+ }
37
38
 
38
- /* Pulse animation */
39
- @keyframes skeleton-pulse {
40
- 0%, 100% {
41
- opacity: 1;
39
+ .stuic-skeleton-text-container > * {
40
+ height: var(--stuic-skeleton-height);
42
41
  }
43
- 50% {
44
- opacity: 0.4;
42
+
43
+ /* Shimmer animation */
44
+ @keyframes skeleton-shimmer {
45
+ 0% {
46
+ background-position: -200% 0;
47
+ }
48
+ 100% {
49
+ background-position: 200% 0;
50
+ }
45
51
  }
46
- }
47
52
 
48
- .stuic-skeleton-pulse {
49
- background-color: var(--stuic-skeleton-bg);
50
- animation: skeleton-pulse var(--stuic-skeleton-duration, 1.5s) ease-in-out infinite;
51
- }
53
+ .stuic-skeleton-shimmer {
54
+ background: linear-gradient(
55
+ 90deg,
56
+ var(--stuic-skeleton-bg) 25%,
57
+ var(--stuic-skeleton-bg-highlight) 50%,
58
+ var(--stuic-skeleton-bg) 75%
59
+ );
60
+ background-size: 200% 100%;
61
+ animation: skeleton-shimmer var(--stuic-skeleton-duration)
62
+ var(--stuic-skeleton-timing) infinite;
63
+ }
64
+
65
+ /* Pulse animation */
66
+ @keyframes skeleton-pulse {
67
+ 0%,
68
+ 100% {
69
+ opacity: 1;
70
+ }
71
+ 50% {
72
+ opacity: var(--stuic-skeleton-pulse-opacity);
73
+ }
74
+ }
52
75
 
53
- /* Reduced motion */
54
- @media (prefers-reduced-motion: reduce) {
55
- .stuic-skeleton-shimmer,
56
76
  .stuic-skeleton-pulse {
57
- animation: none;
77
+ background-color: var(--stuic-skeleton-bg);
78
+ animation: skeleton-pulse var(--stuic-skeleton-duration) var(--stuic-skeleton-timing)
79
+ infinite;
80
+ }
81
+
82
+ /* Reduced motion */
83
+ @media (prefers-reduced-motion: reduce) {
84
+ .stuic-skeleton-shimmer,
85
+ .stuic-skeleton-pulse {
86
+ animation: none;
87
+ }
58
88
  }
59
89
  }
@@ -1,80 +1,192 @@
1
1
  # Spinner
2
2
 
3
- A customizable loading spinner with rotating segments. Pure CSS animation with configurable appearance.
3
+ A family of loading spinner components with different visual styles. All spinners inherit color from `currentColor`, making them easy to style with Tailwind text color classes.
4
4
 
5
- ## Props
5
+ ## Components
6
+
7
+ | Component | Description |
8
+ |-----------|-------------|
9
+ | `Spinner` | Radial bar spinner with fading segments |
10
+ | `SpinnerCircle` | Simple circular border spinner |
11
+ | `SpinnerCircleOscillate` | Circle with oscillating progress animation |
12
+ | `SpinnerUnicode` | Unicode character-based spinner (17+ variants) |
13
+
14
+ ---
15
+
16
+ ## Spinner
17
+
18
+ Rotating segments that fade in sequence. Pure CSS animation.
19
+
20
+ ### Props
6
21
 
7
22
  | Prop | Type | Default | Description |
8
23
  |------|------|---------|-------------|
9
- | `duration` | `number` | `750` | One full rotation duration (ms) |
10
- | `count` | `number` | `8` | Number of segments/hands (3-12) |
11
- | `thickness` | `"thin" \| "normal" \| "thick"` | `"thick"` | Segment width |
24
+ | `count` | `number` | `8` | Number of segments (3-12 recommended) |
25
+ | `thickness` | `"thin" \| "normal" \| "thick"` | `"normal"` | Segment width |
12
26
  | `height` | `"short" \| "normal" \| "tall"` | `"normal"` | Segment length |
13
- | `direction` | `"cw" \| "ccw"` | `"cw"` | Rotation direction (clockwise/counter-clockwise) |
14
- | `class` | `string` | - | CSS classes for sizing |
15
-
16
- ## Usage
27
+ | `direction` | `"cw" \| "ccw"` | `"cw"` | Rotation direction |
28
+ | `duration` | `number` | `750` | Animation duration (ms) |
29
+ | `rounded` | `number` | `2` | Border radius of segments (px) |
30
+ | `class` | `string` | - | Additional CSS classes |
17
31
 
18
- ### Basic Spinner
32
+ ### Usage
19
33
 
20
34
  ```svelte
21
- <script lang="ts">
22
- import { Spinner } from 'stuic';
23
- </script>
24
-
25
35
  <Spinner />
36
+ <Spinner thickness="thin" count={12} />
37
+ <Spinner class="text-blue-500" direction="ccw" />
26
38
  ```
27
39
 
28
- ### Different Sizes
40
+ ---
41
+
42
+ ## SpinnerCircle
43
+
44
+ Simple circular spinner using CSS border animation.
45
+
46
+ ### Props
47
+
48
+ | Prop | Type | Default | Description |
49
+ |------|------|---------|-------------|
50
+ | `thickness` | `"thin" \| "normal" \| "thick"` | `"normal"` | Border thickness |
51
+ | `direction` | `"cw" \| "ccw"` | `"cw"` | Rotation direction |
52
+ | `duration` | `number` | `750` | Animation duration (ms) |
53
+ | `class` | `string` | - | Additional CSS classes |
54
+
55
+ ### Usage
29
56
 
30
57
  ```svelte
31
- <Spinner class="w-4" />
32
- <Spinner class="w-6" />
33
- <Spinner class="w-8" />
34
- <Spinner class="w-12" />
58
+ <SpinnerCircle />
59
+ <SpinnerCircle thickness="thick" class="size-8" />
60
+ <SpinnerCircle class="text-red-500 size-6" direction="ccw" />
35
61
  ```
36
62
 
37
- ### Customized Appearance
63
+ ---
38
64
 
39
- ```svelte
40
- <!-- More segments, thinner -->
41
- <Spinner count={12} thickness="thin" />
65
+ ## SpinnerCircleOscillate
66
+
67
+ Circle progress indicator with oscillating completeness animation.
68
+
69
+ ### Props
42
70
 
43
- <!-- Fewer segments, thicker, taller -->
44
- <Spinner count={4} thickness="thick" height="tall" />
71
+ | Prop | Type | Default | Description |
72
+ |------|------|---------|-------------|
73
+ | `bgStrokeColor` | `string` | CSS variable | Background stroke color |
74
+ | `strokeWidth` | `number` | - | Stroke width |
75
+ | `noOscillate` | `boolean` | `false` | Disable oscillation (static 66%) |
76
+ | `rotateDuration` | `string` | CSS variable | Rotation duration (e.g., ".75s") |
77
+ | `class` | `string` | - | Additional CSS classes |
78
+
79
+ ### Usage
80
+
81
+ ```svelte
82
+ <SpinnerCircleOscillate />
83
+ <SpinnerCircleOscillate class="text-blue-500 size-8" />
84
+ <SpinnerCircleOscillate noOscillate bgStrokeColor="" />
45
85
  ```
46
86
 
47
- ### Slower/Faster Animation
87
+ ---
88
+
89
+ ## SpinnerUnicode
90
+
91
+ Text-based spinner cycling through Unicode characters.
92
+
93
+ ### Props
94
+
95
+ | Prop | Type | Default | Description |
96
+ |------|------|---------|-------------|
97
+ | `variant` | `SpinnerUnicodeVariant` | `"braille_bar_dot"` | Built-in animation variant |
98
+ | `speed` | `number` | `100` | Frame duration (ms) |
99
+ | `reversed` | `boolean` | `false` | Reverse animation direction |
100
+ | `frames` | `string[]` | - | Custom frame array |
101
+ | `class` | `string` | - | Additional CSS classes |
102
+
103
+ ### Built-in Variants
104
+
105
+ `braille_bar`, `braille_bar_dot`, `braille_dot_circle`, `braille_dot_bounce`, `half_circle`, `quarter_circle`, `ascii`, `bar_v`, `bar_h`, `shade`, `arrows`, `arrows2`, `asterix`, `asterix2`, `asterix3`, `asterix4`, `asterix5`
106
+
107
+ ### Usage
48
108
 
49
109
  ```svelte
50
- <Spinner duration={500} /> <!-- Faster -->
51
- <Spinner duration={1500} /> <!-- Slower -->
110
+ <SpinnerUnicode />
111
+ <SpinnerUnicode variant="ascii" />
112
+ <SpinnerUnicode variant="arrows" class="text-green-500" />
113
+
114
+ <!-- Custom frames -->
115
+ <SpinnerUnicode frames={spinnerCreateBackAndForthCharFrames(5, "■", "□")} />
116
+ ```
117
+
118
+ ---
119
+
120
+ ## CSS Customization
121
+
122
+ All spinners support customization via CSS variables.
123
+
124
+ ### Available Variables
125
+
126
+ ```css
127
+ :root {
128
+ /* Spinner (radial bars) */
129
+ --stuic-spinner-opacity: 0.8;
130
+ --stuic-spinner-fade-end-opacity: 0.12;
131
+ --stuic-spinner-duration: 750ms;
132
+
133
+ /* SpinnerCircle */
134
+ --stuic-spinner-circle-thickness-thin: 1px;
135
+ --stuic-spinner-circle-thickness-normal: 2px;
136
+ --stuic-spinner-circle-thickness-thick: 4px;
137
+ --stuic-spinner-circle-duration: 750ms;
138
+
139
+ /* SpinnerCircleOscillate */
140
+ --stuic-spinner-circle-oscillate-bg-stroke: var(--stuic-color-border, rgba(0 0 0 / 0.1));
141
+ --stuic-spinner-circle-oscillate-duration: 0.75s;
142
+
143
+ /* SpinnerUnicode */
144
+ --stuic-spinner-unicode-font-size: var(--text-xl);
145
+ }
52
146
  ```
53
147
 
54
- ### Counter-Clockwise
148
+ ### Global Override
149
+
150
+ ```css
151
+ :root {
152
+ --stuic-spinner-opacity: 1;
153
+ --stuic-spinner-circle-thickness-normal: 3px;
154
+ }
155
+ ```
156
+
157
+ ### Local Override
55
158
 
56
159
  ```svelte
57
- <Spinner direction="ccw" />
160
+ <Spinner style="--stuic-spinner-opacity: 0.5;" />
161
+ <SpinnerCircle style="--stuic-spinner-circle-duration: 500ms;" />
58
162
  ```
59
163
 
60
- ### With Custom Color
164
+ ---
165
+
166
+ ## Color Customization
167
+
168
+ All spinners use `currentColor`, so apply Tailwind text color classes:
61
169
 
62
170
  ```svelte
63
- <Spinner class="w-8 text-blue-500" />
64
- <Spinner class="w-8 text-green-500" />
171
+ <Spinner class="text-blue-500" />
172
+ <SpinnerCircle class="text-red-600" />
173
+ <SpinnerUnicode class="text-green-500" />
65
174
  ```
66
175
 
67
- ### Loading Button
176
+ ---
177
+
178
+ ## Loading Button Example
68
179
 
69
180
  ```svelte
70
181
  <script lang="ts">
182
+ import { Button, SpinnerCircle } from 'stuic';
71
183
  let loading = $state(false);
72
184
  </script>
73
185
 
74
- <button disabled={loading}>
186
+ <Button disabled={loading}>
75
187
  {#if loading}
76
- <Spinner class="w-4 mr-2" />
188
+ <SpinnerCircle class="size-4" />
77
189
  {/if}
78
190
  Submit
79
- </button>
191
+ </Button>
80
192
  ```
@@ -1,9 +1,10 @@
1
1
  <script lang="ts" module>
2
2
  export interface Props {
3
3
  class?: string;
4
+ style?: string;
4
5
  count?: number;
5
6
  thickness?: "thin" | "normal" | "thick";
6
- height?: "short" | "normal" | "tall";
7
+ size?: "sm" | "md" | "lg";
7
8
  direction?: "cw" | "ccw";
8
9
  rounded?: number;
9
10
  duration?: number;
@@ -15,9 +16,10 @@
15
16
 
16
17
  let {
17
18
  class: classProp,
19
+ style: styleProp,
18
20
  count = 8,
19
21
  thickness = "normal",
20
- height = "normal",
22
+ size = "md",
21
23
  direction = "cw",
22
24
  rounded = 2,
23
25
  duration = 750,
@@ -28,29 +30,28 @@
28
30
  normal: 2,
29
31
  thick: 4,
30
32
  };
31
- const heightMap: Record<NonNullable<Props["height"]>, number> = {
32
- short: 5,
33
- normal: 6,
34
- tall: 10,
33
+ const sizeMap: Record<NonNullable<Props["size"]>, number> = {
34
+ sm: 5,
35
+ md: 6,
36
+ lg: 10,
35
37
  };
36
38
 
37
- const barLength = $derived(heightMap[height]);
39
+ const barLength = $derived(sizeMap[size]);
38
40
  const barWidth = $derived(thicknessMap[thickness]);
39
- const size = $derived(barLength * 3);
40
- const center = $derived(size / 2);
41
+ const containerSize = $derived(barLength * 3);
42
+ const center = $derived(containerSize / 2);
41
43
  const barHeight = $derived(barLength - 1);
42
44
  </script>
43
45
 
44
46
  <div
45
- class={twMerge("spinner opacity-80", classProp)}
46
- style:--size="{size}px"
47
- style:--duration="{duration}ms"
47
+ class={twMerge("stuic-spinner", classProp)}
48
+ style="{styleProp ?? ''}; width: {containerSize}px; height: {containerSize}px; --stuic-spinner-duration: {duration}ms;"
48
49
  >
49
50
  {#each Array(count) as _, i}
50
51
  {@const angle = (360 / count) * i}
51
52
  {@const delay = direction === "ccw" ? i / count : (count - i) / count}
52
53
  <span
53
- class="bar"
54
+ class="stuic-spinner-bar"
54
55
  style:width="{barWidth}px"
55
56
  style:height="{barHeight}px"
56
57
  style:border-radius="{rounded}px"
@@ -60,28 +61,3 @@
60
61
  ></span>
61
62
  {/each}
62
63
  </div>
63
-
64
- <style>
65
- .spinner {
66
- position: relative;
67
- width: var(--size);
68
- height: var(--size);
69
- }
70
-
71
- .bar {
72
- position: absolute;
73
- left: 50%;
74
- top: 0px;
75
- background: currentColor;
76
- animation: fade var(--duration) linear infinite;
77
- }
78
-
79
- @keyframes fade {
80
- from {
81
- opacity: 1;
82
- }
83
- to {
84
- opacity: 0.12;
85
- }
86
- }
87
- </style>
@@ -1,8 +1,9 @@
1
1
  export interface Props {
2
2
  class?: string;
3
+ style?: string;
3
4
  count?: number;
4
5
  thickness?: "thin" | "normal" | "thick";
5
- height?: "short" | "normal" | "tall";
6
+ size?: "sm" | "md" | "lg";
6
7
  direction?: "cw" | "ccw";
7
8
  rounded?: number;
8
9
  duration?: number;
@@ -1,6 +1,7 @@
1
1
  <script lang="ts" module>
2
2
  export interface Props {
3
3
  class?: string;
4
+ style?: string;
4
5
  /** One "loop" duration in ms */
5
6
  duration?: number;
6
7
  /** Border thickness preset */
@@ -15,48 +16,19 @@
15
16
 
16
17
  let {
17
18
  class: classProp,
19
+ style: styleProp,
18
20
  duration = 750,
19
21
  thickness = "normal",
20
22
  direction = "cw",
21
23
  }: Props = $props();
22
24
 
23
25
  let _thickness = $derived(
24
- "thickness-" +
25
- (["normal", "thin", "thick"].includes(thickness) ? thickness : "normal")
26
+ ["normal", "thin", "thick"].includes(thickness) ? thickness : "normal"
26
27
  );
27
28
  </script>
28
29
 
29
30
  <span
30
- class={twMerge("stuic-spinner-basic inline-block size-4", _thickness, classProp)}
31
- style="animation-duration: {duration}ms; animation-direction: {direction === 'ccw'
32
- ? 'reverse'
33
- : 'normal'};"
31
+ class={twMerge("stuic-spinner-circle size-4", classProp)}
32
+ data-thickness={_thickness}
33
+ style="{styleProp ?? ''}; --stuic-spinner-circle-duration: {duration}ms; animation-direction: {direction === 'ccw' ? 'reverse' : 'normal'};"
34
34
  ></span>
35
-
36
- <style>
37
- .stuic-spinner-basic {
38
- box-sizing: border-box;
39
- border-radius: 50%;
40
- border-style: solid;
41
- border-color: currentColor;
42
- border-top-color: transparent;
43
- animation: spin linear infinite;
44
- }
45
-
46
- /* Thickness presets */
47
- .stuic-spinner-basic.thickness-thin {
48
- border-width: 1px;
49
- }
50
- .stuic-spinner-basic.thickness-normal {
51
- border-width: 2px;
52
- }
53
- .stuic-spinner-basic.thickness-thick {
54
- border-width: 4px;
55
- }
56
-
57
- @keyframes spin {
58
- to {
59
- transform: rotate(360deg);
60
- }
61
- }
62
- </style>
@@ -1,5 +1,6 @@
1
1
  export interface Props {
2
2
  class?: string;
3
+ style?: string;
3
4
  /** One "loop" duration in ms */
4
5
  duration?: number;
5
6
  /** Border thickness preset */
@@ -17,12 +17,17 @@
17
17
 
18
18
  let {
19
19
  class: classProp = "",
20
- bgStrokeColor = "rgba(0 0 0 / .1)",
20
+ bgStrokeColor,
21
21
  strokeWidth,
22
22
  noOscillate,
23
- rotateDuration = ".75s",
23
+ rotateDuration,
24
24
  }: Props = $props();
25
25
 
26
+ // Use CSS variable as default when bgStrokeColor is not provided
27
+ const _bgStrokeColor = $derived(
28
+ bgStrokeColor ?? "var(--stuic-spinner-circle-oscillate-bg-stroke)"
29
+ );
30
+
26
31
  /**
27
32
  * NOTE: we happen to have 4 distinct values here which effect the overall look and feel...
28
33
  * 1. the tick frequency
@@ -40,8 +45,8 @@
40
45
  <Circle
41
46
  animateCompletenessMs={0}
42
47
  {completeness}
43
- class={twMerge("stuic-spinner-circle animate-spin", classProp)}
44
- {bgStrokeColor}
48
+ class={twMerge("stuic-spinner-circle-oscillate", classProp)}
49
+ bgStrokeColor={_bgStrokeColor}
45
50
  {strokeWidth}
46
- style="animation-duration: {rotateDuration}"
51
+ style={rotateDuration ? `--stuic-spinner-circle-oscillate-duration: ${rotateDuration}` : undefined}
47
52
  />
@@ -20,6 +20,7 @@
20
20
 
21
21
  export interface Props {
22
22
  class?: string;
23
+ style?: string;
23
24
  speed?: number;
24
25
  variant?: SpinnerUnicodeVariant;
25
26
  reversed?: boolean;
@@ -68,6 +69,7 @@
68
69
 
69
70
  let {
70
71
  class: _class = "",
72
+ style: _style,
71
73
  speed = 100,
72
74
  variant = "braille_bar_dot",
73
75
  reversed = false,
@@ -152,6 +154,6 @@
152
154
  });
153
155
  </script>
154
156
 
155
- <span class={twMerge(`inline-block font-mono leading-none text-current text-xl`, _class)}>
157
+ <span class={twMerge("stuic-spinner-unicode", _class)} style={_style}>
156
158
  {_frames[currentFrame]}
157
159
  </span>
@@ -1,6 +1,7 @@
1
1
  export type SpinnerUnicodeVariant = "braille_bar" | "braille_bar_dot" | "braille_dot_circle" | "braille_dot_bounce" | "half_circle" | "quarter_circle" | "ascii" | "bar_v" | "bar_h" | "shade" | "arrows" | "arrows2" | "asterix" | "asterix2" | "asterix3" | "asterix4" | "asterix5";
2
2
  export interface Props {
3
3
  class?: string;
4
+ style?: string;
4
5
  speed?: number;
5
6
  variant?: SpinnerUnicodeVariant;
6
7
  reversed?: boolean;