@duskmoon-dev/core 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/dist/components/button.css +47 -46
  2. package/dist/components/checkbox.css +231 -0
  3. package/dist/components/datepicker.css +404 -10
  4. package/dist/components/form-group.css +308 -0
  5. package/dist/components/index.css +4077 -687
  6. package/dist/components/multi-select.css +491 -0
  7. package/dist/components/navigation.css +153 -2
  8. package/dist/components/otp-input.css +195 -0
  9. package/dist/components/pin-input.css +184 -0
  10. package/dist/components/radio.css +183 -0
  11. package/dist/components/segment-control.css +186 -0
  12. package/dist/components/select.css +205 -0
  13. package/dist/components/switch.css +150 -193
  14. package/dist/components/textarea.css +202 -0
  15. package/dist/components/time-input.css +252 -0
  16. package/dist/components/tree-select.css +439 -0
  17. package/dist/esm/components/button.js +47 -46
  18. package/dist/esm/components/checkbox.js +238 -0
  19. package/dist/esm/components/datepicker.js +404 -10
  20. package/dist/esm/components/form-group.js +315 -0
  21. package/dist/esm/components/multi-select.js +498 -0
  22. package/dist/esm/components/navigation.js +153 -2
  23. package/dist/esm/components/otp-input.js +202 -0
  24. package/dist/esm/components/pin-input.js +191 -0
  25. package/dist/esm/components/radio.js +190 -0
  26. package/dist/esm/components/segment-control.js +193 -0
  27. package/dist/esm/components/select.js +212 -0
  28. package/dist/esm/components/switch.js +150 -193
  29. package/dist/esm/components/textarea.js +209 -0
  30. package/dist/esm/components/time-input.js +259 -0
  31. package/dist/esm/components/tree-select.js +446 -0
  32. package/dist/index.css +4073 -683
  33. package/package.json +56 -1
@@ -1,278 +1,235 @@
1
1
  // Auto-generated from switch.css
2
2
  export const css = `/**
3
3
  * Switch Component Styles
4
- * DuskMoonUI - Material Design 3 inspired switch/toggle system
4
+ * DuskMoonUI - Material Design 3 inspired switch/toggle
5
+ *
6
+ * Usage: <input type="checkbox" class="switch" />
7
+ * With label: <label class="switch-label"><input type="checkbox" class="switch" /><span>Label</span></label>
5
8
  */
6
9
 
7
10
  @layer components {
8
- /* Base Switch */
11
+ /* Base Switch - applied directly to input[type="checkbox"] */
9
12
  .switch {
13
+ --switch-width: 3.25rem;
14
+ --switch-height: 2rem;
15
+ --switch-thumb-size: 1rem;
16
+ --switch-color: var(--color-primary);
17
+ --switch-track-color: var(--color-surface-container-highest);
18
+ --switch-border-color: var(--color-outline);
19
+ --switch-thumb-color: var(--color-outline);
20
+
10
21
  position: relative;
11
- display: inline-flex;
22
+ display: inline-grid;
23
+ grid-template-columns: 0fr 1fr 1fr;
12
24
  align-items: center;
13
- gap: 0.75rem;
25
+ width: var(--switch-width);
26
+ height: var(--switch-height);
27
+ margin: 0;
28
+ padding: 0.25rem;
14
29
  cursor: pointer;
15
- user-select: none;
16
- }
17
-
18
- /* Hidden Input */
19
- .switch-input {
20
- position: absolute;
21
- width: 0;
22
- height: 0;
23
- opacity: 0;
24
- }
25
-
26
- /* Switch Track */
27
- .switch-track {
28
- position: relative;
29
- width: 3.25rem;
30
- height: 2rem;
31
- background-color: var(--color-surface-container-highest);
32
- border: 2px solid var(--color-outline);
33
- border-radius: 9999px;
34
- transition: background-color 200ms ease-in-out, border-color 200ms ease-in-out;
35
- }
36
-
37
- /* Switch Thumb */
38
- .switch-thumb {
39
- position: absolute;
40
- top: 50%;
41
- left: 0.25rem;
42
- width: 1rem;
43
- height: 1rem;
44
- background-color: var(--color-outline);
30
+ appearance: none;
31
+ background-color: var(--switch-track-color);
32
+ border: 2px solid var(--switch-border-color);
33
+ border-radius: var(--switch-height);
34
+ /* Use !important to override global * { transition } rules from layers */
35
+ transition: background-color 200ms ease-in-out !important,
36
+ border-color 200ms ease-in-out !important,
37
+ grid-template-columns 200ms ease-in-out !important;
38
+ }
39
+
40
+ /* Thumb using ::before pseudo-element */
41
+ .switch::before {
42
+ content: "";
43
+ grid-column: 2;
44
+ width: var(--switch-thumb-size);
45
+ height: var(--switch-thumb-size);
46
+ background-color: var(--switch-thumb-color);
45
47
  border-radius: 50%;
46
- transform: translateY(-50%);
47
- transition: left 200ms ease-in-out, width 200ms ease-in-out, height 200ms ease-in-out, background-color 200ms ease-in-out;
48
+ /* Use !important to override global * { transition } rules */
49
+ transition: background-color 200ms ease-in-out !important,
50
+ width 200ms ease-in-out !important,
51
+ margin 200ms ease-in-out !important;
48
52
  }
49
53
 
50
54
  /* Checked State */
51
- .switch-input:checked + .switch-track {
52
- background-color: var(--color-primary);
53
- border-color: var(--color-primary);
55
+ .switch:checked {
56
+ grid-template-columns: 1fr 1fr 0fr;
57
+ background-color: var(--switch-color);
58
+ border-color: var(--switch-color);
54
59
  }
55
60
 
56
- .switch-input:checked + .switch-track .switch-thumb {
57
- left: calc(100% - 1.5rem);
58
- width: 1.5rem;
59
- height: 1.5rem;
61
+ .switch:checked::before {
60
62
  background-color: var(--color-primary-content);
61
63
  }
62
64
 
63
- /* Hover State */
64
- .switch:hover .switch-track::before {
65
- content: '';
66
- position: absolute;
67
- top: 50%;
68
- left: 0.125rem;
69
- width: 2.5rem;
70
- height: 2.5rem;
71
- background-color: var(--color-on-surface);
72
- border-radius: 50%;
73
- transform: translate(-0.75rem, -50%);
74
- opacity: 0.08;
75
- transition: opacity 150ms ease-in-out;
65
+ /* Hover State (unchecked) */
66
+ .switch:hover:not(:disabled):not(:checked) {
67
+ background-color: var(--color-surface-container-high);
76
68
  }
77
69
 
78
- .switch:hover .switch-input:checked + .switch-track::before {
79
- left: auto;
80
- right: 0.125rem;
81
- transform: translate(0.75rem, -50%);
82
- background-color: var(--color-primary);
70
+ .switch:hover:not(:disabled):not(:checked)::before {
71
+ background-color: var(--color-on-surface-variant);
83
72
  }
84
73
 
85
- /* Focus State */
86
- .switch-input:focus-visible + .switch-track {
87
- outline: 2px solid var(--color-primary);
88
- outline-offset: 2px;
74
+ /* Hover State (checked) */
75
+ .switch:checked:hover:not(:disabled) {
76
+ background-color: color-mix(in oklch, var(--switch-color), black 10%);
77
+ border-color: color-mix(in oklch, var(--switch-color), black 10%);
89
78
  }
90
79
 
91
- /* Disabled State */
92
- .switch-input:disabled + .switch-track {
93
- opacity: 0.38;
94
- cursor: not-allowed;
80
+ .switch:checked:hover:not(:disabled)::before {
81
+ background-color: var(--color-primary-container);
95
82
  }
96
83
 
97
- .switch:has(.switch-input:disabled) {
98
- cursor: not-allowed;
84
+ /* Focus State */
85
+ .switch:focus-visible {
86
+ outline: 2px solid var(--switch-color);
87
+ outline-offset: 2px;
99
88
  }
100
89
 
101
- /* Switch Label */
102
- .switch-label {
103
- font-size: 0.875rem;
104
- color: var(--color-on-surface);
90
+ /* Pressed/Active State - expand thumb slightly */
91
+ .switch:active:not(:disabled)::before {
92
+ width: calc(var(--switch-thumb-size) + 0.25rem);
105
93
  }
106
94
 
107
- .switch-label-left {
108
- order: -1;
95
+ .switch:checked:active:not(:disabled)::before {
96
+ margin-left: -0.25rem;
109
97
  }
110
98
 
111
- /* Size Variants */
112
- .switch-sm .switch-track {
113
- width: 2.5rem;
114
- height: 1.5rem;
99
+ /* Disabled State */
100
+ .switch:disabled {
101
+ cursor: not-allowed;
102
+ opacity: 0.38;
115
103
  }
116
104
 
117
- .switch-sm .switch-thumb {
118
- width: 0.75rem;
119
- height: 0.75rem;
105
+ .switch:disabled:not(:checked) {
106
+ background-color: color-mix(in oklch, var(--color-surface-container-highest) 12%, transparent);
107
+ border-color: color-mix(in oklch, var(--color-on-surface) 12%, transparent);
120
108
  }
121
109
 
122
- .switch-sm .switch-input:checked + .switch-track .switch-thumb {
123
- left: calc(100% - 1.125rem);
124
- width: 1.125rem;
125
- height: 1.125rem;
110
+ .switch:disabled:not(:checked)::before {
111
+ background-color: color-mix(in oklch, var(--color-on-surface) 38%, transparent);
126
112
  }
127
113
 
128
- .switch-lg .switch-track {
129
- width: 4rem;
130
- height: 2.5rem;
114
+ .switch:disabled:checked {
115
+ background-color: color-mix(in oklch, var(--color-on-surface) 12%, transparent);
116
+ border-color: transparent;
131
117
  }
132
118
 
133
- .switch-lg .switch-thumb {
134
- width: 1.25rem;
135
- height: 1.25rem;
136
- left: 0.375rem;
119
+ .switch:disabled:checked::before {
120
+ background-color: var(--color-surface);
137
121
  }
138
122
 
139
- .switch-lg .switch-input:checked + .switch-track .switch-thumb {
140
- left: calc(100% - 1.875rem);
141
- width: 1.875rem;
142
- height: 1.875rem;
143
- }
123
+ /* ========================================
124
+ * Size Variants
125
+ * Thumb size = height - 4px (border) - 8px (padding/gap)
126
+ * ======================================== */
144
127
 
145
- /* Color Variants - on parent .switch or on .switch-track */
146
- /* Primary is default, but explicit class for consistency */
147
- .switch-primary .switch-input:checked + .switch-track,
148
- .switch-input:checked + .switch-track.switch-primary {
149
- background-color: var(--color-primary);
150
- border-color: var(--color-primary);
128
+ .switch-xs {
129
+ --switch-width: 2rem;
130
+ --switch-height: 1.25rem;
131
+ --switch-thumb-size: 0.5rem;
151
132
  }
152
133
 
153
- .switch-primary .switch-input:checked + .switch-track .switch-thumb,
154
- .switch-input:checked + .switch-track.switch-primary .switch-thumb {
155
- background-color: var(--color-primary-content);
134
+ .switch-sm {
135
+ --switch-width: 2.5rem;
136
+ --switch-height: 1.5rem;
137
+ --switch-thumb-size: 0.75rem;
156
138
  }
157
139
 
158
- .switch-secondary .switch-input:checked + .switch-track,
159
- .switch-input:checked + .switch-track.switch-secondary {
160
- background-color: var(--color-secondary);
161
- border-color: var(--color-secondary);
140
+ .switch-md {
141
+ --switch-width: 3.25rem;
142
+ --switch-height: 2rem;
143
+ --switch-thumb-size: 1rem;
162
144
  }
163
145
 
164
- .switch-secondary .switch-input:checked + .switch-track .switch-thumb,
165
- .switch-input:checked + .switch-track.switch-secondary .switch-thumb {
166
- background-color: var(--color-secondary-content);
146
+ .switch-lg {
147
+ --switch-width: 4rem;
148
+ --switch-height: 2.5rem;
149
+ --switch-thumb-size: 1.25rem;
167
150
  }
168
151
 
169
- .switch-tertiary .switch-input:checked + .switch-track,
170
- .switch-input:checked + .switch-track.switch-tertiary {
171
- background-color: var(--color-tertiary);
172
- border-color: var(--color-tertiary);
152
+ .switch-xl {
153
+ --switch-width: 4.75rem;
154
+ --switch-height: 3rem;
155
+ --switch-thumb-size: 1.5rem;
173
156
  }
174
157
 
175
- .switch-tertiary .switch-input:checked + .switch-track .switch-thumb,
176
- .switch-input:checked + .switch-track.switch-tertiary .switch-thumb {
177
- background-color: var(--color-tertiary-content);
178
- }
158
+ /* ========================================
159
+ * Color Variants
160
+ * ======================================== */
179
161
 
180
- .switch-success .switch-input:checked + .switch-track,
181
- .switch-input:checked + .switch-track.switch-success {
182
- background-color: var(--color-success);
183
- border-color: var(--color-success);
162
+ .switch-primary {
163
+ --switch-color: var(--color-primary);
184
164
  }
185
165
 
186
- .switch-error .switch-input:checked + .switch-track,
187
- .switch-input:checked + .switch-track.switch-error {
188
- background-color: var(--color-error);
189
- border-color: var(--color-error);
166
+ .switch-secondary {
167
+ --switch-color: var(--color-secondary);
190
168
  }
191
169
 
192
- /* With Icons */
193
- .switch-icon .switch-thumb {
194
- display: flex;
195
- align-items: center;
196
- justify-content: center;
197
- font-size: 0.625rem;
170
+ .switch-tertiary {
171
+ --switch-color: var(--color-tertiary);
198
172
  }
199
173
 
200
- .switch-icon .switch-input:checked + .switch-track .switch-thumb {
201
- font-size: 0.875rem;
174
+ .switch-success {
175
+ --switch-color: var(--color-success);
202
176
  }
203
177
 
204
- /* Labeled Track */
205
- .switch-labeled-track .switch-track {
206
- width: 4rem;
207
- display: flex;
208
- align-items: center;
209
- justify-content: space-between;
210
- padding: 0 0.5rem;
178
+ .switch-warning {
179
+ --switch-color: var(--color-warning);
211
180
  }
212
181
 
213
- .switch-labeled-track .switch-track-label {
214
- font-size: 0.625rem;
215
- font-weight: 600;
216
- color: var(--color-on-surface-variant);
217
- text-transform: uppercase;
218
- transition: opacity 150ms ease-in-out;
182
+ .switch-error {
183
+ --switch-color: var(--color-error);
219
184
  }
220
185
 
221
- .switch-labeled-track .switch-track-on {
222
- opacity: 0;
186
+ .switch-info {
187
+ --switch-color: var(--color-info);
223
188
  }
224
189
 
225
- .switch-labeled-track .switch-track-off {
226
- opacity: 1;
227
- }
190
+ /* ========================================
191
+ * Switch with Label
192
+ * ======================================== */
228
193
 
229
- .switch-labeled-track .switch-input:checked + .switch-track .switch-track-on {
230
- opacity: 1;
231
- color: var(--color-primary-content);
232
- }
233
-
234
- .switch-labeled-track .switch-input:checked + .switch-track .switch-track-off {
235
- opacity: 0;
194
+ .switch-label {
195
+ display: inline-flex;
196
+ align-items: center;
197
+ gap: 0.75rem;
198
+ cursor: pointer;
199
+ user-select: none;
200
+ font-size: 0.875rem;
201
+ color: var(--color-on-surface);
236
202
  }
237
203
 
238
- /* Loading State */
239
- .switch-loading .switch-thumb::after {
240
- content: '';
241
- position: absolute;
242
- top: 50%;
243
- left: 50%;
244
- width: 0.75rem;
245
- height: 0.75rem;
246
- border: 2px solid transparent;
247
- border-top-color: var(--color-on-surface);
248
- border-radius: 50%;
249
- transform: translate(-50%, -50%);
250
- animation: switch-spin 600ms linear infinite;
204
+ .switch-label:has(.switch:disabled) {
205
+ cursor: not-allowed;
206
+ opacity: 0.38;
251
207
  }
252
208
 
253
- @keyframes switch-spin {
254
- to {
255
- transform: translate(-50%, -50%) rotate(360deg);
256
- }
257
- }
209
+ /* ========================================
210
+ * Switch Group
211
+ * ======================================== */
258
212
 
259
- /* Group */
260
213
  .switch-group {
261
214
  display: flex;
262
215
  flex-direction: column;
263
216
  gap: 0.75rem;
264
217
  }
265
218
 
266
- /* Reduce Motion */
267
- @media (prefers-reduced-motion: reduce) {
268
- .switch-track,
269
- .switch-thumb,
270
- .switch-track::before {
271
- transition: none;
272
- }
219
+ .switch-group-horizontal {
220
+ flex-direction: row;
221
+ flex-wrap: wrap;
222
+ gap: 1.5rem;
223
+ }
224
+
225
+ /* ========================================
226
+ * Reduce Motion
227
+ * ======================================== */
273
228
 
274
- .switch-loading .switch-thumb::after {
275
- animation: none;
229
+ @media (prefers-reduced-motion: reduce) {
230
+ .switch,
231
+ .switch::before {
232
+ transition: none !important;
276
233
  }
277
234
  }
278
235
  }
@@ -0,0 +1,209 @@
1
+ // Auto-generated from textarea.css
2
+ export const css = `/**
3
+ * Textarea Component Styles
4
+ * DuskMoonUI - Material Design 3 inspired multi-line text input
5
+ */
6
+
7
+ @layer components {
8
+ /* Base Textarea */
9
+ .textarea {
10
+ display: block;
11
+ width: 100%;
12
+ min-height: 6rem;
13
+ padding: 0.75rem 1rem;
14
+ font-size: 1rem;
15
+ line-height: 1.5rem;
16
+ font-family: inherit;
17
+ color: var(--color-on-surface);
18
+ background-color: var(--color-surface);
19
+ border: 1px solid var(--color-outline);
20
+ border-radius: 0.5rem;
21
+ outline: none;
22
+ resize: vertical;
23
+ transition: border-color 150ms ease-in-out, box-shadow 150ms ease-in-out;
24
+ }
25
+
26
+ .textarea::placeholder {
27
+ color: var(--color-on-surface-variant);
28
+ opacity: 0.7;
29
+ }
30
+
31
+ .textarea:hover:not(:disabled) {
32
+ border-color: var(--color-on-surface-variant);
33
+ }
34
+
35
+ .textarea:focus {
36
+ outline: none;
37
+ }
38
+
39
+ .textarea:focus-visible {
40
+ border-color: var(--color-primary);
41
+ box-shadow: 0 0 0 3px color-mix(in oklch, var(--color-primary) 10%, transparent);
42
+ }
43
+
44
+ .textarea:disabled {
45
+ cursor: not-allowed;
46
+ opacity: 0.5;
47
+ background-color: var(--color-surface-container);
48
+ resize: none;
49
+ }
50
+
51
+ .textarea[readonly] {
52
+ background-color: var(--color-surface-container);
53
+ cursor: default;
54
+ }
55
+
56
+ /* Filled Variant */
57
+ .textarea-filled {
58
+ background-color: var(--color-surface-container);
59
+ border: none;
60
+ border-bottom: 2px solid var(--color-outline);
61
+ border-radius: 0.5rem 0.5rem 0 0;
62
+ }
63
+
64
+ .textarea-filled:hover:not(:disabled) {
65
+ background-color: var(--color-surface-container-high);
66
+ border-bottom-color: var(--color-on-surface);
67
+ }
68
+
69
+ .textarea-filled:focus-visible {
70
+ border-bottom-color: var(--color-primary);
71
+ box-shadow: none;
72
+ }
73
+
74
+ /* Outlined Variant (default) */
75
+ .textarea-outlined {
76
+ background-color: transparent;
77
+ border: 1px solid var(--color-outline);
78
+ border-radius: 0.5rem;
79
+ }
80
+
81
+ /* Ghost Variant */
82
+ .textarea-ghost {
83
+ background-color: transparent;
84
+ border-color: transparent;
85
+ }
86
+
87
+ .textarea-ghost:hover:not(:disabled) {
88
+ background-color: var(--color-surface-container);
89
+ border-color: transparent;
90
+ }
91
+
92
+ .textarea-ghost:focus-visible {
93
+ background-color: var(--color-surface-container);
94
+ border-color: transparent;
95
+ box-shadow: none;
96
+ }
97
+
98
+ /* Color Variants */
99
+ .textarea-primary:focus-visible {
100
+ border-color: var(--color-primary);
101
+ box-shadow: 0 0 0 3px color-mix(in oklch, var(--color-primary) 10%, transparent);
102
+ }
103
+
104
+ .textarea-secondary:focus-visible {
105
+ border-color: var(--color-secondary);
106
+ box-shadow: 0 0 0 3px color-mix(in oklch, var(--color-secondary) 10%, transparent);
107
+ }
108
+
109
+ .textarea-tertiary:focus-visible {
110
+ border-color: var(--color-tertiary);
111
+ box-shadow: 0 0 0 3px color-mix(in oklch, var(--color-tertiary) 10%, transparent);
112
+ }
113
+
114
+ /* Semantic Colors */
115
+ .textarea-error {
116
+ border-color: var(--color-error);
117
+ }
118
+
119
+ .textarea-error:focus-visible {
120
+ border-color: var(--color-error);
121
+ box-shadow: 0 0 0 3px color-mix(in oklch, var(--color-error) 10%, transparent);
122
+ }
123
+
124
+ .textarea-success {
125
+ border-color: var(--color-success);
126
+ }
127
+
128
+ .textarea-success:focus-visible {
129
+ border-color: var(--color-success);
130
+ box-shadow: 0 0 0 3px color-mix(in oklch, var(--color-success) 10%, transparent);
131
+ }
132
+
133
+ .textarea-warning {
134
+ border-color: var(--color-warning);
135
+ }
136
+
137
+ .textarea-warning:focus-visible {
138
+ border-color: var(--color-warning);
139
+ box-shadow: 0 0 0 3px color-mix(in oklch, var(--color-warning) 10%, transparent);
140
+ }
141
+
142
+ /* Size Variants */
143
+ .textarea-sm {
144
+ min-height: 4rem;
145
+ padding: 0.5rem 0.75rem;
146
+ font-size: 0.875rem;
147
+ line-height: 1.25rem;
148
+ border-radius: 0.375rem;
149
+ }
150
+
151
+ .textarea-lg {
152
+ min-height: 8rem;
153
+ padding: 1rem 1.25rem;
154
+ font-size: 1.125rem;
155
+ line-height: 1.75rem;
156
+ border-radius: 0.625rem;
157
+ }
158
+
159
+ /* Resize Options */
160
+ .textarea-resize-none {
161
+ resize: none;
162
+ }
163
+
164
+ .textarea-resize-horizontal {
165
+ resize: horizontal;
166
+ }
167
+
168
+ .textarea-resize-both {
169
+ resize: both;
170
+ }
171
+
172
+ /* Auto-resize (requires JS) */
173
+ .textarea-autosize {
174
+ resize: none;
175
+ overflow: hidden;
176
+ }
177
+
178
+ /* Character Counter */
179
+ .textarea-wrapper {
180
+ position: relative;
181
+ display: flex;
182
+ flex-direction: column;
183
+ gap: 0.25rem;
184
+ }
185
+
186
+ .textarea-counter {
187
+ font-size: 0.75rem;
188
+ line-height: 1rem;
189
+ color: var(--color-on-surface-variant);
190
+ text-align: right;
191
+ }
192
+
193
+ .textarea-counter-error {
194
+ color: var(--color-error);
195
+ }
196
+
197
+ /* Reduce Motion */
198
+ @media (prefers-reduced-motion: reduce) {
199
+ .textarea {
200
+ transition: none;
201
+ }
202
+ }
203
+ }
204
+ `;
205
+
206
+ const sheet = new CSSStyleSheet();
207
+ sheet.replaceSync(css);
208
+ export const styles = sheet;
209
+ export default sheet;