@duskmoon-dev/core 1.19.3 → 1.19.4

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 (101) hide show
  1. package/README.md +1 -1
  2. package/dist/base.css +484 -0
  3. package/dist/components/accordion.css +33 -9
  4. package/dist/components/autocomplete.css +67 -13
  5. package/dist/components/avatar.css +39 -15
  6. package/dist/components/badge.css +15 -3
  7. package/dist/components/card.css +12 -0
  8. package/dist/components/carousel.css +28 -0
  9. package/dist/components/chat.css +15 -11
  10. package/dist/components/checkbox.css +83 -13
  11. package/dist/components/collapse.css +67 -16
  12. package/dist/components/countdown.css +22 -0
  13. package/dist/components/datepicker.css +76 -0
  14. package/dist/components/diff.css +33 -0
  15. package/dist/components/file-input.css +107 -0
  16. package/dist/components/filter-group.css +452 -0
  17. package/dist/components/form-group.css +95 -204
  18. package/dist/components/form.css +1551 -421
  19. package/dist/components/index.css +5991 -6060
  20. package/dist/components/input.css +114 -31
  21. package/dist/components/kbd.css +28 -0
  22. package/dist/components/list.css +22 -3
  23. package/dist/components/otp-input.css +124 -6
  24. package/dist/components/radio.css +70 -0
  25. package/dist/components/range.css +41 -0
  26. package/dist/components/rating.css +39 -12
  27. package/dist/components/select.css +74 -0
  28. package/dist/components/stat.css +40 -0
  29. package/dist/components/switch.css +70 -0
  30. package/dist/components/table.css +8 -0
  31. package/dist/components/textarea.css +74 -0
  32. package/dist/components/timeline.css +40 -25
  33. package/dist/components/toggle-switch.css +165 -0
  34. package/dist/components/toggle.css +198 -32
  35. package/dist/components/validator.css +66 -0
  36. package/dist/effects/aura.css +22 -0
  37. package/dist/effects/hover-3d.css +8 -0
  38. package/dist/effects/hover-gallery.css +14 -0
  39. package/dist/effects/index.css +65 -0
  40. package/dist/effects/text-rotate.css +16 -0
  41. package/dist/esm/components/accordion.js +33 -9
  42. package/dist/esm/components/autocomplete.js +67 -13
  43. package/dist/esm/components/avatar.js +39 -15
  44. package/dist/esm/components/badge.js +15 -3
  45. package/dist/esm/components/card.js +12 -0
  46. package/dist/esm/components/carousel.d.ts +5 -0
  47. package/dist/esm/components/carousel.js +37 -0
  48. package/dist/esm/components/chat.js +15 -11
  49. package/dist/esm/components/checkbox.js +84 -14
  50. package/dist/esm/components/collapse.js +67 -16
  51. package/dist/esm/components/countdown.d.ts +5 -0
  52. package/dist/esm/components/countdown.js +31 -0
  53. package/dist/esm/components/datepicker.js +77 -1
  54. package/dist/esm/components/diff.d.ts +5 -0
  55. package/dist/esm/components/diff.js +42 -0
  56. package/dist/esm/components/file-input.d.ts +5 -0
  57. package/dist/esm/components/file-input.js +116 -0
  58. package/dist/esm/components/filter-group.d.ts +5 -0
  59. package/dist/esm/components/filter-group.js +461 -0
  60. package/dist/esm/components/form-group.js +96 -205
  61. package/dist/esm/components/form.js +1539 -409
  62. package/dist/esm/components/input.js +115 -32
  63. package/dist/esm/components/kbd.d.ts +5 -0
  64. package/dist/esm/components/kbd.js +37 -0
  65. package/dist/esm/components/list.js +22 -3
  66. package/dist/esm/components/otp-input.js +125 -7
  67. package/dist/esm/components/radio.js +71 -1
  68. package/dist/esm/components/range.d.ts +5 -0
  69. package/dist/esm/components/range.js +50 -0
  70. package/dist/esm/components/rating.js +39 -12
  71. package/dist/esm/components/select.js +75 -1
  72. package/dist/esm/components/stat.d.ts +5 -0
  73. package/dist/esm/components/stat.js +49 -0
  74. package/dist/esm/components/switch.js +71 -1
  75. package/dist/esm/components/table.js +8 -0
  76. package/dist/esm/components/textarea.js +75 -1
  77. package/dist/esm/components/timeline.js +40 -25
  78. package/dist/esm/components/toggle-switch.d.ts +5 -0
  79. package/dist/esm/components/toggle-switch.js +174 -0
  80. package/dist/esm/components/toggle.js +198 -32
  81. package/dist/esm/components/validator.d.ts +5 -0
  82. package/dist/esm/components/validator.js +75 -0
  83. package/dist/esm/effects/aura.d.ts +5 -0
  84. package/dist/esm/effects/aura.js +31 -0
  85. package/dist/esm/effects/hover-3d.d.ts +5 -0
  86. package/dist/esm/effects/hover-3d.js +17 -0
  87. package/dist/esm/effects/hover-gallery.d.ts +5 -0
  88. package/dist/esm/effects/hover-gallery.js +23 -0
  89. package/dist/esm/effects/index.d.ts +5 -0
  90. package/dist/esm/effects/index.js +74 -0
  91. package/dist/esm/effects/text-rotate.d.ts +5 -0
  92. package/dist/esm/effects/text-rotate.js +25 -0
  93. package/dist/index.css +5977 -6047
  94. package/dist/index.min.css +1 -1
  95. package/dist/standalone/duskmoonui-themes.css +1 -1
  96. package/dist/standalone/duskmoonui.css +6967 -7028
  97. package/dist/standalone/duskmoonui.js +11 -12
  98. package/dist/standalone/duskmoonui.mjs +11 -12
  99. package/dist/types/types/plugin.d.ts +1 -1
  100. package/dist/types/types/plugin.d.ts.map +1 -1
  101. package/package.json +98 -1
@@ -1,5 +1,115 @@
1
1
  // Auto-generated from input.css
2
- export const css = `/**
2
+ export const css = `/** Opt-in native presentation. Applications own errors, messages and announcements. */
3
+ @layer components {
4
+ /* Compatibility wrapper states are intentionally immediate. */
5
+ :is(.form-group-info, .form-control.info) { --dm-validation-color: var(--color-info); }
6
+ :is(.form-group-warning, .form-control.warning) { --dm-validation-color: var(--color-warning); }
7
+ :is(.form-group-success, .form-control.success) { --dm-validation-color: var(--color-success); }
8
+
9
+ :is(.input, .select, .textarea, .checkbox, .radio, .switch, .toggle, .file-input, .otp-input-field, .otp-code, .datepicker-input):is(.validate :valid, .validate:valid, .validator.validator-success:user-valid):not([aria-invalid="true"]):not(:where(.form-group-error *, .form-control.error *)):not(:disabled) {
10
+ --dm-validation-color: var(--color-success);
11
+ --dm-validation-content: var(--color-success-content);
12
+ }
13
+
14
+ :is(.input, .select, .textarea, .checkbox, .radio, .switch, .toggle, .file-input, .otp-input-field, .otp-code, .datepicker-input):is(.validate :invalid, .validate:invalid, .validator:user-invalid):not(:disabled) {
15
+ --dm-validation-color: var(--color-error);
16
+ --dm-validation-content: var(--color-error-content);
17
+ }
18
+
19
+ :is(.form-group-error, .form-control.error) {
20
+ --dm-validation-color: var(--color-error);
21
+ --dm-validation-content: var(--color-error-content);
22
+ }
23
+
24
+ /* Higher specificity than native states, including server-invalid + user-valid. */
25
+ :is(.input, .select, .textarea, .checkbox, .radio, .switch, .toggle, .file-input, .otp-input-field, .otp-code, .datepicker-input):is([aria-invalid="true"], .form-group-error *, .form-control.error *):not(:disabled):is(:focus, :not(:focus)) {
26
+ --dm-validation-color: var(--color-error);
27
+ --dm-validation-content: var(--color-error-content);
28
+ }
29
+
30
+ /* This shared selector wins over filled/ghost focus and semantic modifiers. */
31
+ :is(.input, .select, .textarea, .checkbox, .radio, .switch, .toggle, .file-input, .otp-input-field, .otp-code, .datepicker-input):is([aria-invalid="true"], .validator:user-invalid, .validator.validator-success:user-valid, .validate :invalid, .validate :valid, .validate:invalid, .validate:valid, .form-group-error *, .form-group-success *, .form-group-warning *, .form-group-info *, .form-control.error *, .form-control.success *, .form-control.warning *, .form-control.info *):not(:disabled) {
32
+ color: var(--dm-validation-color);
33
+ border-color: var(--dm-validation-color);
34
+ --checkbox-color: var(--dm-validation-color);
35
+ --radio-color: var(--dm-validation-color);
36
+ --switch-color: var(--dm-validation-color);
37
+ --switch-content-color: var(--dm-validation-content, var(--color-primary-content));
38
+ --toggle-color: var(--dm-validation-color);
39
+ }
40
+
41
+ :is(.input, .select, .textarea, .checkbox, .radio, .switch, .toggle, .file-input, .otp-input-field, .otp-code, .datepicker-input):is([aria-invalid="true"], .validator:user-invalid, .validator.validator-success:user-valid, .validate :invalid, .validate :valid, .validate:invalid, .validate:valid, .form-group-error *, .form-group-success *, .form-group-warning *, .form-group-info *, .form-control.error *, .form-control.success *, .form-control.warning *, .form-control.info *):not(:disabled):focus {
42
+ border-color: var(--dm-validation-color);
43
+ box-shadow: 0 0 0 3px color-mix(in oklch, var(--dm-validation-color) 20%, transparent);
44
+ }
45
+
46
+ :is(.form-group-error, .form-control.error) :is(.form-label, .label-text) { color: var(--color-error); }
47
+ :is(.form-group-success, .form-control.success) :is(.form-label, .label-text) { color: var(--color-success); }
48
+ :is(.form-group-warning, .form-control.warning) :is(.form-label, .label-text) { color: var(--color-warning); }
49
+ :is(.form-group-info, .form-control.info) :is(.form-label, .label-text) { color: var(--color-info); }
50
+
51
+ .validator-hint { font-size: 0.75rem; color: var(--color-on-surface-variant); }
52
+ .validator-error { display: none; font-size: 0.75rem; color: var(--color-error); }
53
+ /* Keep OTP actions stationary when blur reveals an error during a click. */
54
+ .otp-code ~ .validator-error { display: block; visibility: hidden; }
55
+ :is(.form-group, .form-control):has(:is([aria-invalid="true"], .validator:user-invalid, .validate :invalid, .validate:invalid):not(:disabled)) > .validator-error,
56
+ :is(.form-group-error, .form-control.error) > .validator-error { display: block; visibility: visible; }
57
+
58
+ @media (forced-colors: active) {
59
+ :is(input, select, textarea):is(.input, .select, .textarea, .checkbox, .radio, .switch, .toggle, .file-input, .otp-input-field, .otp-code, .datepicker-input):focus-visible {
60
+ outline: 2px solid Highlight;
61
+ outline-offset: 2px;
62
+ }
63
+ input:is(.checkbox, .radio, .switch, .toggle) { appearance: auto; }
64
+ input:is(.checkbox, .radio, .switch, .toggle)::before,
65
+ input:is(.checkbox, .radio, .switch, .toggle)::after { content: none; }
66
+ }
67
+ }
68
+
69
+
70
+
71
+ @layer components {
72
+ .file-input {
73
+ display: block;
74
+ box-sizing: border-box;
75
+ width: 100%;
76
+ min-width: 0;
77
+ padding: 0;
78
+ font: inherit;
79
+ color: var(--color-on-surface);
80
+ background-color: var(--color-surface);
81
+ border: 1px solid currentColor;
82
+ border-radius: var(--radius-sm);
83
+ cursor: pointer;
84
+ }
85
+ .file-input::file-selector-button {
86
+ padding: 0.75rem 1rem;
87
+ margin-inline-end: 0.75rem;
88
+ font: inherit;
89
+ color: inherit;
90
+ background-color: var(--color-surface-container);
91
+ border: none;
92
+ border-inline-end: 1px solid currentColor;
93
+ cursor: inherit;
94
+ }
95
+ .file-input:hover:not(:disabled)::file-selector-button { background-color: var(--color-surface-container-high); }
96
+ .file-input:focus-visible { outline: none; box-shadow: 0 0 0 3px color-mix(in oklch, currentColor 20%, transparent); }
97
+ .file-input:disabled { opacity: 0.5; cursor: not-allowed; }
98
+ .file-input-xs::file-selector-button { padding: 0.375rem 0.625rem; }
99
+ .file-input-sm::file-selector-button { padding: 0.5rem 0.75rem; }
100
+ .file-input-lg::file-selector-button { padding: 1rem 1.25rem; }
101
+ .file-input-primary { color: var(--color-primary); }
102
+ .file-input-secondary { color: var(--color-secondary); }
103
+ .file-input-tertiary { color: var(--color-tertiary); }
104
+ .file-input-info { color: var(--color-info); }
105
+ .file-input-success { color: var(--color-success); }
106
+ .file-input-warning { color: var(--color-warning); }
107
+ .file-input-error { color: var(--color-error); }
108
+ .file-input-ghost { border-color: transparent; }
109
+ }
110
+
111
+
112
+ /**
3
113
  * Input Component Styles
4
114
  * DuskMoonUI - Material Design 3 inspired input system
5
115
  */
@@ -7,6 +117,8 @@ export const css = `/**
7
117
  @layer components {
8
118
  /* Base Input */
9
119
  .input {
120
+ box-sizing: border-box;
121
+ min-width: 0;
10
122
  display: flex;
11
123
  width: 100%;
12
124
  padding: 0.75rem 1rem;
@@ -40,6 +152,7 @@ export const css = `/**
40
152
  }
41
153
 
42
154
  /* Bordered Input */
155
+ .input-outlined { background-color: transparent; border-color: var(--color-outline); }
43
156
  .input-bordered {
44
157
  border-color: var(--color-outline);
45
158
  background-color: var(--color-surface);
@@ -90,6 +203,7 @@ export const css = `/**
90
203
  }
91
204
 
92
205
  /* Ghost Input */
206
+ .input-md { height: 3rem; }
93
207
  .input-ghost {
94
208
  background-color: transparent;
95
209
  border-color: transparent;
@@ -168,37 +282,6 @@ export const css = `/**
168
282
  border-left: none;
169
283
  }
170
284
 
171
- /* File Input */
172
- .file-input {
173
- display: flex;
174
- width: 100%;
175
- padding: 0;
176
- background-color: var(--color-surface);
177
- border: 1px solid var(--color-outline);
178
- border-radius: var(--radius-sm);
179
- overflow: hidden;
180
- cursor: pointer;
181
- }
182
-
183
- .file-input::file-selector-button {
184
- padding: 0.75rem 1rem;
185
- background-color: var(--color-surface-container);
186
- color: var(--color-on-surface);
187
- border: none;
188
- border-right: 1px solid var(--color-outline);
189
- cursor: pointer;
190
- transition: background-color 150ms ease-in-out;
191
- }
192
-
193
- .file-input::file-selector-button:hover {
194
- background-color: var(--color-surface-container-high);
195
- }
196
-
197
- .file-input:focus-visible {
198
- box-shadow: 0 0 0 3px color-mix(in oklch, currentColor 20%, transparent);
199
- outline: none;
200
- }
201
-
202
285
  /* Reduce Motion */
203
286
  @media (prefers-reduced-motion: reduce) {
204
287
  .input,
@@ -0,0 +1,5 @@
1
+ // Auto-generated type declaration for kbd
2
+ export declare const css: string;
3
+ export declare const styles: CSSStyleSheet | null;
4
+ declare const sheet: CSSStyleSheet | null;
5
+ export default sheet;
@@ -0,0 +1,37 @@
1
+ // Auto-generated from kbd.css
2
+ export const css = `@layer components {
3
+ .kbd {
4
+ display: inline-flex;
5
+ align-items: center;
6
+ justify-content: center;
7
+ min-inline-size: 1.5rem;
8
+ padding: 0.125rem 0.375rem;
9
+ font: 0.875rem ui-monospace, monospace;
10
+ line-height: 1.5;
11
+ color: var(--color-on-surface);
12
+ background: var(--color-surface-container);
13
+ border: 1px solid currentColor;
14
+ border-block-end-width: 2px;
15
+ border-radius: var(--radius-sm);
16
+ vertical-align: middle;
17
+ }
18
+ .kbd-xs { font-size: 0.625rem; }
19
+ .kbd-sm { font-size: 0.75rem; }
20
+ .kbd-lg { font-size: 1rem; padding: 0.25rem 0.5rem; }
21
+ .kbd-primary { color: var(--color-primary); }
22
+ .kbd-secondary { color: var(--color-secondary); }
23
+ .kbd-tertiary { color: var(--color-tertiary); }
24
+ .kbd-info { color: var(--color-info); }
25
+ .kbd-success { color: var(--color-success); }
26
+ .kbd-warning { color: var(--color-warning); }
27
+ .kbd-error { color: var(--color-error); }
28
+ .kbd-ghost { border-color: transparent; }
29
+ }
30
+ `;
31
+
32
+ const sheet = typeof CSSStyleSheet !== 'undefined' ? new CSSStyleSheet() : null;
33
+ if (sheet) {
34
+ sheet.replaceSync(css);
35
+ }
36
+ export const styles = sheet;
37
+ export default sheet;
@@ -64,14 +64,18 @@ export const css = `/**
64
64
  min-width: 0;
65
65
  }
66
66
 
67
- .list-item-title {
67
+ .list-item-title,
68
+ .list-item-text {
69
+ overflow-wrap: anywhere;
68
70
  font-size: 1rem;
69
71
  font-weight: 500;
70
72
  line-height: 1.5rem;
71
73
  color: var(--color-on-surface);
72
74
  }
73
75
 
74
- .list-item-subtitle {
76
+ .list-item-subtitle,
77
+ .list-item-secondary {
78
+ overflow-wrap: anywhere;
75
79
  font-size: 0.875rem;
76
80
  line-height: 1.25rem;
77
81
  color: var(--color-on-surface-variant);
@@ -85,6 +89,21 @@ export const css = `/**
85
89
  color: var(--color-on-surface-variant);
86
90
  }
87
91
 
92
+ .list-item-leading, .list-item-trailing { display: inline-flex; align-items: center; gap: 0.5rem; flex: none; }
93
+ .list-item-trailing { margin-inline-start: auto; }
94
+ .list-item-two-line, .list-item-three-line { align-items: flex-start; }
95
+ .list-item-interactive { cursor: pointer; }
96
+ .list-item-interactive:hover { background: var(--color-surface-container); }
97
+ .list-item-interactive:focus-visible { outline: 2px solid var(--color-primary); outline-offset: -2px; }
98
+ .list-item-active-primary { background: var(--color-primary-container); color: var(--color-on-primary-container); }
99
+ .list-item-active-secondary { background: var(--color-secondary-container); color: var(--color-on-secondary-container); }
100
+ .list-item-active-tertiary { background: var(--color-tertiary-container); color: var(--color-on-tertiary-container); }
101
+ .list-comfortable > .list-item { padding-block: 1rem; }
102
+ .list-surface-container { background: var(--color-surface-container); }
103
+ .list-surface-container-low { background: var(--color-surface-container-low); }
104
+ .list-surface-container-high { background: var(--color-surface-container-high); }
105
+ .list-nested { margin-inline-start: 1rem; }
106
+
88
107
  /* List Variants */
89
108
  .list-bordered {
90
109
  border: 1px solid var(--color-outline);
@@ -121,7 +140,7 @@ export const css = `/**
121
140
  }
122
141
 
123
142
  .list-divider-inset {
124
- margin-left: 3.5rem;
143
+ margin-inline-start: 3.5rem;
125
144
  }
126
145
 
127
146
  /* List Subheader */
@@ -1,12 +1,83 @@
1
1
  // Auto-generated from otp-input.css
2
- export const css = `/**
2
+ export const css = `/** Opt-in native presentation. Applications own errors, messages and announcements. */
3
+ @layer components {
4
+ /* Compatibility wrapper states are intentionally immediate. */
5
+ :is(.form-group-info, .form-control.info) { --dm-validation-color: var(--color-info); }
6
+ :is(.form-group-warning, .form-control.warning) { --dm-validation-color: var(--color-warning); }
7
+ :is(.form-group-success, .form-control.success) { --dm-validation-color: var(--color-success); }
8
+
9
+ :is(.input, .select, .textarea, .checkbox, .radio, .switch, .toggle, .file-input, .otp-input-field, .otp-code, .datepicker-input):is(.validate :valid, .validate:valid, .validator.validator-success:user-valid):not([aria-invalid="true"]):not(:where(.form-group-error *, .form-control.error *)):not(:disabled) {
10
+ --dm-validation-color: var(--color-success);
11
+ --dm-validation-content: var(--color-success-content);
12
+ }
13
+
14
+ :is(.input, .select, .textarea, .checkbox, .radio, .switch, .toggle, .file-input, .otp-input-field, .otp-code, .datepicker-input):is(.validate :invalid, .validate:invalid, .validator:user-invalid):not(:disabled) {
15
+ --dm-validation-color: var(--color-error);
16
+ --dm-validation-content: var(--color-error-content);
17
+ }
18
+
19
+ :is(.form-group-error, .form-control.error) {
20
+ --dm-validation-color: var(--color-error);
21
+ --dm-validation-content: var(--color-error-content);
22
+ }
23
+
24
+ /* Higher specificity than native states, including server-invalid + user-valid. */
25
+ :is(.input, .select, .textarea, .checkbox, .radio, .switch, .toggle, .file-input, .otp-input-field, .otp-code, .datepicker-input):is([aria-invalid="true"], .form-group-error *, .form-control.error *):not(:disabled):is(:focus, :not(:focus)) {
26
+ --dm-validation-color: var(--color-error);
27
+ --dm-validation-content: var(--color-error-content);
28
+ }
29
+
30
+ /* This shared selector wins over filled/ghost focus and semantic modifiers. */
31
+ :is(.input, .select, .textarea, .checkbox, .radio, .switch, .toggle, .file-input, .otp-input-field, .otp-code, .datepicker-input):is([aria-invalid="true"], .validator:user-invalid, .validator.validator-success:user-valid, .validate :invalid, .validate :valid, .validate:invalid, .validate:valid, .form-group-error *, .form-group-success *, .form-group-warning *, .form-group-info *, .form-control.error *, .form-control.success *, .form-control.warning *, .form-control.info *):not(:disabled) {
32
+ color: var(--dm-validation-color);
33
+ border-color: var(--dm-validation-color);
34
+ --checkbox-color: var(--dm-validation-color);
35
+ --radio-color: var(--dm-validation-color);
36
+ --switch-color: var(--dm-validation-color);
37
+ --switch-content-color: var(--dm-validation-content, var(--color-primary-content));
38
+ --toggle-color: var(--dm-validation-color);
39
+ }
40
+
41
+ :is(.input, .select, .textarea, .checkbox, .radio, .switch, .toggle, .file-input, .otp-input-field, .otp-code, .datepicker-input):is([aria-invalid="true"], .validator:user-invalid, .validator.validator-success:user-valid, .validate :invalid, .validate :valid, .validate:invalid, .validate:valid, .form-group-error *, .form-group-success *, .form-group-warning *, .form-group-info *, .form-control.error *, .form-control.success *, .form-control.warning *, .form-control.info *):not(:disabled):focus {
42
+ border-color: var(--dm-validation-color);
43
+ box-shadow: 0 0 0 3px color-mix(in oklch, var(--dm-validation-color) 20%, transparent);
44
+ }
45
+
46
+ :is(.form-group-error, .form-control.error) :is(.form-label, .label-text) { color: var(--color-error); }
47
+ :is(.form-group-success, .form-control.success) :is(.form-label, .label-text) { color: var(--color-success); }
48
+ :is(.form-group-warning, .form-control.warning) :is(.form-label, .label-text) { color: var(--color-warning); }
49
+ :is(.form-group-info, .form-control.info) :is(.form-label, .label-text) { color: var(--color-info); }
50
+
51
+ .validator-hint { font-size: 0.75rem; color: var(--color-on-surface-variant); }
52
+ .validator-error { display: none; font-size: 0.75rem; color: var(--color-error); }
53
+ /* Keep OTP actions stationary when blur reveals an error during a click. */
54
+ .otp-code ~ .validator-error { display: block; visibility: hidden; }
55
+ :is(.form-group, .form-control):has(:is([aria-invalid="true"], .validator:user-invalid, .validate :invalid, .validate:invalid):not(:disabled)) > .validator-error,
56
+ :is(.form-group-error, .form-control.error) > .validator-error { display: block; visibility: visible; }
57
+
58
+ @media (forced-colors: active) {
59
+ :is(input, select, textarea):is(.input, .select, .textarea, .checkbox, .radio, .switch, .toggle, .file-input, .otp-input-field, .otp-code, .datepicker-input):focus-visible {
60
+ outline: 2px solid Highlight;
61
+ outline-offset: 2px;
62
+ }
63
+ input:is(.checkbox, .radio, .switch, .toggle) { appearance: auto; }
64
+ input:is(.checkbox, .radio, .switch, .toggle)::before,
65
+ input:is(.checkbox, .radio, .switch, .toggle)::after { content: none; }
66
+ }
67
+ }
68
+
69
+
70
+ /**
3
71
  * OTP Input Component Styles
4
72
  * DuskMoonUI - One-Time Password input for verification codes
5
73
  */
6
74
 
7
75
  @layer components {
76
+ :where(.otp-input, .otp-input-field) { box-sizing: border-box; }
77
+
8
78
  /* Base OTP Container */
9
79
  .otp-input {
80
+ flex-wrap: wrap;
10
81
  display: inline-flex;
11
82
  align-items: center;
12
83
  gap: 0.5rem;
@@ -55,7 +126,8 @@ export const css = `/**
55
126
  }
56
127
 
57
128
  /* Separator */
58
- .otp-separator {
129
+ .otp-separator,
130
+ .otp-input-separator {
59
131
  display: flex;
60
132
  align-items: center;
61
133
  justify-content: center;
@@ -109,14 +181,16 @@ export const css = `/**
109
181
  }
110
182
 
111
183
  /* Underline Variant */
112
- .otp-input-underline .otp-input-field {
184
+ .otp-input-underline .otp-input-field,
185
+ .otp-input-underlined .otp-input-field {
113
186
  background-color: transparent;
114
187
  border: none;
115
188
  border-bottom: 2px solid var(--color-outline);
116
189
  border-radius: 0;
117
190
  }
118
191
 
119
- .otp-input-underline .otp-input-field:focus {
192
+ .otp-input-underline .otp-input-field:focus,
193
+ .otp-input-underlined .otp-input-field:focus {
120
194
  border-bottom-color: var(--color-primary);
121
195
  box-shadow: none;
122
196
  }
@@ -233,17 +307,61 @@ export const css = `/**
233
307
  color: var(--color-on-surface);
234
308
  }
235
309
 
236
- .otp-helper {
310
+ .otp-helper,
311
+ .otp-input-helper {
237
312
  font-size: 0.75rem;
238
313
  color: var(--color-on-surface-variant);
239
314
  }
240
315
 
241
- .otp-error-message {
316
+ .otp-error-message,
317
+ .otp-input-helper-error {
242
318
  font-size: 0.75rem;
243
319
  color: var(--color-error);
244
320
  }
245
321
 
246
- /* Reduce Motion */
322
+ /* One complete native code. Length guides never create separate fields. */
323
+ .otp-code {
324
+ --otp-length: 6;
325
+ display: block;
326
+ box-sizing: border-box;
327
+ /* The extra two content pixels keep the trailing native caret in view. */
328
+ inline-size: calc(var(--otp-length) * 1ch + 1.5rem + 4px);
329
+ max-inline-size: 100%;
330
+ min-inline-size: 0;
331
+ padding: 0.75rem;
332
+ font: 1.5rem / 1.5 ui-monospace, monospace;
333
+ font-variant-numeric: tabular-nums;
334
+ direction: ltr;
335
+ text-align: start;
336
+ color: var(--color-on-surface);
337
+ caret-color: currentColor;
338
+ background-color: var(--color-surface);
339
+ border: 1px solid currentColor;
340
+ border-radius: var(--radius-sm);
341
+ }
342
+ .otp-code-4 { --otp-length: 4; }
343
+ .otp-code:focus { outline: 2px solid currentColor; outline-offset: 3px; }
344
+ .otp-code:disabled { opacity: 0.38; cursor: not-allowed; }
345
+ .otp-code-primary { color: var(--color-primary); }
346
+ .otp-code-secondary { color: var(--color-secondary); }
347
+ .otp-code-tertiary { color: var(--color-tertiary); }
348
+ .otp-code-info { color: var(--color-info); }
349
+ .otp-code-success { color: var(--color-success); }
350
+ .otp-code-warning { color: var(--color-warning); }
351
+ .otp-code-error { color: var(--color-error); }
352
+ .otp-input-helper-success { font-size: 0.75rem; color: var(--color-success); }
353
+
354
+ @supports (background-image: repeating-linear-gradient(to right, transparent 0 1ch)) {
355
+ .otp-code {
356
+ background-image: repeating-linear-gradient(to right, transparent 0 0.125ch, var(--color-outline-variant) 0.125ch 0.875ch, transparent 0.875ch 1ch);
357
+ background-size: calc(var(--otp-length) * 1ch) 3px;
358
+ background-repeat: no-repeat;
359
+ background-origin: content-box;
360
+ background-position: left bottom;
361
+ }
362
+ }
363
+ @media (forced-colors: active) { .otp-code { background-image: none; } }
364
+
247
365
  @media (prefers-reduced-motion: reduce) {
248
366
  .otp-input-field {
249
367
  transition: none;
@@ -1,5 +1,73 @@
1
1
  // Auto-generated from radio.css
2
- export const css = `/**
2
+ export const css = `/** Opt-in native presentation. Applications own errors, messages and announcements. */
3
+ @layer components {
4
+ /* Compatibility wrapper states are intentionally immediate. */
5
+ :is(.form-group-info, .form-control.info) { --dm-validation-color: var(--color-info); }
6
+ :is(.form-group-warning, .form-control.warning) { --dm-validation-color: var(--color-warning); }
7
+ :is(.form-group-success, .form-control.success) { --dm-validation-color: var(--color-success); }
8
+
9
+ :is(.input, .select, .textarea, .checkbox, .radio, .switch, .toggle, .file-input, .otp-input-field, .otp-code, .datepicker-input):is(.validate :valid, .validate:valid, .validator.validator-success:user-valid):not([aria-invalid="true"]):not(:where(.form-group-error *, .form-control.error *)):not(:disabled) {
10
+ --dm-validation-color: var(--color-success);
11
+ --dm-validation-content: var(--color-success-content);
12
+ }
13
+
14
+ :is(.input, .select, .textarea, .checkbox, .radio, .switch, .toggle, .file-input, .otp-input-field, .otp-code, .datepicker-input):is(.validate :invalid, .validate:invalid, .validator:user-invalid):not(:disabled) {
15
+ --dm-validation-color: var(--color-error);
16
+ --dm-validation-content: var(--color-error-content);
17
+ }
18
+
19
+ :is(.form-group-error, .form-control.error) {
20
+ --dm-validation-color: var(--color-error);
21
+ --dm-validation-content: var(--color-error-content);
22
+ }
23
+
24
+ /* Higher specificity than native states, including server-invalid + user-valid. */
25
+ :is(.input, .select, .textarea, .checkbox, .radio, .switch, .toggle, .file-input, .otp-input-field, .otp-code, .datepicker-input):is([aria-invalid="true"], .form-group-error *, .form-control.error *):not(:disabled):is(:focus, :not(:focus)) {
26
+ --dm-validation-color: var(--color-error);
27
+ --dm-validation-content: var(--color-error-content);
28
+ }
29
+
30
+ /* This shared selector wins over filled/ghost focus and semantic modifiers. */
31
+ :is(.input, .select, .textarea, .checkbox, .radio, .switch, .toggle, .file-input, .otp-input-field, .otp-code, .datepicker-input):is([aria-invalid="true"], .validator:user-invalid, .validator.validator-success:user-valid, .validate :invalid, .validate :valid, .validate:invalid, .validate:valid, .form-group-error *, .form-group-success *, .form-group-warning *, .form-group-info *, .form-control.error *, .form-control.success *, .form-control.warning *, .form-control.info *):not(:disabled) {
32
+ color: var(--dm-validation-color);
33
+ border-color: var(--dm-validation-color);
34
+ --checkbox-color: var(--dm-validation-color);
35
+ --radio-color: var(--dm-validation-color);
36
+ --switch-color: var(--dm-validation-color);
37
+ --switch-content-color: var(--dm-validation-content, var(--color-primary-content));
38
+ --toggle-color: var(--dm-validation-color);
39
+ }
40
+
41
+ :is(.input, .select, .textarea, .checkbox, .radio, .switch, .toggle, .file-input, .otp-input-field, .otp-code, .datepicker-input):is([aria-invalid="true"], .validator:user-invalid, .validator.validator-success:user-valid, .validate :invalid, .validate :valid, .validate:invalid, .validate:valid, .form-group-error *, .form-group-success *, .form-group-warning *, .form-group-info *, .form-control.error *, .form-control.success *, .form-control.warning *, .form-control.info *):not(:disabled):focus {
42
+ border-color: var(--dm-validation-color);
43
+ box-shadow: 0 0 0 3px color-mix(in oklch, var(--dm-validation-color) 20%, transparent);
44
+ }
45
+
46
+ :is(.form-group-error, .form-control.error) :is(.form-label, .label-text) { color: var(--color-error); }
47
+ :is(.form-group-success, .form-control.success) :is(.form-label, .label-text) { color: var(--color-success); }
48
+ :is(.form-group-warning, .form-control.warning) :is(.form-label, .label-text) { color: var(--color-warning); }
49
+ :is(.form-group-info, .form-control.info) :is(.form-label, .label-text) { color: var(--color-info); }
50
+
51
+ .validator-hint { font-size: 0.75rem; color: var(--color-on-surface-variant); }
52
+ .validator-error { display: none; font-size: 0.75rem; color: var(--color-error); }
53
+ /* Keep OTP actions stationary when blur reveals an error during a click. */
54
+ .otp-code ~ .validator-error { display: block; visibility: hidden; }
55
+ :is(.form-group, .form-control):has(:is([aria-invalid="true"], .validator:user-invalid, .validate :invalid, .validate:invalid):not(:disabled)) > .validator-error,
56
+ :is(.form-group-error, .form-control.error) > .validator-error { display: block; visibility: visible; }
57
+
58
+ @media (forced-colors: active) {
59
+ :is(input, select, textarea):is(.input, .select, .textarea, .checkbox, .radio, .switch, .toggle, .file-input, .otp-input-field, .otp-code, .datepicker-input):focus-visible {
60
+ outline: 2px solid Highlight;
61
+ outline-offset: 2px;
62
+ }
63
+ input:is(.checkbox, .radio, .switch, .toggle) { appearance: auto; }
64
+ input:is(.checkbox, .radio, .switch, .toggle)::before,
65
+ input:is(.checkbox, .radio, .switch, .toggle)::after { content: none; }
66
+ }
67
+ }
68
+
69
+
70
+ /**
3
71
  * Radio Component Styles
4
72
  * DuskMoonUI - Material Design 3 inspired radio button
5
73
  *
@@ -8,6 +76,8 @@ export const css = `/**
8
76
  */
9
77
 
10
78
  @layer components {
79
+ :where(.radio) { box-sizing: border-box; }
80
+
11
81
  /* Base Radio - applied directly to input[type="radio"] */
12
82
  .radio {
13
83
  --radio-size: 1.25rem;
@@ -0,0 +1,5 @@
1
+ // Auto-generated type declaration for range
2
+ export declare const css: string;
3
+ export declare const styles: CSSStyleSheet | null;
4
+ declare const sheet: CSSStyleSheet | null;
5
+ export default sheet;
@@ -0,0 +1,50 @@
1
+ // Auto-generated from range.css
2
+ export const css = `@layer components {
3
+ .range {
4
+ --range-thumb-size: 1.25rem;
5
+ appearance: none;
6
+ display: block;
7
+ box-sizing: border-box;
8
+ width: 100%;
9
+ min-width: 0;
10
+ height: var(--range-thumb-size);
11
+ margin: 0;
12
+ color: var(--color-on-surface);
13
+ accent-color: currentColor;
14
+ background: transparent;
15
+ cursor: pointer;
16
+ }
17
+ .range::-webkit-slider-runnable-track { height: 0.5rem; background: var(--color-surface-container-highest); border-radius: var(--radius-xs); }
18
+ .range::-moz-range-track { height: 0.5rem; background: var(--color-surface-container-highest); border-radius: var(--radius-xs); }
19
+ .range::-webkit-slider-thumb {
20
+ appearance: none;
21
+ width: var(--range-thumb-size);
22
+ height: var(--range-thumb-size);
23
+ margin-top: calc((0.5rem - var(--range-thumb-size)) / 2);
24
+ background: currentColor;
25
+ border: 1px solid currentColor;
26
+ border-radius: var(--radius-full);
27
+ }
28
+ .range::-moz-range-thumb { width: var(--range-thumb-size); height: var(--range-thumb-size); background: currentColor; border: 1px solid currentColor; border-radius: var(--radius-full); }
29
+ .range:focus-visible { outline: 2px solid currentColor; outline-offset: 3px; }
30
+ .range:disabled { opacity: 0.5; cursor: not-allowed; }
31
+ .range-xs { --range-thumb-size: 0.875rem; }
32
+ .range-sm { --range-thumb-size: 1rem; }
33
+ .range-lg { --range-thumb-size: 1.5rem; }
34
+ .range-primary { color: var(--color-primary); }
35
+ .range-secondary { color: var(--color-secondary); }
36
+ .range-tertiary { color: var(--color-tertiary); }
37
+ .range-info { color: var(--color-info); }
38
+ .range-success { color: var(--color-success); }
39
+ .range-warning { color: var(--color-warning); }
40
+ .range-error { color: var(--color-error); }
41
+ @media (forced-colors: active) { .range { appearance: auto; } .range:focus-visible { outline-color: Highlight; } }
42
+ }
43
+ `;
44
+
45
+ const sheet = typeof CSSStyleSheet !== 'undefined' ? new CSSStyleSheet() : null;
46
+ if (sheet) {
47
+ sheet.replaceSync(css);
48
+ }
49
+ export const styles = sheet;
50
+ export default sheet;
@@ -176,23 +176,23 @@ export const css = `/**
176
176
  }
177
177
 
178
178
  /* Hover Preview */
179
- .rating:not(.rating-readonly) .rating-item:hover ~ .rating-item {
179
+ .rating:not(.rating-readonly):not(.rating-native) .rating-item:hover ~ .rating-item {
180
180
  color: var(--color-outline);
181
181
  }
182
182
 
183
- .rating:not(.rating-readonly):hover .rating-item {
183
+ .rating:not(.rating-readonly):not(.rating-native):hover .rating-item {
184
184
  color: var(--color-warning);
185
185
  }
186
186
 
187
- .rating-primary:not(.rating-readonly):hover .rating-item { color: var(--color-primary); }
188
- .rating-secondary:not(.rating-readonly):hover .rating-item { color: var(--color-secondary); }
189
- .rating-tertiary:not(.rating-readonly):hover .rating-item { color: var(--color-tertiary); }
190
- .rating-info:not(.rating-readonly):hover .rating-item { color: var(--color-info); }
191
- .rating-success:not(.rating-readonly):hover .rating-item { color: var(--color-success); }
192
- .rating-error:not(.rating-readonly):hover .rating-item { color: var(--color-error); }
193
- .rating-accent:not(.rating-readonly):hover .rating-item { color: var(--color-accent); }
194
- .rating-neutral:not(.rating-readonly):hover .rating-item { color: var(--color-neutral); }
195
- .rating-base:not(.rating-readonly):hover .rating-item { color: var(--color-base-content); }
187
+ .rating-primary:not(.rating-readonly):not(.rating-native):hover .rating-item { color: var(--color-primary); }
188
+ .rating-secondary:not(.rating-readonly):not(.rating-native):hover .rating-item { color: var(--color-secondary); }
189
+ .rating-tertiary:not(.rating-readonly):not(.rating-native):hover .rating-item { color: var(--color-tertiary); }
190
+ .rating-info:not(.rating-readonly):not(.rating-native):hover .rating-item { color: var(--color-info); }
191
+ .rating-success:not(.rating-readonly):not(.rating-native):hover .rating-item { color: var(--color-success); }
192
+ .rating-error:not(.rating-readonly):not(.rating-native):hover .rating-item { color: var(--color-error); }
193
+ .rating-accent:not(.rating-readonly):not(.rating-native):hover .rating-item { color: var(--color-accent); }
194
+ .rating-neutral:not(.rating-readonly):not(.rating-native):hover .rating-item { color: var(--color-neutral); }
195
+ .rating-base:not(.rating-readonly):not(.rating-native):hover .rating-item { color: var(--color-base-content); }
196
196
 
197
197
  /* Focus Visible — use warning (the default fill color) for the base ring;
198
198
  per-variant overrides below match the active fill color for each variant. */
@@ -267,7 +267,34 @@ export const css = `/**
267
267
  }
268
268
  }
269
269
 
270
- /* Reduce Motion */
270
+ /* Native radio pattern: selection is authoritative, not .filled/.active. */
271
+ .rating-native { --rating-color: var(--color-warning); flex-wrap: wrap; max-inline-size: 100%; }
272
+ .rating-native.rating-primary { --rating-color: var(--color-primary); }
273
+ .rating-native.rating-secondary { --rating-color: var(--color-secondary); }
274
+ .rating-native.rating-tertiary { --rating-color: var(--color-tertiary); }
275
+ .rating-native.rating-info { --rating-color: var(--color-info); }
276
+ .rating-native.rating-success { --rating-color: var(--color-success); }
277
+ .rating-native.rating-warning { --rating-color: var(--color-warning); }
278
+ .rating-native.rating-error { --rating-color: var(--color-error); }
279
+ .rating-native .rating-item { position: relative; padding: 0.25rem; }
280
+ .rating-native .rating-input {
281
+ inset: 0;
282
+ width: 100%;
283
+ height: 100%;
284
+ margin: 0;
285
+ cursor: inherit;
286
+ }
287
+ .rating-native .rating-item:is(.filled, .active, :hover),
288
+ .rating-native .rating-item { color: var(--color-outline); transform: none; }
289
+ .rating-native .rating-item:has(.rating-input:checked),
290
+ .rating-native .rating-item:not(.rating-none):has(~ .rating-item .rating-input:checked) { color: var(--rating-color); }
291
+ .rating-native .rating-item:has(.rating-input:focus-visible) { outline: 2px solid currentColor; outline-offset: 2px; border-radius: var(--radius-xs); }
292
+ .rating-native .rating-item:has(.rating-input:disabled) { opacity: 0.38; cursor: not-allowed; }
293
+ .rating-native .rating-none { color: var(--color-on-surface); font-size: 0.875rem; }
294
+ @media (forced-colors: active) {
295
+ .rating-native .rating-item:has(.rating-input:checked) { outline: 2px solid Highlight; }
296
+ }
297
+
271
298
  @media (prefers-reduced-motion: reduce) {
272
299
  .rating-item,
273
300
  .rating-animated .rating-item {