@datametria/vue-components 2.1.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/README.md +32 -10
  2. package/dist/index.d.ts +2 -0
  3. package/dist/index.es.js +1814 -1735
  4. package/dist/index.umd.js +9 -9
  5. package/dist/src/components/DatametriaAlert.vue.d.ts +33 -0
  6. package/dist/src/components/DatametriaAutocomplete.vue.d.ts +28 -0
  7. package/dist/src/components/DatametriaAvatar.vue.d.ts +25 -0
  8. package/dist/src/components/DatametriaBadge.vue.d.ts +26 -0
  9. package/dist/src/components/DatametriaBreadcrumb.vue.d.ts +16 -0
  10. package/dist/src/components/DatametriaButton.vue.d.ts +37 -0
  11. package/dist/src/components/DatametriaCard.vue.d.ts +25 -0
  12. package/dist/src/components/DatametriaCheckbox.vue.d.ts +14 -0
  13. package/dist/src/components/DatametriaChip.vue.d.ts +34 -0
  14. package/dist/src/components/DatametriaContainer.vue.d.ts +24 -0
  15. package/dist/src/components/DatametriaDatePicker.vue.d.ts +55 -0
  16. package/dist/src/components/DatametriaDivider.vue.d.ts +25 -0
  17. package/dist/src/components/DatametriaFileUpload.vue.d.ts +28 -0
  18. package/dist/src/components/DatametriaFloatingBar.vue.d.ts +32 -0
  19. package/dist/src/components/DatametriaGrid.vue.d.ts +24 -0
  20. package/dist/src/components/DatametriaInput.vue.d.ts +18 -0
  21. package/dist/src/components/DatametriaMenu.vue.d.ts +71 -0
  22. package/dist/src/components/DatametriaModal.vue.d.ts +34 -0
  23. package/dist/src/components/DatametriaNavbar.vue.d.ts +34 -0
  24. package/dist/src/components/DatametriaPasswordInput.vue.d.ts +29 -0
  25. package/dist/src/components/DatametriaProgress.vue.d.ts +12 -0
  26. package/dist/src/components/DatametriaRadio.vue.d.ts +17 -0
  27. package/dist/src/components/DatametriaSelect.vue.d.ts +23 -0
  28. package/dist/src/components/DatametriaSidebar.vue.d.ts +45 -0
  29. package/dist/src/components/DatametriaSkeleton.vue.d.ts +18 -0
  30. package/dist/src/components/DatametriaSlider.vue.d.ts +41 -0
  31. package/dist/src/components/DatametriaSortableTable.vue.d.ts +32 -0
  32. package/dist/src/components/DatametriaSpinner.vue.d.ts +12 -0
  33. package/dist/src/components/DatametriaSwitch.vue.d.ts +16 -0
  34. package/dist/src/components/DatametriaTable.vue.d.ts +29 -0
  35. package/dist/src/components/DatametriaTabs.vue.d.ts +41 -0
  36. package/dist/src/components/DatametriaTextarea.vue.d.ts +22 -0
  37. package/dist/src/components/DatametriaTimePicker.vue.d.ts +36 -0
  38. package/dist/src/components/DatametriaToast.vue.d.ts +20 -0
  39. package/dist/src/components/DatametriaTooltip.vue.d.ts +58 -0
  40. package/dist/src/composables/useAPI.d.ts +14 -0
  41. package/dist/src/composables/useAccessibilityScale.d.ts +14 -0
  42. package/dist/src/composables/useBreakpoints.d.ts +33 -0
  43. package/dist/src/composables/useClipboard.d.ts +6 -0
  44. package/dist/src/composables/useDebounce.d.ts +2 -0
  45. package/dist/src/composables/useHapticFeedback.d.ts +34 -0
  46. package/dist/src/composables/useLocalStorage.d.ts +2 -0
  47. package/dist/src/composables/useRipple.d.ts +49 -0
  48. package/dist/src/composables/useTheme.d.ts +10 -0
  49. package/dist/src/composables/useValidation.d.ts +14 -0
  50. package/dist/src/index.d.ts +53 -0
  51. package/dist/src/theme/ThemeProvider.vue.d.ts +24 -0
  52. package/dist/src/theme/constants.d.ts +5 -0
  53. package/dist/src/theme/index.d.ts +11 -0
  54. package/dist/src/theme/presets/datametria.d.ts +2 -0
  55. package/dist/src/theme/presets/default.d.ts +2 -0
  56. package/dist/src/theme/presets/index.d.ts +7 -0
  57. package/dist/src/theme/tokens/colors.d.ts +2 -0
  58. package/dist/src/theme/tokens/index.d.ts +8 -0
  59. package/dist/src/theme/tokens/spacing.d.ts +2 -0
  60. package/dist/src/theme/tokens/typography.d.ts +2 -0
  61. package/dist/src/theme/types.d.ts +102 -0
  62. package/dist/src/theme/useTheme.d.ts +8 -0
  63. package/dist/src/types/index.d.ts +52 -0
  64. package/dist/vue-components.css +1 -1
  65. package/package.json +4 -2
  66. package/src/components/DatametriaSortableTable.vue +204 -14
  67. package/src/types/index.ts +2 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@datametria/vue-components",
3
- "version": "2.1.0",
3
+ "version": "2.2.0",
4
4
  "description": "DATAMETRIA Vue.js 3 Component Library with Multi-Brand Theming - 32 components with theming support, WCAG 2.2 AA, dark mode, responsive system",
5
5
  "type": "module",
6
6
  "main": "./dist/index.umd.js",
@@ -12,7 +12,8 @@
12
12
  "import": "./dist/index.es.js",
13
13
  "require": "./dist/index.umd.js"
14
14
  },
15
- "./style.css": "./dist/style.css"
15
+ "./style.css": "./dist/vue-components.css",
16
+ "./dist/vue-components.css": "./dist/vue-components.css"
16
17
  },
17
18
  "files": [
18
19
  "dist",
@@ -59,6 +60,7 @@
59
60
  "prettier": "^3.4.0",
60
61
  "typescript": "~5.7.0",
61
62
  "vite": "^6.0.0",
63
+ "vite-plugin-dts": "^4.5.4",
62
64
  "vitest": "^2.1.0",
63
65
  "vue-tsc": "^2.2.0"
64
66
  },
@@ -56,15 +56,68 @@
56
56
  </div>
57
57
 
58
58
  <!-- Column Filter -->
59
- <input
60
- v-if="filterable && column.filterable !== false"
61
- v-model="columnFilters[column.key]"
62
- type="text"
63
- :placeholder="`Filtrar ${column.label}...`"
64
- :aria-label="`Filtrar por ${column.label}`"
65
- class="datametria-sortable-table__filter-input"
66
- @click.stop
67
- />
59
+ <div v-if="filterable && column.filterable !== false" @click.stop>
60
+ <!-- Select Filter -->
61
+ <select
62
+ v-if="column.filterType === 'select'"
63
+ v-model="columnFilters[column.key]"
64
+ :aria-label="`Filtrar por ${column.label}`"
65
+ class="datametria-sortable-table__filter-input"
66
+ @keydown.stop
67
+ >
68
+ <option value="">Todos</option>
69
+ <option
70
+ v-for="option in getFilterOptions(column)"
71
+ :key="option.value"
72
+ :value="option.value"
73
+ >
74
+ {{ option.label }}
75
+ </option>
76
+ </select>
77
+
78
+ <!-- Multi-Select Filter -->
79
+ <div
80
+ v-else-if="column.filterType === 'multiselect'"
81
+ class="datametria-sortable-table__multiselect"
82
+ >
83
+ <button
84
+ type="button"
85
+ class="datametria-sortable-table__multiselect-trigger"
86
+ @click="toggleMultiselect(column.key)"
87
+ >
88
+ {{ getMultiselectLabel(column) }}
89
+ </button>
90
+ <div
91
+ v-if="activeMultiselect === column.key"
92
+ class="datametria-sortable-table__multiselect-dropdown"
93
+ >
94
+ <label
95
+ v-for="option in getFilterOptions(column)"
96
+ :key="option.value"
97
+ class="datametria-sortable-table__multiselect-option"
98
+ >
99
+ <input
100
+ type="checkbox"
101
+ :value="option.value"
102
+ :checked="isMultiselectChecked(column.key, option.value)"
103
+ @change="toggleMultiselectOption(column.key, option.value)"
104
+ />
105
+ {{ option.label }}
106
+ </label>
107
+ </div>
108
+ </div>
109
+
110
+ <!-- Text/Date Filter -->
111
+ <input
112
+ v-else
113
+ v-model="columnFilters[column.key]"
114
+ :type="column.filterType || getFilterInputType(column)"
115
+ :placeholder="`Filtrar ${column.label}...`"
116
+ :aria-label="`Filtrar por ${column.label}`"
117
+ class="datametria-sortable-table__filter-input"
118
+ @keydown.stop
119
+ />
120
+ </div>
68
121
  </th>
69
122
  </tr>
70
123
  </thead>
@@ -204,6 +257,72 @@ const emit = defineEmits<{
204
257
  'selection-change': [selectedIds: (string | number)[]]
205
258
  }>()
206
259
 
260
+ // Detect filter input type based on column data
261
+ const getFilterInputType = (column: any) => {
262
+ if (!props.data || props.data.length === 0) return 'text'
263
+
264
+ const sampleValue = props.data[0][column.key]
265
+
266
+ // Check if it's a date
267
+ if (sampleValue instanceof Date) return 'date'
268
+ if (typeof sampleValue === 'string' && !isNaN(Date.parse(sampleValue))) {
269
+ // Check if it looks like a date string (YYYY-MM-DD, DD/MM/YYYY, etc)
270
+ const datePattern = /^\d{4}-\d{2}-\d{2}|\d{2}\/\d{2}\/\d{4}/
271
+ if (datePattern.test(sampleValue)) return 'date'
272
+ }
273
+
274
+ return 'text'
275
+ }
276
+
277
+ // Get filter options (auto-generate if 'auto')
278
+ const getFilterOptions = (column: any) => {
279
+ if (column.filterOptions === 'auto') {
280
+ const uniqueValues = new Set<string>()
281
+ props.data.forEach(row => {
282
+ const value = row[column.key]
283
+ if (value !== null && value !== undefined && value !== '') {
284
+ uniqueValues.add(String(value))
285
+ }
286
+ })
287
+ return Array.from(uniqueValues)
288
+ .sort()
289
+ .map(value => ({ value, label: value }))
290
+ }
291
+ return column.filterOptions || []
292
+ }
293
+
294
+ // Multi-select methods
295
+ const toggleMultiselect = (key: string) => {
296
+ activeMultiselect.value = activeMultiselect.value === key ? null : key
297
+ }
298
+
299
+ const getMultiselectLabel = (column: any) => {
300
+ const selected = columnFilters.value[column.key] as string[] || []
301
+ if (selected.length === 0) return 'Todos'
302
+ if (selected.length === 1) {
303
+ const options = getFilterOptions(column)
304
+ const option = options.find((o: any) => o.value === selected[0])
305
+ return option?.label || selected[0]
306
+ }
307
+ return `${selected.length} selecionados`
308
+ }
309
+
310
+ const isMultiselectChecked = (key: string, value: string) => {
311
+ const selected = columnFilters.value[key] as string[] || []
312
+ return selected.includes(value)
313
+ }
314
+
315
+ const toggleMultiselectOption = (key: string, value: string) => {
316
+ const selected = (columnFilters.value[key] as string[]) || []
317
+ const index = selected.indexOf(value)
318
+
319
+ if (index > -1) {
320
+ columnFilters.value[key] = selected.filter(v => v !== value)
321
+ } else {
322
+ columnFilters.value[key] = [...selected, value]
323
+ }
324
+ }
325
+
207
326
  // Search
208
327
  const searchQuery = ref('')
209
328
 
@@ -212,7 +331,8 @@ const sortKey = ref<string>('')
212
331
  const sortOrder = ref<'asc' | 'desc'>('asc')
213
332
 
214
333
  // Filtering
215
- const columnFilters = ref<Record<string, string>>({})
334
+ const columnFilters = ref<Record<string, string | string[]>>({})
335
+ const activeMultiselect = ref<string | null>(null)
216
336
 
217
337
  // Selection
218
338
  const selectedRows = ref<Set<string | number>>(new Set())
@@ -238,10 +358,19 @@ const filteredData = computed(() => {
238
358
  // Column filters
239
359
  Object.entries(columnFilters.value).forEach(([key, filterValue]) => {
240
360
  if (filterValue) {
241
- const query = filterValue.toLowerCase()
242
- result = result.filter(row =>
243
- String(row[key]).toLowerCase().includes(query)
244
- )
361
+ // Multi-select filter
362
+ if (Array.isArray(filterValue) && filterValue.length > 0) {
363
+ result = result.filter(row =>
364
+ filterValue.includes(String(row[key]))
365
+ )
366
+ }
367
+ // Text/Date/Select filter
368
+ else if (typeof filterValue === 'string') {
369
+ const query = filterValue.toLowerCase()
370
+ result = result.filter(row =>
371
+ String(row[key]).toLowerCase().includes(query)
372
+ )
373
+ }
245
374
  }
246
375
  })
247
376
 
@@ -438,6 +567,67 @@ watch(totalPages, (newTotal) => {
438
567
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--dm-primary, #0072CE) 20%, transparent);
439
568
  }
440
569
 
570
+ .datametria-sortable-table__multiselect {
571
+ position: relative;
572
+ margin-top: var(--dm-spacing-2, 0.5rem);
573
+ }
574
+
575
+ .datametria-sortable-table__multiselect-trigger {
576
+ width: 100%;
577
+ padding: var(--dm-spacing-2, 0.5rem);
578
+ border: 1px solid var(--dm-neutral-200, #e5e7eb);
579
+ border-radius: var(--dm-radius-md, 0.375rem);
580
+ font-size: var(--dm-font-size-sm, 0.875rem);
581
+ font-weight: 400;
582
+ text-align: left;
583
+ background: var(--dm-neutral-50, #ffffff);
584
+ cursor: pointer;
585
+ transition: all 0.2s ease;
586
+ }
587
+
588
+ .datametria-sortable-table__multiselect-trigger:hover {
589
+ border-color: var(--dm-primary, #0072CE);
590
+ }
591
+
592
+ .datametria-sortable-table__multiselect-trigger:focus {
593
+ outline: none;
594
+ border-color: var(--dm-primary, #0072CE);
595
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--dm-primary, #0072CE) 20%, transparent);
596
+ }
597
+
598
+ .datametria-sortable-table__multiselect-dropdown {
599
+ position: absolute;
600
+ top: 100%;
601
+ left: 0;
602
+ right: 0;
603
+ margin-top: var(--dm-spacing-1, 0.25rem);
604
+ max-height: 200px;
605
+ overflow-y: auto;
606
+ background: var(--dm-neutral-50, #ffffff);
607
+ border: 1px solid var(--dm-neutral-200, #e5e7eb);
608
+ border-radius: var(--dm-radius-md, 0.375rem);
609
+ box-shadow: var(--dm-shadow-lg, 0 10px 15px rgba(0, 0, 0, 0.1));
610
+ z-index: 10;
611
+ }
612
+
613
+ .datametria-sortable-table__multiselect-option {
614
+ display: flex;
615
+ align-items: center;
616
+ gap: var(--dm-spacing-2, 0.5rem);
617
+ padding: var(--dm-spacing-2, 0.5rem) var(--dm-spacing-3, 0.75rem);
618
+ font-size: var(--dm-font-size-sm, 0.875rem);
619
+ cursor: pointer;
620
+ transition: background-color 0.2s ease;
621
+ }
622
+
623
+ .datametria-sortable-table__multiselect-option:hover {
624
+ background: var(--dm-neutral-100, #f3f4f6);
625
+ }
626
+
627
+ .datametria-sortable-table__multiselect-option input[type="checkbox"] {
628
+ margin: 0;
629
+ }
630
+
441
631
  .datametria-sortable-table__tbody {
442
632
  background: var(--dm-neutral-50, #ffffff);
443
633
  }
@@ -39,6 +39,8 @@ export interface TableColumn {
39
39
  width?: string
40
40
  sortable?: boolean
41
41
  filterable?: boolean
42
+ filterType?: 'text' | 'date' | 'select' | 'multiselect'
43
+ filterOptions?: Array<{ value: string; label: string }> | 'auto'
42
44
  }
43
45
 
44
46
  export interface SortableTableProps {