@datametria/vue-components 1.2.0 → 2.1.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 (103) hide show
  1. package/README.md +554 -657
  2. package/dist/index.es.js +2570 -1433
  3. package/dist/index.umd.js +10 -10
  4. package/dist/vue-components.css +1 -1
  5. package/package.json +102 -98
  6. package/src/components/DatametriaAlert.vue +137 -137
  7. package/src/components/DatametriaAutocomplete.vue +184 -138
  8. package/src/components/DatametriaAvatar.vue +177 -33
  9. package/src/components/DatametriaBadge.vue +98 -98
  10. package/src/components/DatametriaBreadcrumb.vue +21 -21
  11. package/src/components/DatametriaButton.vue +177 -165
  12. package/src/components/DatametriaCard.vue +12 -12
  13. package/src/components/DatametriaCheckbox.vue +8 -8
  14. package/src/components/DatametriaChip.vue +145 -149
  15. package/src/components/DatametriaContainer.vue +4 -4
  16. package/src/components/DatametriaDatePicker.vue +686 -68
  17. package/src/components/DatametriaDivider.vue +13 -13
  18. package/src/components/DatametriaFileUpload.vue +272 -140
  19. package/src/components/DatametriaFloatingBar.vue +126 -0
  20. package/src/components/DatametriaGrid.vue +3 -3
  21. package/src/components/DatametriaInput.vue +15 -15
  22. package/src/components/DatametriaMenu.vue +604 -619
  23. package/src/components/DatametriaModal.vue +16 -16
  24. package/src/components/DatametriaNavbar.vue +230 -252
  25. package/src/components/DatametriaPasswordInput.vue +430 -0
  26. package/src/components/DatametriaProgress.vue +18 -18
  27. package/src/components/DatametriaRadio.vue +20 -20
  28. package/src/components/DatametriaSelect.vue +15 -15
  29. package/src/components/DatametriaSidebar.vue +230 -0
  30. package/src/components/DatametriaSkeleton.vue +243 -239
  31. package/src/components/DatametriaSlider.vue +395 -407
  32. package/src/components/DatametriaSortableTable.vue +585 -0
  33. package/src/components/DatametriaSpinner.vue +7 -7
  34. package/src/components/DatametriaSwitch.vue +16 -16
  35. package/src/components/DatametriaTable.vue +14 -14
  36. package/src/components/DatametriaTabs.vue +150 -29
  37. package/src/components/DatametriaTextarea.vue +28 -28
  38. package/src/components/DatametriaTimePicker.vue +285 -285
  39. package/src/components/DatametriaToast.vue +176 -176
  40. package/src/components/DatametriaTooltip.vue +408 -408
  41. package/src/components/__tests__/DatametriaAlert.test.js +35 -35
  42. package/src/components/__tests__/DatametriaAlert.test.ts +190 -0
  43. package/src/components/__tests__/DatametriaAutocomplete.test.ts +180 -0
  44. package/src/components/__tests__/DatametriaAvatar.test.ts +152 -0
  45. package/src/components/__tests__/DatametriaBadge.test.js +29 -29
  46. package/src/components/__tests__/DatametriaBadge.test.ts +167 -0
  47. package/src/components/__tests__/DatametriaBreadcrumb.test.ts +75 -0
  48. package/src/components/__tests__/DatametriaButton.test.js +30 -30
  49. package/src/components/__tests__/DatametriaButton.test.ts +283 -0
  50. package/src/components/__tests__/DatametriaCard.test.ts +201 -0
  51. package/src/components/__tests__/DatametriaCheckbox.test.ts +47 -0
  52. package/src/components/__tests__/DatametriaChip.test.js +38 -38
  53. package/src/components/__tests__/DatametriaContainer.test.ts +52 -0
  54. package/src/components/__tests__/DatametriaDatePicker.test.ts +234 -0
  55. package/src/components/__tests__/DatametriaDivider.test.ts +54 -0
  56. package/src/components/__tests__/DatametriaFileUpload.test.ts +291 -0
  57. package/src/components/__tests__/DatametriaFloatingBar.test.ts +137 -0
  58. package/src/components/__tests__/DatametriaGrid.test.ts +31 -0
  59. package/src/components/__tests__/DatametriaInput.test.ts +72 -0
  60. package/src/components/__tests__/DatametriaMenu.test.ts +366 -0
  61. package/src/components/__tests__/DatametriaModal.test.ts +86 -0
  62. package/src/components/__tests__/DatametriaNavbar.test.js +48 -48
  63. package/src/components/__tests__/DatametriaNavbar.test.ts +203 -0
  64. package/src/components/__tests__/DatametriaPasswordInput.test.js +305 -0
  65. package/src/components/__tests__/DatametriaProgress.test.ts +90 -0
  66. package/src/components/__tests__/DatametriaRadio.test.ts +77 -0
  67. package/src/components/__tests__/DatametriaSelect.test.ts +77 -0
  68. package/src/components/__tests__/DatametriaSidebar.test.ts +169 -0
  69. package/src/components/__tests__/DatametriaSlider.test.ts +261 -0
  70. package/src/components/__tests__/DatametriaSortableTable.test.js +168 -0
  71. package/src/components/__tests__/DatametriaSpinner.test.ts +156 -0
  72. package/src/components/__tests__/DatametriaSwitch.test.ts +64 -0
  73. package/src/components/__tests__/DatametriaTable.test.ts +97 -0
  74. package/src/components/__tests__/DatametriaTabs.test.ts +232 -0
  75. package/src/components/__tests__/DatametriaTextarea.test.ts +66 -0
  76. package/src/components/__tests__/DatametriaToast.test.js +48 -48
  77. package/src/components/__tests__/DatametriaToast.test.ts +99 -0
  78. package/src/composables/useAccessibilityScale.ts +94 -94
  79. package/src/composables/useBreakpoints.ts +82 -82
  80. package/src/composables/useHapticFeedback.ts +439 -439
  81. package/src/composables/useRipple.ts +218 -218
  82. package/src/index.ts +70 -61
  83. package/src/stories/Variants.stories.js +95 -95
  84. package/src/styles/design-tokens.css +623 -623
  85. package/src/theme/ThemeProvider.vue +96 -0
  86. package/src/theme/__tests__/ThemeProvider.test.ts +208 -0
  87. package/src/theme/__tests__/constants.test.ts +31 -0
  88. package/src/theme/__tests__/presets.test.ts +166 -0
  89. package/src/theme/__tests__/tokens.test.ts +155 -0
  90. package/src/theme/__tests__/types.test.ts +153 -0
  91. package/src/theme/__tests__/useTheme.test.ts +146 -0
  92. package/src/theme/constants.ts +14 -0
  93. package/src/theme/index.ts +12 -0
  94. package/src/theme/presets/datametria.ts +94 -0
  95. package/src/theme/presets/default.ts +94 -0
  96. package/src/theme/presets/index.ts +8 -0
  97. package/src/theme/tokens/colors.ts +28 -0
  98. package/src/theme/tokens/index.ts +47 -0
  99. package/src/theme/tokens/spacing.ts +21 -0
  100. package/src/theme/tokens/typography.ts +35 -0
  101. package/src/theme/types.ts +111 -0
  102. package/src/theme/useTheme.ts +28 -0
  103. package/src/types/index.ts +19 -0
@@ -49,16 +49,16 @@ const handleChange = (event: Event) => {
49
49
  .dm-switch {
50
50
  display: flex;
51
51
  flex-direction: column;
52
- gap: var(--dm-space-1);
52
+ gap: var(--dm-spacing-1, 0.25rem);
53
53
  }
54
54
 
55
55
  .dm-switch__label {
56
56
  display: inline-flex;
57
57
  align-items: center;
58
- gap: var(--dm-space-3);
58
+ gap: var(--dm-spacing-3, 0.75rem);
59
59
  cursor: pointer;
60
60
  min-height: 44px;
61
- padding: var(--dm-space-2);
61
+ padding: var(--dm-spacing-2, 0.5rem);
62
62
  user-select: none;
63
63
  }
64
64
 
@@ -78,9 +78,9 @@ const handleChange = (event: Event) => {
78
78
  position: relative;
79
79
  width: 44px;
80
80
  height: 24px;
81
- background: var(--dm-gray-300);
81
+ background: var(--dm-neutral-300, #d1d5db);
82
82
  border-radius: 12px;
83
- transition: var(--dm-transition);
83
+ transition: all 0.2s;
84
84
  flex-shrink: 0;
85
85
  }
86
86
 
@@ -90,14 +90,14 @@ const handleChange = (event: Event) => {
90
90
  left: 2px;
91
91
  width: 20px;
92
92
  height: 20px;
93
- background: var(--dm-white);
93
+ background: white;
94
94
  border-radius: 50%;
95
- transition: var(--dm-transition);
95
+ transition: all 0.2s;
96
96
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
97
97
  }
98
98
 
99
99
  .dm-switch__input:checked + .dm-switch__track {
100
- background: var(--dm-primary);
100
+ background: var(--dm-primary, #0072CE);
101
101
  }
102
102
 
103
103
  .dm-switch__input:checked + .dm-switch__track .dm-switch__thumb {
@@ -105,33 +105,33 @@ const handleChange = (event: Event) => {
105
105
  }
106
106
 
107
107
  .dm-switch__input:focus-visible + .dm-switch__track {
108
- outline: var(--dm-focus-ring);
108
+ outline: 2px solid var(--dm-primary, #0072CE);
109
109
  outline-offset: 2px;
110
110
  }
111
111
 
112
112
  .dm-switch__input:disabled + .dm-switch__track {
113
- background: var(--dm-gray-200);
113
+ background: var(--dm-neutral-200, #e5e7eb);
114
114
  }
115
115
 
116
116
  .dm-switch__text {
117
- color: var(--dm-text-primary);
118
- font-size: var(--dm-text-base);
117
+ color: var(--dm-neutral-900, #111827);
118
+ font-size: var(--dm-font-size-base, 1rem);
119
119
  line-height: 1.5;
120
120
  }
121
121
 
122
122
  .dm-switch__error {
123
- color: var(--dm-error);
124
- font-size: var(--dm-text-sm);
123
+ color: var(--dm-error, #ef4444);
124
+ font-size: var(--dm-font-size-sm, 0.875rem);
125
125
  margin: 0;
126
126
  }
127
127
 
128
128
  @media (prefers-color-scheme: dark) {
129
129
  .dm-switch__track {
130
- background: var(--dm-gray-700);
130
+ background: var(--dm-neutral-700, #374151);
131
131
  }
132
132
 
133
133
  .dm-switch__input:disabled + .dm-switch__track {
134
- background: var(--dm-gray-800);
134
+ background: var(--dm-neutral-800, #1f2937);
135
135
  }
136
136
  }
137
137
  </style>
@@ -65,16 +65,16 @@ defineProps<Props>()
65
65
  }
66
66
 
67
67
  .datametria-table__thead {
68
- background: #f9fafb;
69
- border-bottom: 2px solid #e5e7eb;
68
+ background: var(--dm-neutral-50, #f9fafb);
69
+ border-bottom: 2px solid var(--dm-neutral-200, #e5e7eb);
70
70
  }
71
71
 
72
72
  .datametria-table__th {
73
- padding: 0.75rem 1rem;
73
+ padding: var(--dm-spacing-3, 0.75rem) var(--dm-spacing-4, 1rem);
74
74
  text-align: left;
75
- font-size: 0.875rem;
76
- font-weight: 600;
77
- color: #374151;
75
+ font-size: var(--dm-font-size-sm, 0.875rem);
76
+ font-weight: var(--dm-font-weight-semibold, 600);
77
+ color: var(--dm-neutral-700, #374151);
78
78
  }
79
79
 
80
80
  .datametria-table__tbody {
@@ -82,24 +82,24 @@ defineProps<Props>()
82
82
  }
83
83
 
84
84
  .datametria-table__tr {
85
- border-bottom: 1px solid #e5e7eb;
85
+ border-bottom: 1px solid var(--dm-neutral-200, #e5e7eb);
86
86
  transition: background 0.2s;
87
87
  }
88
88
 
89
89
  .datametria-table__tr:hover {
90
- background: #f9fafb;
90
+ background: var(--dm-neutral-50, #f9fafb);
91
91
  }
92
92
 
93
93
  .datametria-table__td {
94
- padding: 0.75rem 1rem;
95
- font-size: 0.875rem;
96
- color: #111827;
94
+ padding: var(--dm-spacing-3, 0.75rem) var(--dm-spacing-4, 1rem);
95
+ font-size: var(--dm-font-size-sm, 0.875rem);
96
+ color: var(--dm-neutral-900, #111827);
97
97
  }
98
98
 
99
99
  .datametria-table__empty {
100
- padding: 3rem;
100
+ padding: var(--dm-spacing-12, 3rem);
101
101
  text-align: center;
102
- color: #6b7280;
103
- font-size: 0.875rem;
102
+ color: var(--dm-neutral-500, #6b7280);
103
+ font-size: var(--dm-font-size-sm, 0.875rem);
104
104
  }
105
105
  </style>
@@ -1,24 +1,29 @@
1
1
  <template>
2
- <div class="dm-tabs">
3
- <div class="dm-tabs__header" role="tablist" :aria-label="ariaLabel">
2
+ <div :class="tabsClasses">
3
+ <div class="dm-tabs__header" role="tablist" :aria-label="ariaLabel" :aria-orientation="orientation">
4
4
  <button
5
5
  v-for="(tab, index) in tabs"
6
6
  :key="index"
7
7
  :id="`tab-${index}`"
8
8
  class="dm-tabs__tab"
9
- :class="{ 'dm-tabs__tab--active': activeTab === index }"
9
+ :class="{ 'dm-tabs__tab--active': activeTab === index, 'dm-tabs__tab--disabled': typeof tab === 'object' && 'disabled' in tab && tab.disabled }"
10
10
  role="tab"
11
11
  :aria-selected="activeTab === index"
12
12
  :aria-controls="`panel-${index}`"
13
+ :aria-disabled="typeof tab === 'object' && 'disabled' in tab ? tab.disabled : false"
13
14
  :tabindex="activeTab === index ? 0 : -1"
15
+ :disabled="typeof tab === 'object' && 'disabled' in tab ? tab.disabled : false"
14
16
  @click="selectTab(index)"
15
17
  @keydown="handleKeydown($event, index)"
16
18
  >
17
- {{ tab }}
19
+ <span v-if="typeof tab === 'object' && 'icon' in tab && tab.icon" class="dm-tabs__icon">{{ tab.icon }}</span>
20
+ <span class="dm-tabs__label">{{ typeof tab === 'string' ? tab : tab.label }}</span>
21
+ <span v-if="typeof tab === 'object' && 'badge' in tab && tab.badge" class="dm-tabs__badge">{{ tab.badge }}</span>
18
22
  </button>
19
23
  <div
24
+ v-if="showIndicator"
20
25
  class="dm-tabs__indicator"
21
- :style="{ transform: `translateX(${activeTab * 100}%)` }"
26
+ :style="indicatorStyle"
22
27
  ></div>
23
28
  </div>
24
29
  <div class="dm-tabs__panels">
@@ -39,21 +44,35 @@
39
44
  </template>
40
45
 
41
46
  <script setup lang="ts">
42
- import { ref, watch } from 'vue'
47
+ import { ref, watch, computed } from 'vue'
48
+
49
+ interface Tab {
50
+ label: string
51
+ icon?: string
52
+ badge?: string | number
53
+ disabled?: boolean
54
+ }
43
55
 
44
56
  interface Props {
45
- tabs: string[]
57
+ tabs: (string | Tab)[]
46
58
  modelValue?: number
59
+ variant?: 'default' | 'pills' | 'underline'
60
+ orientation?: 'horizontal' | 'vertical'
61
+ showIndicator?: boolean
47
62
  ariaLabel?: string
48
63
  }
49
64
 
50
65
  const props = withDefaults(defineProps<Props>(), {
51
66
  modelValue: 0,
67
+ variant: 'default',
68
+ orientation: 'horizontal',
69
+ showIndicator: true,
52
70
  ariaLabel: 'Tabs'
53
71
  })
54
72
 
55
73
  const emit = defineEmits<{
56
74
  'update:modelValue': [index: number]
75
+ change: [index: number]
57
76
  }>()
58
77
 
59
78
  const activeTab = ref(props.modelValue)
@@ -62,20 +81,59 @@ watch(() => props.modelValue, (newValue) => {
62
81
  activeTab.value = newValue
63
82
  })
64
83
 
84
+ const tabsClasses = computed(() => [
85
+ 'dm-tabs',
86
+ `dm-tabs--${props.variant}`,
87
+ `dm-tabs--${props.orientation}`
88
+ ])
89
+
90
+ const indicatorStyle = computed(() => {
91
+ const count = props.tabs.length
92
+ const position = props.orientation === 'horizontal'
93
+ ? `translateX(${activeTab.value * 100}%)`
94
+ : `translateY(${activeTab.value * 100}%)`
95
+
96
+ return {
97
+ transform: position,
98
+ width: props.orientation === 'horizontal' ? `${100 / count}%` : '100%',
99
+ height: props.orientation === 'vertical' ? `${100 / count}%` : '2px'
100
+ }
101
+ })
102
+
65
103
  const selectTab = (index: number) => {
104
+ const tab = props.tabs[index]
105
+ const isDisabled = typeof tab === 'object' && 'disabled' in tab && tab.disabled
106
+
107
+ if (isDisabled) return
108
+
66
109
  activeTab.value = index
67
110
  emit('update:modelValue', index)
111
+ emit('change', index)
68
112
  }
69
113
 
70
114
  const handleKeydown = (event: KeyboardEvent, index: number) => {
71
115
  let newIndex = index
72
116
 
117
+ const isHorizontal = props.orientation === 'horizontal'
118
+
73
119
  switch (event.key) {
74
120
  case 'ArrowLeft':
121
+ if (!isHorizontal) return
75
122
  event.preventDefault()
76
123
  newIndex = index > 0 ? index - 1 : props.tabs.length - 1
77
124
  break
78
125
  case 'ArrowRight':
126
+ if (!isHorizontal) return
127
+ event.preventDefault()
128
+ newIndex = index < props.tabs.length - 1 ? index + 1 : 0
129
+ break
130
+ case 'ArrowUp':
131
+ if (isHorizontal) return
132
+ event.preventDefault()
133
+ newIndex = index > 0 ? index - 1 : props.tabs.length - 1
134
+ break
135
+ case 'ArrowDown':
136
+ if (isHorizontal) return
79
137
  event.preventDefault()
80
138
  newIndex = index < props.tabs.length - 1 ? index + 1 : 0
81
139
  break
@@ -102,10 +160,24 @@ const handleKeydown = (event: KeyboardEvent, index: number) => {
102
160
  flex-direction: column;
103
161
  }
104
162
 
163
+ .dm-tabs--vertical {
164
+ flex-direction: row;
165
+ }
166
+
167
+ .dm-tabs--vertical .dm-tabs__header {
168
+ flex-direction: column;
169
+ border-bottom: none;
170
+ border-right: 2px solid var(--dm-neutral-200, #e5e7eb);
171
+ }
172
+
173
+ .dm-tabs--vertical .dm-tabs__tab {
174
+ text-align: left;
175
+ }
176
+
105
177
  .dm-tabs__header {
106
178
  display: flex;
107
179
  position: relative;
108
- border-bottom: 2px solid var(--dm-gray-200);
180
+ border-bottom: 2px solid var(--dm-neutral-200, #e5e7eb);
109
181
  overflow-x: auto;
110
182
  scrollbar-width: none;
111
183
  }
@@ -117,43 +189,95 @@ const handleKeydown = (event: KeyboardEvent, index: number) => {
117
189
  .dm-tabs__tab {
118
190
  flex: 1;
119
191
  min-width: max-content;
120
- padding: var(--dm-space-3) var(--dm-space-4);
192
+ padding: var(--dm-spacing-3, 0.75rem) var(--dm-spacing-4, 1rem);
121
193
  border: none;
122
194
  background: transparent;
123
- color: var(--dm-text-secondary);
124
- font-size: var(--dm-text-base);
195
+ color: var(--dm-neutral-600, #6b7280);
196
+ font-size: 1rem;
125
197
  font-weight: 500;
126
198
  cursor: pointer;
127
- transition: var(--dm-transition);
199
+ transition: all 0.2s ease;
128
200
  position: relative;
129
201
  white-space: nowrap;
202
+ display: flex;
203
+ align-items: center;
204
+ gap: var(--dm-spacing-2, 0.5rem);
130
205
  }
131
206
 
132
- .dm-tabs__tab:hover {
133
- color: var(--dm-text-primary);
207
+ .dm-tabs__tab--disabled {
208
+ opacity: 0.5;
209
+ cursor: not-allowed;
210
+ }
211
+
212
+ .dm-tabs__icon {
213
+ font-size: 1.25rem;
214
+ }
215
+
216
+ .dm-tabs__badge {
217
+ display: inline-flex;
218
+ align-items: center;
219
+ justify-content: center;
220
+ min-width: 20px;
221
+ height: 20px;
222
+ padding: 0 6px;
223
+ background: var(--dm-primary, #0072CE);
224
+ color: white;
225
+ font-size: 0.75rem;
226
+ font-weight: 600;
227
+ border-radius: 10px;
228
+ }
229
+
230
+ .dm-tabs__tab:hover:not(:disabled) {
231
+ color: var(--dm-neutral-900, #111827);
134
232
  }
135
233
 
136
234
  .dm-tabs__tab:focus-visible {
137
- outline: var(--dm-focus-ring);
235
+ outline: 2px solid var(--dm-primary, #0072CE);
138
236
  outline-offset: -2px;
237
+ border-radius: 4px;
139
238
  }
140
239
 
141
240
  .dm-tabs__tab--active {
142
- color: var(--dm-primary);
241
+ color: var(--dm-primary, #0072CE);
143
242
  }
144
243
 
145
244
  .dm-tabs__indicator {
146
245
  position: absolute;
147
246
  bottom: -2px;
148
247
  left: 0;
149
- width: calc(100% / var(--tab-count, 1));
150
- height: 2px;
151
- background: var(--dm-primary);
248
+ background: var(--dm-primary, #0072CE);
152
249
  transition: transform 0.3s ease;
153
250
  }
154
251
 
252
+ .dm-tabs--vertical .dm-tabs__indicator {
253
+ bottom: auto;
254
+ left: auto;
255
+ right: -2px;
256
+ top: 0;
257
+ width: 2px;
258
+ }
259
+
260
+ .dm-tabs--pills .dm-tabs__header {
261
+ border-bottom: none;
262
+ gap: var(--dm-spacing-2, 0.5rem);
263
+ }
264
+
265
+ .dm-tabs--pills .dm-tabs__tab {
266
+ border-radius: var(--dm-radius-md, 0.375rem);
267
+ }
268
+
269
+ .dm-tabs--pills .dm-tabs__tab--active {
270
+ background: var(--dm-primary, #0072CE);
271
+ color: white;
272
+ }
273
+
274
+ .dm-tabs--pills .dm-tabs__indicator {
275
+ display: none;
276
+ }
277
+
155
278
  .dm-tabs__panels {
156
- padding: var(--dm-space-4);
279
+ padding: var(--dm-spacing-4, 1rem);
280
+ flex: 1;
157
281
  }
158
282
 
159
283
  .dm-tabs__panel {
@@ -164,17 +288,14 @@ const handleKeydown = (event: KeyboardEvent, index: number) => {
164
288
  display: block;
165
289
  }
166
290
 
167
- @media (prefers-color-scheme: dark) {
168
- .dm-tabs__header {
169
- border-bottom-color: var(--dm-gray-700);
170
- }
171
-
291
+ @media (max-width: 768px) {
172
292
  .dm-tabs__tab {
173
- color: var(--dm-gray-400);
293
+ padding: var(--dm-spacing-2, 0.5rem) var(--dm-spacing-3, 0.75rem);
294
+ font-size: 0.875rem;
174
295
  }
175
-
176
- .dm-tabs__tab:hover {
177
- color: var(--dm-white);
296
+
297
+ .dm-tabs__icon {
298
+ font-size: 1rem;
178
299
  }
179
300
  }
180
301
  </style>
@@ -70,90 +70,90 @@ const handleInput = () => {
70
70
  .dm-textarea {
71
71
  display: flex;
72
72
  flex-direction: column;
73
- gap: var(--dm-space-2);
73
+ gap: var(--dm-spacing-2, 0.5rem);
74
74
  }
75
75
 
76
76
  .dm-textarea__label {
77
- color: var(--dm-text-primary);
78
- font-size: var(--dm-text-sm);
79
- font-weight: 500;
77
+ color: var(--dm-neutral-900, #111827);
78
+ font-size: var(--dm-font-size-sm, 0.875rem);
79
+ font-weight: var(--dm-font-weight-medium, 500);
80
80
  }
81
81
 
82
82
  .dm-textarea__required {
83
- color: var(--dm-error);
83
+ color: var(--dm-error, #ef4444);
84
84
  }
85
85
 
86
86
  .dm-textarea__input {
87
87
  width: 100%;
88
- padding: var(--dm-space-3);
89
- border: 1px solid var(--dm-gray-300);
90
- border-radius: var(--dm-radius);
91
- font-size: var(--dm-text-base);
92
- color: var(--dm-text-primary);
93
- background: var(--dm-white);
94
- transition: var(--dm-transition);
88
+ padding: var(--dm-spacing-3, 0.75rem);
89
+ border: 1px solid var(--dm-neutral-300, #d1d5db);
90
+ border-radius: var(--dm-radius-md, 0.375rem);
91
+ font-size: var(--dm-font-size-base, 1rem);
92
+ color: var(--dm-neutral-900, #111827);
93
+ background: white;
94
+ transition: all 0.2s;
95
95
  resize: vertical;
96
96
  font-family: inherit;
97
97
  line-height: 1.5;
98
98
  }
99
99
 
100
100
  .dm-textarea__input::placeholder {
101
- color: var(--dm-gray-400);
101
+ color: var(--dm-neutral-400, #9ca3af);
102
102
  }
103
103
 
104
104
  .dm-textarea__input:hover:not(:disabled) {
105
- border-color: var(--dm-gray-400);
105
+ border-color: var(--dm-neutral-400, #9ca3af);
106
106
  }
107
107
 
108
108
  .dm-textarea__input:focus {
109
- outline: var(--dm-focus-ring);
109
+ outline: 2px solid var(--dm-primary, #0072CE);
110
110
  outline-offset: 0;
111
- border-color: var(--dm-primary);
111
+ border-color: var(--dm-primary, #0072CE);
112
112
  }
113
113
 
114
114
  .dm-textarea__input:disabled {
115
- background: var(--dm-gray-100);
115
+ background: var(--dm-neutral-100, #f3f4f6);
116
116
  cursor: not-allowed;
117
117
  opacity: 0.6;
118
118
  }
119
119
 
120
120
  .dm-textarea__input--error {
121
- border-color: var(--dm-error);
121
+ border-color: var(--dm-error, #ef4444);
122
122
  }
123
123
 
124
124
  .dm-textarea__input--error:focus {
125
- outline-color: var(--dm-error);
125
+ outline-color: var(--dm-error, #ef4444);
126
126
  }
127
127
 
128
128
  .dm-textarea__footer {
129
129
  display: flex;
130
130
  justify-content: space-between;
131
131
  align-items: center;
132
- gap: var(--dm-space-2);
132
+ gap: var(--dm-spacing-2, 0.5rem);
133
133
  }
134
134
 
135
135
  .dm-textarea__error {
136
- color: var(--dm-error);
137
- font-size: var(--dm-text-sm);
136
+ color: var(--dm-error, #ef4444);
137
+ font-size: var(--dm-font-size-sm, 0.875rem);
138
138
  margin: 0;
139
139
  flex: 1;
140
140
  }
141
141
 
142
142
  .dm-textarea__counter {
143
- color: var(--dm-gray-500);
144
- font-size: var(--dm-text-sm);
143
+ color: var(--dm-neutral-500, #6b7280);
144
+ font-size: var(--dm-font-size-sm, 0.875rem);
145
145
  white-space: nowrap;
146
146
  }
147
147
 
148
148
  @media (prefers-color-scheme: dark) {
149
149
  .dm-textarea__input {
150
- background: var(--dm-gray-800);
151
- border-color: var(--dm-gray-600);
152
- color: var(--dm-white);
150
+ background: var(--dm-neutral-800, #1f2937);
151
+ border-color: var(--dm-neutral-600, #4b5563);
152
+ color: white;
153
153
  }
154
154
 
155
155
  .dm-textarea__input:disabled {
156
- background: var(--dm-gray-900);
156
+ background: var(--dm-neutral-900, #111827);
157
157
  }
158
158
  }
159
159
  </style>