@datametria/vue-components 2.4.0 → 2.4.2

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 (36) hide show
  1. package/README.md +57 -5
  2. package/dist/index.es.js +5812 -2837
  3. package/dist/index.umd.js +670 -10
  4. package/dist/src/components/DatametriaCheckbox.vue.d.ts +2 -0
  5. package/dist/src/components/DatametriaCheckboxGroup.vue.d.ts +6 -0
  6. package/dist/src/components/DatametriaFileUpload.vue.d.ts +5 -0
  7. package/dist/src/components/DatametriaFloatingBar.vue.d.ts +1 -1
  8. package/dist/src/components/DatametriaInput.vue.d.ts +2 -22
  9. package/dist/src/components/DatametriaNavbar.vue.d.ts +1 -1
  10. package/dist/src/components/DatametriaPasswordInput.vue.d.ts +2 -0
  11. package/dist/src/components/DatametriaRadio.vue.d.ts +2 -0
  12. package/dist/src/components/DatametriaRadioGroup.vue.d.ts +6 -0
  13. package/dist/src/components/DatametriaSelect.vue.d.ts +2 -3
  14. package/dist/src/components/DatametriaSidebar.vue.d.ts +1 -1
  15. package/dist/src/components/DatametriaSwitch.vue.d.ts +8 -1
  16. package/dist/src/components/DatametriaTabs.vue.d.ts +2 -2
  17. package/dist/src/components/DatametriaTextarea.vue.d.ts +6 -0
  18. package/dist/src/composables/useAnalytics.d.ts +8 -0
  19. package/dist/src/types/analytics.d.ts +50 -0
  20. package/dist/vue-components.css +1 -1
  21. package/package.json +3 -2
  22. package/src/components/DatametriaButton.vue +196 -195
  23. package/src/components/DatametriaCheckbox.vue +289 -197
  24. package/src/components/DatametriaCheckboxGroup.vue +161 -58
  25. package/src/components/DatametriaFileUpload.vue +493 -414
  26. package/src/components/DatametriaInput.vue +342 -316
  27. package/src/components/DatametriaPasswordInput.vue +433 -444
  28. package/src/components/DatametriaRadio.vue +240 -151
  29. package/src/components/DatametriaRadioGroup.vue +160 -57
  30. package/src/components/DatametriaSelect.vue +409 -313
  31. package/src/components/DatametriaSortableTable.vue +35 -29
  32. package/src/components/DatametriaSwitch.vue +319 -146
  33. package/src/components/DatametriaTabs.vue +2 -2
  34. package/src/components/DatametriaTextarea.vue +285 -213
  35. package/src/composables/useAnalytics.ts +70 -0
  36. package/src/types/analytics.ts +59 -0
@@ -1,317 +1,413 @@
1
- <template>
2
- <div class="datametria-select" :class="{ 'is-disabled': disabled }">
3
- <!-- Label -->
4
- <label v-if="label" class="datametria-select__label">
5
- {{ label }}
6
- <span v-if="required" class="datametria-select__required">*</span>
7
- </label>
8
-
9
- <div ref="triggerRef" class="datametria-select__trigger" @click="toggleDropdown">
10
- <span v-if="displayValue" class="datametria-select__value">{{ displayValue }}</span>
11
- <span v-else class="datametria-select__placeholder">{{ placeholder }}</span>
12
- <span class="datametria-select__arrow">▼</span>
13
-
14
- <!-- Hidden select for testing -->
15
- <select
16
- v-model="selectedValue"
17
- :disabled="disabled"
18
- style="position: absolute; opacity: 0; pointer-events: none;"
19
- @change="handleNativeChange"
20
- >
21
- <option value="" disabled>{{ placeholder }}</option>
22
- <option
23
- v-for="option in options"
24
- :key="option.value"
25
- :value="option.value"
26
- >
27
- {{ option.label }}
28
- </option>
29
- </select>
30
- </div>
31
-
32
- <Teleport to="body">
33
- <div v-if="isOpen" class="datametria-select__dropdown" :style="dropdownStyle">
34
- <input
35
- v-if="filterable"
36
- v-model="filterText"
37
- class="datametria-select__filter"
38
- placeholder="Buscar..."
39
- @click.stop
40
- />
41
- <div class="datametria-select__options">
42
- <div
43
- v-for="option in filteredOptions"
44
- :key="option.value"
45
- class="datametria-select__option"
46
- :class="{ 'is-selected': isSelected(option.value) }"
47
- @click="handleSelect(option)"
48
- >
49
- {{ option.label }}
50
- </div>
51
- <div v-if="filteredOptions.length === 0" class="datametria-select__empty">
52
- Nenhum resultado
53
- </div>
54
- </div>
55
- </div>
56
- </Teleport>
57
-
58
- <!-- Error Message -->
59
- <div v-if="errorMessage" class="datametria-select__error">
60
- {{ errorMessage }}
61
- </div>
62
- </div>
63
- </template>
64
-
65
- <script setup lang="ts">
66
- import { ref, computed, watch, onMounted, onUnmounted } from 'vue'
67
-
68
- interface SelectOption {
69
- label: string
70
- value: any
71
- disabled?: boolean
72
- }
73
-
74
- interface Props {
75
- modelValue: any | any[]
76
- options: SelectOption[]
77
- /** Label do select */
78
- label?: string
79
- /** Campo obrigatório */
80
- required?: boolean
81
- /** Mensagem de erro */
82
- errorMessage?: string
83
- placeholder?: string
84
- disabled?: boolean
85
- clearable?: boolean
86
- filterable?: boolean
87
- multiple?: boolean
88
- }
89
-
90
- const props = withDefaults(defineProps<Props>(), {
91
- placeholder: 'Selecione',
92
- disabled: false,
93
- clearable: false,
94
- filterable: false,
95
- multiple: false,
96
- required: false
97
- })
98
-
99
- const emit = defineEmits<{
100
- 'update:modelValue': [value: any]
101
- 'change': [value: any]
102
- }>()
103
-
104
- const isOpen = ref(false)
105
- const filterText = ref('')
106
- const dropdownStyle = ref({})
107
- const triggerRef = ref<HTMLElement>()
108
-
109
- const selectedValue = computed({
110
- get: () => props.modelValue,
111
- set: (value) => {
112
- emit('update:modelValue', value)
113
- emit('change', value)
114
- }
115
- })
116
-
117
- const displayValue = computed(() => {
118
- if (props.multiple && Array.isArray(props.modelValue)) {
119
- const labels = props.modelValue.map(v =>
120
- props.options.find(o => o.value === v)?.label
121
- ).filter(Boolean)
122
- return labels.join(', ')
123
- }
124
- return props.options.find(o => o.value === props.modelValue)?.label || ''
125
- })
126
-
127
- const filteredOptions = computed(() => {
128
- if (!props.filterable || !filterText.value) return props.options
129
- return props.options.filter(o =>
130
- o.label.toLowerCase().includes(filterText.value.toLowerCase())
131
- )
132
- })
133
-
134
- const isSelected = (value: any) => {
135
- if (props.multiple && Array.isArray(props.modelValue)) {
136
- return props.modelValue.includes(value)
137
- }
138
- return props.modelValue === value
139
- }
140
-
141
- const toggleDropdown = () => {
142
- if (!props.disabled) {
143
- isOpen.value = !isOpen.value
144
- if (isOpen.value && triggerRef.value) {
145
- updateDropdownPosition()
146
- }
147
- }
148
- }
149
-
150
- const updateDropdownPosition = () => {
151
- if (!triggerRef.value) return
152
- const rect = triggerRef.value.getBoundingClientRect()
153
- dropdownStyle.value = {
154
- top: `${rect.bottom + window.scrollY + 4}px`,
155
- left: `${rect.left + window.scrollX}px`,
156
- width: `${rect.width}px`
157
- }
158
- }
159
-
160
- const handleSelect = (option: SelectOption) => {
161
- if (props.multiple) {
162
- const current = Array.isArray(props.modelValue) ? [...props.modelValue] : []
163
- const index = current.indexOf(option.value)
164
- if (index > -1) {
165
- current.splice(index, 1)
166
- } else {
167
- current.push(option.value)
168
- }
169
- emit('update:modelValue', current)
170
- emit('change', current)
171
- } else {
172
- emit('update:modelValue', option.value)
173
- emit('change', option.value)
174
- isOpen.value = false
175
- }
176
- }
177
-
178
- const handleNativeChange = (event: Event) => {
179
- const target = event.target as HTMLSelectElement
180
- emit('update:modelValue', target.value)
181
- emit('change', target.value)
182
- }
183
-
184
- const handleClickOutside = (e: MouseEvent) => {
185
- const target = e.target as HTMLElement
186
- if (!target.closest('.datametria-select')) {
187
- isOpen.value = false
188
- }
189
- }
190
-
191
- onMounted(() => {
192
- document.addEventListener('click', handleClickOutside)
193
- })
194
-
195
- onUnmounted(() => {
196
- document.removeEventListener('click', handleClickOutside)
197
- })
198
- </script>
199
-
200
- <style scoped>
201
- .datametria-select__label {
202
- display: block;
203
- margin-bottom: 4px;
204
- font-size: 14px;
205
- font-weight: 500;
206
- color: var(--color-text-primary, #1f2937);
207
- }
208
-
209
- .datametria-select__required {
210
- color: var(--color-error, #ef4444);
211
- margin-left: 2px;
212
- }
213
-
214
- .datametria-select__error {
215
- margin-top: 4px;
216
- font-size: 12px;
217
- color: var(--color-error, #ef4444);
218
- }
219
-
220
- .datametria-select {
221
- position: relative;
222
- width: 100%;
223
- }
224
-
225
- .datametria-select__trigger {
226
- display: flex;
227
- align-items: center;
228
- justify-content: space-between;
229
- padding: 8px 12px;
230
- border: 1px solid var(--color-border, #d1d5db);
231
- border-radius: 6px;
232
- background: var(--color-background, #fff);
233
- cursor: pointer;
234
- transition: all 0.2s;
235
- }
236
-
237
- .datametria-select__trigger:hover {
238
- border-color: var(--color-primary, #3b82f6);
239
- }
240
-
241
- .is-disabled .datametria-select__trigger {
242
- opacity: 0.6;
243
- cursor: not-allowed;
244
- }
245
-
246
- .datametria-select__placeholder {
247
- color: var(--color-text-secondary, #9ca3af);
248
- }
249
-
250
- .datametria-select__arrow {
251
- font-size: 12px;
252
- transition: transform 0.2s;
253
- }
254
-
255
- .datametria-select__dropdown {
256
- position: fixed;
257
- z-index: 2000;
258
- background: var(--color-background, #fff);
259
- border: 1px solid var(--color-border, #d1d5db);
260
- border-radius: 6px;
261
- box-shadow: 0 4px 12px rgba(0,0,0,0.15);
262
- max-height: 300px;
263
- overflow: hidden;
264
- }
265
-
266
- .datametria-select__filter {
267
- width: 100%;
268
- padding: 8px 12px;
269
- border: none;
270
- border-bottom: 1px solid var(--color-border, #d1d5db);
271
- outline: none;
272
- }
273
-
274
- .datametria-select__options {
275
- max-height: 250px;
276
- overflow-y: auto;
277
- }
278
-
279
- .datametria-select__option {
280
- padding: 8px 12px;
281
- cursor: pointer;
282
- transition: background 0.2s;
283
- }
284
-
285
- .datametria-select__option:hover {
286
- background: var(--color-background-hover, #f3f4f6);
287
- }
288
-
289
- .datametria-select__option.is-selected {
290
- background: var(--color-primary-light, #dbeafe);
291
- color: var(--color-primary, #3b82f6);
292
- }
293
-
294
- .datametria-select__empty {
295
- padding: 16px;
296
- text-align: center;
297
- color: var(--color-text-secondary, #9ca3af);
298
- }
299
-
300
- /* Dark Mode Support - Hybrid Approach */
301
-
302
- /* Fallback automático (sem JS) */
303
- @media (prefers-color-scheme: dark) {
304
- .datametria-select {
305
- background: var(--dm-bg-color-dark, #1e1e1e);
306
- color: var(--dm-text-primary-dark, #e0e0e0);
307
- border-color: var(--dm-border-color-dark, #404040);
1
+ <template>
2
+ <div class="datametria-select" :class="selectClasses">
3
+ <label v-if="label" :for="selectId" class="datametria-select__label">
4
+ {{ label }}
5
+ <span v-if="required" class="datametria-select__required">*</span>
6
+ </label>
7
+
8
+ <div
9
+ ref="triggerRef"
10
+ class="datametria-select__trigger"
11
+ :aria-expanded="isOpen"
12
+ :aria-haspopup="true"
13
+ :aria-disabled="disabled"
14
+ :aria-invalid="!!errorMessage"
15
+ :aria-describedby="errorMessage ? `${selectId}-error` : undefined"
16
+ role="combobox"
17
+ tabindex="0"
18
+ @click.stop="toggleDropdown"
19
+ @keydown.enter.prevent="toggleDropdown"
20
+ @keydown.space.prevent="toggleDropdown"
21
+ @keydown.escape="isOpen = false"
22
+ >
23
+ <span v-if="displayValue" class="datametria-select__value">{{ displayValue }}</span>
24
+ <span v-else class="datametria-select__placeholder">{{ placeholder }}</span>
25
+ <span class="datametria-select__arrow" :class="{ 'is-open': isOpen }">▼</span>
26
+
27
+ <select
28
+ :id="selectId"
29
+ v-model="selectedValue"
30
+ :disabled="disabled"
31
+ :aria-label="label || placeholder"
32
+ style="position: absolute; opacity: 0; pointer-events: none;"
33
+ @change="handleNativeChange"
34
+ >
35
+ <option value="" disabled>{{ placeholder }}</option>
36
+ <option
37
+ v-for="option in options"
38
+ :key="option.value"
39
+ :value="option.value"
40
+ >
41
+ {{ option.label }}
42
+ </option>
43
+ </select>
44
+ </div>
45
+
46
+ <Teleport to="body">
47
+ <div
48
+ v-if="isOpen"
49
+ class="datametria-select__dropdown"
50
+ :style="dropdownStyle"
51
+ role="listbox"
52
+ >
53
+ <input
54
+ v-if="filterable"
55
+ v-model="filterText"
56
+ class="datametria-select__filter"
57
+ placeholder="Buscar..."
58
+ aria-label="Filtrar opções"
59
+ @click.stop
60
+ />
61
+ <div class="datametria-select__options">
62
+ <div
63
+ v-for="option in filteredOptions"
64
+ :key="option.value"
65
+ class="datametria-select__option"
66
+ :class="{ 'is-selected': isSelected(option.value) }"
67
+ role="option"
68
+ :aria-selected="isSelected(option.value)"
69
+ @click="handleSelect(option)"
70
+ >
71
+ {{ option.label }}
72
+ </div>
73
+ <div v-if="filteredOptions.length === 0" class="datametria-select__empty">
74
+ Nenhum resultado
75
+ </div>
76
+ </div>
77
+ </div>
78
+ </Teleport>
79
+
80
+ <div
81
+ v-if="errorMessage"
82
+ :id="`${selectId}-error`"
83
+ role="alert"
84
+ aria-live="polite"
85
+ class="datametria-select__error"
86
+ >
87
+ {{ errorMessage }}
88
+ </div>
89
+ </div>
90
+ </template>
91
+
92
+ <script setup lang="ts">
93
+ import { ref, computed, onMounted, onUnmounted } from 'vue'
94
+ import { useAnalytics } from '@/composables/useAnalytics'
95
+
96
+ interface SelectOption {
97
+ label: string
98
+ value: any
99
+ disabled?: boolean
100
+ }
101
+
102
+ interface Props {
103
+ modelValue: any | any[]
104
+ options: SelectOption[]
105
+ label?: string
106
+ required?: boolean
107
+ errorMessage?: string
108
+ placeholder?: string
109
+ disabled?: boolean
110
+ clearable?: boolean
111
+ filterable?: boolean
112
+ multiple?: boolean
113
+ size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'
114
+ }
115
+
116
+ const props = withDefaults(defineProps<Props>(), {
117
+ placeholder: 'Selecione',
118
+ disabled: false,
119
+ clearable: false,
120
+ filterable: false,
121
+ multiple: false,
122
+ required: false,
123
+ size: 'md'
124
+ })
125
+
126
+ const emit = defineEmits<{
127
+ 'update:modelValue': [value: any]
128
+ 'change': [value: any]
129
+ }>()
130
+
131
+ const { trackEvent } = useAnalytics()
132
+ const isOpen = ref(false)
133
+ const filterText = ref('')
134
+ const dropdownStyle = ref({})
135
+ const triggerRef = ref<HTMLElement>()
136
+ const selectId = `datametria-select-${Math.random().toString(36).substr(2, 9)}`
137
+
138
+ const selectedValue = computed({
139
+ get: () => props.modelValue,
140
+ set: (value) => {
141
+ emit('update:modelValue', value)
142
+ emit('change', value)
143
+ }
144
+ })
145
+
146
+ const displayValue = computed(() => {
147
+ if (props.multiple && Array.isArray(props.modelValue)) {
148
+ const labels = props.modelValue.map(v =>
149
+ props.options.find(o => o.value === v)?.label
150
+ ).filter(Boolean)
151
+ return labels.join(', ')
152
+ }
153
+ return props.options.find(o => o.value === props.modelValue)?.label || ''
154
+ })
155
+
156
+ const filteredOptions = computed(() => {
157
+ if (!props.filterable || !filterText.value) return props.options
158
+ return props.options.filter(o =>
159
+ o.label.toLowerCase().includes(filterText.value.toLowerCase())
160
+ )
161
+ })
162
+
163
+ const selectClasses = computed(() => ({
164
+ 'is-disabled': props.disabled,
165
+ 'is-error': !!props.errorMessage,
166
+ [`datametria-select--${props.size}`]: true
167
+ }))
168
+
169
+ const isSelected = (value: any) => {
170
+ if (props.multiple && Array.isArray(props.modelValue)) {
171
+ return props.modelValue.includes(value)
172
+ }
173
+ return props.modelValue === value
174
+ }
175
+
176
+ const toggleDropdown = () => {
177
+ if (!props.disabled) {
178
+ isOpen.value = !isOpen.value
179
+ if (isOpen.value) {
180
+ trackEvent('select_open', {
181
+ component: 'DatametriaSelect',
182
+ multiple: props.multiple,
183
+ size: props.size
184
+ })
185
+ if (triggerRef.value) {
186
+ updateDropdownPosition()
187
+ }
188
+ }
189
+ }
190
+ }
191
+
192
+ const updateDropdownPosition = () => {
193
+ if (!triggerRef.value) return
194
+ const rect = triggerRef.value.getBoundingClientRect()
195
+ dropdownStyle.value = {
196
+ top: `${rect.bottom + window.scrollY + 4}px`,
197
+ left: `${rect.left + window.scrollX}px`,
198
+ width: `${rect.width}px`
199
+ }
200
+ }
201
+
202
+ const handleSelect = (option: SelectOption) => {
203
+ if (props.multiple) {
204
+ const current = Array.isArray(props.modelValue) ? [...props.modelValue] : []
205
+ const index = current.indexOf(option.value)
206
+ if (index > -1) {
207
+ current.splice(index, 1)
208
+ } else {
209
+ current.push(option.value)
210
+ }
211
+ emit('update:modelValue', current)
212
+ emit('change', current)
213
+ } else {
214
+ emit('update:modelValue', option.value)
215
+ emit('change', option.value)
216
+ isOpen.value = false
308
217
  }
218
+
219
+ trackEvent('select_change', {
220
+ component: 'DatametriaSelect',
221
+ multiple: props.multiple,
222
+ optionCount: props.multiple ? (Array.isArray(props.modelValue) ? props.modelValue.length : 0) : 1
223
+ })
224
+ }
225
+
226
+ const handleNativeChange = (event: Event) => {
227
+ const target = event.target as HTMLSelectElement
228
+ emit('update:modelValue', target.value)
229
+ emit('change', target.value)
230
+ }
231
+
232
+ const handleClickOutside = (e: MouseEvent) => {
233
+ const target = e.target as HTMLElement
234
+ if (!target.closest('.datametria-select')) {
235
+ isOpen.value = false
236
+ }
237
+ }
238
+
239
+ onMounted(() => {
240
+ document.addEventListener('click', handleClickOutside)
241
+ })
242
+
243
+ onUnmounted(() => {
244
+ document.removeEventListener('click', handleClickOutside)
245
+ })
246
+ </script>
247
+
248
+ <style scoped>
249
+ .datametria-select {
250
+ position: relative;
251
+ width: 100%;
252
+ }
253
+
254
+ .datametria-select__label {
255
+ display: block;
256
+ margin-bottom: 4px;
257
+ font-size: 14px;
258
+ font-weight: 500;
259
+ color: var(--color-text-primary, #1f2937);
260
+ }
261
+
262
+ .datametria-select__required {
263
+ color: var(--color-error, #ef4444);
264
+ margin-left: 2px;
265
+ }
266
+
267
+ .datametria-select__trigger {
268
+ display: flex;
269
+ align-items: center;
270
+ justify-content: space-between;
271
+ border: 1px solid var(--color-border, #d1d5db);
272
+ border-radius: 6px;
273
+ background: var(--color-background, #fff);
274
+ cursor: pointer;
275
+ transition: all 0.2s;
276
+ touch-action: manipulation;
277
+ -webkit-tap-highlight-color: transparent;
278
+ }
279
+
280
+ .datametria-select__trigger:hover:not([aria-disabled="true"]) {
281
+ border-color: var(--color-primary, #3b82f6);
282
+ }
283
+
284
+ .datametria-select__trigger:focus-visible {
285
+ outline: none;
286
+ border-color: var(--color-primary, #3b82f6);
287
+ box-shadow: 0 0 0 3px var(--color-primary-alpha, rgba(59, 130, 246, 0.1));
288
+ }
289
+
290
+ .is-disabled .datametria-select__trigger {
291
+ background: var(--color-background-muted, #f3f4f6);
292
+ cursor: not-allowed;
293
+ opacity: 0.6;
294
+ }
295
+
296
+ .is-error .datametria-select__trigger {
297
+ border-color: var(--color-error, #ef4444);
298
+ }
299
+
300
+ .datametria-select__value {
301
+ color: var(--color-text-primary, #1f2937);
302
+ }
303
+
304
+ .datametria-select__placeholder {
305
+ color: var(--color-text-secondary, #6b7280);
306
+ }
307
+
308
+ .datametria-select__arrow {
309
+ font-size: 12px;
310
+ transition: transform 0.2s;
311
+ }
312
+
313
+ .datametria-select__arrow.is-open {
314
+ transform: rotate(180deg);
315
+ }
316
+
317
+ .datametria-select__dropdown {
318
+ position: fixed;
319
+ z-index: 2000;
320
+ background: var(--color-background, #fff);
321
+ border: 1px solid var(--color-border, #d1d5db);
322
+ border-radius: 6px;
323
+ box-shadow: 0 4px 12px rgba(0,0,0,0.15);
324
+ max-height: 300px;
325
+ overflow: hidden;
326
+ }
327
+
328
+ .datametria-select__filter {
329
+ width: 100%;
330
+ padding: 8px 12px;
331
+ border: none;
332
+ border-bottom: 1px solid var(--color-border, #d1d5db);
333
+ outline: none;
334
+ background: var(--color-background, #fff);
335
+ color: var(--color-text-primary, #1f2937);
336
+ }
337
+
338
+ .datametria-select__options {
339
+ max-height: 250px;
340
+ overflow-y: auto;
341
+ }
342
+
343
+ .datametria-select__option {
344
+ padding: 8px 12px;
345
+ cursor: pointer;
346
+ transition: background 0.2s;
347
+ color: var(--color-text-primary, #1f2937);
348
+ min-height: 44px;
349
+ display: flex;
350
+ align-items: center;
351
+ }
352
+
353
+ .datametria-select__option:hover {
354
+ background: var(--color-background-muted, #f3f4f6);
355
+ }
356
+
357
+ .datametria-select__option.is-selected {
358
+ background: var(--color-primary-alpha, rgba(59, 130, 246, 0.1));
359
+ color: var(--color-primary, #3b82f6);
360
+ }
361
+
362
+ .datametria-select__empty {
363
+ padding: 16px;
364
+ text-align: center;
365
+ color: var(--color-text-secondary, #6b7280);
366
+ }
367
+
368
+ .datametria-select__error {
369
+ margin-top: 4px;
370
+ font-size: 12px;
371
+ color: var(--color-error, #ef4444);
372
+ }
373
+
374
+ /* Tamanhos */
375
+ .datametria-select--xs .datametria-select__trigger {
376
+ padding: 2px 6px;
377
+ font-size: 11px;
378
+ min-height: 1.75rem;
379
+ }
380
+
381
+ .datametria-select--sm .datametria-select__trigger {
382
+ padding: 4px 8px;
383
+ font-size: 12px;
384
+ min-height: 2rem;
385
+ }
386
+
387
+ .datametria-select--md .datametria-select__trigger {
388
+ padding: 8px 12px;
389
+ font-size: 14px;
390
+ min-height: 2.5rem;
391
+ }
392
+
393
+ .datametria-select--lg .datametria-select__trigger {
394
+ padding: 12px 16px;
395
+ font-size: 16px;
396
+ min-height: 3rem;
397
+ }
398
+
399
+ .datametria-select--xl .datametria-select__trigger {
400
+ padding: 16px 20px;
401
+ font-size: 18px;
402
+ min-height: 3.5rem;
309
403
  }
310
404
 
311
- /* Controle manual via useTheme() */
312
- [data-theme="dark"] .datametria-select {
313
- background: var(--dm-bg-color-dark, #1e1e1e);
314
- color: var(--dm-text-primary-dark, #e0e0e0);
315
- border-color: var(--dm-border-color-dark, #404040);
405
+ /* Responsividade mobile */
406
+ @media (max-width: 640px) {
407
+ .datametria-select--xs .datametria-select__trigger { min-height: 2rem; }
408
+ .datametria-select--sm .datametria-select__trigger { min-height: 2.25rem; }
409
+ .datametria-select--md .datametria-select__trigger { min-height: 2.75rem; }
410
+ .datametria-select--lg .datametria-select__trigger { min-height: 3.25rem; }
411
+ .datametria-select--xl .datametria-select__trigger { min-height: 3.75rem; }
316
412
  }
317
- </style>
413
+ </style>