@duskmoon-dev/core 1.19.3 → 1.19.5

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 (121) 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/alert.css +81 -3
  5. package/dist/components/autocomplete.css +67 -13
  6. package/dist/components/avatar.css +39 -15
  7. package/dist/components/badge.css +15 -3
  8. package/dist/components/card.css +12 -0
  9. package/dist/components/carousel.css +28 -0
  10. package/dist/components/chat.css +15 -11
  11. package/dist/components/checkbox.css +83 -13
  12. package/dist/components/collapse.css +67 -16
  13. package/dist/components/countdown.css +22 -0
  14. package/dist/components/datepicker.css +76 -0
  15. package/dist/components/diff.css +33 -0
  16. package/dist/components/file-input.css +107 -0
  17. package/dist/components/filter-group.css +452 -0
  18. package/dist/components/form-group.css +95 -204
  19. package/dist/components/form.css +1551 -421
  20. package/dist/components/index.css +6248 -5799
  21. package/dist/components/input.css +114 -31
  22. package/dist/components/kbd.css +28 -0
  23. package/dist/components/list.css +22 -3
  24. package/dist/components/loading.css +105 -0
  25. package/dist/components/modal.css +62 -1
  26. package/dist/components/otp-input.css +124 -6
  27. package/dist/components/progress.css +74 -0
  28. package/dist/components/radial-progress.css +47 -0
  29. package/dist/components/radio.css +70 -0
  30. package/dist/components/range.css +41 -0
  31. package/dist/components/rating.css +39 -12
  32. package/dist/components/select.css +74 -0
  33. package/dist/components/skeleton.css +13 -1
  34. package/dist/components/snackbar.css +48 -18
  35. package/dist/components/stat.css +40 -0
  36. package/dist/components/switch.css +70 -0
  37. package/dist/components/table.css +8 -0
  38. package/dist/components/textarea.css +74 -0
  39. package/dist/components/timeline.css +40 -25
  40. package/dist/components/toast.css +188 -34
  41. package/dist/components/toggle-switch.css +165 -0
  42. package/dist/components/toggle.css +198 -32
  43. package/dist/components/tooltip.css +2 -47
  44. package/dist/components/validator.css +66 -0
  45. package/dist/effects/aura.css +22 -0
  46. package/dist/effects/hover-3d.css +8 -0
  47. package/dist/effects/hover-gallery.css +14 -0
  48. package/dist/effects/index.css +65 -0
  49. package/dist/effects/text-rotate.css +16 -0
  50. package/dist/esm/components/accordion.js +33 -9
  51. package/dist/esm/components/alert.js +81 -3
  52. package/dist/esm/components/autocomplete.js +67 -13
  53. package/dist/esm/components/avatar.js +39 -15
  54. package/dist/esm/components/badge.js +15 -3
  55. package/dist/esm/components/card.js +12 -0
  56. package/dist/esm/components/carousel.d.ts +5 -0
  57. package/dist/esm/components/carousel.js +37 -0
  58. package/dist/esm/components/chat.js +15 -11
  59. package/dist/esm/components/checkbox.js +84 -14
  60. package/dist/esm/components/collapse.js +67 -16
  61. package/dist/esm/components/countdown.d.ts +5 -0
  62. package/dist/esm/components/countdown.js +31 -0
  63. package/dist/esm/components/datepicker.js +77 -1
  64. package/dist/esm/components/diff.d.ts +5 -0
  65. package/dist/esm/components/diff.js +42 -0
  66. package/dist/esm/components/file-input.d.ts +5 -0
  67. package/dist/esm/components/file-input.js +116 -0
  68. package/dist/esm/components/filter-group.d.ts +5 -0
  69. package/dist/esm/components/filter-group.js +461 -0
  70. package/dist/esm/components/form-group.js +96 -205
  71. package/dist/esm/components/form.js +1539 -409
  72. package/dist/esm/components/input.js +115 -32
  73. package/dist/esm/components/kbd.d.ts +5 -0
  74. package/dist/esm/components/kbd.js +37 -0
  75. package/dist/esm/components/list.js +22 -3
  76. package/dist/esm/components/loading.d.ts +5 -0
  77. package/dist/esm/components/loading.js +114 -0
  78. package/dist/esm/components/modal.js +62 -1
  79. package/dist/esm/components/otp-input.js +125 -7
  80. package/dist/esm/components/progress.js +74 -0
  81. package/dist/esm/components/radial-progress.d.ts +5 -0
  82. package/dist/esm/components/radial-progress.js +56 -0
  83. package/dist/esm/components/radio.js +71 -1
  84. package/dist/esm/components/range.d.ts +5 -0
  85. package/dist/esm/components/range.js +50 -0
  86. package/dist/esm/components/rating.js +39 -12
  87. package/dist/esm/components/select.js +75 -1
  88. package/dist/esm/components/skeleton.js +13 -1
  89. package/dist/esm/components/snackbar.js +48 -18
  90. package/dist/esm/components/stat.d.ts +5 -0
  91. package/dist/esm/components/stat.js +49 -0
  92. package/dist/esm/components/switch.js +71 -1
  93. package/dist/esm/components/table.js +8 -0
  94. package/dist/esm/components/textarea.js +75 -1
  95. package/dist/esm/components/timeline.js +40 -25
  96. package/dist/esm/components/toast.js +188 -34
  97. package/dist/esm/components/toggle-switch.d.ts +5 -0
  98. package/dist/esm/components/toggle-switch.js +174 -0
  99. package/dist/esm/components/toggle.js +198 -32
  100. package/dist/esm/components/tooltip.js +2 -47
  101. package/dist/esm/components/validator.d.ts +5 -0
  102. package/dist/esm/components/validator.js +75 -0
  103. package/dist/esm/effects/aura.d.ts +5 -0
  104. package/dist/esm/effects/aura.js +31 -0
  105. package/dist/esm/effects/hover-3d.d.ts +5 -0
  106. package/dist/esm/effects/hover-3d.js +17 -0
  107. package/dist/esm/effects/hover-gallery.d.ts +5 -0
  108. package/dist/esm/effects/hover-gallery.js +23 -0
  109. package/dist/esm/effects/index.d.ts +5 -0
  110. package/dist/esm/effects/index.js +74 -0
  111. package/dist/esm/effects/text-rotate.d.ts +5 -0
  112. package/dist/esm/effects/text-rotate.js +25 -0
  113. package/dist/index.css +7652 -7204
  114. package/dist/index.min.css +1 -1
  115. package/dist/standalone/duskmoonui-themes.css +1 -1
  116. package/dist/standalone/duskmoonui.css +7598 -7141
  117. package/dist/standalone/duskmoonui.js +18 -16
  118. package/dist/standalone/duskmoonui.mjs +18 -16
  119. package/dist/types/types/plugin.d.ts +1 -1
  120. package/dist/types/types/plugin.d.ts.map +1 -1
  121. package/package.json +110 -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 */
@@ -0,0 +1,5 @@
1
+ // Auto-generated type declaration for loading
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,114 @@
1
+ // Auto-generated from loading.css
2
+ export const css = `/**
3
+ * Loading Component Styles
4
+ * CSS-only activity indicators. State, aria-busy, and disabling remain consumer-owned.
5
+ */
6
+
7
+ @layer components {
8
+ .loading {
9
+ --loading-size: 1.25rem;
10
+ display: inline-flex;
11
+ width: var(--loading-size);
12
+ height: var(--loading-size);
13
+ flex: 0 0 var(--loading-size);
14
+ color: currentColor;
15
+ vertical-align: middle;
16
+ }
17
+
18
+ .loading-spinner {
19
+ border: max(2px, calc(var(--loading-size) / 8)) solid color-mix(in oklch, currentColor 25%, transparent);
20
+ border-top-color: currentColor;
21
+ border-radius: var(--radius-full);
22
+ animation: loading-spin 800ms linear infinite;
23
+ }
24
+
25
+ .loading-dots,
26
+ .loading-bars {
27
+ align-items: center;
28
+ justify-content: center;
29
+ gap: max(2px, calc(var(--loading-size) / 8));
30
+ }
31
+
32
+ .loading-dots::before,
33
+ .loading-dots::after,
34
+ .loading-bars::before,
35
+ .loading-bars::after {
36
+ content: "";
37
+ display: block;
38
+ background: currentColor;
39
+ }
40
+
41
+ .loading-dots::before,
42
+ .loading-dots::after {
43
+ width: 25%;
44
+ height: 25%;
45
+ border-radius: var(--radius-full);
46
+ box-shadow: calc(var(--loading-size) / 3) 0 currentColor;
47
+ animation: loading-dots 900ms ease-in-out infinite;
48
+ }
49
+
50
+ .loading-dots::after {
51
+ display: none;
52
+ }
53
+
54
+ .loading-bars {
55
+ padding-inline: 10%;
56
+ }
57
+
58
+ .loading-bars::before,
59
+ .loading-bars::after {
60
+ width: 18%;
61
+ height: 65%;
62
+ border-radius: var(--radius-xs);
63
+ box-shadow: calc(var(--loading-size) / 3) 0 currentColor, calc(var(--loading-size) * 2 / 3) 0 currentColor;
64
+ animation: loading-bars 900ms ease-in-out infinite;
65
+ }
66
+
67
+ .loading-bars::after {
68
+ display: none;
69
+ }
70
+
71
+ .loading-xs { --loading-size: 0.75rem; }
72
+ .loading-sm { --loading-size: 1rem; }
73
+ .loading-md { --loading-size: 1.25rem; }
74
+ .loading-lg { --loading-size: 1.75rem; }
75
+ .loading-xl { --loading-size: 2.5rem; }
76
+
77
+ .loading-primary { color: var(--color-primary); }
78
+ .loading-secondary { color: var(--color-secondary); }
79
+ .loading-tertiary { color: var(--color-tertiary); }
80
+ .loading-info { color: var(--color-info); }
81
+ .loading-success { color: var(--color-success); }
82
+ .loading-warning { color: var(--color-warning); }
83
+ .loading-error { color: var(--color-error); }
84
+
85
+ @keyframes loading-spin {
86
+ to { transform: rotate(360deg); }
87
+ }
88
+
89
+ @keyframes loading-dots {
90
+ 0%, 100% { opacity: 0.35; transform: scale(0.75); }
91
+ 50% { opacity: 1; transform: scale(1); }
92
+ }
93
+
94
+ @keyframes loading-bars {
95
+ 0%, 100% { opacity: 0.35; transform: scaleY(0.65); }
96
+ 50% { opacity: 1; transform: scaleY(1); }
97
+ }
98
+
99
+ @media (prefers-reduced-motion: reduce) {
100
+ .loading-spinner,
101
+ .loading-dots::before,
102
+ .loading-bars::before {
103
+ animation: none;
104
+ }
105
+ }
106
+ }
107
+ `;
108
+
109
+ const sheet = typeof CSSStyleSheet !== 'undefined' ? new CSSStyleSheet() : null;
110
+ if (sheet) {
111
+ sheet.replaceSync(css);
112
+ }
113
+ export const styles = sheet;
114
+ export default sheet;
@@ -63,7 +63,8 @@ export const css = `/**
63
63
  }
64
64
 
65
65
  /* Modal Action */
66
- .modal-action {
66
+ .modal-action,
67
+ .modal-footer {
67
68
  display: flex;
68
69
  justify-content: flex-end;
69
70
  gap: 0.5rem;
@@ -94,10 +95,18 @@ export const css = `/**
94
95
  max-width: 20rem;
95
96
  }
96
97
 
98
+ .modal-md .modal-box {
99
+ max-width: 32rem;
100
+ }
101
+
97
102
  .modal-lg .modal-box {
98
103
  max-width: 48rem;
99
104
  }
100
105
 
106
+ .modal-xl .modal-box {
107
+ max-width: 64rem;
108
+ }
109
+
101
110
  .modal-full .modal-box {
102
111
  max-width: calc(100vw - 2rem);
103
112
  max-height: calc(100vh - 2rem);
@@ -120,6 +129,38 @@ export const css = `/**
120
129
  align-items: center;
121
130
  }
122
131
 
132
+ /* Animation Variants */
133
+ .modal-slide-up .modal-box {
134
+ transform: translateY(6rem) scale(0.95);
135
+ }
136
+
137
+ .modal-slide-down .modal-box {
138
+ transform: translateY(-6rem) scale(0.95);
139
+ }
140
+
141
+ .modal-zoom .modal-box {
142
+ transform: scale(0.75);
143
+ }
144
+
145
+ :is(.modal-slide-up, .modal-slide-down, .modal-zoom).modal-open .modal-box,
146
+ :is(.modal-slide-up, .modal-slide-down, .modal-zoom):target .modal-box {
147
+ transform: translateY(0) scale(1);
148
+ }
149
+
150
+ /* Backdrop Variants */
151
+ .modal-backdrop-light {
152
+ background-color: color-mix(in srgb, white 80%, transparent);
153
+ }
154
+
155
+ .modal-backdrop-blur {
156
+ background-color: color-mix(in srgb, var(--color-scrim) 30%, transparent);
157
+ backdrop-filter: blur(8px);
158
+ }
159
+
160
+ .modal-no-backdrop {
161
+ background-color: transparent;
162
+ }
163
+
123
164
  /* Modal Close Button */
124
165
  .modal-close {
125
166
  position: absolute;
@@ -168,6 +209,22 @@ export const css = `/**
168
209
  line-height: 1.5;
169
210
  }
170
211
 
212
+ .modal-scrollable .modal-body {
213
+ max-height: 60vh;
214
+ overflow-y: auto;
215
+ }
216
+
217
+ .modal-no-padding .modal-body {
218
+ padding: 0;
219
+ }
220
+
221
+ .modal-centered .modal-body {
222
+ display: flex;
223
+ align-items: center;
224
+ justify-content: center;
225
+ text-align: center;
226
+ }
227
+
171
228
  /* Responsive Modal */
172
229
  @media (max-width: 640px) {
173
230
  .modal-box {
@@ -289,6 +346,10 @@ export const css = `/**
289
346
  white-space: nowrap;
290
347
  border: 0;
291
348
  }
349
+
350
+ body.modal-open {
351
+ overflow: hidden;
352
+ }
292
353
  }
293
354
  `;
294
355
 
@@ -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;