{"_id":"@clube-certo/front-commons","_rev":"4-76d77ea7fc5342571afa8b74f852d7db","name":"@clube-certo/front-commons","dist-tags":{"latest":"1.0.3"},"versions":{"1.0.0":{"name":"@clube-certo/front-commons","version":"1.0.0","keywords":["vue","vue3","components","utils","typescript","clubecerto"],"author":{"name":"Clube Certo"},"license":"MIT","_id":"@clube-certo/front-commons@1.0.0","maintainers":[{"name":"clube-certo","email":"ti@clubecerto.com.br"}],"homepage":"https://github.com/clubecerto/front-commons#readme","bugs":{"url":"https://github.com/clubecerto/front-commons/issues"},"dist":{"shasum":"9ac059cb82ea63917cd575bc95d541337c83e210","tarball":"https://registry.npmjs.org/@clube-certo/front-commons/-/front-commons-1.0.0.tgz","fileCount":348,"integrity":"sha512-NaNe32IIhIBzLuhetdd+M3krxjJBLU1Q4F0NgR0r4SWN64ZKiaqq/13iCadA4XJ33dCNFoOmMWyDWYJer1JHGA==","signatures":[{"sig":"MEUCIHKL51oKj44TlSh+b0y9h/4VWdbppfyjxdcYb0uvJ8OtAiEAixe5PK/0D2MJBziyAdrB8DZIloe/fGgTZ8m+eDWNajA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3485345},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","module":"dist/index.esm.js","gitHead":"22f093d281ac343524a4a7b8933407c03e60360c","scripts":{"dev":"rollup -c -w","lint":"eslint src --ext .ts,.vue,.js","test":"vitest","build":"rollup -c","test:ui":"vitest --ui","lint:fix":"eslint src --ext .ts,.vue,.js --fix","test:watch":"vitest --watch","type-check":"vue-tsc --noEmit","build:watch":"rollup -c -w","prepublishOnly":"npm run build"},"_npmUser":{"name":"clube-certo","actor":{"name":"clube-certo","type":"user","email":"ti@clubecerto.com.br"},"email":"ti@clubecerto.com.br"},"repository":{"url":"git+https://github.com/clubecerto/front-commons.git","type":"git"},"_npmVersion":"10.2.4","description":"Biblioteca de componentes, funções e utils compartilhados para projetos Vue 3 do Clube Certo","directories":{},"_nodeVersion":"20.11.0","dependencies":{"vue":"^3.0.0","clsx":"^2.1.1","axios":"^1.10.0","jwt-decode":"^4.0.0","vue3-toastify":"^0.2.8","tailwind-merge":"^3.3.1"},"_hasShrinkwrap":false,"devDependencies":{"jsdom":"^22.1.0","eslint":"^8.45.0","rollup":"^3.26.0","vitest":"^0.34.0","vue-tsc":"^1.8.0","typescript":"^5.1.0","@types/node":"^20.4.0","@vue/test-utils":"^2.4.0","@types/jwt-decode":"^3.1.0","eslint-plugin-vue":"^9.15.0","rollup-plugin-vue":"^6.0.0","@vitejs/plugin-vue":"^4.2.0","@rollup/plugin-json":"^6.1.0","rollup-plugin-postcss":"^4.0.2","@rollup/plugin-commonjs":"^25.0.0","@rollup/plugin-typescript":"^11.1.0","@typescript-eslint/parser":"^6.0.0","@rollup/plugin-node-resolve":"^15.1.0","@vue/eslint-config-typescript":"^11.0.0","@typescript-eslint/eslint-plugin":"^6.0.0","rollup-plugin-peer-deps-external":"^2.2.4"},"peerDependencies":{"vue":"^3.0.0"},"_npmOperationalInternal":{"tmp":"tmp/front-commons_1.0.0_1750447375433_0.6266675683162903","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@clube-certo/front-commons","version":"1.0.1","keywords":["vue","vue3","components","utils","typescript","clubecerto"],"author":{"name":"Clube Certo"},"license":"MIT","_id":"@clube-certo/front-commons@1.0.1","maintainers":[{"name":"clube-certo","email":"ti@clubecerto.com.br"}],"homepage":"https://github.com/clubecerto/front-commons#readme","bugs":{"url":"https://github.com/clubecerto/front-commons/issues"},"dist":{"shasum":"2f5967b3fde35fd898de265f3700a112f88552fa","tarball":"https://registry.npmjs.org/@clube-certo/front-commons/-/front-commons-1.0.1.tgz","fileCount":348,"integrity":"sha512-lxKX8E1dO4HOJTvLe/SYYTeTMNN79qT6+CbSTfUMiO3rI83efHrF21QbwQV6+Rt5dPr/NKyBPVrJsTe4WTaU8w==","signatures":[{"sig":"MEQCICJYYn9AEMU2Z0ml3mlC5tmiuWt2R3jWqeq4k3SLTc5FAiA7Qd78URA4N/2LyeuZ4oWx8C31AwNZLQH841IX2CBckQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3486605},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","module":"dist/index.esm.js","gitHead":"f81a92f7ccff865d9daa9cfb83b9e1749d5ead8e","scripts":{"dev":"rollup -c -w","lint":"eslint src --ext .ts,.vue,.js","test":"vitest","build":"rollup -c","test:ui":"vitest --ui","lint:fix":"eslint src --ext .ts,.vue,.js --fix","test:watch":"vitest --watch","type-check":"vue-tsc --noEmit","build:watch":"rollup -c -w","prepublishOnly":"npm run build"},"_npmUser":{"name":"clube-certo","actor":{"name":"clube-certo","type":"user","email":"ti@clubecerto.com.br"},"email":"ti@clubecerto.com.br"},"repository":{"url":"git+https://github.com/clubecerto/front-commons.git","type":"git"},"_npmVersion":"10.2.4","description":"Biblioteca de componentes, funções e utils compartilhados para projetos Vue 3 do Clube Certo","directories":{},"_nodeVersion":"20.11.0","dependencies":{"vue":"^3.0.0","zod":"^3.23.8","clsx":"^2.1.1","vuex":"^4.0.2","xlsx":"^0.18.5","axios":"^1.10.0","jspdf":"^3.0.0","maska":"^2.1.11","pagedjs":"^0.4.3","reka-ui":"^2.2.0","v-money":"^0.8.1","chart.js":"^4.4.7","firebase":"^10.9.0","v-money3":"^3.24.1","@casl/vue":"^2.2.2","crypto-js":"^4.2.0","radix-vue":"^1.9.4","@unovis/ts":"^1.5.0","jwt-decode":"^4.0.0","v-calendar":"^3.1.2","vue-router":"4.3.0","vue-select":"^4.0.0-beta.6","vue-sonner":"^1.1.4","@unovis/vue":"^1.5.0","html2canvas":"^1.4.1","@vueuse/core":"^10.11.1","vee-validate":"^4.13.2","vue-cryptojs":"^2.4.7","vuedraggable":"^4.1.0","vue3-toastify":"^0.2.8","tailwind-merge":"^3.3.1","vue-dragscroll":"^4.0.6","lucide-vue-next":"^0.427.0","vue-color-input":"^2.0.0","@vee-validate/zod":"^4.13.2","vue-signature-pad":"^3.0.2","@wangeditor/editor":"^5.1.23","@tanstack/vue-query":"^5.74.6","@tanstack/vue-table":"^8.21.3","tailwindcss-animate":"^1.0.7","@tinymce/tinymce-vue":"^5.1.1","@tanstack/vue-virtual":"^3.13.10","@fawmi/vue-google-maps":"^0.9.79","@vuepic/vue-datepicker":"^9.0.2","class-variance-authority":"^0.7.0","@wangeditor/editor-for-vue":"^5.1.12"},"_hasShrinkwrap":false,"devDependencies":{"jsdom":"^22.1.0","eslint":"^8.45.0","rollup":"^3.26.0","vitest":"^0.34.0","vue-tsc":"^1.8.0","typescript":"^5.1.0","@types/node":"^20.4.0","@vue/test-utils":"^2.4.0","@types/jwt-decode":"^3.1.0","eslint-plugin-vue":"^9.15.0","rollup-plugin-vue":"^6.0.0","@vitejs/plugin-vue":"^4.2.0","@rollup/plugin-json":"^6.1.0","rollup-plugin-postcss":"^4.0.2","@rollup/plugin-commonjs":"^25.0.0","@rollup/plugin-typescript":"^11.1.0","@typescript-eslint/parser":"^6.0.0","@rollup/plugin-node-resolve":"^15.1.0","@vue/eslint-config-typescript":"^11.0.0","@typescript-eslint/eslint-plugin":"^6.0.0","rollup-plugin-peer-deps-external":"^2.2.4"},"peerDependencies":{"vue":"^3.0.0"},"_npmOperationalInternal":{"tmp":"tmp/front-commons_1.0.1_1750448015358_0.20897114147671703","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@clube-certo/front-commons","version":"1.0.2","keywords":["vue","vue3","components","utils","typescript","clubecerto"],"author":{"name":"Clube Certo"},"license":"MIT","_id":"@clube-certo/front-commons@1.0.2","maintainers":[{"name":"clube-certo","email":"ti@clubecerto.com.br"}],"homepage":"https://github.com/clubecerto/front-commons#readme","bugs":{"url":"https://github.com/clubecerto/front-commons/issues"},"dist":{"shasum":"e8e3637d5ece68ca0a4dbea2924bb1b5744a9e6d","tarball":"https://registry.npmjs.org/@clube-certo/front-commons/-/front-commons-1.0.2.tgz","fileCount":348,"integrity":"sha512-vGF2TVrpA6lQLLDK1pMygamBOQTK4MZLrTKNPdksT+SjL+zp+FEj2ZAR5Y7K87kXfLkhpYdC5gSz+AXq7cnpMQ==","signatures":[{"sig":"MEUCIQCEgVWKW3EoeHUI7Uv2EGEbN9KnbtUbMAcm8fQ40cUmYQIgJmKo5XpzTc2u8TplVlgilc0YlWJnrvW/y6U9QJPjRvI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3498920},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","module":"dist/index.esm.js","gitHead":"c433f746e0983b70de88ad4734407398abc469ba","scripts":{"dev":"rollup -c -w","lint":"eslint src --ext .ts,.vue,.js","test":"vitest","build":"rollup -c","test:ui":"vitest --ui","lint:fix":"eslint src --ext .ts,.vue,.js --fix","test:watch":"vitest --watch","type-check":"vue-tsc --noEmit","build:watch":"rollup -c -w","prepublishOnly":"npm run build"},"_npmUser":{"name":"clube-certo","actor":{"name":"clube-certo","type":"user","email":"ti@clubecerto.com.br"},"email":"ti@clubecerto.com.br"},"repository":{"url":"git+https://github.com/clubecerto/front-commons.git","type":"git"},"_npmVersion":"10.2.4","description":"Biblioteca de componentes, funções e utils compartilhados para projetos Vue 3 do Clube Certo","directories":{},"_nodeVersion":"20.11.0","dependencies":{"vue":"^3.0.0","zod":"^3.23.8","clsx":"^2.1.1","vuex":"^4.0.2","xlsx":"^0.18.5","axios":"^1.10.0","jspdf":"^3.0.0","maska":"^2.1.11","pagedjs":"^0.4.3","reka-ui":"^2.2.0","v-money":"^0.8.1","chart.js":"^4.4.7","firebase":"^10.9.0","v-money3":"^3.24.1","@casl/vue":"^2.2.2","crypto-js":"^4.2.0","radix-vue":"^1.9.4","@unovis/ts":"^1.5.0","jwt-decode":"^4.0.0","v-calendar":"^3.1.2","vue-router":"4.3.0","vue-select":"^4.0.0-beta.6","vue-sonner":"^1.1.4","@unovis/vue":"^1.5.0","html2canvas":"^1.4.1","@vueuse/core":"^10.11.1","vee-validate":"^4.13.2","vue-cryptojs":"^2.4.7","vuedraggable":"^4.1.0","vue3-toastify":"^0.2.8","tailwind-merge":"^3.3.1","vue-dragscroll":"^4.0.6","lucide-vue-next":"^0.427.0","vue-color-input":"^2.0.0","@vee-validate/zod":"^4.13.2","vue-signature-pad":"^3.0.2","@wangeditor/editor":"^5.1.23","@tanstack/vue-query":"^5.74.6","@tanstack/vue-table":"^8.21.3","tailwindcss-animate":"^1.0.7","@tinymce/tinymce-vue":"^5.1.1","@tanstack/vue-virtual":"^3.13.10","@fawmi/vue-google-maps":"^0.9.79","@vuepic/vue-datepicker":"^9.0.2","class-variance-authority":"^0.7.0","@wangeditor/editor-for-vue":"^5.1.12"},"_hasShrinkwrap":false,"devDependencies":{"jsdom":"^22.1.0","eslint":"^8.45.0","rollup":"^3.26.0","vitest":"^0.34.0","vue-tsc":"^1.8.0","typescript":"^5.1.0","@types/node":"^20.4.0","@vue/test-utils":"^2.4.0","@types/jwt-decode":"^3.1.0","eslint-plugin-vue":"^9.15.0","rollup-plugin-vue":"^6.0.0","@vitejs/plugin-vue":"^4.2.0","@rollup/plugin-json":"^6.1.0","rollup-plugin-postcss":"^4.0.2","@rollup/plugin-commonjs":"^25.0.0","@rollup/plugin-typescript":"^11.1.0","@typescript-eslint/parser":"^6.0.0","@rollup/plugin-node-resolve":"^15.1.0","@vue/eslint-config-typescript":"^11.0.0","@typescript-eslint/eslint-plugin":"^6.0.0","rollup-plugin-peer-deps-external":"^2.2.4"},"peerDependencies":{"vue":"^3.0.0"},"_npmOperationalInternal":{"tmp":"tmp/front-commons_1.0.2_1750450407793_0.5601278053255816","host":"s3://npm-registry-packages-npm-production"}},"1.0.3":{"name":"@clube-certo/front-commons","version":"1.0.3","type":"module","description":"Biblioteca de componentes, funções e utils compartilhados para projetos Vue 3 do Clube Certo","main":"dist/index.js","module":"dist/index.esm.js","types":"dist/index.d.ts","scripts":{"build":"rollup -c","build:watch":"rollup -c -w","dev":"rollup -c -w","test":"vitest","test:watch":"vitest --watch","test:ui":"vitest --ui","lint":"eslint src --ext .ts,.vue,.js","lint:fix":"eslint src --ext .ts,.vue,.js --fix","type-check":"vue-tsc --noEmit","prepublishOnly":"npm run build"},"keywords":["vue","vue3","components","utils","typescript","clubecerto"],"author":{"name":"Clube Certo"},"license":"MIT","peerDependencies":{"vue":"^3.0.0"},"devDependencies":{"@rollup/plugin-commonjs":"^25.0.0","@rollup/plugin-json":"^6.1.0","@rollup/plugin-node-resolve":"^15.1.0","@rollup/plugin-typescript":"^11.1.0","@types/jwt-decode":"^3.1.0","@types/node":"^20.4.0","@typescript-eslint/eslint-plugin":"^6.0.0","@typescript-eslint/parser":"^6.0.0","@vitejs/plugin-vue":"^4.2.0","@vue/eslint-config-typescript":"^11.0.0","@vue/test-utils":"^2.4.0","eslint":"^8.45.0","eslint-plugin-vue":"^9.15.0","jsdom":"^22.1.0","rollup":"^3.26.0","rollup-plugin-peer-deps-external":"^2.2.4","rollup-plugin-postcss":"^4.0.2","rollup-plugin-vue":"^6.0.0","typescript":"^5.1.0","vitest":"^0.34.0","vue-tsc":"^1.8.0"},"dependencies":{"axios":"^1.10.0","clsx":"^2.1.1","jwt-decode":"^4.0.0","tailwind-merge":"^3.3.1","vue":"^3.0.0","vue3-toastify":"^0.2.8","@casl/vue":"^2.2.2","@fawmi/vue-google-maps":"^0.9.79","@tanstack/vue-query":"^5.74.6","@tanstack/vue-table":"^8.21.3","@tanstack/vue-virtual":"^3.13.10","@tinymce/tinymce-vue":"^5.1.1","@unovis/ts":"^1.5.0","@unovis/vue":"^1.5.0","@vee-validate/zod":"^4.13.2","@vuepic/vue-datepicker":"^9.0.2","@vueuse/core":"^10.11.1","@wangeditor/editor":"^5.1.23","@wangeditor/editor-for-vue":"^5.1.12","chart.js":"^4.4.7","class-variance-authority":"^0.7.0","crypto-js":"^4.2.0","firebase":"^10.9.0","html2canvas":"^1.4.1","jspdf":"^3.0.0","lucide-vue-next":"^0.427.0","maska":"^2.1.11","pagedjs":"^0.4.3","radix-vue":"^1.9.4","reka-ui":"^2.2.0","tailwindcss-animate":"^1.0.7","v-calendar":"^3.1.2","v-money":"^0.8.1","v-money3":"^3.24.1","vee-validate":"^4.13.2","vue-color-input":"^2.0.0","vue-cryptojs":"^2.4.7","vue-dragscroll":"^4.0.6","vue-router":"4.3.0","vue-select":"^4.0.0-beta.6","vue-signature-pad":"^3.0.2","vue-sonner":"^1.1.4","vuedraggable":"^4.1.0","vuex":"^4.0.2","vaul-vue":"^0.4.1","xlsx":"^0.18.5","zod":"^3.23.8"},"repository":{"type":"git","url":"git+https://github.com/clubecerto/front-commons.git"},"bugs":{"url":"https://github.com/clubecerto/front-commons/issues"},"homepage":"https://github.com/clubecerto/front-commons#readme","_id":"@clube-certo/front-commons@1.0.3","gitHead":"d39adda0c8ac9741990e2b43a71ea84d0e76b735","_nodeVersion":"23.11.0","_npmVersion":"10.9.2","dist":{"integrity":"sha512-dcbZJrayZN0Uh2CuMiJHlSOtYNTEJkWzopVlg66fa25BFSNc9YhJQS3jV7ffkJSX8XP3gR7V8YknIPKemYqB9g==","shasum":"5acfae3804a582d4d624b3de7c677fb609d74109","tarball":"https://registry.npmjs.org/@clube-certo/front-commons/-/front-commons-1.0.3.tgz","fileCount":359,"unpackedSize":4452194,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIA4gMLZwD5XgXwHFRqNJ+nWQMf0FzVTwTjoUDTItt9SCAiEAwN1HcLvda0PyJnwbEROs3XP5tDCKhsOX6K5MU3SdWPs="}]},"_npmUser":{"name":"clube-certo","email":"ti@clubecerto.com.br","actor":{"name":"clube-certo","email":"ti@clubecerto.com.br","type":"user"}},"directories":{},"maintainers":[{"name":"clube-certo","email":"ti@clubecerto.com.br"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/front-commons_1.0.3_1750782028511_0.2241180149280182"},"_hasShrinkwrap":false}},"time":{"created":"2025-06-20T19:22:55.327Z","modified":"2025-06-24T16:20:29.044Z","1.0.0":"2025-06-20T19:22:55.624Z","1.0.1":"2025-06-20T19:33:35.615Z","1.0.2":"2025-06-20T20:13:28.202Z","1.0.3":"2025-06-24T16:20:28.853Z"},"bugs":{"url":"https://github.com/clubecerto/front-commons/issues"},"author":{"name":"Clube Certo"},"license":"MIT","homepage":"https://github.com/clubecerto/front-commons#readme","keywords":["vue","vue3","components","utils","typescript","clubecerto"],"repository":{"type":"git","url":"git+https://github.com/clubecerto/front-commons.git"},"description":"Biblioteca de componentes, funções e utils compartilhados para projetos Vue 3 do Clube Certo","maintainers":[{"name":"clube-certo","email":"ti@clubecerto.com.br"}],"readme":"# Front Commons - Biblioteca Vue 3\n\nBiblioteca de componentes, funções e utils compartilhados para projetos Vue 3 do Clube Certo.\n\n## 📦 Instalação\n\n### Via NPM (Recomendado)\n\n```bash\nnpm install @clube-certo/front-commons\n```\n\n### Via Git\n\n```bash\nnpm install git+https://github.com/clubecerto/front-commons.git\n```\n\n## 🚀 Uso\n\n### Importando Componentes\n\n```vue\n<template>\n  <div>\n    <AutoComplete\n      v-model=\"selectedUser\"\n      :search-fn=\"searchUsers\"\n      placeholder=\"Buscar usuário...\"\n    />\n\n    <Input\n      v-model=\"inputValue\"\n      placeholder=\"Digite algo...\"\n      type=\"text\"\n    />\n  </div>\n</template>\n\n<script setup>\nimport { ref } from \"vue\";\n// Importação direta dos componentes Vue\nimport AutoComplete from \"@clube-certo/front-commons/src/components/generic/AutoComplete.vue\";\nimport Input from \"@clube-certo/front-commons/src/components/generic/Input.vue\";\n\nconst selectedUser = ref(null);\nconst inputValue = ref(\"\");\n\nconst searchUsers = async (term) => {\n  // Implementar busca de usuários\n  return [];\n};\n</script>\n```\n\n### Importando Utilitários e Composables\n\n```javascript\n// Importação de utilitários e composables (disponíveis no bundle principal)\nimport { formatCurrency, formatCPF, isValidEmail, httpClient, useApi, useLocalStorage } from \"@clube-certo/front-commons\";\n```\n\n### Usando Utilitários\n\n```javascript\nimport { formatCurrency, formatCPF, isValidEmail, httpClient } from \"@clube-certo/front-commons\";\n\n// Formatação\nconst price = formatCurrency(1234.56); // R$ 1.234,56\nconst cpf = formatCPF(\"12345678901\"); // 123.456.789-01\n\n// Validação\nconst isValid = isValidEmail(\"user@example.com\"); // true\n\n// API\nconst response = await httpClient.get(\"/api/users\");\n```\n\n### Usando Composables\n\n```vue\n<script setup>\nimport { ref } from \"vue\";\nimport { useApi, useLocalStorage, useValidation, useClipboard } from \"@clube-certo/front-commons\";\n\n// API\nconst { data: users, loading, error } = useApi(\"/api/users\");\n\n// Storage\nconst [theme, setTheme] = useLocalStorage(\"theme\", \"light\");\n\n// Validação\nconst { data, errors, validate } = useValidation({\n  email: { required: true, pattern: /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/ },\n  password: { required: true, minLength: 8 },\n});\n\n// Clipboard\nconst { copy, copied } = useClipboard();\n</script>\n```\n\n## 📚 Documentação\n\n### Componentes Disponíveis\n\n#### Componentes Genéricos\n\n##### Formulários e Inputs\n\n- **AutoComplete** - Campo de autocomplete com busca assíncrona e seleção de itens\n- **DatePicker** - Seletor de data avançado com suporte a range, modo mês e formatos customizáveis\n- **Input** - Campo de entrada versátil com máscaras, validação e tipos especiais (moeda, telefone, cor, CEP)\n- **InputCalendar** - Calendário para seleção de data/hora com suporte a datetime\n- **Select** - Dropdown altamente customizável com busca, múltipla seleção, agrupamento e modo simples/grupo\n- **Toggle** - Switch segmentado com rótulos e ícones personalizáveis\n- **ValidatorErrors** - Componente para exibição estruturada de erros de validação\n- **RichText** - Editor de texto rico com toolbar customizável\n\n##### Tabelas e Listas\n\n- **GenericTable** - Tabela completa com paginação, ordenação, filtros, seleção múltipla e edição inline\n- **HeaderList** - Cabeçalho de lista com controles de busca, filtros e botões de ação\n- **Pagination** - Componente de paginação com informações detalhadas\n\n##### Modais e Diálogos\n\n- **ConfirmDialog** - Modal de confirmação com botões e estilos customizáveis\n- **GenericDialog** - Modal genérico altamente configurável e reutilizável\n- **ModalFileReader** - Modal avançado para importação e leitura de arquivos (Excel, CSV, OFX) com preview e edição\n- **SideForms** - Formulários laterais deslizantes com posicionamento configurável\n\n##### Visualização e Feedback\n\n- **Error** - Página de erro com ilustração SVG animada\n- **Loader** - Indicador de carregamento com overlay\n- **PhoneMockup** - Simulação de notificação push em dispositivo móvel\n- **PhoneMockupFullscreen** - Simulação completa de tela de aplicativo móvel com múltiplos templates\n- **Kanban** - Board Kanban com drag & drop, filtros de coluna e estados customizáveis\n\n##### Utilitários\n\n- **CopyText** - Botão inteligente para copiar texto para clipboard com feedback\n- **ExcelExportModal** - Modal completo para exportação de dados para Excel com seleção de colunas e renomeação\n\n##### Upload e Mídia\n\n- **Dropzone** - Área de upload com drag & drop, preview de arquivos e validação\n- **UploadIcon** - Ícone dinâmico baseado no tipo de arquivo\n\n##### Mapas\n\n- **Map** - Componente de mapa interativo com Google Maps, círculos, polígonos e controles de zoom/raio\n\n#### Exemplos de Uso dos Componentes Genéricos\n\n##### AutoComplete\n\n```vue\n<template>\n  <AutoComplete\n    v-model=\"selectedUser\"\n    :search-fn=\"searchUsers\"\n    placeholder=\"Buscar usuário...\"\n    label=\"name\"\n    value=\"id\"\n  />\n</template>\n\n<script setup>\nimport { ref } from \"vue\";\nimport AutoComplete from \"@clube-certo/front-commons/src/components/generic/AutoComplete.vue\";\n\nconst selectedUser = ref(null);\n\nconst searchUsers = async (term) => {\n  const response = await fetch(`/api/users?search=${term}`);\n  return response.json();\n};\n</script>\n```\n\n##### GenericTable\n\n```vue\n<template>\n  <GenericTable\n    :data=\"users\"\n    :columns=\"columns\"\n    :enable-pagination=\"true\"\n    :enable-selection=\"true\"\n    :editable=\"true\"\n    :editable-columns-config=\"editableConfig\"\n    @update:selectedItems=\"handleSelection\"\n  />\n</template>\n\n<script setup>\nimport { ref } from \"vue\";\nimport GenericTable from \"@clube-certo/front-commons/src/components/generic/GenericTable.vue\";\n\nconst users = ref([]);\nconst columns = [\n  { accessorKey: \"name\", header: \"Nome\" },\n  { accessorKey: \"email\", header: \"Email\" },\n  { accessorKey: \"status\", header: \"Status\" },\n];\n\nconst editableConfig = [\n  { column: \"name\", type: \"string\" },\n  {\n    column: \"status\",\n    type: \"select\",\n    selectOptions: [\n      { label: \"Ativo\", value: \"active\" },\n      { label: \"Inativo\", value: \"inactive\" },\n    ],\n  },\n];\n</script>\n```\n\n##### Kanban\n\n```vue\n<template>\n  <Kanban\n    entity-name=\"tarefa\"\n    :items=\"tasks\"\n    id-item=\"id\"\n    :status-list=\"statusList\"\n    status-mapping=\"status\"\n    @status-change=\"updateTaskStatus\"\n  >\n    <template #default=\"{ item }\">\n      <div class=\"task-card\">\n        <h3>{{ item.title }}</h3>\n        <p>{{ item.description }}</p>\n      </div>\n    </template>\n  </Kanban>\n</template>\n\n<script setup>\nimport { ref } from \"vue\";\nimport Kanban from \"@clube-certo/front-commons/src/components/generic/Kanban.vue\";\n\nconst tasks = ref([]);\nconst statusList = [\n  { value: 1, label: \"A Fazer\", cor: \"#ff6b6b\" },\n  { value: 2, label: \"Em Progresso\", cor: \"#4ecdc4\" },\n  { value: 3, label: \"Concluído\", cor: \"#45b7d1\" },\n];\n\nconst updateTaskStatus = (newStatus, taskId) => {\n  // Atualizar status da tarefa\n};\n</script>\n```\n\n##### ModalFileReader\n\n```vue\n<template>\n  <ModalFileReader\n    title=\"Importar Usuários\"\n    type-file=\".xlsx,.csv\"\n    entity-search=\"users\"\n    :search=\"true\"\n    :mapping=\"{ nome: 'name', email: 'email' }\"\n    @process-selected=\"processUsers\"\n    @refetch-data=\"refreshData\"\n  />\n</template>\n\n<script setup>\nimport ModalFileReader from \"@clube-certo/front-commons/src/components/generic/ModalFileReader.vue\";\n\nconst processUsers = async (users) => {\n  try {\n    await api.post(\"/users/import\", { users });\n    return { success: true };\n  } catch (error) {\n    return { error };\n  }\n};\n</script>\n```\n\n##### DatePicker\n\n```vue\n<template>\n  <div>\n    <!-- Data simples -->\n    <DatePicker v-model=\"selectedDate\" />\n\n    <!-- Seleção de mês -->\n    <DatePicker\n      v-model=\"selectedMonth\"\n      :month=\"true\"\n    />\n\n    <!-- Range de datas -->\n    <DatePicker\n      v-model=\"dateRange\"\n      :range=\"true\"\n      :start=\"startDate\"\n      :end=\"endDate\"\n      @update:start=\"startDate = $event\"\n      @update:end=\"endDate = $event\"\n    />\n  </div>\n</template>\n\n<script setup>\nimport { ref } from \"vue\";\nimport DatePicker from \"@clube-certo/front-commons/src/components/generic/DatePicker.vue\";\n\nconst selectedDate = ref(null);\nconst selectedMonth = ref(null);\nconst dateRange = ref(null);\nconst startDate = ref(null);\nconst endDate = ref(null);\n</script>\n```\n\n## 📋 Documentação Detalhada dos Componentes\n\n### AutoComplete\n\n**Descrição:** Campo de autocomplete com busca assíncrona e seleção de itens.\n\n**Props:**\n\n- `modelValue` (String/Number) - Valor selecionado\n- `placeHolder` (String, default: 'Select framework...') - Texto placeholder\n- `notFoundMessage` (String, default: 'No framework found.') - Mensagem quando não encontra resultados\n- `searchFn` (Function) - Função de busca assíncrona\n- `label` (String, default: 'label') - Propriedade para exibição do texto\n- `value` (String, default: 'value') - Propriedade para o valor\n- `disabled` (Boolean, default: false) - Desabilita o componente\n\n**Eventos:**\n\n- `update:modelValue` - Emitido quando o valor é alterado\n\n**Exemplo:**\n\n```vue\n<AutoComplete v-model=\"selectedUser\" :search-fn=\"searchUsers\" placeholder=\"Buscar usuário...\" label=\"name\" value=\"id\" :disabled=\"false\" />\n```\n\n### ConfirmDialog\n\n**Descrição:** Modal de confirmação com botões e estilos customizáveis.\n\n**Props:**\n\n- `titulo` (String, required) - Título do modal\n- `textoConfirmacao` (String, required) - Texto de confirmação\n- `labelBotaoCancelar` (String, default: 'Cancelar') - Texto do botão cancelar\n- `labelBotaoConfirmar` (String, default: 'Confirmar') - Texto do botão confirmar\n- `classBotaoCancelar` (String, default: 'bg-red-100 text-red-600') - Classes CSS do botão cancelar\n- `classBotaoConfirmar` (String, default: 'bg-green-600 text-white') - Classes CSS do botão confirmar\n\n**Eventos:**\n\n- `click:button-cancelar` - Emitido ao clicar em cancelar\n- `click:button-confirmar` - Emitido ao clicar em confirmar\n\n**Slots:**\n\n- `button-trigger` - Slot para o botão que abre o modal\n\n### CopyText\n\n**Descrição:** Botão inteligente para copiar texto para clipboard com feedback.\n\n**Props:**\n\n- `text` (String, required) - Texto a ser copiado\n- `label` (String, default: '') - Rótulo do botão\n- `showIcon` (Boolean, default: true) - Exibe ícone de cópia\n- `entityName` (String, default: 'Texto') - Nome da entidade para feedback\n- `showText` (Boolean, default: true) - Exibe o texto no botão\n\n**Exemplo:**\n\n```vue\n<CopyText text=\"Texto para copiar\" label=\"Copiar:\" entity-name=\"Código\" :show-icon=\"true\" :show-text=\"true\" />\n```\n\n### DatePicker\n\n**Descrição:** Seletor de data avançado com suporte a range, modo mês e formatos customizáveis.\n\n**Props:**\n\n- `modelValue` (DateValue/String/DateRange) - Valor da data\n- `placeholder` (String, default: 'Selecione uma data') - Placeholder\n- `formatOptions` (Object, default: { dateStyle: 'short' }) - Opções de formatação\n- `locale` (String, default: 'pt-BR') - Localização\n- `month` (Boolean, default: false) - Modo seleção de mês\n- `range` (Boolean, default: false) - Modo range de datas\n- `start` (DateValue) - Data inicial (modo range)\n- `end` (DateValue) - Data final (modo range)\n\n**Eventos:**\n\n- `update:modelValue` - Emitido quando o valor é alterado\n- `update:start` - Emitido quando a data inicial é alterada (modo range)\n- `update:end` - Emitido quando a data final é alterada (modo range)\n\n### GenericTable\n\n**Descrição:** Tabela completa com paginação, ordenação, filtros, seleção múltipla e edição inline.\n\n**Props:**\n\n- `data` (Array, required) - Dados da tabela\n- `columns` (Array) - Configuração das colunas\n- `autoGenerateColumns` (Boolean, default: true) - Gerar colunas automaticamente\n- `enablePagination` (Boolean, default: true) - Habilitar paginação\n- `initialPageSize` (Number, default: 50) - Tamanho inicial da página\n- `enableGlobalFilter` (Boolean, default: true) - Habilitar busca global\n- `enableSorting` (Boolean, default: true) - Habilitar ordenação\n- `enableSelection` (Boolean, default: false) - Habilitar seleção múltipla\n- `selectionKey` (String, default: 'id') - Chave para seleção\n- `editable` (Boolean, default: false) - Habilitar edição\n- `editableColumnsConfig` (Array) - Configuração de colunas editáveis\n\n**Eventos:**\n\n- `update:selectedItems` - Emitido quando itens são selecionados\n- `update:data` - Emitido quando dados são editados\n\n### Input\n\n**Descrição:** Campo de entrada versátil com máscaras, validação e tipos especiais.\n\n**Props:**\n\n- `modelValue` (String) - Valor do input\n- `type` (String, default: 'text') - Tipo do input\n- `placeholder` (String) - Placeholder\n- `size` (String, default: 'default') - Tamanho do input\n- `disabled` (Boolean, default: false) - Desabilitar input\n- `readonly` (Boolean, default: false) - Somente leitura\n- `money` (Boolean, default: false) - Modo moeda\n- `phone` (Boolean, default: false) - Modo telefone\n- `color` (Boolean, default: false) - Modo cor\n- `cep` (Boolean, default: false) - Modo CEP\n- `dataMaska` (String) - Máscara personalizada\n- `icon` (String) - Ícone do input\n- `iconDir` (String) - Direção do ícone ('left' ou 'right')\n\n**Eventos:**\n\n- `update:modelValue` - Emitido quando o valor é alterado\n- `blur` - Emitido quando o input perde o foco\n\n### Kanban\n\n**Descrição:** Board Kanban com drag & drop, filtros de coluna e estados customizáveis.\n\n**Props:**\n\n- `entityName` (String, required) - Nome da entidade\n- `items` (Array, required) - Lista de itens\n- `idItem` (String, required) - Campo ID dos itens\n- `statusList` (Array, required) - Lista de status/colunas\n- `statusMapping` (String, required) - Mapeamento do campo status\n- `onStatusChange` (Function) - Função para alterar status\n- `onStatusMutation` (Function) - Função alternativa para alterar status\n- `cardComponent` (Component) - Componente do card\n- `loading` (Boolean, default: false) - Estado de carregamento\n\n**Eventos:**\n\n- Não emite eventos diretamente, usa as funções `onStatusChange` ou `onStatusMutation`\n\n**Slots:**\n\n- `default` - Slot para o conteúdo do card (recebe `{ item }`)\n\n### Select\n\n**Descrição:** Dropdown altamente customizável com busca, múltipla seleção e agrupamento.\n\n**Props:**\n\n- `modelValue` (String/Number/Array) - Valor selecionado\n- `multiple` (Boolean, default: false) - Seleção múltipla\n- `options` (Array, required) - Opções do select\n- `placeholder` (String, default: 'Selecione uma opção') - Placeholder\n- `mode` (String, default: 'simple') - Modo ('simple' ou 'group')\n- `clearable` (Boolean, default: true) - Permitir limpar seleção\n- `search` (Boolean, default: false) - Habilitar busca\n- `hideSelected` (Boolean, default: false) - Ocultar itens selecionados\n- `label` (String, default: 'label') - Propriedade para label\n- `value` (String, default: 'value') - Propriedade para valor\n- `groupName` (String, default: 'group') - Propriedade para agrupamento\n\n**Eventos:**\n\n- `update:modelValue` - Emitido quando o valor é alterado\n\n### ModalFileReader\n\n**Descrição:** Modal avançado para importação e leitura de arquivos com preview e edição.\n\n**Props:**\n\n- `title` (String, default: 'Importação de Arquivo') - Título do modal\n- `description` (String) - Descrição do modal\n- `typeFile` (String, default: '.xls,.xlsx,.ofx,.csv,.numbers') - Tipos de arquivo aceitos\n- `entitySearch` (String, default: 'noentity') - Entidade para busca\n- `search` (Boolean, default: false) - Habilitar busca/comparação\n- `mapping` (Object) - Mapeamento de colunas\n- `ofxFilter` (String) - Filtro para arquivos OFX ('all', 'expenses', 'revenues')\n- `editable` (Boolean, default: false) - Habilitar edição\n- `editableColumnsConfig` (Array) - Configuração de colunas editáveis\n- `chunkSize` (Number, default: 100) - Tamanho do chunk para importação\n- `chunkInterval` (Number, default: 1000) - Intervalo entre chunks\n- `planilhaModeloNome` (String) - Nome da planilha modelo\n- `dadosPlanilhaModelo` (Array) - Dados da planilha modelo\n\n**Eventos:**\n\n- `process-selected` - Emitido para processar itens selecionados\n- `refetch-data` - Emitido para recarregar dados\n\n### Toggle\n\n**Descrição:** Switch segmentado com rótulos e ícones personalizáveis.\n\n**Props:**\n\n- `modelValue` (Boolean) - Valor do toggle\n- `leftLabel` (String, default: 'One Way') - Rótulo da esquerda\n- `rightLabel` (String, default: 'Return') - Rótulo da direita\n- `leftIcon` (String) - Ícone da esquerda\n- `rightIcon` (String) - Ícone da direita\n- `disabled` (Boolean, default: false) - Desabilitar toggle\n- `variant` (String, default: 'default') - Variante de cor\n\n**Eventos:**\n\n- `update:modelValue` - Emitido quando o valor é alterado\n\n### Dropzone\n\n**Descrição:** Área de upload com drag & drop, preview de arquivos e validação.\n\n**Props:**\n\n- `modelValue` (Array, default: []) - Arquivos selecionados\n- `multiple` (Boolean, default: false) - Múltiplos arquivos\n- `previews` (Array, default: []) - URLs de preview\n- `mode` (String, default: 'drop') - Modo ('drop' ou 'preview')\n- `disabled` (Boolean, default: false) - Desabilitar componente\n- `accept` (String) - Tipos de arquivo aceitos\n- `maxFileSize` (Number, default: 5) - Tamanho máximo em MB\n- `maxFiles` (Number, default: 5) - Número máximo de arquivos\n- `showSelectButton` (Boolean, default: true) - Exibir botão de seleção\n\n**Eventos:**\n\n- `drop` - Emitido quando arquivos são soltos\n- `update:modelValue` - Emitido quando arquivos são alterados\n- `error` - Emitido em caso de erro\n\n**Slots:**\n\n- `placeholder-img` - Slot para imagem placeholder\n- `title` - Slot para título\n- `button` - Slot para botão personalizado\n- `description` - Slot para descrição\n- `preview` - Slot para preview personalizado\n\n### Map\n\n**Descrição:** Componente de mapa interativo com Google Maps, círculos e polígonos.\n\n**Props:**\n\n- `center` (Object, default: { lat: 37.7749, lng: -122.4194 }) - Centro do mapa\n- `national` (Boolean, default: false) - Modo nacional\n- `zoom` (Number, default: 13) - Zoom inicial\n- `geolocations` (Array, default: []) - Lista de geolocalizações\n\n**Eventos:**\n\n- `update:range` - Emitido quando o raio é alterado\n\n**Funcionalidades:**\n\n- Controle de raio de disparo\n- Controle de zoom\n- Círculos e polígonos baseados em geolocalizações\n- Detecção automática de localização\n\n### Utilitários\n\n#### Formatação\n\n- `formatCurrency(value, currency?, locale?)` - Formatar moeda\n- `formatCPF(cpf)` - Formatar CPF\n- `formatCNPJ(cnpj)` - Formatar CNPJ\n- `formatPhone(phone)` - Formatar telefone\n- `formatCEP(cep)` - Formatar CEP\n- `formatDate(date, format?, locale?)` - Formatar data\n\n#### Cores\n\n- `hexToHSL(hex)` - Converte cor hexadecimal para formato HSL\n- `darkenColor(hex, percent)` - Escurece uma cor hexadecimal em uma porcentagem específica\n- `lightenColor(hex, percent)` - Clareia uma cor hexadecimal em uma porcentagem específica\n\n##### Exemplos de Uso das Funções de Cores\n\n```javascript\nimport { hexToHSL, darkenColor, lightenColor } from \"@clube-certo/front-commons\";\n\n// Conversão de hexadecimal para HSL\nconst hslColor = hexToHSL(\"#00A24D\"); // \"123 100% 32%\"\nconst hslFromShort = hexToHSL(\"#0A2\"); // \"123 100% 32%\" (expande automaticamente)\n\n// Escurecer uma cor\nconst darkerGreen = darkenColor(\"#00A24D\", 20); // Escurece 20%\nconst muchDarker = darkenColor(\"#FF5733\", 50); // Escurece 50%\n\n// Clarear uma cor\nconst lighterGreen = lightenColor(\"#00A24D\", 30); // Clareia 30%\nconst muchLighter = lightenColor(\"#FF5733\", 60); // Clareia 60%\n\n// Uso prático em temas dinâmicos\nconst primaryColor = \"#007bff\";\nconst hoverColor = darkenColor(primaryColor, 15);\nconst activeColor = darkenColor(primaryColor, 25);\nconst lightVariant = lightenColor(primaryColor, 40);\n\n// Aplicação em CSS-in-JS ou estilos dinâmicos\nconst buttonStyles = {\n  backgroundColor: primaryColor,\n  \":hover\": {\n    backgroundColor: hoverColor,\n  },\n  \":active\": {\n    backgroundColor: activeColor,\n  },\n};\n```\n\n#### Validação\n\n- `isValidEmail(email)` - Validar email\n- `isValidCPF(cpf)` - Validar CPF\n- `isValidCNPJ(cnpj)` - Validar CNPJ\n- `isValidPhone(phone)` - Validar telefone\n- `isStrongPassword(password)` - Validar senha forte\n\n#### API\n\nA biblioteca oferece um conjunto completo de utilitários para requisições HTTP baseados em Axios:\n\n##### Funções Principais\n\n- `get<T>(controllerName, action?, extraParams?)` - Requisições GET\n- `getQueryParams<T>(controllerName, action?, extraParams?)` - GET com parâmetros customizados\n- `post<T>(controllerName, action?, data, extraParams?)` - Requisições POST\n- `put<T>(controllerName, action?, data?, extraParams?)` - Requisições PUT\n- `patch<T>(controllerName, action?, data, extraParams?)` - Requisições PATCH\n- `del<T>(controllerName, action?, extraParams?, body?)` - Requisições DELETE\n- `upload<T>(controllerName, action?, data, extraParams?)` - Upload de arquivos\n- `postDownload(controllerName, action?, data, extraParams?)` - Download de arquivos\n\n##### Configuração e Autenticação\n\n- `getDecodedToken()` - Decodificar token JWT do localStorage\n- `setAuthToken(token)` - Configurar token de autorização\n- `removeAuthToken()` - Remover token de autorização\n- `setHeader(key, value)` - Configurar header global\n- `removeHeader(key)` - Remover header\n- `httpClient` - Instância do Axios configurada\n\n##### Utilitários Adicionais\n\n- `retryRequest(requestFn, maxRetries?, delay?)` - Retry automático de requisições\n- `createPaginationParams(page, limit)` - Criar parâmetros de paginação\n- `parsePaginationResponse<T>(response)` - Processar resposta paginada\n\n##### Exemplos de Uso\n\n```javascript\nimport { get, post, put, del, upload, setAuthToken, getDecodedToken } from \"@clube-certo/front-commons\";\n\n// Configurar autenticação\nsetAuthToken(\"seu-jwt-token\");\n\n// Obter dados decodificados do token\nconst userData = getDecodedToken();\n\n// Requisições básicas\nconst users = await get(\"users\");\nconst user = await get(\"users\", \"123\");\nconst newUser = await post(\"users\", \"\", { name: \"João\", email: \"joao@email.com\" });\nconst updatedUser = await put(\"users\", \"123\", { name: \"João Silva\" });\nawait del(\"users\", \"123\");\n\n// Requisições com parâmetros\nconst filteredUsers = await get(\"users\", \"\", {\n  page: 1,\n  itensPerPage: 10,\n  status: \"active\",\n});\n\n// Requisições com parâmetros customizados\nconst searchResults = await getQueryParams(\"search\", \"\", [\n  { key: \"q\", value: \"termo de busca\" },\n  { key: \"category\", value: \"produtos\" },\n]);\n\n// Upload de arquivo\nconst formData = new FormData();\nformData.append(\"file\", file);\nconst uploadResult = await upload(\"files\", \"upload\", formData);\n\n// Download de arquivo\nconst blob = await postDownload(\"reports\", \"generate\", {\n  type: \"pdf\",\n  filters: { startDate: \"2023-01-01\" },\n});\n\n// Retry automático\nconst dataWithRetry = await retryRequest(\n  () => get(\"unstable-endpoint\"),\n  3, // máximo 3 tentativas\n  1000 // delay de 1 segundo\n);\n```\n\n##### Configuração de Ambiente\n\nConfigure a URL base da API através da variável de ambiente:\n\n```bash\n# .env\nVITE_API_URL=https://api.exemplo.com/\n```\n\nSe não configurada, será usado `http://localhost:3030/` por padrão.\n\n#### Storage\n\n- `localStorage` - Wrapper para localStorage\n- `sessionStorage` - Wrapper para sessionStorage\n- `cookies` - Utilitários para cookies\n- `MemoryCache` - Cache em memória com TTL\n\n#### Toast Notifications\n\nA biblioteca inclui utilitários completos para exibição de notificações toast usando vue3-toastify:\n\n- `prepareToast(functionToCall, successMessage?, errorMessage?)` - Executa função assíncrona com toasts automáticos\n- `errorToast(errorMessage?, description?)` - Exibe toast de erro\n- `successToast(successMessage?, description?)` - Exibe toast de sucesso\n- `infoToast(infoMessage?, description?)` - Exibe toast informativo\n- `warningToast(warningMessage?, description?)` - Exibe toast de aviso\n- `cn(...inputs)` - Combina classes CSS usando clsx e tailwind-merge\n\n##### Configuração dos Toasts\n\nPara usar os toasts, configure o vue3-toastify em sua aplicação:\n\n```typescript\n// main.ts\nimport { createApp } from \"vue\";\nimport Vue3Toastify, { type ToastContainerOptions } from \"vue3-toastify\";\nimport \"vue3-toastify/dist/index.css\";\n\nconst app = createApp(App);\n\napp.use(Vue3Toastify, {\n  autoClose: 3000,\n  // outras opções...\n} as ToastContainerOptions);\n```\n\n##### Exemplos de Uso dos Toasts\n\n```javascript\nimport { prepareToast, successToast, errorToast, warningToast, infoToast } from \"@clube-certo/front-commons\";\n\n// Toast com função assíncrona\nawait prepareToast(() => api.saveData(data), \"Dados salvos com sucesso!\", \"Erro ao salvar dados\");\n\n// Toasts simples\nsuccessToast(\"Operação realizada com sucesso!\");\nerrorToast(\"Erro de validação\", \"O campo email é obrigatório\");\nwarningToast(\"Sessão expirando\", \"Sua sessão expirará em 5 minutos\");\ninfoToast(\"Nova funcionalidade\", \"Agora você pode exportar relatórios em PDF\");\n```\n\n#### Schemas de Validação (Zod)\n\nA biblioteca inclui schemas de validação pré-configurados usando Zod para validação de dados comuns:\n\n- `schemas.cpf` - Validação de CPF brasileiro\n- `schemas.cnpj` - Validação de CNPJ brasileiro\n- `schemas.email` - Validação de email\n- `schemas.fullName` - Validação de nome completo (mínimo 2 palavras)\n- `schemas.cep` - Validação de CEP no formato 99.999-999\n- `schemas.celular` - Validação de celular no formato (99)99999-9999\n- `schemas.creditCard` - Validação de cartão de crédito\n- `schemas.senha` - Validação de senha forte (8+ caracteres, maiúscula, minúscula, número, especial)\n- `schemas.url` - Validação de URL (http/https)\n- `schemas.money` - Validação de valor monetário (formato 123.45)\n- `schemas.date` - Validação de data\n- `schemas.dateTime` - Validação de data e hora (ISO 8601)\n- `schemas.calendar` - Schema para datas de calendário\n\n##### Exemplos de Uso dos Schemas\n\n```javascript\nimport { schemas } from \"@clube-certo/front-commons\";\n\n// Validação de CPF\ntry {\n  const cpf = schemas.cpf.parse(\"123.456.789-01\");\n  console.log(\"CPF válido:\", cpf);\n} catch (error) {\n  console.error(\"CPF inválido:\", error.message);\n}\n\n// Validação de email\nconst emailResult = schemas.email.safeParse(\"usuario@exemplo.com\");\nif (emailResult.success) {\n  console.log(\"Email válido:\", emailResult.data);\n} else {\n  console.error(\"Email inválido:\", emailResult.error.issues);\n}\n\n// Validação de senha\nconst senhaResult = schemas.senha.safeParse(\"MinhaSenh@123\");\nif (senhaResult.success) {\n  console.log(\"Senha válida\");\n} else {\n  console.error(\"Senha inválida:\", senhaResult.error.issues[0].message);\n}\n\n// Validação de valor monetário\nconst valorResult = schemas.money.safeParse(\"1234.56\");\nif (valorResult.success) {\n  console.log(\"Valor válido:\", valorResult.data);\n}\n\n// Validação de nome completo\nconst nomeResult = schemas.fullName.safeParse(\"João Silva Santos\");\nif (nomeResult.success) {\n  console.log(\"Nome válido:\", nomeResult.data);\n}\n\n// Validação de CNPJ\nconst cnpjResult = schemas.cnpj.safeParse(\"12.345.678/0001-90\");\nif (cnpjResult.success) {\n  console.log(\"CNPJ válido:\", cnpjResult.data);\n}\n\n// Uso em formulários Vue com validação\nimport { z } from \"zod\";\n\nconst formSchema = z.object({\n  nome: schemas.fullName,\n  email: schemas.email,\n  cpf: schemas.cpf,\n  celular: schemas.celular,\n  senha: schemas.senha,\n  cep: schemas.cep,\n  valorPedido: schemas.money,\n});\n\n// Validação de objeto completo\nconst dadosFormulario = {\n  nome: \"João Silva Santos\",\n  email: \"joao@exemplo.com\",\n  cpf: \"123.456.789-01\",\n  celular: \"(11)99999-9999\",\n  senha: \"MinhaSenh@123\",\n  cep: \"01234-567\",\n  valorPedido: \"150.00\",\n};\n\ntry {\n  const dadosValidados = formSchema.parse(dadosFormulario);\n  console.log(\"Formulário válido:\", dadosValidados);\n} catch (error) {\n  console.error(\"Erros de validação:\", error.issues);\n}\n```\n\n##### Schemas Disponíveis\n\n| Schema       | Descrição          | Formato Esperado                                 | Exemplo                           |\n| ------------ | ------------------ | ------------------------------------------------ | --------------------------------- |\n| `cpf`        | CPF brasileiro     | Com ou sem máscara                               | \"123.456.789-01\" ou \"12345678901\" |\n| `cnpj`       | CNPJ brasileiro    | Com ou sem máscara                               | \"12.345.678/0001-90\"              |\n| `email`      | Email válido       | Formato padrão                                   | \"usuario@exemplo.com\"             |\n| `fullName`   | Nome completo      | Mínimo 2 palavras, 5 caracteres                  | \"João Silva\"                      |\n| `cep`        | CEP brasileiro     | Formato 99.999-999                               | \"01234-567\"                       |\n| `celular`    | Celular brasileiro | Formato (99)99999-9999                           | \"(11)99999-9999\"                  |\n| `creditCard` | Cartão de crédito  | 16 dígitos com ou sem traços                     | \"1234-5678-9012-3456\"             |\n| `senha`      | Senha forte        | 8+ chars, maiúscula, minúscula, número, especial | \"MinhaSenh@123\"                   |\n| `url`        | URL válida         | Deve começar com http/https                      | \"https://exemplo.com\"             |\n| `money`      | Valor monetário    | Formato decimal                                  | \"1234.56\"                         |\n| `date`       | Data válida        | Qualquer formato de data válido                  | \"2023-12-25\"                      |\n| `dateTime`   | Data e hora        | Formato ISO 8601                                 | \"2023-12-25T10:30:00Z\"            |\n| `calendar`   | Data de calendário | Coerção para Date                                | Date object                       |\n\n#### DOM\n\n- `querySelector()` - Seletor de elementos\n- `createElement()` - Criar elementos\n- `copyToClipboard()` - Copiar para clipboard\n- `scrollToElement()` - Scroll suave\n- `debounce()` - Debounce de funções\n- `throttle()` - Throttle de funções\n\n### Composables\n\n#### useApi\n\n```javascript\nconst { data, loading, error, execute } = useApi(\"/api/endpoint\");\nconst { post } = usePost(\"/api/create\");\nconst { put } = usePut(\"/api/update\");\nconst { remove } = useDelete(\"/api/delete\");\n```\n\n#### useStorage\n\n```javascript\nconst [value, setValue] = useLocalStorage(\"key\", defaultValue);\nconst [sessionValue, setSessionValue] = useSessionStorage(\"key\", defaultValue);\n```\n\n#### useValidation\n\n```javascript\nconst { data, errors, isValid, validate } = useValidation(rules);\n```\n\n#### useDebounce\n\n```javascript\nconst debouncedValue = useDebounce(value, 500);\nconst debouncedFn = useDebouncedFunction(fn, 300);\n```\n\n#### useClipboard\n\n```javascript\nconst { copy, copied, isSupported } = useClipboard();\n```\n\n#### useDevice\n\n```javascript\nconst { deviceType, isMobile, isTablet, orientation } = useDevice();\n```\n\n## 🛠️ Desenvolvimento\n\n### Configuração do Ambiente\n\n```bash\n# Instalar dependências\nnpm install\n\n# Executar em modo desenvolvimento\nnpm run dev\n\n# Build da biblioteca\nnpm run build\n\n# Executar testes\nnpm run test\n\n# Lint do código\nnpm run lint\n```\n\n### Estrutura do Projeto\n\n```\nsrc/\n├── components/          # Componentes Vue\n├── composables/         # Composables do Vue 3\n├── utils/              # Funções utilitárias\n│   ├── api.ts          # Utilitários de API\n│   ├── dom.ts          # Utilitários DOM\n│   ├── format.ts       # Formatação\n│   ├── storage.ts      # Armazenamento\n│   └── validation.ts   # Validação\n├── types/              # Tipos TypeScript\n└── index.ts            # Exportações principais\n```\n\n## 📦 Publicação no NPM\n\n### Pré-requisitos\n\nAntes de publicar uma nova versão, certifique-se de estar logado no NPM:\n\n```bash\n# Login no NPM\nnpm login\n\n# Credenciais:\n# Username: clube-certo\n# Password: [mesma senha da AWS]\n# Email: [email associado à conta]\n```\n\n### Processo de Publicação\n\n1. **Atualizar o código e fazer commit das alterações:**\n\n   ```bash\n   git add .\n   git commit -m \"feat: descrição das alterações\"\n   git push origin main\n   ```\n\n2. **Atualizar a versão no package.json:**\n\n   ```bash\n   # Para patch (correções de bugs): 1.0.0 -> 1.0.1\n   npm version patch\n\n   # Para minor (novas funcionalidades): 1.0.0 -> 1.1.0\n   npm version minor\n\n   # Para major (breaking changes): 1.0.0 -> 2.0.0\n   npm version major\n   ```\n\n3. **Gerar o build da biblioteca:**\n\n   ```bash\n   npm run build\n   ```\n\n4. **Publicar no NPM:**\n\n   ```bash\n   npm publish --access public\n   ```\n\n5. **Fazer push da tag de versão:**\n   ```bash\n   git push origin --tags\n   ```\n\n### Verificação da Publicação\n\nApós a publicação, você pode verificar se a nova versão está disponível:\n\n```bash\n# Verificar versões disponíveis\nnpm view @clube-certo/front-commons versions --json\n\n# Verificar informações da versão atual\nnpm view @clube-certo/front-commons\n```\n\n### Notas Importantes\n\n- ⚠️ **Sempre teste localmente** antes de publicar uma nova versão\n- 📋 **Documente as alterações** no commit e considere manter um CHANGELOG\n- 🔄 **Use versionamento semântico** (SemVer) para as versões\n- 🧪 **Execute os testes** antes da publicação: `npm run test`\n- 🔍 **Verifique o lint** antes da publicação: `npm run lint`\n\n## 📝 Contribuição\n\n1. Fork o projeto\n2. Crie uma branch para sua feature (`git checkout -b feature/nova-feature`)\n3. Commit suas mudanças (`git commit -am 'Adiciona nova feature'`)\n4. Push para a branch (`git push origin feature/nova-feature`)\n5. Abra um Pull Request\n\n## 📄 Licença\n\nMIT © Clube Certo\n\n## 🔗 Links Úteis\n\n- [Vue 3 Documentation](https://vuejs.org/)\n- [TypeScript Documentation](https://www.typescriptlang.org/)\n- [Vitest Documentation](https://vitest.dev/)\n","readmeFilename":"README.md"}