@luis-angel-martin-dzul/input-styles 0.0.32 → 0.0.33

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 CHANGED
@@ -1078,6 +1078,32 @@ loader.close()
1078
1078
 
1079
1079
  ------
1080
1080
 
1081
+ # 🧭 Directivas
1082
+
1083
+ ## `v-title-style`
1084
+
1085
+ Muestra un **tooltip** ("globo de diálogo") sobre **cualquier etiqueta o componente**, reemplazando al atributo `title` nativo del navegador. Su **fondo es ligeramente transparente** con un sutil desenfoque del contenido que queda detrás.
1086
+
1087
+ - **Escritorio (mouse):** aparece al pasar el cursor y se oculta al salir.
1088
+ - **Móvil (touch):** se muestra al tocar el elemento y se oculta al tocar de nuevo o fuera.
1089
+ - Acepta **texto plano** (fijo o desde una variable reactiva).
1090
+
1091
+ Si instalas la librería con `app.use(InputStyles)`, la directiva queda registrada **global** automáticamente. Si la usas en un componente que no instala el plugin, regístrala local: `import { TitleStyle } from '@luis-angel-martin-dzul/input-styles'` y `directives: { titleStyle: TitleStyle }`.
1092
+
1093
+ ```vue
1094
+ <!-- Texto fijo (nota las comillas simples internas) -->
1095
+ <button v-title-style="'Guarda los cambios'">Guardar</button>
1096
+
1097
+ <!-- Sobre cualquier etiqueta o componente -->
1098
+ <span v-title-style="'Información adicional'">ⓘ</span>
1099
+ <button-style v-title-style="'Tooltip translúcido sobre un ButtonStyle'">Con tooltip</button-style>
1100
+
1101
+ <!-- Texto dinámico -->
1102
+ <button v-title-style="mensajeAyuda">Enviar</button>
1103
+ ```
1104
+
1105
+ ------
1106
+
1081
1107
  ## UtilStyle (utilidades)
1082
1108
 
1083
1109
  Clase con métodos estáticos de utilidad (formateo, validaciones, manejo de archivos, etc.). Disponible como propiedad global `$utilstyle` tras instalar el plugin, o mediante importación directa.
@@ -1096,6 +1122,7 @@ UtilStyle.getUUID()
1096
1122
  | `getUUID()` | — | Genera un UUID v4 (usa `crypto.randomUUID` con fallback manual). |
1097
1123
  | `formatMoney(valor, dollar?, digit?)` | `Number, String, Number` | Formatea un número como moneda (ej: `$1,234.56`). |
1098
1124
  | `formatNumber(valor, digit?)` | `Number, Number` | Formatea un número con separadores de miles y decimales fijos. |
1125
+ | `formatBytes(bytes, digit?)` | `Number, Number` | Formatea un tamaño en bytes a `B` / `KB` / `MB` legible (ej: `296.0 KB`). |
1099
1126
  | `formatDateShort(dateString)` | `String` | Fecha en formato corto en español (ej: `9 jul 2026`). |
1100
1127
  | `formatDateLong(dateString)` | `String` | Fecha en formato largo en español (ej: `9 de julio de 2026`). |
1101
1128
  | `formatDateTimeShort(dateString, hour12?)` | `String, Boolean` | Fecha y hora en formato corto en español (ej: `9 jul 2026, 12:00 p. m.`). `hour12` (default `true`) alterna entre 12h y 24h. |
@@ -1113,11 +1140,124 @@ UtilStyle.getUUID()
1113
1140
  | `fileToBase64(file)` | `File` | Convierte un `File` a base64 (async, retorna `Promise`). |
1114
1141
  | `base64ToBlob(base64, mimeType?)` | `String, String` | Convierte una cadena base64 a `Blob`. |
1115
1142
  | `base64ToFile(base64, fileName?, mimeType?)` | `String, String, String` | Convierte una cadena base64 a `File`. |
1143
+ | `fileToImage(file)` | `File` | Carga un `File` de imagen en un `HTMLImageElement` (async, retorna `Promise`). Libera el object URL al terminar. |
1144
+ | `compressToWebp(file, quality?, maxWidth?)` | `File, Number, Number` | Comprime una imagen a **WebP** en el navegador (async). Ver [Compresión de imágenes a WebP](#compresión-de-imágenes-a-webp). |
1116
1145
 
1117
1146
  > 💡 Los métodos de validación (`validateTel`, `validateEmail`, `validateFile*`) devuelven `true` si el valor es válido, o un `String` con el mensaje de error si no lo es.
1118
1147
 
1119
1148
  ------
1120
1149
 
1150
+ # 🖼️ Compresión de imágenes a WebP
1151
+
1152
+ Convierte imágenes (PNG, JPEG, etc.) a **WebP** directamente en el navegador —sin subir nada al servidor— usando la Canvas API. Útil para reducir el peso de las imágenes **antes** de enviarlas a tu backend.
1153
+
1154
+ El método principal es `UtilStyle.compressToWebp(file, quality, maxWidth)`.
1155
+
1156
+ ```js
1157
+ // file: Number, quality: 0 a 1 (ej. 0.8 = 80%), maxWidth: px (opcional)
1158
+ const res = await UtilStyle.compressToWebp(file, 0.8, 1920)
1159
+ ```
1160
+
1161
+ | Parámetro | Tipo | Default | Descripción |
1162
+ | --------- | ---- | ------- | ----------- |
1163
+ | `file` | `File` | — | Archivo de imagen original (PNG/JPEG/etc). |
1164
+ | `quality` | `Number` | `0.8` | Calidad de `0` a `1` (ej: `0.8` = 80%). Solo aplica en WebP con pérdida. |
1165
+ | `maxWidth` | `Number \| null` | `null` | Si se indica, redimensiona manteniendo proporción. Recomendado para fotos grandes. |
1166
+
1167
+ **Retorna** una `Promise` que resuelve a un objeto:
1168
+
1169
+ ```js
1170
+ {
1171
+ blob, // Blob de la imagen WebP (listo para subir o descargar)
1172
+ originalSize, // Tamaño original en bytes
1173
+ compressedSize, // Tamaño comprimido en bytes
1174
+ ratio, // % de ahorro (positivo = más ligero; negativo = más pesado)
1175
+ width, height, // Dimensiones finales del WebP
1176
+ }
1177
+ ```
1178
+
1179
+ ## ¿Cuándo usarlo?
1180
+
1181
+ ✅ **Úsalo cuando:**
1182
+ - Quieras **reducir el peso** de imágenes que suben tus usuarios antes de enviarlas al servidor (ahorra ancho de banda y almacenamiento).
1183
+ - Trabajes con **fotos** o imágenes con muchos colores/degradados (es donde WebP más ahorra).
1184
+ - Quieras **previsualizar** el ahorro antes de confirmar la subida.
1185
+
1186
+ ⚠️ **Evítalo / revísalo cuando:**
1187
+ - Necesites soportar **Safari**: su canvas no codifica WebP de forma fiable y puede devolver un PNG disfrazado. El método **detecta esto y lanza un error explícito** en vez de entregar un archivo "mentiroso". Para soporte universal usa un encoder WASM (p. ej. `@jsquash/webp`) como fallback.
1188
+ - La imagen sea un **ícono/ilustración plana con pocos colores**: el ahorro de WebP con pérdida es mínimo y puede generar ruido en los bordes. Considera dejarla como PNG.
1189
+ - Necesites conservar **metadatos EXIF** (orientación, geolocalización): el canvas los descarta. Pásale `maxWidth` y ten en cuenta que fotos con orientación EXIF podrían rotarse.
1190
+
1191
+ > 💡 **Referencia de ahorro** (cifras oficiales del equipo WebP de Google): lossless ≈ 26% menos que PNG; con pérdida 25–34% menos que JPEG a calidad visual equivalente. No hay un porcentaje fijo: depende del contenido. **Calidad recomendada:** 75–85% para fotos (a partir de 75% la diferencia suele ser imperceptible).
1192
+
1193
+ ## Uso básico (un archivo)
1194
+
1195
+ ```js
1196
+ import { UtilStyle } from '@luis-angel-martin-dzul/input-styles'
1197
+
1198
+ async function comprimir(file) {
1199
+ try {
1200
+ const res = await UtilStyle.compressToWebp(file, 0.8, 1920)
1201
+
1202
+ console.log(`Ahorro: ${res.ratio}%`)
1203
+ console.log(`${UtilStyle.formatBytes(res.originalSize)} → ${UtilStyle.formatBytes(res.compressedSize)}`)
1204
+
1205
+ // Subir al servidor
1206
+ const formData = new FormData()
1207
+ formData.append('imagen', res.blob, file.name.replace(/\.\w+$/, '.webp'))
1208
+ // await fetch('/api/upload', { method: 'POST', body: formData })
1209
+
1210
+ // O descargar localmente (reutiliza downloadBlob de UtilStyle)
1211
+ UtilStyle.downloadBlob(res.blob, 'imagen.webp', 'image/webp')
1212
+ } catch (e) {
1213
+ console.error(e.message) // p. ej. error de Safari
1214
+ }
1215
+ }
1216
+ ```
1217
+
1218
+ ## Uso con validación y múltiples archivos (Options API)
1219
+
1220
+ ```vue
1221
+ <template>
1222
+ <input type="file" accept="image/*" multiple @change="onFiles" />
1223
+ <p v-if="error" class="text-red-500">{{ error }}</p>
1224
+ </template>
1225
+
1226
+ <script>
1227
+ export default {
1228
+ data() {
1229
+ return { error: '', resultados: [] }
1230
+ },
1231
+ methods: {
1232
+ async onFiles(e) {
1233
+ this.error = ''
1234
+ const files = Array.from(e.target.files || [])
1235
+
1236
+ for (const file of files) {
1237
+ // Reutiliza las validaciones de UtilStyle
1238
+ const extOk = this.$utilstyle.validateFileExtension(file, ['png', 'jpg', 'jpeg'])
1239
+ if (extOk !== true) { this.error = extOk; continue }
1240
+
1241
+ const sizeOk = this.$utilstyle.validateFileSize(file, 10)
1242
+ if (sizeOk !== true) { this.error = sizeOk; continue }
1243
+
1244
+ try {
1245
+ const res = await this.$utilstyle.compressToWebp(file, 0.8, 1920)
1246
+ this.resultados.push(res)
1247
+ } catch (err) {
1248
+ this.error = err.message
1249
+ }
1250
+ }
1251
+ }
1252
+ }
1253
+ }
1254
+ </script>
1255
+ ```
1256
+
1257
+ > ℹ️ La librería expone **solo los métodos** de compresión en `UtilStyle`; no incluye un componente visual. Si necesitas una UI lista (selector + comparación de tamaños + descarga), puedes construirla sobre estos métodos como en el ejemplo anterior.
1258
+
1259
+ ------
1260
+
1121
1261
  ## Ejemplo de uso completo
1122
1262
 
1123
1263
  ```vue
@@ -1,2 +1,2 @@
1
- .alert-container{z-index:99999;flex-direction:column;gap:10px;width:340px;display:flex;position:fixed;top:20px;right:20px}.alert{opacity:0;background-color:#f9fafb;border:1px solid #0000;border-radius:.375rem;align-items:center;gap:12px;padding:12px 16px;transition:opacity .25s,transform .25s;display:flex;transform:translate(40px);box-shadow:0 2px 6px #0000001f}.alert.show{opacity:1;transform:translate(0)}.alert.hide{opacity:0;transform:translate(40px)}.alert-icon{justify-content:center;align-items:center;width:26px;display:flex}.alert-icon svg{width:22px;height:22px;display:block}.alert-icon svg path{fill:currentColor!important}.alert-texts{flex:1}.alert-title{text-overflow:ellipsis;font-size:14px;font-weight:700;overflow:hidden}.alert-message{-webkit-box-orient:vertical;margin-top:2px;font-size:13px;display:-webkit-box;overflow:hidden}.alert-close{cursor:pointer;border-radius:.5rem;justify-content:center;align-items:center;width:28px;height:28px;font-size:18px;font-weight:700;transition:all .2s;display:flex}.alert-close:hover{background:#d1d5db}.alert-success{color:#065f46;background-color:#ecfdf5;border-color:#b4dfc6}.alert-error{color:#991b1b;background-color:#fef2f2;border-color:#f0c5c5}.alert-warning{color:#92400e;background-color:#fffbeb;border-color:#f0dfa5}.alert-info{color:#1e40af;background-color:#eff6ff;border-color:#c7daf5}.alert-neutral{color:#374151;background-color:#f3f4f6;border-color:#cbd5e1}.dialog-overlay{z-index:99998;opacity:0;background:#00000073;justify-content:center;align-items:center;width:100%;height:100%;transition:opacity .25s;display:flex;position:fixed;top:0;left:0}.dialog-overlay.show{opacity:1}.dialog-box{background:#fff;border-radius:.5rem;flex-direction:column;width:400px;max-width:90%;max-height:90vh;padding:1rem;transition:transform .25s;display:flex;transform:translateY(-20px);box-shadow:0 25px 50px -12px #00000040}.dialog-overlay.show .dialog-box{transform:translateY(0)}.dialog-box.fixed-width{width:380px;max-width:90%}.dialog-title{color:#1f2937;font-size:18px;font-weight:700}.dialog-description{color:#374151;white-space:pre-line;margin-bottom:10px;font-size:14px}.dialog-buttons{gap:10px;margin-top:10px;display:flex}.dialog-buttons.two-buttons{grid-template-columns:1fr 1fr;gap:10px;display:grid}.dialog-buttons.one-button{display:flex}.dialog-buttons.one-button .dialog-btn{flex:1}.dialog-btn{cursor:pointer;text-align:center;justify-content:center;align-items:center;gap:6px;font-size:14px;font-weight:600;transition:all .2s;display:inline-flex}.dialog-buttons .dialog-btn{flex:1}.btn-blue{color:#fff;cursor:pointer;background-color:#0284c7;border:none;border-radius:.125rem;padding:.25rem .5rem;font-size:.75rem;transition:background-color .2s}.btn-blue:hover{background-color:#0ea5e9}.btn-blue:disabled{color:#6b7280;cursor:not-allowed;background-color:#7dd3fc}.btn-white{color:#374151;cursor:pointer;background-color:#fff;border:1px solid #d1d5db;border-radius:.125rem;padding:.25rem .5rem;font-size:.75rem;transition:background-color .2s}.btn-white:hover{background-color:#f3f4f6}.btn-white:disabled{color:#6b7280;cursor:not-allowed;background-color:#d1d5db}.dialog-btn-cancel{color:#374151;cursor:pointer;background-color:#fff;border:1px solid #d1d5db;border-radius:.125rem;padding:.25rem .5rem;font-size:.75rem;transition:background-color .2s}.dialog-btn-cancel:hover{background-color:#f3f4f6}.dialog-btn-cancel:disabled{color:#6b7280;cursor:not-allowed;background-color:#d1d5db}.dialog-btn-accept{color:#fff;cursor:pointer;background-color:#0284c7;border:none;border-radius:.125rem;padding:.25rem .5rem;font-size:.75rem;transition:background-color .2s}.dialog-btn-accept:hover{background-color:#0ea5e9}.dialog-btn-accept:disabled{color:#6b7280;cursor:not-allowed;background-color:#7dd3fc}.dialog-loading-layout{gap:16px;min-height:60px;margin-top:16px;display:flex}.dialog-loading-icon{flex-shrink:0;align-items:center;min-height:60px;display:flex}.dialog-loading-spinner{border:3px solid #e5e7eb;border-top-color:#0d9488;border-radius:50%;width:40px;height:40px;animation:.8s linear infinite dialog-spin}.dialog-loading-texts{flex-direction:column;flex:1;justify-content:center;gap:4px;display:flex}.dialog-loading-title{color:#1f2937;font-size:15px;font-weight:600;line-height:1.4}.dialog-loading-message{color:#6b7280;font-size:13px;line-height:1.4}@keyframes dialog-spin{to{transform:rotate(360deg)}}@keyframes dialogShake{0%{transform:translateY(0)}30%{transform:translateY(-6px)}60%{transform:translateY(3px)}to{transform:translateY(0)}}.dialog-shake{animation:.25s dialogShake}.dialog-box:has(.dialog-loading-layout) .dialog-title{display:none}.dialog-box:has(.dialog-loading-layout) .dialog-description{display:none}.dialog-box:has(.dialog-loading-layout:only-child){padding:1rem}.dialog-box:has(.dialog-loading-layout):not(:has(.dialog-buttons)){padding-bottom:1rem}.dialog-box:has(.dialog-loading-layout:first-child:last-child) .dialog-loading-layout{margin-top:0}input[type=date][data-v-6906d068]::-webkit-calendar-picker-indicator{-webkit-appearance:none;display:none}input[type=datetime-local][data-v-6906d068]::-webkit-calendar-picker-indicator{-webkit-appearance:none;display:none}input[type=time][data-v-6906d068]::-webkit-calendar-picker-indicator{-webkit-appearance:none;display:none}input[type=date][data-v-6906d068],input[type=datetime-local][data-v-6906d068],input[type=time][data-v-6906d068]{appearance:none;-moz-appearance:textfield}input[type=date][data-v-0b52f379]::-webkit-calendar-picker-indicator{-webkit-appearance:none;display:none}input[type=datetime-local][data-v-0b52f379]::-webkit-calendar-picker-indicator{-webkit-appearance:none;display:none}input[type=time][data-v-0b52f379]::-webkit-calendar-picker-indicator{-webkit-appearance:none;display:none}input[type=date][data-v-0b52f379],input[type=datetime-local][data-v-0b52f379],input[type=time][data-v-0b52f379]{appearance:none;-moz-appearance:textfield}input[type=date][data-v-b6006f07]::-webkit-calendar-picker-indicator{-webkit-appearance:none;display:none}input[type=datetime-local][data-v-b6006f07]::-webkit-calendar-picker-indicator{-webkit-appearance:none;display:none}input[type=time][data-v-b6006f07]::-webkit-calendar-picker-indicator{-webkit-appearance:none;display:none}input[type=date][data-v-b6006f07],input[type=datetime-local][data-v-b6006f07],input[type=time][data-v-b6006f07]{appearance:none;-moz-appearance:textfield}
1
+ .alert-container{z-index:99999;flex-direction:column;gap:10px;width:340px;display:flex;position:fixed;top:20px;right:20px}.alert{opacity:0;background-color:#f9fafb;border:1px solid #0000;border-radius:.375rem;align-items:center;gap:12px;padding:12px 16px;transition:opacity .25s,transform .25s;display:flex;transform:translate(40px);box-shadow:0 2px 6px #0000001f}.alert.show{opacity:1;transform:translate(0)}.alert.hide{opacity:0;transform:translate(40px)}.alert-icon{justify-content:center;align-items:center;width:26px;display:flex}.alert-icon svg{width:22px;height:22px;display:block}.alert-icon svg path{fill:currentColor!important}.alert-texts{flex:1}.alert-title{text-overflow:ellipsis;font-size:14px;font-weight:700;overflow:hidden}.alert-message{-webkit-box-orient:vertical;margin-top:2px;font-size:13px;display:-webkit-box;overflow:hidden}.alert-close{cursor:pointer;border-radius:.5rem;justify-content:center;align-items:center;width:28px;height:28px;font-size:18px;font-weight:700;transition:all .2s;display:flex}.alert-close:hover{background:#d1d5db}.alert-success{color:#065f46;background-color:#ecfdf5;border-color:#b4dfc6}.alert-error{color:#991b1b;background-color:#fef2f2;border-color:#f0c5c5}.alert-warning{color:#92400e;background-color:#fffbeb;border-color:#f0dfa5}.alert-info{color:#1e40af;background-color:#eff6ff;border-color:#c7daf5}.alert-neutral{color:#374151;background-color:#f3f4f6;border-color:#cbd5e1}.dialog-overlay{z-index:99998;opacity:0;background:#00000073;justify-content:center;align-items:center;width:100%;height:100%;transition:opacity .25s;display:flex;position:fixed;top:0;left:0}.dialog-overlay.show{opacity:1}.dialog-box{background:#fff;border-radius:.5rem;flex-direction:column;width:400px;max-width:90%;max-height:90vh;padding:1rem;transition:transform .25s;display:flex;transform:translateY(-20px);box-shadow:0 25px 50px -12px #00000040}.dialog-overlay.show .dialog-box{transform:translateY(0)}.dialog-box.fixed-width{width:380px;max-width:90%}.dialog-title{color:#1f2937;font-size:18px;font-weight:700}.dialog-description{color:#374151;white-space:pre-line;margin-bottom:10px;font-size:14px}.dialog-buttons{gap:10px;margin-top:10px;display:flex}.dialog-buttons.two-buttons{grid-template-columns:1fr 1fr;gap:10px;display:grid}.dialog-buttons.one-button{display:flex}.dialog-buttons.one-button .dialog-btn{flex:1}.dialog-btn{cursor:pointer;text-align:center;justify-content:center;align-items:center;gap:6px;font-size:14px;font-weight:600;transition:all .2s;display:inline-flex}.dialog-buttons .dialog-btn{flex:1}.btn-blue{color:#fff;cursor:pointer;background-color:#0284c7;border:none;border-radius:.125rem;padding:.25rem .5rem;font-size:.75rem;transition:background-color .2s}.btn-blue:hover{background-color:#0ea5e9}.btn-blue:disabled{color:#6b7280;cursor:not-allowed;background-color:#7dd3fc}.btn-white{color:#374151;cursor:pointer;background-color:#fff;border:1px solid #d1d5db;border-radius:.125rem;padding:.25rem .5rem;font-size:.75rem;transition:background-color .2s}.btn-white:hover{background-color:#f3f4f6}.btn-white:disabled{color:#6b7280;cursor:not-allowed;background-color:#d1d5db}.dialog-btn-cancel{color:#374151;cursor:pointer;background-color:#fff;border:1px solid #d1d5db;border-radius:.125rem;padding:.25rem .5rem;font-size:.75rem;transition:background-color .2s}.dialog-btn-cancel:hover{background-color:#f3f4f6}.dialog-btn-cancel:disabled{color:#6b7280;cursor:not-allowed;background-color:#d1d5db}.dialog-btn-accept{color:#fff;cursor:pointer;background-color:#0284c7;border:none;border-radius:.125rem;padding:.25rem .5rem;font-size:.75rem;transition:background-color .2s}.dialog-btn-accept:hover{background-color:#0ea5e9}.dialog-btn-accept:disabled{color:#6b7280;cursor:not-allowed;background-color:#7dd3fc}.dialog-loading-layout{gap:16px;min-height:60px;margin-top:16px;display:flex}.dialog-loading-icon{flex-shrink:0;align-items:center;min-height:60px;display:flex}.dialog-loading-spinner{border:3px solid #e5e7eb;border-top-color:#0d9488;border-radius:50%;width:40px;height:40px;animation:.8s linear infinite dialog-spin}.dialog-loading-texts{flex-direction:column;flex:1;justify-content:center;gap:4px;display:flex}.dialog-loading-title{color:#1f2937;font-size:15px;font-weight:600;line-height:1.4}.dialog-loading-message{color:#6b7280;font-size:13px;line-height:1.4}@keyframes dialog-spin{to{transform:rotate(360deg)}}@keyframes dialogShake{0%{transform:translateY(0)}30%{transform:translateY(-6px)}60%{transform:translateY(3px)}to{transform:translateY(0)}}.dialog-shake{animation:.25s dialogShake}.dialog-box:has(.dialog-loading-layout) .dialog-title{display:none}.dialog-box:has(.dialog-loading-layout) .dialog-description{display:none}.dialog-box:has(.dialog-loading-layout:only-child){padding:1rem}.dialog-box:has(.dialog-loading-layout):not(:has(.dialog-buttons)){padding-bottom:1rem}.dialog-box:has(.dialog-loading-layout:first-child:last-child) .dialog-loading-layout{margin-top:0}input[type=date][data-v-d92ec80f]::-webkit-calendar-picker-indicator{-webkit-appearance:none;display:none}input[type=datetime-local][data-v-d92ec80f]::-webkit-calendar-picker-indicator{-webkit-appearance:none;display:none}input[type=time][data-v-d92ec80f]::-webkit-calendar-picker-indicator{-webkit-appearance:none;display:none}input[type=date][data-v-d92ec80f],input[type=datetime-local][data-v-d92ec80f],input[type=time][data-v-d92ec80f]{appearance:none;-moz-appearance:textfield}input[type=date][data-v-e97771cd]::-webkit-calendar-picker-indicator{-webkit-appearance:none;display:none}input[type=datetime-local][data-v-e97771cd]::-webkit-calendar-picker-indicator{-webkit-appearance:none;display:none}input[type=time][data-v-e97771cd]::-webkit-calendar-picker-indicator{-webkit-appearance:none;display:none}input[type=date][data-v-e97771cd],input[type=datetime-local][data-v-e97771cd],input[type=time][data-v-e97771cd]{appearance:none;-moz-appearance:textfield}input[type=date][data-v-a247cb20]::-webkit-calendar-picker-indicator{-webkit-appearance:none;display:none}input[type=datetime-local][data-v-a247cb20]::-webkit-calendar-picker-indicator{-webkit-appearance:none;display:none}input[type=time][data-v-a247cb20]::-webkit-calendar-picker-indicator{-webkit-appearance:none;display:none}input[type=date][data-v-a247cb20],input[type=datetime-local][data-v-a247cb20],input[type=time][data-v-a247cb20]{appearance:none;-moz-appearance:textfield}
2
2
  /*$vite$:1*/