@studiocms/ui 0.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 (53) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +564 -0
  3. package/package.json +49 -0
  4. package/src/components/BaseHead.astro +22 -0
  5. package/src/components/Button.astro +338 -0
  6. package/src/components/Card.astro +62 -0
  7. package/src/components/Center.astro +16 -0
  8. package/src/components/Checkbox.astro +180 -0
  9. package/src/components/Divider.astro +39 -0
  10. package/src/components/Dropdown/Dropdown.astro +253 -0
  11. package/src/components/Dropdown/dropdown.ts +170 -0
  12. package/src/components/Dropdown/index.ts +2 -0
  13. package/src/components/Input.astro +93 -0
  14. package/src/components/Modal/Modal.astro +164 -0
  15. package/src/components/Modal/index.ts +2 -0
  16. package/src/components/Modal/modal.ts +129 -0
  17. package/src/components/RadioGroup.astro +175 -0
  18. package/src/components/Row.astro +38 -0
  19. package/src/components/SearchSelect.astro +430 -0
  20. package/src/components/Select.astro +334 -0
  21. package/src/components/Sidebar/Double.astro +91 -0
  22. package/src/components/Sidebar/Single.astro +42 -0
  23. package/src/components/Sidebar/helpers.ts +133 -0
  24. package/src/components/Sidebar/index.ts +3 -0
  25. package/src/components/Textarea.astro +102 -0
  26. package/src/components/ThemeToggle.astro +40 -0
  27. package/src/components/Toast/Toaster.astro +330 -0
  28. package/src/components/Toast/index.ts +2 -0
  29. package/src/components/Toast/toast.ts +16 -0
  30. package/src/components/Toggle.astro +146 -0
  31. package/src/components/User.astro +68 -0
  32. package/src/components/index.ts +25 -0
  33. package/src/components.ts +24 -0
  34. package/src/css/colors.css +106 -0
  35. package/src/css/global.css +2 -0
  36. package/src/css/resets.css +55 -0
  37. package/src/env.d.ts +15 -0
  38. package/src/icons/Checkmark.astro +13 -0
  39. package/src/icons/ChevronUpDown.astro +13 -0
  40. package/src/icons/User.astro +13 -0
  41. package/src/icons/X-Mark.astro +13 -0
  42. package/src/layouts/RootLayout.astro +34 -0
  43. package/src/layouts/index.ts +2 -0
  44. package/src/layouts.ts +1 -0
  45. package/src/types/index.ts +11 -0
  46. package/src/utils/Icon.astro +41 -0
  47. package/src/utils/ThemeHelper.ts +127 -0
  48. package/src/utils/colors.ts +1 -0
  49. package/src/utils/generateID.ts +5 -0
  50. package/src/utils/headers.ts +190 -0
  51. package/src/utils/iconStrings.ts +29 -0
  52. package/src/utils/iconType.ts +3 -0
  53. package/src/utils/index.ts +1 -0
@@ -0,0 +1,338 @@
1
+ ---
2
+ import type { HTMLTag, Polymorphic } from 'astro/types';
3
+ import type { StudioCMSColorway } from '../utils/colors';
4
+
5
+ type Props<As extends HTMLTag = 'button'> = Omit<Polymorphic<{ as: As }>, 'as'> & {
6
+ as?: As;
7
+ size?: 'sm' | 'md' | 'lg';
8
+ fullWidth?: boolean;
9
+ color?: StudioCMSColorway;
10
+ variant?: 'solid' | 'outlined' | 'flat';
11
+ class?: string;
12
+ disabled?: boolean;
13
+ };
14
+
15
+ const {
16
+ size = 'md',
17
+ fullWidth = false,
18
+ color = 'default',
19
+ variant = 'default',
20
+ as: As = 'button',
21
+ class: className,
22
+ disabled = false,
23
+ ...props
24
+ } = Astro.props;
25
+ ---
26
+
27
+ <As
28
+ class="button"
29
+ class:list={[
30
+ fullWidth && "full",
31
+ disabled && "disabled",
32
+ className,
33
+ size,
34
+ color,
35
+ variant,
36
+ ]}
37
+ disabled={disabled}
38
+ tabindex={0}
39
+ {...props}
40
+ >
41
+ <slot name="start-content" />
42
+ <slot />
43
+ <slot name="end-content" />
44
+ </As>
45
+ <style>
46
+ /* Default Styles */
47
+ .button {
48
+ display: flex;
49
+ flex-direction: row;
50
+ align-items: center;
51
+ text-align: center;
52
+
53
+ position: relative;
54
+
55
+ /* Move gaps & radii to spacings.css later on */
56
+ gap: 0.5rem;
57
+
58
+ outline: none;
59
+ border: none;
60
+
61
+ font-weight: 400;
62
+
63
+ border-radius: 0.5rem;
64
+
65
+ transition: all 0.15s ease;
66
+
67
+ cursor: pointer;
68
+
69
+ /* Default colorway */
70
+
71
+ background-color: hsl(var(--default-base));
72
+ border-color: hsl(var(--border));
73
+ color: hsl(var(--text-muted));
74
+
75
+ min-width: fit-content;
76
+
77
+ will-change: transform;
78
+
79
+ text-decoration: none;
80
+ }
81
+
82
+ .button.disabled {
83
+ pointer-events: none;
84
+ opacity: 0.5;
85
+ }
86
+
87
+ .button.outlined {
88
+ border-width: 1px;
89
+ border-style: solid;
90
+ }
91
+
92
+ .button:hover {
93
+ background-color: hsl(var(--default-hover));
94
+ }
95
+
96
+ .button:active {
97
+ background-color: hsl(var(--default-active));
98
+ transform: scale(0.95);
99
+ }
100
+
101
+ .button.flat {
102
+ background: hsla(var(--default-flat));
103
+ }
104
+
105
+ .button.flat:hover {
106
+ background: hsla(var(--default-flat-hover));
107
+ }
108
+
109
+ .button.flat:active {
110
+ background: hsla(var(--default-flat-active));
111
+ }
112
+
113
+ /* Sizes */
114
+ .button.sm {
115
+ height: 32px;
116
+ padding: 0.5rem 0.75rem;
117
+
118
+ font-size: 0.825em;
119
+ }
120
+
121
+ .button.md {
122
+ height: 40px;
123
+ padding: 0.5rem 0.75rem;
124
+
125
+ font-size: 0.875em;
126
+ }
127
+
128
+ .button.lg {
129
+ height: 48px;
130
+ padding: 0.75rem 1rem;
131
+
132
+ font-size: 1em;
133
+ }
134
+
135
+ /* Primary Colorway */
136
+ .button.primary {
137
+ background-color: hsl(var(--primary-base));
138
+ border-color: hsl(var(--primary-base));
139
+ color: hsl(var(--text-inverted));
140
+ }
141
+
142
+ .button.primary:hover {
143
+ background-color: hsl(var(--primary-hover));
144
+ }
145
+
146
+ .button.primary:active {
147
+ background-color: hsl(var(--primary-active));
148
+ }
149
+
150
+ .button.primary.outlined {
151
+ background-color: hsl(var(--default-base));
152
+ color: hsl(var(--text-normal));
153
+ }
154
+
155
+ .button.primary.outlined:hover {
156
+ background-color: hsl(var(--default-hover));
157
+ }
158
+
159
+ .button.primary.outlined:active {
160
+ background-color: hsl(var(--default-active));
161
+ }
162
+
163
+ .button.primary.flat {
164
+ background-color: hsla(var(--primary-flat));
165
+ color: hsl(259, 96%, 79%);
166
+ }
167
+
168
+ .button.primary.flat:hover {
169
+ background-color: hsla(var(--primary-flat-hover));
170
+ }
171
+
172
+ .button.primary.flat:active {
173
+ background-color: hsla(var(--primary-flat-active));
174
+ }
175
+
176
+ /* Success Colorway */
177
+ .button.success {
178
+ background-color: hsl(var(--success-base));
179
+ border-color: hsl(var(--success-base));
180
+ color: hsl(var(--text-dark));
181
+ }
182
+
183
+ .button.success:hover {
184
+ background-color: hsl(var(--success-hover));
185
+ }
186
+
187
+ .button.success:active {
188
+ background-color: hsl(var(--success-active));
189
+ }
190
+
191
+ .button.success.outlined {
192
+ background-color: hsl(var(--default-base));
193
+ color: hsl(var(--text-normal));
194
+ }
195
+
196
+ .button.success.outlined:hover {
197
+ background-color: hsl(var(--default-hover));
198
+ }
199
+
200
+ .button.success.outlined:active {
201
+ background-color: hsl(var(--default-active));
202
+ }
203
+
204
+ .button.success.flat {
205
+ background-color: hsla(var(--success-flat));
206
+ color: hsl(var(--success-base));
207
+ }
208
+
209
+ .button.success.flat:hover {
210
+ background-color: hsla(var(--success-flat-hover));
211
+ }
212
+
213
+ .button.success.flat:active {
214
+ background-color: hsla(var(--success-flat-active));
215
+ }
216
+
217
+ /* Warning Colorway */
218
+ .button.warning {
219
+ background-color: hsl(var(--warning-base));
220
+ border-color: hsl(var(--warning-base));
221
+ color: hsl(var(--text-dark));
222
+ }
223
+
224
+ .button.warning:hover {
225
+ background-color: hsl(var(--warning-hover));
226
+ }
227
+
228
+ .button.warning:active {
229
+ background-color: hsl(var(--warning-active));
230
+ }
231
+
232
+ .button.warning.outlined {
233
+ background-color: hsl(var(--default-base));
234
+ color: hsl(var(--text-normal));
235
+ }
236
+
237
+ .button.warning.outlined:hover {
238
+ background-color: hsl(var(--default-hover));
239
+ }
240
+
241
+ .button.warning.outlined:active {
242
+ background-color: hsl(var(--default-active));
243
+ }
244
+
245
+ .button.warning.flat {
246
+ background-color: hsla(var(--warning-flat));
247
+ color: hsl(var(--warning-base));
248
+ }
249
+
250
+ .button.warning.flat:hover {
251
+ background-color: hsla(var(--warning-flat-hover));
252
+ }
253
+
254
+ .button.warning.flat:active {
255
+ background-color: hsla(var(--warning-flat-active));
256
+ }
257
+
258
+ /* Danger Colorway */
259
+ .button.danger {
260
+ background-color: hsl(var(--danger-base));
261
+ border-color: hsl(var(--danger-base));
262
+ color: hsl(var(--text-light));
263
+ }
264
+
265
+ .button.danger:hover {
266
+ background-color: hsl(var(--danger-hover));
267
+ }
268
+
269
+ .button.danger:active {
270
+ background-color: hsl(var(--danger-active));
271
+ }
272
+
273
+ .button.danger.outlined {
274
+ background-color: hsl(var(--default-base));
275
+ color: hsl(var(--text-normal));
276
+ }
277
+
278
+ .button.danger.outlined:hover {
279
+ background-color: hsl(var(--default-hover));
280
+ }
281
+
282
+ .button.danger.outlined:active {
283
+ background-color: hsl(var(--default-active));
284
+ }
285
+
286
+ .button.danger.flat {
287
+ background-color: hsla(var(--danger-flat));
288
+ color: hsl(337, 92%, 71%);
289
+ }
290
+
291
+ .button.danger.flat:hover {
292
+ background-color: hsla(var(--danger-flat-hover));
293
+ }
294
+
295
+ .button.danger.flat:active {
296
+ background-color: hsla(var(--danger-flat-active));
297
+ }
298
+
299
+ .button.full {
300
+ width: 100%;
301
+ }
302
+
303
+ [data-theme="light"] {
304
+ .button.primary.flat {
305
+ color: hsl(259, 84%, 45%);
306
+ }
307
+
308
+ .button.success.flat {
309
+ background-color: hsl(var(--success-base), 0.2);
310
+ color: hsl(143, 59%, 20%);
311
+ }
312
+
313
+ .button.success.flat:hover {
314
+ background-color: hsla(var(--success-flat-hover));
315
+ }
316
+
317
+ .button.success.flat:active {
318
+ background-color: hsla(var(--success-flat-active));
319
+ }
320
+
321
+ .button.warning.flat {
322
+ background-color: hsla(var(--warning-base), 0.2);
323
+ color: hsl(48, 78%, 20%);
324
+ }
325
+
326
+ .button.warning.flat:hover {
327
+ background-color: hsla(var(--warning-base), 0.25);
328
+ }
329
+
330
+ .button.warning.flat:active {
331
+ background-color: hsla(var(--warning-base), 0.4);
332
+ }
333
+
334
+ .button.danger.flat {
335
+ color: hsl(339, 97%, 29%);
336
+ }
337
+ }
338
+ </style>
@@ -0,0 +1,62 @@
1
+ ---
2
+ import type { HTMLTag, Polymorphic } from 'astro/types';
3
+
4
+ type Props<As extends HTMLTag = 'div'> = Omit<Polymorphic<{ as: As }>, 'as'> & {
5
+ as?: As;
6
+ class?: string;
7
+ fullWidth?: boolean;
8
+ fullHeight?: boolean;
9
+ };
10
+
11
+ const { as: As = 'div', class: className, fullWidth, fullHeight, ...props } = Astro.props;
12
+ ---
13
+ <As class="card" class:list={[fullWidth && "full-w", fullHeight && "full-h", className]} {...props}>
14
+ <div class="card-header">
15
+ <slot name="header" />
16
+ </div>
17
+ <div class="card-body">
18
+ <slot />
19
+ </div>
20
+ <div class="card-footer">
21
+ <slot name="footer" />
22
+ </div>
23
+ </As>
24
+ <style>
25
+ .card {
26
+ border: 1px solid hsl(var(--border));
27
+ background-color: hsl(var(--background-base));
28
+ border-radius: .5rem;
29
+ width: fit-content;
30
+ height: fit-content;
31
+ }
32
+
33
+ .card.full-w {
34
+ width: 100%;
35
+ }
36
+
37
+ .card.full-h {
38
+ height: 100%;
39
+ }
40
+
41
+ .card-header:has(*) {
42
+ padding: 1rem 1rem 0rem 1rem;
43
+ * {
44
+ margin: 0;
45
+ }
46
+ }
47
+
48
+ .card-body {
49
+ padding: 1rem;
50
+ }
51
+
52
+ .card-footer:has(*) {
53
+ border-top: 1px solid hsl(var(--border));
54
+ padding: 1rem;
55
+ }
56
+
57
+ @media screen and (max-width: 840px) {
58
+ .card {
59
+ width: 100%;
60
+ }
61
+ }
62
+ </style>
@@ -0,0 +1,16 @@
1
+ <!-- This was made for Jumper, to keep him happy <3 -->
2
+ <div class="center">
3
+ <slot />
4
+ </div>
5
+ <style>
6
+ .center {
7
+ display: flex;
8
+ align-items: center;
9
+ justify-content: center;
10
+
11
+ width: 100%;
12
+ height: 100%;
13
+
14
+ text-align: center;
15
+ }
16
+ </style>
@@ -0,0 +1,180 @@
1
+ ---
2
+ import Checkmark from '../icons/Checkmark.astro';
3
+ import type { StudioCMSColorway } from '../utils/colors';
4
+ import { generateID } from '../utils/generateID';
5
+
6
+ interface Props {
7
+ label: string;
8
+ size?: 'sm' | 'md' | 'lg';
9
+ color?: StudioCMSColorway;
10
+ defaultChecked?: boolean;
11
+ disabled?: boolean;
12
+ name?: string;
13
+ isRequired?: boolean;
14
+ };
15
+
16
+ const {
17
+ size = 'md',
18
+ color = 'default',
19
+ defaultChecked,
20
+ disabled,
21
+ name = generateID('checkbox'),
22
+ label,
23
+ isRequired,
24
+ } = Astro.props;
25
+
26
+ const iconSizes = {
27
+ sm: 14,
28
+ md: 16,
29
+ lg: 24,
30
+ };
31
+ ---
32
+ <label
33
+ class="checkmark-label"
34
+ for={name}
35
+ class:list={[
36
+ disabled && "disabled",
37
+ color,
38
+ size,
39
+ ]}
40
+ >
41
+ <div class="checkmark-container">
42
+ <Checkmark
43
+ class={'checkmark'}
44
+ width={iconSizes[size]}
45
+ height={iconSizes[size]}
46
+ />
47
+ <input
48
+ type="checkbox"
49
+ name={name}
50
+ id={name}
51
+ checked={defaultChecked}
52
+ disabled={disabled}
53
+ required={isRequired}
54
+ class="checkbox"
55
+ />
56
+ </div>
57
+ <span>
58
+ {label} <span class="req-star">{isRequired && "*"}</span>
59
+ </span>
60
+ </label>
61
+ <style>
62
+ .checkmark-label {
63
+ display: flex;
64
+ flex-direction: row;
65
+ align-items: center;
66
+ gap: .5rem;
67
+ position: relative;
68
+ margin: .25rem 0;
69
+ }
70
+
71
+ .checkmark-label.disabled {
72
+ opacity: 0.5;
73
+ pointer-events: none;
74
+ color: hsl(var(--text-muted));
75
+ }
76
+
77
+ .checkmark-container {
78
+ display: flex;
79
+ align-items: center;
80
+ justify-content: center;
81
+ background-color: hsl(var(--default-base));
82
+ border: 2px solid hsl(var(--default-base));
83
+ border-radius: .5rem;
84
+ cursor: pointer;
85
+ transition: all .15s ease;
86
+ }
87
+
88
+ .checkmark-label:hover .checkmark-container {
89
+ background-color: hsl(var(--default-hover));
90
+ }
91
+
92
+ .checkmark-label:active .checkmark-container {
93
+ background-color: hsl(var(--default-active));
94
+ scale: 0.9;
95
+ }
96
+
97
+ .checkmark-label.sm {
98
+ font-size: .875em;
99
+ }
100
+
101
+ .checkmark-label.sm .checkmark-container {
102
+ width: 1.25rem;
103
+ height: 1.25rem;
104
+ }
105
+
106
+ .checkmark-label.md .checkmark-container {
107
+ width: 1.5rem;
108
+ height: 1.5rem;
109
+ }
110
+
111
+ .checkmark-label.lg {
112
+ font-size: 1.125em;
113
+ }
114
+
115
+ .checkmark-label.lg .checkmark-container {
116
+ width: 1.75rem;
117
+ height: 1.75rem;
118
+ }
119
+
120
+ .primary .checkmark-container:has(.checkbox:checked) {
121
+ border-color: hsl(var(--primary-base));
122
+ background-color: hsl(var(--primary-base));
123
+ }
124
+
125
+ .success .checkmark-container:has(.checkbox:checked) {
126
+ border-color: hsl(var(--success-base));
127
+ background-color: hsl(var(--success-base));
128
+ }
129
+
130
+ .warning .checkmark-container:has(.checkbox:checked) {
131
+ border-color: hsl(var(--warning-base));
132
+ background-color: hsl(var(--warning-base));
133
+ }
134
+
135
+ .danger .checkmark-container:has(.checkbox:checked) {
136
+ border-color: hsl(var(--danger-base));
137
+ background-color: hsl(var(--danger-base));
138
+ }
139
+
140
+ .req-star {
141
+ color: hsl(var(--danger-base));
142
+ font-weight: 700;
143
+ }
144
+
145
+ .checkbox {
146
+ width: 0;
147
+ height: 0;
148
+ visibility: hidden;
149
+ opacity: 0;
150
+ margin: 0;
151
+ }
152
+ </style>
153
+ <style is:global>
154
+ .checkmark polyline {
155
+ transition: all .15s ease;
156
+ color: hsl(var(--text-normal));
157
+ }
158
+
159
+ .primary .checkmark polyline {
160
+ color: hsl(var(--text-inverted));
161
+ }
162
+
163
+ .success .checkmark polyline {
164
+ color: hsl(var(--text-dark));
165
+ }
166
+
167
+ .warning .checkmark polyline {
168
+ color: hsl(var(--text-dark));
169
+ }
170
+
171
+ .danger .checkmark polyline {
172
+ color: hsl(var(--text-light));
173
+ }
174
+
175
+ .checkmark-container:has(.checkbox:checked) {
176
+ .checkmark polyline {
177
+ stroke-dashoffset: 44;
178
+ }
179
+ }
180
+ </style>
@@ -0,0 +1,39 @@
1
+ ---
2
+ interface Props {
3
+ background?: 'background-base' | 'background-step-1' | 'background-step-2' | 'background-step-3';
4
+ };
5
+
6
+ const { background = 'background-base' } = Astro.props;
7
+ ---
8
+ <div class="divide-container">
9
+ <div class="line" />
10
+ <div class="content" style={`background-color: hsl(var(--${background}));`}>
11
+ <slot />
12
+ </div>
13
+ </div>
14
+ <style>
15
+ .divide-container {
16
+ display: flex;
17
+ width: 100%;
18
+ align-items: center;
19
+ justify-content: center;
20
+ position: relative;
21
+ }
22
+
23
+ .line {
24
+ position: absolute;
25
+ top: 50%;
26
+ left: 50%;
27
+ transform: translate(-50%, -50%);
28
+ width: 100%;
29
+ height: 1px;
30
+ background-color: hsl(var(--border));
31
+ z-index: 1;
32
+ }
33
+
34
+ .content {
35
+ padding: .25rem .5rem;
36
+ z-index: 2;
37
+ color: hsl(var(--text-muted));
38
+ }
39
+ </style>