@datametria/vue-components 2.3.1 → 2.4.1
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.
- package/README.md +625 -594
- package/dist/index.es.js +1962 -1887
- package/dist/index.umd.js +6 -6
- package/dist/src/components/DatametriaForm.vue.d.ts +1 -1
- package/dist/src/components/DatametriaInput.vue.d.ts +9 -1
- package/dist/src/components/DatametriaSelect.vue.d.ts +10 -1
- package/dist/vue-components.css +1 -1
- package/package.json +103 -102
- package/src/components/DatametriaAlert.vue +151 -133
- package/src/components/DatametriaAutocomplete.vue +250 -229
- package/src/components/DatametriaAvatar.vue +256 -238
- package/src/components/DatametriaBadge.vue +101 -96
- package/src/components/DatametriaBreadcrumb.vue +132 -128
- package/src/components/DatametriaButton.vue +191 -173
- package/src/components/DatametriaCard.vue +84 -66
- package/src/components/DatametriaCheckbox.vue +197 -193
- package/src/components/DatametriaChip.vue +159 -141
- package/src/components/DatametriaContainer.vue +70 -52
- package/src/components/DatametriaDataTable.vue +318 -300
- package/src/components/DatametriaDatePicker.vue +396 -378
- package/src/components/DatametriaDialog.vue +297 -293
- package/src/components/DatametriaDivider.vue +105 -98
- package/src/components/DatametriaDropdown.vue +356 -350
- package/src/components/DatametriaEmpty.vue +155 -151
- package/src/components/DatametriaFileUpload.vue +413 -395
- package/src/components/DatametriaFloatingBar.vue +144 -126
- package/src/components/DatametriaForm.vue +174 -156
- package/src/components/DatametriaFormItem.vue +183 -179
- package/src/components/DatametriaGrid.vue +55 -37
- package/src/components/DatametriaInput.vue +314 -263
- package/src/components/DatametriaMenu.vue +618 -600
- package/src/components/DatametriaModal.vue +147 -129
- package/src/components/DatametriaNavbar.vue +277 -223
- package/src/components/DatametriaPagination.vue +375 -371
- package/src/components/DatametriaPasswordInput.vue +446 -426
- package/src/components/DatametriaPopconfirm.vue +240 -234
- package/src/components/DatametriaProgress.vue +228 -224
- package/src/components/DatametriaRadio.vue +151 -147
- package/src/components/DatametriaResult.vue +135 -131
- package/src/components/DatametriaSelect.vue +311 -211
- package/src/components/DatametriaSidebar.vue +294 -222
- package/src/components/DatametriaSkeleton.vue +257 -234
- package/src/components/DatametriaSlider.vue +409 -391
- package/src/components/DatametriaSortableTable.vue +826 -802
- package/src/components/DatametriaSpinner.vue +114 -110
- package/src/components/DatametriaSteps.vue +318 -312
- package/src/components/DatametriaSwitch.vue +146 -142
- package/src/components/DatametriaTabPane.vue +94 -76
- package/src/components/DatametriaTable.vue +118 -100
- package/src/components/DatametriaTabs.vue +315 -297
- package/src/components/DatametriaTextarea.vue +213 -195
- package/src/components/DatametriaTimePicker.vue +317 -299
- package/src/components/DatametriaToast.vue +176 -176
- package/src/components/DatametriaTooltip.vue +421 -400
- package/src/components/DatametriaTree.vue +126 -122
- package/src/components/DatametriaTreeNode.vue +176 -172
- package/src/components/DatametriaUpload.vue +379 -361
- package/src/components/__tests__/DatametriaAlert.test.js +35 -35
- package/src/components/__tests__/DatametriaAlert.test.ts +190 -190
- package/src/components/__tests__/DatametriaAvatar.test.ts +151 -151
- package/src/components/__tests__/DatametriaBadge.test.js +29 -29
- package/src/components/__tests__/DatametriaBadge.test.ts +167 -167
- package/src/components/__tests__/DatametriaBreadcrumb.test.ts +187 -0
- package/src/components/__tests__/DatametriaButton.test.js +30 -30
- package/src/components/__tests__/DatametriaButton.test.ts +283 -283
- package/src/components/__tests__/DatametriaCard.test.ts +201 -201
- package/src/components/__tests__/DatametriaCheckbox.test.ts +204 -0
- package/src/components/__tests__/DatametriaChip.test.js +38 -38
- package/src/components/__tests__/DatametriaContainer.test.ts +52 -52
- package/src/components/__tests__/DatametriaDialog.test.ts +338 -0
- package/src/components/__tests__/DatametriaDivider.test.ts +54 -54
- package/src/components/__tests__/DatametriaDropdown.test.ts +357 -0
- package/src/components/__tests__/DatametriaEmpty.test.ts +261 -0
- package/src/components/__tests__/DatametriaFileUpload.test.ts +290 -290
- package/src/components/__tests__/DatametriaFloatingBar.test.ts +137 -137
- package/src/components/__tests__/DatametriaForm.test.ts +96 -0
- package/src/components/__tests__/DatametriaFormItem.test.ts +58 -0
- package/src/components/__tests__/DatametriaGrid.test.ts +31 -31
- package/src/components/__tests__/DatametriaInput.test.ts +72 -72
- package/src/components/__tests__/DatametriaMenu.test.ts +366 -366
- package/src/components/__tests__/DatametriaModal.test.ts +86 -86
- package/src/components/__tests__/DatametriaNavbar.test.js +48 -48
- package/src/components/__tests__/DatametriaNavbar.test.ts +203 -203
- package/src/components/__tests__/DatametriaPasswordInput.test.js +305 -305
- package/src/components/__tests__/DatametriaRadio.test.ts +195 -0
- package/src/components/__tests__/DatametriaSelect.test.ts +77 -77
- package/src/components/__tests__/DatametriaSidebar.test.ts +169 -169
- package/src/components/__tests__/DatametriaSlider.test.ts +261 -261
- package/src/components/__tests__/DatametriaSortableTable.test.js +168 -168
- package/src/components/__tests__/DatametriaSpinner.test.ts +156 -156
- package/src/components/__tests__/DatametriaSteps.test.ts +211 -0
- package/src/components/__tests__/DatametriaSwitch.test.ts +129 -0
- package/src/components/__tests__/DatametriaTabPane.test.ts +205 -0
- package/src/components/__tests__/DatametriaTable.test.ts +97 -97
- package/src/components/__tests__/DatametriaTabs.test.ts +232 -232
- package/src/components/__tests__/DatametriaToast.test.js +48 -48
- package/src/components/__tests__/DatametriaToast.test.ts +99 -99
- package/src/components/__tests__/DatametriaTree.test.ts +376 -0
- package/src/components/__tests__/index.test.ts +48 -0
- package/src/composables/useAccessibilityScale.ts +94 -94
- package/src/composables/useBreakpoints.ts +82 -82
- package/src/composables/useHapticFeedback.ts +439 -439
- package/src/composables/useRipple.ts +218 -218
- package/src/composables/useTheme.ts +5 -1
- package/src/index.ts +84 -84
- package/src/stories/Variants.stories.js +95 -95
- package/src/styles/design-tokens.css +623 -623
- package/src/theme/ThemeProvider.vue +96 -96
- package/src/theme/__tests__/ThemeProvider.test.ts +208 -208
- package/src/theme/__tests__/constants.test.ts +31 -31
- package/src/theme/__tests__/presets.test.ts +166 -166
- package/src/theme/__tests__/tokens.test.ts +155 -155
- package/src/theme/__tests__/types.test.ts +153 -153
- package/src/theme/__tests__/useTheme.test.ts +146 -146
- package/src/theme/constants.ts +14 -14
- package/src/theme/index.ts +12 -12
- package/src/theme/presets/datametria.ts +94 -94
- package/src/theme/presets/default.ts +94 -94
- package/src/theme/presets/index.ts +8 -8
- package/src/theme/tokens/colors.ts +28 -28
- package/src/theme/tokens/index.ts +47 -47
- package/src/theme/tokens/spacing.ts +21 -21
- package/src/theme/tokens/typography.ts +35 -35
- package/src/theme/types.ts +111 -111
- package/src/theme/useTheme.ts +28 -28
- package/src/types/index.ts +55 -55
|
@@ -1,219 +1,219 @@
|
|
|
1
|
-
import { ref, onMounted, onUnmounted, watch } from 'vue'
|
|
2
|
-
|
|
3
|
-
interface RippleOptions {
|
|
4
|
-
color?: string
|
|
5
|
-
duration?: number
|
|
6
|
-
disabled?: boolean
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
interface RippleEffect {
|
|
10
|
-
x: number
|
|
11
|
-
y: number
|
|
12
|
-
size: number
|
|
13
|
-
id: string
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Composable para efeito ripple em elementos clicáveis
|
|
18
|
-
* Implementa Material Design ripple effect com acessibilidade
|
|
19
|
-
*/
|
|
20
|
-
export function useRipple(options: RippleOptions = {}) {
|
|
21
|
-
const {
|
|
22
|
-
color = 'rgba(255, 255, 255, 0.3)',
|
|
23
|
-
duration = 600,
|
|
24
|
-
disabled = false
|
|
25
|
-
} = options
|
|
26
|
-
|
|
27
|
-
const elementRef = ref<HTMLElement>()
|
|
28
|
-
const ripples = ref<RippleEffect[]>([])
|
|
29
|
-
|
|
30
|
-
// Criar elemento ripple DOM
|
|
31
|
-
const createRipple = (event: MouseEvent | TouchEvent) => {
|
|
32
|
-
if (disabled || !elementRef.value) return
|
|
33
|
-
|
|
34
|
-
const element = elementRef.value
|
|
35
|
-
const rect = element.getBoundingClientRect()
|
|
36
|
-
|
|
37
|
-
// Calcular posição do clique
|
|
38
|
-
let clientX: number, clientY: number
|
|
39
|
-
|
|
40
|
-
if (event instanceof MouseEvent) {
|
|
41
|
-
clientX = event.clientX
|
|
42
|
-
clientY = event.clientY
|
|
43
|
-
} else {
|
|
44
|
-
const touch = event.touches[0] || event.changedTouches[0]
|
|
45
|
-
clientX = touch.clientX
|
|
46
|
-
clientY = touch.clientY
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const x = clientX - rect.left
|
|
50
|
-
const y = clientY - rect.top
|
|
51
|
-
|
|
52
|
-
// Calcular tamanho do ripple (maior dimensão)
|
|
53
|
-
const size = Math.max(rect.width, rect.height)
|
|
54
|
-
|
|
55
|
-
// Criar elemento DOM do ripple
|
|
56
|
-
const rippleElement = document.createElement('div')
|
|
57
|
-
rippleElement.className = 'datametria-ripple'
|
|
58
|
-
rippleElement.style.cssText = `
|
|
59
|
-
position: absolute;
|
|
60
|
-
left: ${x - size / 2}px;
|
|
61
|
-
top: ${y - size / 2}px;
|
|
62
|
-
width: ${size}px;
|
|
63
|
-
height: ${size}px;
|
|
64
|
-
border-radius: 50%;
|
|
65
|
-
background: ${color};
|
|
66
|
-
transform: scale(0);
|
|
67
|
-
animation: ripple-animation ${duration / 1000}s ease-out;
|
|
68
|
-
pointer-events: none;
|
|
69
|
-
z-index: 1;
|
|
70
|
-
`
|
|
71
|
-
|
|
72
|
-
element.appendChild(rippleElement)
|
|
73
|
-
|
|
74
|
-
// Remover ripple após animação
|
|
75
|
-
setTimeout(() => {
|
|
76
|
-
if (rippleElement.parentNode) {
|
|
77
|
-
rippleElement.parentNode.removeChild(rippleElement)
|
|
78
|
-
}
|
|
79
|
-
}, duration)
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// Event handlers
|
|
83
|
-
const handleClick = (event: MouseEvent) => {
|
|
84
|
-
createRipple(event)
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// Aplicar ripple ao elemento
|
|
88
|
-
const applyRipple = (element: HTMLElement) => {
|
|
89
|
-
if (!element) return
|
|
90
|
-
|
|
91
|
-
elementRef.value = element
|
|
92
|
-
|
|
93
|
-
// Garantir posição relativa para ripples
|
|
94
|
-
const computedStyle = window.getComputedStyle(element)
|
|
95
|
-
if (computedStyle.position === 'static') {
|
|
96
|
-
element.style.position = 'relative'
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// Garantir overflow hidden
|
|
100
|
-
element.style.overflow = 'hidden'
|
|
101
|
-
|
|
102
|
-
// Adicionar event listeners
|
|
103
|
-
element.addEventListener('click', handleClick)
|
|
104
|
-
|
|
105
|
-
return () => {
|
|
106
|
-
element.removeEventListener('click', handleClick)
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// Remover ripple específico
|
|
111
|
-
const removeRipple = (id: string) => {
|
|
112
|
-
const index = ripples.value.findIndex(r => r.id === id)
|
|
113
|
-
if (index > -1) {
|
|
114
|
-
ripples.value.splice(index, 1)
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// Limpar todos os ripples
|
|
119
|
-
const clearRipples = () => {
|
|
120
|
-
ripples.value = []
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// Cleanup
|
|
124
|
-
onUnmounted(() => {
|
|
125
|
-
clearRipples()
|
|
126
|
-
})
|
|
127
|
-
|
|
128
|
-
// Computed styles para ripples
|
|
129
|
-
const getRippleStyle = (ripple: RippleEffect) => ({
|
|
130
|
-
position: 'absolute' as const,
|
|
131
|
-
left: `${ripple.x}px`,
|
|
132
|
-
top: `${ripple.y}px`,
|
|
133
|
-
width: `${ripple.size}px`,
|
|
134
|
-
height: `${ripple.size}px`,
|
|
135
|
-
borderRadius: '50%',
|
|
136
|
-
backgroundColor: color,
|
|
137
|
-
transform: 'scale(0)',
|
|
138
|
-
animation: `ripple-animation ${duration}ms ease-out`,
|
|
139
|
-
pointerEvents: 'none' as const,
|
|
140
|
-
zIndex: 1
|
|
141
|
-
})
|
|
142
|
-
|
|
143
|
-
// CSS para animação (deve ser injetado no head)
|
|
144
|
-
const injectRippleCSS = () => {
|
|
145
|
-
const styleId = 'ripple-keyframes'
|
|
146
|
-
|
|
147
|
-
if (document.getElementById(styleId)) return
|
|
148
|
-
|
|
149
|
-
const style = document.createElement('style')
|
|
150
|
-
style.id = styleId
|
|
151
|
-
style.textContent = `
|
|
152
|
-
@keyframes ripple-animation {
|
|
153
|
-
0% {
|
|
154
|
-
transform: scale(0);
|
|
155
|
-
opacity: 1;
|
|
156
|
-
}
|
|
157
|
-
100% {
|
|
158
|
-
transform: scale(2);
|
|
159
|
-
opacity: 0;
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
@media (prefers-reduced-motion: reduce) {
|
|
164
|
-
@keyframes ripple-animation {
|
|
165
|
-
0%, 100% {
|
|
166
|
-
transform: scale(0);
|
|
167
|
-
opacity: 0;
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
`
|
|
172
|
-
|
|
173
|
-
document.head.appendChild(style)
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
// Método para adicionar efeito ripple ao elemento
|
|
179
|
-
const addRippleEffect = () => {
|
|
180
|
-
if (!elementRef.value) return
|
|
181
|
-
return applyRipple(elementRef.value)
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
// Método para remover efeito ripple do elemento
|
|
185
|
-
const removeRippleEffect = () => {
|
|
186
|
-
if (!elementRef.value) return
|
|
187
|
-
|
|
188
|
-
elementRef.value.removeEventListener('click', handleClick)
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
// Injetar CSS na montagem
|
|
192
|
-
onMounted(() => {
|
|
193
|
-
injectRippleCSS()
|
|
194
|
-
|
|
195
|
-
// Auto-aplicar se elemento já existe
|
|
196
|
-
if (elementRef.value) {
|
|
197
|
-
addRippleEffect()
|
|
198
|
-
}
|
|
199
|
-
})
|
|
200
|
-
|
|
201
|
-
// Watch para aplicar ripple quando elemento for definido
|
|
202
|
-
watch(elementRef, (newElement) => {
|
|
203
|
-
if (newElement) {
|
|
204
|
-
addRippleEffect()
|
|
205
|
-
}
|
|
206
|
-
})
|
|
207
|
-
|
|
208
|
-
return {
|
|
209
|
-
rippleRef: elementRef,
|
|
210
|
-
ripples,
|
|
211
|
-
applyRipple,
|
|
212
|
-
removeRipple,
|
|
213
|
-
clearRipples,
|
|
214
|
-
getRippleStyle,
|
|
215
|
-
createRipple,
|
|
216
|
-
addRippleEffect,
|
|
217
|
-
removeRippleEffect
|
|
218
|
-
}
|
|
1
|
+
import { ref, onMounted, onUnmounted, watch } from 'vue'
|
|
2
|
+
|
|
3
|
+
interface RippleOptions {
|
|
4
|
+
color?: string
|
|
5
|
+
duration?: number
|
|
6
|
+
disabled?: boolean
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
interface RippleEffect {
|
|
10
|
+
x: number
|
|
11
|
+
y: number
|
|
12
|
+
size: number
|
|
13
|
+
id: string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Composable para efeito ripple em elementos clicáveis
|
|
18
|
+
* Implementa Material Design ripple effect com acessibilidade
|
|
19
|
+
*/
|
|
20
|
+
export function useRipple(options: RippleOptions = {}) {
|
|
21
|
+
const {
|
|
22
|
+
color = 'rgba(255, 255, 255, 0.3)',
|
|
23
|
+
duration = 600,
|
|
24
|
+
disabled = false
|
|
25
|
+
} = options
|
|
26
|
+
|
|
27
|
+
const elementRef = ref<HTMLElement>()
|
|
28
|
+
const ripples = ref<RippleEffect[]>([])
|
|
29
|
+
|
|
30
|
+
// Criar elemento ripple DOM
|
|
31
|
+
const createRipple = (event: MouseEvent | TouchEvent) => {
|
|
32
|
+
if (disabled || !elementRef.value) return
|
|
33
|
+
|
|
34
|
+
const element = elementRef.value
|
|
35
|
+
const rect = element.getBoundingClientRect()
|
|
36
|
+
|
|
37
|
+
// Calcular posição do clique
|
|
38
|
+
let clientX: number, clientY: number
|
|
39
|
+
|
|
40
|
+
if (event instanceof MouseEvent) {
|
|
41
|
+
clientX = event.clientX
|
|
42
|
+
clientY = event.clientY
|
|
43
|
+
} else {
|
|
44
|
+
const touch = event.touches[0] || event.changedTouches[0]
|
|
45
|
+
clientX = touch.clientX
|
|
46
|
+
clientY = touch.clientY
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const x = clientX - rect.left
|
|
50
|
+
const y = clientY - rect.top
|
|
51
|
+
|
|
52
|
+
// Calcular tamanho do ripple (maior dimensão)
|
|
53
|
+
const size = Math.max(rect.width, rect.height)
|
|
54
|
+
|
|
55
|
+
// Criar elemento DOM do ripple
|
|
56
|
+
const rippleElement = document.createElement('div')
|
|
57
|
+
rippleElement.className = 'datametria-ripple'
|
|
58
|
+
rippleElement.style.cssText = `
|
|
59
|
+
position: absolute;
|
|
60
|
+
left: ${x - size / 2}px;
|
|
61
|
+
top: ${y - size / 2}px;
|
|
62
|
+
width: ${size}px;
|
|
63
|
+
height: ${size}px;
|
|
64
|
+
border-radius: 50%;
|
|
65
|
+
background: ${color};
|
|
66
|
+
transform: scale(0);
|
|
67
|
+
animation: ripple-animation ${duration / 1000}s ease-out;
|
|
68
|
+
pointer-events: none;
|
|
69
|
+
z-index: 1;
|
|
70
|
+
`
|
|
71
|
+
|
|
72
|
+
element.appendChild(rippleElement)
|
|
73
|
+
|
|
74
|
+
// Remover ripple após animação
|
|
75
|
+
setTimeout(() => {
|
|
76
|
+
if (rippleElement.parentNode) {
|
|
77
|
+
rippleElement.parentNode.removeChild(rippleElement)
|
|
78
|
+
}
|
|
79
|
+
}, duration)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Event handlers
|
|
83
|
+
const handleClick = (event: MouseEvent) => {
|
|
84
|
+
createRipple(event)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Aplicar ripple ao elemento
|
|
88
|
+
const applyRipple = (element: HTMLElement) => {
|
|
89
|
+
if (!element) return
|
|
90
|
+
|
|
91
|
+
elementRef.value = element
|
|
92
|
+
|
|
93
|
+
// Garantir posição relativa para ripples
|
|
94
|
+
const computedStyle = window.getComputedStyle(element)
|
|
95
|
+
if (computedStyle.position === 'static') {
|
|
96
|
+
element.style.position = 'relative'
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Garantir overflow hidden
|
|
100
|
+
element.style.overflow = 'hidden'
|
|
101
|
+
|
|
102
|
+
// Adicionar event listeners
|
|
103
|
+
element.addEventListener('click', handleClick)
|
|
104
|
+
|
|
105
|
+
return () => {
|
|
106
|
+
element.removeEventListener('click', handleClick)
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Remover ripple específico
|
|
111
|
+
const removeRipple = (id: string) => {
|
|
112
|
+
const index = ripples.value.findIndex(r => r.id === id)
|
|
113
|
+
if (index > -1) {
|
|
114
|
+
ripples.value.splice(index, 1)
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Limpar todos os ripples
|
|
119
|
+
const clearRipples = () => {
|
|
120
|
+
ripples.value = []
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Cleanup
|
|
124
|
+
onUnmounted(() => {
|
|
125
|
+
clearRipples()
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
// Computed styles para ripples
|
|
129
|
+
const getRippleStyle = (ripple: RippleEffect) => ({
|
|
130
|
+
position: 'absolute' as const,
|
|
131
|
+
left: `${ripple.x}px`,
|
|
132
|
+
top: `${ripple.y}px`,
|
|
133
|
+
width: `${ripple.size}px`,
|
|
134
|
+
height: `${ripple.size}px`,
|
|
135
|
+
borderRadius: '50%',
|
|
136
|
+
backgroundColor: color,
|
|
137
|
+
transform: 'scale(0)',
|
|
138
|
+
animation: `ripple-animation ${duration}ms ease-out`,
|
|
139
|
+
pointerEvents: 'none' as const,
|
|
140
|
+
zIndex: 1
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
// CSS para animação (deve ser injetado no head)
|
|
144
|
+
const injectRippleCSS = () => {
|
|
145
|
+
const styleId = 'ripple-keyframes'
|
|
146
|
+
|
|
147
|
+
if (document.getElementById(styleId)) return
|
|
148
|
+
|
|
149
|
+
const style = document.createElement('style')
|
|
150
|
+
style.id = styleId
|
|
151
|
+
style.textContent = `
|
|
152
|
+
@keyframes ripple-animation {
|
|
153
|
+
0% {
|
|
154
|
+
transform: scale(0);
|
|
155
|
+
opacity: 1;
|
|
156
|
+
}
|
|
157
|
+
100% {
|
|
158
|
+
transform: scale(2);
|
|
159
|
+
opacity: 0;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
@media (prefers-reduced-motion: reduce) {
|
|
164
|
+
@keyframes ripple-animation {
|
|
165
|
+
0%, 100% {
|
|
166
|
+
transform: scale(0);
|
|
167
|
+
opacity: 0;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
`
|
|
172
|
+
|
|
173
|
+
document.head.appendChild(style)
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
// Método para adicionar efeito ripple ao elemento
|
|
179
|
+
const addRippleEffect = () => {
|
|
180
|
+
if (!elementRef.value) return
|
|
181
|
+
return applyRipple(elementRef.value)
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Método para remover efeito ripple do elemento
|
|
185
|
+
const removeRippleEffect = () => {
|
|
186
|
+
if (!elementRef.value) return
|
|
187
|
+
|
|
188
|
+
elementRef.value.removeEventListener('click', handleClick)
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Injetar CSS na montagem
|
|
192
|
+
onMounted(() => {
|
|
193
|
+
injectRippleCSS()
|
|
194
|
+
|
|
195
|
+
// Auto-aplicar se elemento já existe
|
|
196
|
+
if (elementRef.value) {
|
|
197
|
+
addRippleEffect()
|
|
198
|
+
}
|
|
199
|
+
})
|
|
200
|
+
|
|
201
|
+
// Watch para aplicar ripple quando elemento for definido
|
|
202
|
+
watch(elementRef, (newElement) => {
|
|
203
|
+
if (newElement) {
|
|
204
|
+
addRippleEffect()
|
|
205
|
+
}
|
|
206
|
+
})
|
|
207
|
+
|
|
208
|
+
return {
|
|
209
|
+
rippleRef: elementRef,
|
|
210
|
+
ripples,
|
|
211
|
+
applyRipple,
|
|
212
|
+
removeRipple,
|
|
213
|
+
clearRipples,
|
|
214
|
+
getRippleStyle,
|
|
215
|
+
createRipple,
|
|
216
|
+
addRippleEffect,
|
|
217
|
+
removeRippleEffect
|
|
218
|
+
}
|
|
219
219
|
}
|
|
@@ -8,18 +8,22 @@ export function resetTheme() {
|
|
|
8
8
|
isDark = ref(false)
|
|
9
9
|
initialized = false
|
|
10
10
|
document.documentElement.classList.remove('dark')
|
|
11
|
+
document.documentElement.removeAttribute('data-theme')
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
export function useTheme() {
|
|
14
15
|
const toggleTheme = () => {
|
|
15
16
|
isDark.value = !isDark.value
|
|
17
|
+
const theme = isDark.value ? 'dark' : 'light'
|
|
16
18
|
document.documentElement.classList.toggle('dark', isDark.value)
|
|
17
|
-
|
|
19
|
+
document.documentElement.setAttribute('data-theme', theme)
|
|
20
|
+
localStorage.setItem('theme', theme)
|
|
18
21
|
}
|
|
19
22
|
|
|
20
23
|
const setTheme = (theme: 'light' | 'dark') => {
|
|
21
24
|
isDark.value = theme === 'dark'
|
|
22
25
|
document.documentElement.classList.toggle('dark', isDark.value)
|
|
26
|
+
document.documentElement.setAttribute('data-theme', theme)
|
|
23
27
|
localStorage.setItem('theme', theme)
|
|
24
28
|
}
|
|
25
29
|
|
package/src/index.ts
CHANGED
|
@@ -1,84 +1,84 @@
|
|
|
1
|
-
// Components - Form
|
|
2
|
-
export { default as DatametriaButton } from './components/DatametriaButton.vue'
|
|
3
|
-
export { default as DatametriaInput } from './components/DatametriaInput.vue' // v2.3.0
|
|
4
|
-
export { default as DatametriaPasswordInput } from './components/DatametriaPasswordInput.vue'
|
|
5
|
-
export { default as DatametriaSelect } from './components/DatametriaSelect.vue' // v2.3.0
|
|
6
|
-
export { default as DatametriaCheckbox } from './components/DatametriaCheckbox.vue' // v2.3.0
|
|
7
|
-
export { default as DatametriaCheckboxGroup } from './components/DatametriaCheckboxGroup.vue' // v2.3.0
|
|
8
|
-
export { default as DatametriaRadio } from './components/DatametriaRadio.vue' // v2.3.0
|
|
9
|
-
export { default as DatametriaRadioGroup } from './components/DatametriaRadioGroup.vue' // v2.3.0
|
|
10
|
-
export { default as DatametriaSwitch } from './components/DatametriaSwitch.vue' // v2.3.0
|
|
11
|
-
export { default as DatametriaTextarea } from './components/DatametriaTextarea.vue' // v2.3.0
|
|
12
|
-
export { default as DatametriaDatePicker } from './components/DatametriaDatePicker.vue' // v2.3.0
|
|
13
|
-
export { default as DatametriaTimePicker } from './components/DatametriaTimePicker.vue' // v2.3.0
|
|
14
|
-
export { default as DatametriaSlider } from './components/DatametriaSlider.vue'
|
|
15
|
-
export { default as DatametriaFileUpload } from './components/DatametriaFileUpload.vue'
|
|
16
|
-
export { default as DatametriaUpload } from './components/DatametriaUpload.vue' // v2.3.0
|
|
17
|
-
export { default as DatametriaAutocomplete } from './components/DatametriaAutocomplete.vue' // v2.3.0
|
|
18
|
-
export { default as DatametriaForm } from './components/DatametriaForm.vue' // v2.3.0
|
|
19
|
-
export { default as DatametriaFormItem } from './components/DatametriaFormItem.vue' // v2.3.0
|
|
20
|
-
|
|
21
|
-
// Components - Layout
|
|
22
|
-
export { default as DatametriaCard } from './components/DatametriaCard.vue'
|
|
23
|
-
export { default as DatametriaDialog } from './components/DatametriaDialog.vue'
|
|
24
|
-
export { default as DatametriaModal } from './components/DatametriaModal.vue'
|
|
25
|
-
export { default as DatametriaContainer } from './components/DatametriaContainer.vue'
|
|
26
|
-
export { default as DatametriaGrid } from './components/DatametriaGrid.vue'
|
|
27
|
-
export { default as DatametriaDivider } from './components/DatametriaDivider.vue'
|
|
28
|
-
|
|
29
|
-
// Components - Feedback
|
|
30
|
-
export { default as DatametriaAlert } from './components/DatametriaAlert.vue'
|
|
31
|
-
export { default as DatametriaToast } from './components/DatametriaToast.vue'
|
|
32
|
-
export { default as DatametriaTooltip } from './components/DatametriaTooltip.vue'
|
|
33
|
-
export { default as DatametriaSkeleton } from './components/DatametriaSkeleton.vue' // v2.3.0
|
|
34
|
-
export { default as DatametriaProgress } from './components/DatametriaProgress.vue' // v2.3.0
|
|
35
|
-
export { default as DatametriaResult } from './components/DatametriaResult.vue' // v2.3.0
|
|
36
|
-
export { default as DatametriaPopconfirm } from './components/DatametriaPopconfirm.vue' // v2.3.0
|
|
37
|
-
export { default as DatametriaSpinner } from './components/DatametriaSpinner.vue'
|
|
38
|
-
|
|
39
|
-
// Components - Data Display
|
|
40
|
-
export { default as DatametriaTable } from './components/DatametriaTable.vue'
|
|
41
|
-
export { default as DatametriaSortableTable } from './components/DatametriaSortableTable.vue'
|
|
42
|
-
export { default as DatametriaDataTable } from './components/DatametriaDataTable.vue' // v2.3.0
|
|
43
|
-
export { default as DatametriaPagination } from './components/DatametriaPagination.vue' // v2.3.0
|
|
44
|
-
export { default as DatametriaTree } from './components/DatametriaTree.vue' // v2.3.0
|
|
45
|
-
export { default as DatametriaEmpty } from './components/DatametriaEmpty.vue' // v2.3.0
|
|
46
|
-
export { default as DatametriaAvatar } from './components/DatametriaAvatar.vue'
|
|
47
|
-
export { default as DatametriaBadge } from './components/DatametriaBadge.vue'
|
|
48
|
-
export { default as DatametriaChip } from './components/DatametriaChip.vue'
|
|
49
|
-
|
|
50
|
-
// Components - Navigation
|
|
51
|
-
export { default as DatametriaNavbar } from './components/DatametriaNavbar.vue'
|
|
52
|
-
export { default as DatametriaSidebar } from './components/DatametriaSidebar.vue'
|
|
53
|
-
export { default as DatametriaFloatingBar } from './components/DatametriaFloatingBar.vue'
|
|
54
|
-
export { default as DatametriaMenu } from './components/DatametriaMenu.vue'
|
|
55
|
-
export { default as DatametriaBreadcrumb } from './components/DatametriaBreadcrumb.vue'
|
|
56
|
-
export { default as DatametriaSteps } from './components/DatametriaSteps.vue' // v2.3.0
|
|
57
|
-
export { default as DatametriaTabs } from './components/DatametriaTabs.vue'
|
|
58
|
-
export { default as DatametriaTabPane } from './components/DatametriaTabPane.vue' // v2.3.0
|
|
59
|
-
|
|
60
|
-
// Composables - Core
|
|
61
|
-
export { useValidation, required, email, minLength, maxLength, pattern, custom } from './composables/useValidation'
|
|
62
|
-
export { useAPI } from './composables/useAPI'
|
|
63
|
-
|
|
64
|
-
// Composables - Utility
|
|
65
|
-
export { useAccessibilityScale } from './composables/useAccessibilityScale'
|
|
66
|
-
export { useBreakpoints } from './composables/useBreakpoints'
|
|
67
|
-
export { useRipple } from './composables/useRipple'
|
|
68
|
-
export { useHapticFeedback } from './composables/useHapticFeedback'
|
|
69
|
-
export { useLocalStorage } from './composables/useLocalStorage'
|
|
70
|
-
export { useDebounce } from './composables/useDebounce'
|
|
71
|
-
export { useClipboard } from './composables/useClipboard'
|
|
72
|
-
|
|
73
|
-
// Theming System (v2.0)
|
|
74
|
-
export { default as ThemeProvider } from './theme/ThemeProvider.vue'
|
|
75
|
-
export { useTheme } from './theme/useTheme'
|
|
76
|
-
export { datametriaTheme, defaultTheme } from './theme/presets'
|
|
77
|
-
export type { Theme, ThemeTokens } from './theme/types'
|
|
78
|
-
|
|
79
|
-
// Types
|
|
80
|
-
export type ButtonVariant = 'primary' | 'secondary' | 'tertiary' | 'outline'
|
|
81
|
-
export type ButtonSize = 'sm' | 'md' | 'lg'
|
|
82
|
-
export type AlertVariant = 'info' | 'success' | 'warning' | 'error'
|
|
83
|
-
export type BadgeVariant = 'default' | 'primary' | 'success' | 'warning' | 'error' | 'info'
|
|
84
|
-
export type BadgeSize = 'sm' | 'md' | 'lg'
|
|
1
|
+
// Components - Form
|
|
2
|
+
export { default as DatametriaButton } from './components/DatametriaButton.vue'
|
|
3
|
+
export { default as DatametriaInput } from './components/DatametriaInput.vue' // v2.3.0
|
|
4
|
+
export { default as DatametriaPasswordInput } from './components/DatametriaPasswordInput.vue'
|
|
5
|
+
export { default as DatametriaSelect } from './components/DatametriaSelect.vue' // v2.3.0
|
|
6
|
+
export { default as DatametriaCheckbox } from './components/DatametriaCheckbox.vue' // v2.3.0
|
|
7
|
+
export { default as DatametriaCheckboxGroup } from './components/DatametriaCheckboxGroup.vue' // v2.3.0
|
|
8
|
+
export { default as DatametriaRadio } from './components/DatametriaRadio.vue' // v2.3.0
|
|
9
|
+
export { default as DatametriaRadioGroup } from './components/DatametriaRadioGroup.vue' // v2.3.0
|
|
10
|
+
export { default as DatametriaSwitch } from './components/DatametriaSwitch.vue' // v2.3.0
|
|
11
|
+
export { default as DatametriaTextarea } from './components/DatametriaTextarea.vue' // v2.3.0
|
|
12
|
+
export { default as DatametriaDatePicker } from './components/DatametriaDatePicker.vue' // v2.3.0
|
|
13
|
+
export { default as DatametriaTimePicker } from './components/DatametriaTimePicker.vue' // v2.3.0
|
|
14
|
+
export { default as DatametriaSlider } from './components/DatametriaSlider.vue'
|
|
15
|
+
export { default as DatametriaFileUpload } from './components/DatametriaFileUpload.vue'
|
|
16
|
+
export { default as DatametriaUpload } from './components/DatametriaUpload.vue' // v2.3.0
|
|
17
|
+
export { default as DatametriaAutocomplete } from './components/DatametriaAutocomplete.vue' // v2.3.0
|
|
18
|
+
export { default as DatametriaForm } from './components/DatametriaForm.vue' // v2.3.0
|
|
19
|
+
export { default as DatametriaFormItem } from './components/DatametriaFormItem.vue' // v2.3.0
|
|
20
|
+
|
|
21
|
+
// Components - Layout
|
|
22
|
+
export { default as DatametriaCard } from './components/DatametriaCard.vue'
|
|
23
|
+
export { default as DatametriaDialog } from './components/DatametriaDialog.vue'
|
|
24
|
+
export { default as DatametriaModal } from './components/DatametriaModal.vue'
|
|
25
|
+
export { default as DatametriaContainer } from './components/DatametriaContainer.vue'
|
|
26
|
+
export { default as DatametriaGrid } from './components/DatametriaGrid.vue'
|
|
27
|
+
export { default as DatametriaDivider } from './components/DatametriaDivider.vue'
|
|
28
|
+
|
|
29
|
+
// Components - Feedback
|
|
30
|
+
export { default as DatametriaAlert } from './components/DatametriaAlert.vue'
|
|
31
|
+
export { default as DatametriaToast } from './components/DatametriaToast.vue'
|
|
32
|
+
export { default as DatametriaTooltip } from './components/DatametriaTooltip.vue'
|
|
33
|
+
export { default as DatametriaSkeleton } from './components/DatametriaSkeleton.vue' // v2.3.0
|
|
34
|
+
export { default as DatametriaProgress } from './components/DatametriaProgress.vue' // v2.3.0
|
|
35
|
+
export { default as DatametriaResult } from './components/DatametriaResult.vue' // v2.3.0
|
|
36
|
+
export { default as DatametriaPopconfirm } from './components/DatametriaPopconfirm.vue' // v2.3.0
|
|
37
|
+
export { default as DatametriaSpinner } from './components/DatametriaSpinner.vue'
|
|
38
|
+
|
|
39
|
+
// Components - Data Display
|
|
40
|
+
export { default as DatametriaTable } from './components/DatametriaTable.vue'
|
|
41
|
+
export { default as DatametriaSortableTable } from './components/DatametriaSortableTable.vue'
|
|
42
|
+
export { default as DatametriaDataTable } from './components/DatametriaDataTable.vue' // v2.3.0
|
|
43
|
+
export { default as DatametriaPagination } from './components/DatametriaPagination.vue' // v2.3.0
|
|
44
|
+
export { default as DatametriaTree } from './components/DatametriaTree.vue' // v2.3.0
|
|
45
|
+
export { default as DatametriaEmpty } from './components/DatametriaEmpty.vue' // v2.3.0
|
|
46
|
+
export { default as DatametriaAvatar } from './components/DatametriaAvatar.vue'
|
|
47
|
+
export { default as DatametriaBadge } from './components/DatametriaBadge.vue'
|
|
48
|
+
export { default as DatametriaChip } from './components/DatametriaChip.vue'
|
|
49
|
+
|
|
50
|
+
// Components - Navigation
|
|
51
|
+
export { default as DatametriaNavbar } from './components/DatametriaNavbar.vue'
|
|
52
|
+
export { default as DatametriaSidebar } from './components/DatametriaSidebar.vue'
|
|
53
|
+
export { default as DatametriaFloatingBar } from './components/DatametriaFloatingBar.vue'
|
|
54
|
+
export { default as DatametriaMenu } from './components/DatametriaMenu.vue'
|
|
55
|
+
export { default as DatametriaBreadcrumb } from './components/DatametriaBreadcrumb.vue'
|
|
56
|
+
export { default as DatametriaSteps } from './components/DatametriaSteps.vue' // v2.3.0
|
|
57
|
+
export { default as DatametriaTabs } from './components/DatametriaTabs.vue'
|
|
58
|
+
export { default as DatametriaTabPane } from './components/DatametriaTabPane.vue' // v2.3.0
|
|
59
|
+
|
|
60
|
+
// Composables - Core
|
|
61
|
+
export { useValidation, required, email, minLength, maxLength, pattern, custom } from './composables/useValidation'
|
|
62
|
+
export { useAPI } from './composables/useAPI'
|
|
63
|
+
|
|
64
|
+
// Composables - Utility
|
|
65
|
+
export { useAccessibilityScale } from './composables/useAccessibilityScale'
|
|
66
|
+
export { useBreakpoints } from './composables/useBreakpoints'
|
|
67
|
+
export { useRipple } from './composables/useRipple'
|
|
68
|
+
export { useHapticFeedback } from './composables/useHapticFeedback'
|
|
69
|
+
export { useLocalStorage } from './composables/useLocalStorage'
|
|
70
|
+
export { useDebounce } from './composables/useDebounce'
|
|
71
|
+
export { useClipboard } from './composables/useClipboard'
|
|
72
|
+
|
|
73
|
+
// Theming System (v2.0)
|
|
74
|
+
export { default as ThemeProvider } from './theme/ThemeProvider.vue'
|
|
75
|
+
export { useTheme } from './theme/useTheme'
|
|
76
|
+
export { datametriaTheme, defaultTheme } from './theme/presets'
|
|
77
|
+
export type { Theme, ThemeTokens } from './theme/types'
|
|
78
|
+
|
|
79
|
+
// Types
|
|
80
|
+
export type ButtonVariant = 'primary' | 'secondary' | 'tertiary' | 'outline'
|
|
81
|
+
export type ButtonSize = 'sm' | 'md' | 'lg'
|
|
82
|
+
export type AlertVariant = 'info' | 'success' | 'warning' | 'error'
|
|
83
|
+
export type BadgeVariant = 'default' | 'primary' | 'success' | 'warning' | 'error' | 'info'
|
|
84
|
+
export type BadgeSize = 'sm' | 'md' | 'lg'
|