From d0247f5cdd84db35926f7c1acf0ecfcc367af5f5 Mon Sep 17 00:00:00 2001 From: Michael Amaral Date: Sun, 10 Nov 2024 16:22:22 -0300 Subject: [PATCH] Chore/refactoring (#162) * chore(renaming): renaming components, excluding FAB, updating deps, removing scale * chore(refactoring): removing If, Shadow components * chore(refactoring): removing components, adding jest threshold * chore(refactoring): renaming components * chore(refactoring): adding codeway rules + semgrep * chore(refactoring): removing unused deps, remanaging dependencies, devDeps and peerDeps * chore(refactoring): adding numeral * chore(refactoring): updating snapshot using hairline width --- .eslintrc.js | 1 + codeway/rules/performance.yml | 13 + codeway/rules/security.yml | 29 + codeway/rules/structure.yml | 185 + codeway/rules/theme.yml | 146 + codeway/semgrep.txt | 91 + jest.config.js | 13 +- package.json | 155 +- patches/react-native-camera+4.2.1.patch | 20 - ...ative-markdown-display+7.0.0-alpha.2.patch | 12 - .../platformbuilders-helpers.ts} | 2 - src/__mocks__/react-native-haptic-feedback.ts | 3 + .../__snapshots__/Accordion.spec.tsx.snap | 20 +- src/components/Accordion/index.tsx | 13 +- src/components/Accordion/styles.ts | 3 +- .../__snapshots__/Avatar.spec.tsx.snap | 22 +- .../__tests__/Badge.spec.tsx} | 62 +- .../__snapshots__/Badge.spec.tsx.snap} | 27 +- .../{ChipButton => Badge}/index.tsx | 23 +- .../{ChipButton => Badge}/styles.ts | 0 .../__tests__/BottomNavigation.spec.tsx} | 12 +- .../BottomNavigation.spec.tsx.snap} | 20 +- .../index.stories.tsx | 8 +- .../{Navbar => BottomNavigation}/index.tsx | 10 +- .../{Navbar => BottomNavigation}/styles.ts | 19 +- .../Button/__tests__/Button.spec.tsx | 4 - .../__snapshots__/Button.spec.tsx.snap | 5 +- src/components/Button/index.tsx | 17 +- src/components/DatePicker/index.tsx | 4 +- .../__tests__/DisplayVersion.spec.tsx | 16 - .../DisplayVersion.spec.tsx.snap | 28 - .../DisplayVersion/index.stories.tsx | 19 - src/components/DisplayVersion/index.tsx | 18 - src/components/DisplayVersion/styles.ts | 16 - src/components/FAB/__tests__/FAB.spec.tsx | 111 - .../__tests__/__snapshots__/FAB.spec.tsx.snap | 806 -- src/components/FAB/index.stories.tsx | 27 - src/components/FAB/index.tsx | 58 - src/components/FAB/styles.ts | 50 - .../__snapshots__/Header.spec.tsx.snap | 358 +- src/components/Header/index.tsx | 70 +- src/components/Header/styles.ts | 3 +- src/components/Icon/index.tsx | 9 +- src/components/If/__tests__/If.spec.tsx | 50 - .../__tests__/__snapshots__/If.spec.tsx.snap | 9 - src/components/If/index.stories.tsx | 23 - src/components/If/index.ts | 9 - .../__snapshots__/Image.spec.tsx.snap | 20 + .../__tests__/KeyboardAvoidingView.spec.tsx | 14 - .../KeyboardAvoidingView.spec.tsx.snap | 14 - src/components/KeyboardAvoidingView/index.tsx | 25 - src/components/KeyboardAvoidingView/styles.ts | 3 - .../LoadingIndicator.test.tsx.snap | 5 + .../__snapshots__/PinInput.test.tsx.snap | 550 +- src/components/PinInput/index.tsx | 7 +- src/components/PinInput/styles.ts | 3 +- .../__snapshots__/RadioButton.spec.tsx.snap | 60 +- src/components/RadioButton/styles.ts | 16 +- .../__snapshots__/Search.spec.tsx.snap | 374 +- src/components/SearchInput/styles.ts | 5 +- .../__tests__/Separator.spec.tsx} | 8 +- .../__snapshots__/Separator.spec.tsx.snap} | 10 +- .../index.stories.tsx | 8 +- .../{LabelDivider => Separator}/index.tsx | 4 +- .../{LabelDivider => Separator}/styles.ts | 3 +- .../Shadow/__tests__/Shadow.spec.tsx | 17 - .../__snapshots__/Shadow.spec.tsx.snap | 19 - src/components/Shadow/index.stories.tsx | 20 - src/components/Shadow/index.tsx | 25 - src/components/Shadow/styles.ts | 8 - .../Swiper/__tests__/Swiper.spec.tsx | 39 - .../__snapshots__/Swiper.spec.tsx.snap | 176 - src/components/Swiper/index.stories.tsx | 47 - src/components/Swiper/index.tsx | 28 - src/components/TextInput/Floating.style.ts | 21 +- .../TextInput/MaskedTextInput/index.tsx | 191 +- .../TextInput/MaskedTextInput/styles.ts | 6 +- .../__snapshots__/PasswordInput.spec.tsx.snap | 18 +- .../__snapshots__/TextInput.spec.tsx.snap | 84 +- src/components/TextInput/index.tsx | 4 +- src/components/TextInput/styles.ts | 19 +- .../Touchable/__tests__/Touchable.spec.tsx | 4 - src/components/Touchable/index.tsx | 4 +- src/components/Typography/index.tsx | 57 +- .../__snapshots__/UploadPhoto.spec.tsx.snap | 12 +- src/components/index.ts | 14 +- src/types/CheckBox.d.ts | 5 +- src/types/KeyboardAvoidingView.ts | 15 - src/types/Swiper.ts | 15 - src/types/TouchableType.ts | 2 +- src/types/index.ts | 2 - src/utils/helpers/shadow.ts | 6 +- tsconfig.json | 2 +- tsconfig.publish.json | 9 +- yarn.lock | 6849 ++++++----------- 95 files changed, 4152 insertions(+), 7314 deletions(-) create mode 100644 codeway/rules/performance.yml create mode 100644 codeway/rules/security.yml create mode 100644 codeway/rules/structure.yml create mode 100644 codeway/rules/theme.yml create mode 100644 codeway/semgrep.txt delete mode 100644 patches/react-native-camera+4.2.1.patch delete mode 100644 patches/react-native-markdown-display+7.0.0-alpha.2.patch rename src/{test/mocks.tsx => __mocks__/platformbuilders-helpers.ts} (77%) create mode 100644 src/__mocks__/react-native-haptic-feedback.ts rename src/components/{ChipButton/__tests__/ChipButton.spec.tsx => Badge/__tests__/Badge.spec.tsx} (61%) rename src/components/{ChipButton/__tests__/__snapshots__/ChipButton.spec.tsx.snap => Badge/__tests__/__snapshots__/Badge.spec.tsx.snap} (96%) rename src/components/{ChipButton => Badge}/index.tsx (83%) rename src/components/{ChipButton => Badge}/styles.ts (100%) rename src/components/{Navbar/__tests__/Navbar.spec.tsx => BottomNavigation/__tests__/BottomNavigation.spec.tsx} (72%) rename src/components/{Navbar/__tests__/__snapshots__/Navbar.spec.tsx.snap => BottomNavigation/__tests__/__snapshots__/BottomNavigation.spec.tsx.snap} (94%) rename src/components/{Navbar => BottomNavigation}/index.stories.tsx (80%) rename src/components/{Navbar => BottomNavigation}/index.tsx (83%) rename src/components/{Navbar => BottomNavigation}/styles.ts (82%) delete mode 100644 src/components/DisplayVersion/__tests__/DisplayVersion.spec.tsx delete mode 100644 src/components/DisplayVersion/__tests__/__snapshots__/DisplayVersion.spec.tsx.snap delete mode 100644 src/components/DisplayVersion/index.stories.tsx delete mode 100644 src/components/DisplayVersion/index.tsx delete mode 100644 src/components/DisplayVersion/styles.ts delete mode 100644 src/components/FAB/__tests__/FAB.spec.tsx delete mode 100644 src/components/FAB/__tests__/__snapshots__/FAB.spec.tsx.snap delete mode 100644 src/components/FAB/index.stories.tsx delete mode 100644 src/components/FAB/index.tsx delete mode 100644 src/components/FAB/styles.ts delete mode 100644 src/components/If/__tests__/If.spec.tsx delete mode 100644 src/components/If/__tests__/__snapshots__/If.spec.tsx.snap delete mode 100644 src/components/If/index.stories.tsx delete mode 100644 src/components/If/index.ts delete mode 100644 src/components/KeyboardAvoidingView/__tests__/KeyboardAvoidingView.spec.tsx delete mode 100644 src/components/KeyboardAvoidingView/__tests__/__snapshots__/KeyboardAvoidingView.spec.tsx.snap delete mode 100644 src/components/KeyboardAvoidingView/index.tsx delete mode 100644 src/components/KeyboardAvoidingView/styles.ts rename src/components/{LabelDivider/__tests__/LabelDivider.spec.tsx => Separator/__tests__/Separator.spec.tsx} (69%) rename src/components/{LabelDivider/__tests__/__snapshots__/LabelDivider.spec.tsx.snap => Separator/__tests__/__snapshots__/Separator.spec.tsx.snap} (84%) rename src/components/{LabelDivider => Separator}/index.stories.tsx (71%) rename src/components/{LabelDivider => Separator}/index.tsx (75%) rename src/components/{LabelDivider => Separator}/styles.ts (90%) delete mode 100644 src/components/Shadow/__tests__/Shadow.spec.tsx delete mode 100644 src/components/Shadow/__tests__/__snapshots__/Shadow.spec.tsx.snap delete mode 100644 src/components/Shadow/index.stories.tsx delete mode 100644 src/components/Shadow/index.tsx delete mode 100644 src/components/Shadow/styles.ts delete mode 100644 src/components/Swiper/__tests__/Swiper.spec.tsx delete mode 100644 src/components/Swiper/__tests__/__snapshots__/Swiper.spec.tsx.snap delete mode 100644 src/components/Swiper/index.stories.tsx delete mode 100644 src/components/Swiper/index.tsx delete mode 100644 src/types/KeyboardAvoidingView.ts delete mode 100644 src/types/Swiper.ts diff --git a/.eslintrc.js b/.eslintrc.js index 9fc2f664..5cc68653 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,3 +1,4 @@ module.exports = { extends: '@platformbuilders/eslint-config-builders/react', + ignorePatterns: ['jest'], }; diff --git a/codeway/rules/performance.yml b/codeway/rules/performance.yml new file mode 100644 index 00000000..27794de6 --- /dev/null +++ b/codeway/rules/performance.yml @@ -0,0 +1,13 @@ +rules: + - id: use-fastimage-instead-of-image + languages: [javascript, typescript] + message: 'Sempre use o módulo FastImage no lugar de styled.Image para melhorar a performance no carregamento de imagens.' + severity: WARNING + patterns: + - pattern-regex: "styled\\.Image" + paths: + exclude: + - '*.json' + metadata: + description: 'O FastImage oferece melhor desempenho no carregamento de imagens em comparação com o Image padrão do React Native. Use FastImage para garantir uma experiência de usuário mais fluida e eficiente.' + tags: ['styles', 'image', 'performance', 'fastimage'] diff --git a/codeway/rules/security.yml b/codeway/rules/security.yml new file mode 100644 index 00000000..04c5a1c5 --- /dev/null +++ b/codeway/rules/security.yml @@ -0,0 +1,29 @@ +rules: + - id: avoid-console-logs + languages: [javascript, typescript] + message: 'Parece que um console.log() ou similar foi esquecido. Remova para evitar exposição de informações.' + severity: WARNING + patterns: + - pattern-regex: "(console\\.log|console\\.warn|console\\.table|console\\.assert|console\\.count|console\\.dir|console\\.error|console\\.group|console\\.info)" + paths: + exclude: + - '*.json' + - 'src/bootstrap.tsx' + - '*.stories.tsx' + - 'src/components/FormError/index.tsx' + metadata: + description: 'Esta regra captura o uso de funções do console, como log ou warn, que podem ter sido deixadas acidentalmente. É importante remover esses logs em produção para evitar a exposição de informações sensíveis ou desnecessárias.' + tags: ['console', 'logs', 'debugging'] + + - id: avoid-console-tron-in-production + languages: [javascript, typescript] + message: 'Evite usar console.tron em builds de produção. Pode causar crashes silenciosos e dificultar o debugging.' + severity: WARNING + patterns: + - pattern-regex: "(console\\.tron\\.log|console\\.tron\\.warn|console\\.tron\\.table|console\\.tron\\.assert|console\\.tron\\.count|console\\.tron\\.dir|console\\.tron\\.error|console\\.tron\\.group|console\\.tron\\.info)" + paths: + exclude: + - '*.json' + metadata: + description: 'Esta regra detecta o uso de console.tron (Reactotron) em builds de produção, o que pode causar crashes silenciosos. Deve ser removido para evitar problemas graves no ambiente de produção.' + tags: ['reactotron', 'logs', 'debugging', 'production'] diff --git a/codeway/rules/structure.yml b/codeway/rules/structure.yml new file mode 100644 index 00000000..db5726f1 --- /dev/null +++ b/codeway/rules/structure.yml @@ -0,0 +1,185 @@ +rules: + - id: no-class-in-components + languages: [javascript, typescript] + message: 'Evite usar classes em componentes. Use funções ou hooks.' + severity: WARNING + patterns: + - pattern-regex: "class\\s?\\w+\\sextends" + paths: + exclude: + - '*.json' + - 'src/components/PinInput/lib/react-native-smooth-pincode-input/index.d.ts' + metadata: + description: 'Essa regra evita o uso de classes em componentes React. A abordagem funcional com hooks é recomendada para garantir código mais simples e fácil de manter.' + tags: ['classes', 'componentes', 'react'] + + - id: use-enum-instead-of-string-comparisons + languages: [javascript, typescript] + message: 'Use ENUM para comparações em vez de strings. Comparar strings diretamente torna o código menos escalável e mais suscetível a erros.' + severity: WARNING + patterns: + - pattern-regex: '(("|'').+("|'') (===|!==|>=|<=|>|<|=>|=<))|(===|!==|>=|<=|>|<|=>|=<) ("|'').+("|'')' + paths: + exclude: + - '*.json' + - '*.test.tsx' + - '**/**/svg/*' + - 'src/components/FormError/index.tsx' + - 'src/components/Image/index.tsx' + metadata: + description: 'Esta regra sugere o uso de ENUMs em vez de comparações diretas por string. O uso de ENUMs torna o código mais escalável e reduz a chance de erros em comparações lógicas.' + tags: ['comparações', 'enum', 'strings'] + + - id: use-specific-response-type-instead-of-axiosresponse + languages: [javascript, typescript] + message: 'Indique o tipo de dado retornado em vez de utilizar `AxiosResponse` diretamente. Isso ajuda a prever o formato dos dados e garante maior segurança de tipos.' + severity: WARNING + patterns: + - pattern-regex: "\\s?(Promise|AxiosResponse)" + paths: + exclude: + - '*.json' + - 'src/api/interceptors/*' + metadata: + description: 'Esta regra sugere o uso de tipos de dados específicos no lugar de `AxiosResponse` ao trabalhar com Axios. Usar tipos claros ajuda a melhorar a previsibilidade e a segurança dos dados retornados.' + tags: ['axios', 'tipagem', 'promises'] + + - id: return-only-request-data + languages: [javascript, typescript] + message: 'Sempre retorne diretamente o data da requisição: `const { data } = await request`. Isso simplifica o manuseio de respostas.' + severity: WARNING + patterns: + - pattern-regex: "return\\s+await\\s+request\\.[\\w]+\\(" + paths: + exclude: + - '*.json' + metadata: + description: 'Ao retornar respostas de requisições, sempre extraia e retorne o `data` diretamente, garantindo que o código seja mais simples e focado nos dados retornados pela requisição.' + tags: ['request', 'axios', 'data', 'async', 'await'] + + - id: prefer-type-for-simple-types + languages: [javascript, typescript] + message: 'Prefira o uso de Type para definição de tipos simples e união de tipos. Use Interface para objetos ou quando precisar de extensão.' + severity: WARNING + patterns: + - pattern-regex: "interface\\s+\\w+\\s+{\\s*[^extends].*Props.*" + paths: + exclude: + - '*.json' + metadata: + description: 'Recomenda-se o uso de Type para criação de tipos simples ou união de tipos em TypeScript. Interface ainda pode ser usada para definir a estrutura de objetos ou quando é necessária extensão.' + tags: ['typescript', 'types', 'interface', 'props', 'type'] + + - id: use-custom-touchable-component + languages: [javascript, typescript] + message: 'Sempre utilize o componente personalizado Touchable em vez de TouchableOpacity, TouchableHighlight ou Pressable diretamente.' + severity: WARNING + patterns: + - pattern-regex: "styled\\.(TouchableOpacity|TouchableHighlight|Pressable)" + paths: + exclude: + - '*.json' + metadata: + description: 'Para garantir consistência de comportamento e estilos, utilize o componente customizado Touchable no lugar dos componentes nativos TouchableOpacity, TouchableHighlight ou Pressable.' + tags: ['styles', 'touchable', 'components', 'custom-components'] + + - id: use-array-syntax-instead-of-array-generic + languages: [javascript, typescript] + message: "Utilize '[]' em vez de 'Array<>' para definir tipos de arrays." + severity: WARNING + patterns: + - pattern-regex: 'Array<.*>' + paths: + exclude: + - '*.json' + metadata: + description: "Prefira a notação '[]' para definir tipos de arrays em TypeScript, em vez da sintaxe genérica 'Array<>'. A notação de array é mais legível e comum." + tags: ['types', 'array', 'typescript'] + + - id: use-await-instead-of-then + languages: [javascript, typescript] + message: "Utilize 'await' em vez de '.then()' para lidar com Promises. Isso torna o código mais conciso e legível." + severity: WARNING + patterns: + - pattern-regex: ".*\\.then\\(.*\\).*" + paths: + exclude: + - '*.json' + - '*.spec.ts' + - '*.spec.js' + - '*.cy.ts' + metadata: + description: "Prefira usar 'await' em vez de '.then()' ao lidar com Promises, tornando o código mais simples e fácil de ler. Async/await é a abordagem mais moderna e recomendada." + tags: ['async', 'await', 'promises'] + + - id: api-call-only-in-stores + languages: [javascript, typescript] + message: 'Todas as chamadas de API devem ser feitas a partir do diretório /api e consumidas nas Stores para simplificar o fluxo de dados, facilitar o debug e promover a reutilização de dados no state.' + severity: WARNING + patterns: + - pattern-either: + - pattern-regex: "import\\s?{.*}\\s?from\\s?['\"]~\\/api['\"];" + - pattern-regex: "\\.\\s*(get|post|put|delete)\\s*\\(\\s*[`'\"].*\\/.*[`'\"].*\\)" + - pattern-regex: "Api\\." + paths: + exclude: + - '*.store.ts' + - '*.api.ts' + - '*.mock.ts' + - '*.test.ts' + - '*.spec.ts' + + metadata: + description: 'As chamadas de API devem ser feitas no diretório /api e consumidas exclusivamente dentro das Stores. Isso proporciona simplificação do fluxo de dados, facilidade de debug e reutilização eficiente de dados no state. Além disso, essa abordagem melhora a organização e a escalabilidade do código.' + tags: ['api', 'store', 'architecture', 'import', 'post', 'get'] + + - id: avoid-long-functions + languages: [javascript, typescript] + message: 'Funções com mais de 50 linhas devem ser refatoradas para melhorar a legibilidade e modularidade.' + severity: WARNING + patterns: + - pattern-regex: "function\\s+\\w+\\(.*\\)\\s*{((?:[^}]*\\n){50,})" + metadata: + description: 'Funções muito longas podem ser difíceis de entender e manter. Recomendado refatorar funções com mais de 50 linhas.' + tags: ['function', 'modularity', 'readability'] + + - id: avoid-global-variables + languages: [javascript, typescript] + message: 'Evite variáveis globais. Prefira escopo local ou modularização.' + severity: WARNING + patterns: + - pattern-regex: "var\\s+\\w+\\s*=\\s*.*;" + paths: + exclude: + - '*.module.ts' + metadata: + description: 'Variáveis globais podem causar conflitos em grandes aplicações. Prefira usar escopo local ou módulos.' + tags: ['variables', 'global', 'modularity'] + + - id: avoid-too-many-parameters + languages: [javascript, typescript] + message: 'Funções com mais de 3 parâmetros devem ser simplificadas. Prefira passar um objeto com as propriedades.' + severity: WARNING + patterns: + - pattern-regex: "function\\s+\\w+\\([^,]{4,}\\)" + paths: + exclude: + - '*/navigation/*' + metadata: + description: 'Funções com muitos parâmetros são difíceis de ler e manter. Prefira passar um objeto para maior clareza.' + tags: ['function', 'parameters', 'modularity'] + + - id: avoid-single-letter-variables + languages: [javascript, typescript] + message: 'Evite usar nomes de variáveis de uma única letra. Prefira nomes mais descritivos.' + severity: WARNING + patterns: + - pattern-regex: "(var|let|const)\\s+[a-zA-Z]\\s?=.*;" + paths: + exclude: + - '*.json' + - '*.test.*' + - '*.spec.*' + metadata: + description: 'Nomes de variáveis de uma única letra reduzem a legibilidade. Use nomes mais descritivos, exceto em loops simples.' + tags: ['variables', 'naming', 'readability'] diff --git a/codeway/rules/theme.yml b/codeway/rules/theme.yml new file mode 100644 index 00000000..36131dac --- /dev/null +++ b/codeway/rules/theme.yml @@ -0,0 +1,146 @@ +rules: + - id: avoid-scale-functions-react-native + languages: [javascript, typescript] + message: 'Evite usar funções como scale ou moderateScale para definir width ou height. O React Native já faz o scaling nativamente.' + severity: WARNING + patterns: + - pattern-regex: "(moderateScale|scale)\\(\\d+\\)" + paths: + exclude: + - '*.json' + metadata: + description: 'Esta regra sugere evitar o uso de funções como scale ou moderateScale, já que o React Native já faz o scaling de forma nativa, tornando o código mais simples e performático.' + tags: ['width', 'height', 'responsividade', 'react-native'] + + - id: avoid-stylesheet-use-styled-components + languages: [javascript, typescript] + message: 'Evite usar StyleSheet.create. Utilize styled-components para definir estilos.' + severity: WARNING + patterns: + - pattern-regex: "StyleSheet\\.create" + paths: + exclude: + - '*.json' + - 'src/components/PinInput/lib/react-native-smooth-pincode-input/SmoothPinCodeInput.js' + metadata: + description: 'Esta regra proíbe o uso de StyleSheet.create no React Native e recomenda a utilização de styled-components para definir estilos, promovendo uma abordagem mais moderna e flexível.' + tags: ['styles', 'react-native', 'styled-components'] + + - id: avoid-direct-theme-import + languages: [javascript, typescript] + message: 'Importação direta do tema não é permitida. Utilize um módulo intermediário para gerenciar temas.' + severity: WARNING + patterns: + - pattern-regex: "import\\s?{.*}\\s?from\\s?'~\/theme'" + paths: + exclude: + - '*.json' + metadata: + description: "Esta regra impede a importação direta do tema da aplicação ('~/theme'). É recomendada a utilização de módulos intermediários para gerenciar e manter a modularidade do tema no código." + tags: ['theme', 'import', 'modularidade'] + + - id: prefer-hairlinewidth-over-1px + languages: [javascript, typescript] + message: 'O ideal seria usar StyleSheet.hairlineWidth em vez de utilizar 1px ou 1 diretamente. Isso garante consistência de design em múltiplas resoluções.' + severity: WARNING + patterns: + - pattern-regex: "height:\\s?(\\${moderateScale\\(1\\)}|\\${scale\\(1\\)\\}|1;|1\\s|1px)" + paths: + exclude: + - '*.json' + metadata: + description: 'Esta regra sugere o uso de StyleSheet.hairlineWidth ao invés de definir height como 1 ou 1px diretamente, garantindo melhor consistência e adaptabilidade do design entre diferentes resoluções de tela.' + tags: ['styles', 'height', 'hairlineWidth'] + + - id: avoid-scale-or-moderatescale-in-fontsize + languages: [javascript, typescript] + message: 'Evite usar moderateScale ou scale no fontSize. O React Native já faz o escalonamento de fontes de forma nativa.' + severity: WARNING + patterns: + - pattern-regex: "(fontSize:\\s?\\${moderateScale\\(\\d+\\)}|fontSize:\\s?\\${scale\\(\\d+\\)})" + paths: + exclude: + - '*.json' + metadata: + description: 'Essa regra proíbe o uso de moderateScale ou scale para definir o tamanho de fonte. O React Native já realiza o escalonamento de fontes de forma nativa, garantindo consistência entre dispositivos.' + tags: ['styles', 'fontsize', 'scale', 'moderatescale'] + + - id: avoid-styled-text-use-typography + languages: [javascript, typescript] + message: 'Evite usar styled.Text. Use o componente Typography, que contém lógica de renderização e sizing de fontes.' + severity: WARNING + patterns: + - pattern-regex: "styled\\.Text`" + paths: + exclude: + - '*.json' + metadata: + description: 'O componente Typography deve ser utilizado no lugar de styled.Text, pois ele já contém a lógica de renderização e sizing de fontes, garantindo consistência e eficiência no código.' + tags: ['styled-components', 'typography', 'fonts'] + + - id: prefer-font-weight-bold + languages: [javascript, typescript] + message: 'Recomenda-se usar font-weight: bold; para evitar problemas de renderização no Android.' + severity: WARNING + patterns: + - pattern-regex: "font-weight:\\s?600" + paths: + exclude: + - '*.json' + metadata: + description: 'Evite usar font-weight: 600 em estilos, pois pode causar problemas de renderização em dispositivos Android. Use font-weight: bold para garantir uma exibição consistente.' + tags: ['styles', 'font-weight', 'android', 'bold'] + + - id: prefer-correct-border-radius-from-theme + languages: [javascript, typescript] + message: "Recomenda-se usar valores de border-radius obtidos corretamente do tema, por meio de getTheme('borderRadius')." + severity: WARNING + patterns: + - pattern-regex: "const\\s+\\w+\\s?=\\s?getTheme\\('border\\w+'\\);" + paths: + exclude: + - '*.json' + metadata: + description: "Garanta que os valores de border-radius sejam obtidos do tema corretamente utilizando getTheme('borderRadius'). Isso assegura consistência no design." + tags: ['styles', 'border-radius', 'theme'] + + - id: prefer-theme-colors + languages: [javascript, typescript] + message: 'Sempre utilize cores definidas no tema. Evite o uso de códigos hexadecimais hardcoded.' + severity: WARNING + patterns: + - pattern-regex: ".*?:\\s?#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})" + paths: + exclude: + - '*.json' + metadata: + description: 'As cores devem ser obtidas a partir do tema da aplicação, garantindo consistência e facilitando a manutenção. Evite usar códigos hexadecimais diretamente.' + tags: ['styles', 'colors', 'theme'] + + - id: use-theme-spacing + languages: [javascript, typescript] + message: "Utilize valores de spacing vindos do tema corretamente, como 'padding: ${smallSpacing}px'." + severity: WARNING + patterns: + - pattern-regex: "(padding|margin)(-?)(left|right|top|bottom|vertical|horizontal)?:\\s?(\\d+px);" + paths: + exclude: + - '*.json' + metadata: + description: 'Os valores de padding e margin devem ser obtidos diretamente do tema da aplicação, garantindo consistência no espaçamento entre os elementos. Evite usar valores fixos em pixels.' + tags: ['styles', 'spacing', 'theme', 'padding', 'margin'] + + - id: use-variant-instead-of-fontsize + languages: [javascript, typescript] + message: "Utilize a prop 'variant' do componente Typography em vez de definir 'font-size' manualmente." + severity: WARNING + patterns: + - pattern-regex: 'font-size' + paths: + exclude: + - '*.json' + - 'src/components/Avatar/styles.ts' + - 'src/components/Typography/styles.ts' + metadata: + description: "Para garantir consistência tipográfica e centralizar a lógica de estilos de fonte, utilize a prop 'variant' no componente Typography em vez de definir 'font-size' manualmente." + tags: ['styles', 'typography', 'variant', 'font-size'] diff --git a/codeway/semgrep.txt b/codeway/semgrep.txt new file mode 100644 index 00000000..1df0c8ea --- /dev/null +++ b/codeway/semgrep.txt @@ -0,0 +1,91 @@ + + +┌──────────────────┐ +│ 25 Code Findings │ +└──────────────────┘ + +  src/components/Button/index.tsx + ❯❯❱ codeway.rules.use-enum-instead-of-string-comparisons + Use ENUM para comparações em vez de strings. Comparar strings diretamente torna o código menos + escalável e mais suscetível a erros. + + 40┆ hasBorder={variant === 'outline'} + +  src/components/Button/styles.ts + ❯❯❱ codeway.rules.use-enum-instead-of-string-comparisons + Use ENUM para comparações em vez de strings. Comparar strings diretamente torna o código menos + escalável e mais suscetível a erros. + + 55┆ if (props.buttonVariant === 'tint') { + ⋮┆---------------------------------------- + 64┆ props.buttonVariant === 'flat' || + ⋮┆---------------------------------------- + 65┆ props.buttonVariant === 'ghost' || + ⋮┆---------------------------------------- + 66┆ props.buttonVariant === 'outline' + ⋮┆---------------------------------------- + 104┆ props.buttonVariant === 'filled' + ⋮┆---------------------------------------- + 110┆ props.buttonVariant === 'filled' + ⋮┆---------------------------------------- + 116┆ props.buttonVariant === 'filled' + ⋮┆---------------------------------------- + 122┆ props.buttonVariant === 'filled' + ⋮┆---------------------------------------- + 128┆ props.buttonVariant === 'filled' ? infoContrast(props) : infoMain(props) + ⋮┆---------------------------------------- + 132┆ props.buttonVariant === 'filled' + ⋮┆---------------------------------------- + 138┆ props.buttonVariant === 'filled' + +  src/components/PinInput/lib/react-native-smooth-pincode-input/SmoothPinCodeInput.js + ❯❯❱ codeway.rules.no-class-in-components + Evite usar classes em componentes. Use funções ou hooks. + + 23┆ class SmoothPinCodeInput extends Component { + + ❯❯❱ codeway.rules.use-enum-instead-of-string-comparisons + Use ENUM para comparações em vez de strings. Comparar strings diretamente torna o código menos + escalável e mais suscetível a erros. + + 71┆ if (event.nativeEvent.key === 'Backspace') { + ⋮┆---------------------------------------- + 80┆ if (typeof this.props.onFocus === 'function') { + ⋮┆---------------------------------------- + 86┆ if (typeof this.props.onBlur === 'function') { + ⋮┆---------------------------------------- + 91┆ if (typeof this.props.useIndexedAccessibilityLabel === 'string') + ⋮┆---------------------------------------- + 96┆ if (typeof this.props.useIndexedTestID === 'string') + ⋮┆---------------------------------------- + 158┆ const isPlaceholderText = typeof placeholder === 'string'; + ⋮┆---------------------------------------- + 159┆ const isMaskText = typeof mask === 'string'; + ⋮┆---------------------------------------- + 175┆ const isCellText = typeof cellText === 'string'; + +  src/components/TextInput/__tests__/TextInput.spec.tsx + ❯❯❱ codeway.rules.avoid-console-logs + Parece que um console.log() ou similar foi esquecido. Remova para evitar exposição de informações. + + 86┆ console.log(wrapper); + +  src/components/TextInput/index.tsx + ❯❯❱ codeway.rules.use-enum-instead-of-string-comparisons + Use ENUM para comparações em vez de strings. Comparar strings diretamente torna o código menos + escalável e mais suscetível a erros. + + 318┆ fixedLabelVariant === 'animated' + +  src/components/TextInput/styles.ts + ❯❯❱ codeway.rules.use-variant-instead-of-fontsize + Utilize a prop 'variant' do componente Typography em vez de definir 'font-size' manualmente. + + 225┆ font-size: ${getFontSize}px; + +  src/components/Typography/index.tsx + ❯❯❱ codeway.rules.use-enum-instead-of-string-comparisons + Use ENUM para comparações em vez de strings. Comparar strings diretamente torna o código menos + escalável e mais suscetível a erros. + + 17┆ if (variant === 'animated') { diff --git a/jest.config.js b/jest.config.js index 19e668b6..f7cdd41e 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,6 +1,14 @@ const { defaults: tsjPreset } = require('ts-jest/presets'); module.exports = { + coverageThreshold: { + global: { + branches: 70, + functions: 60, + lines: 75, + statements: 70, + }, + }, preset: 'react-native', moduleDirectories: ['node_modules', 'src'], globals: { @@ -15,12 +23,14 @@ module.exports = { transformIgnorePatterns: [ 'node_modules/(?!react-native-haptic|rn-placeholder)/', 'node_modules/jest-runner/', + '.stories.tsx', ], modulePathIgnorePatterns: ['/dist/'], moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], setupFilesAfterEnv: [ '@testing-library/jest-native/extend-expect', - '/src/test/mocks.tsx', + '/src/__mocks__/react-native-haptic-feedback.ts', + '/src/__mocks__/platformbuilders-helpers.ts', ], cacheDirectory: '.jest/cache', collectCoverage: true, @@ -32,6 +42,7 @@ module.exports = { '!**/__tests__/**', '!**/documentation/**', '!**/storybook/**', + '!**/*.stories.tsx', '!**/styles.ts', '!**/*.enum.ts', '!src/enums/index.ts', // No need to test exported files diff --git a/package.json b/package.json index 9f0f93be..8fa5b2dd 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,13 @@ { "name": "@platformbuilders/fluid-react-native", - "version": "0.12.3", + "version": "1.0.0", "private": false, "description": "Builders React Native for Fluid Design System", "keywords": [ "platformbuilders", - "react", + "react native", "fluid", - "elements" + "components" ], "files": [ "dist" @@ -29,7 +29,7 @@ "clean": "rm -rf ./node_modules native yarn.lock dist coverage && yarn install", "ios": "react-native run-ios", "lint": "tsc --noEmit && eslint \"src/**/*.{ts,tsx}\" --fix", - "precommit": "yarn lint && yarn test", + "precommit": "yarn lint && yarn test && yarn semgrep", "pretty": "patch-package && prettier --config ./.prettierrc.js --write \"src/**/*.{ts,tsx,js}\"", "prepublish": "yarn build", "start": "react-native start", @@ -41,7 +41,8 @@ "postversion": "git push && git push --tags", "version:major": "npm version major", "version:minor": "npm version minor", - "version:patch": "npm version patch" + "version:patch": "npm version patch", + "semgrep": "semgrep --config ./codeway/rules ./src --text --output=./codeway/semgrep.txt" }, "lint-staged": { "*.{ts,tsx}": [ @@ -51,109 +52,97 @@ ] }, "dependencies": { - "@babel/runtime": "7.22.6", - "@fnando/cpf": "1.0.2", - "@testing-library/jest-native": "5.4.3", - "@testing-library/react-native": "12.1.3", - "numeral": "2.0.6", - "react-native-animatable": "1.3.3", + "numeral": "^2.0.6", + "react-native-animatable": "1.4.0", + "react-native-check-box": "2.1.7", + "react-native-collapsible": "1.6.2", + "react-native-datepicker": "1.7.2", + "react-native-haptic-feedback": "2.3.3", + "react-native-image-picker": "7.1.2", + "react-native-markdown-display": "7.0.2", "react-native-masked-input": "2.2.3", - "react-native-swiper-flatlist": "3.2.3", - "react-native-testing-library": "6.0.0", "rn-placeholder": "3.0.3" }, "devDependencies": { - "@babel/core": "7.20.2", - "@babel/preset-env": "7.20.2", - "@babel/runtime": "7.22.6", - "@commitlint/config-conventional": "17.6.7", - "@platformbuilders/eslint-config-builders": "1.0.2", - "@platformbuilders/helpers": "0.11.0", + "@babel/core": "7.26.0", + "@babel/preset-env": "7.26.0", + "@babel/runtime": "7.26.0", + "@commitlint/config-conventional": "19.5.0", + "@platformbuilders/eslint-config-builders": "1.2.0", + "@platformbuilders/helpers": "0.11.3", "@platformbuilders/theme-toolkit": "0.3.0", - "@react-native-async-storage/async-storage": "1.22.2", - "@react-native-community/datetimepicker": "7.6.1", - "@react-native-community/slider": "4.4.2", - "@react-native/babel-preset": "0.73.21", - "@react-native/eslint-config": "0.73.2", - "@react-native/metro-config": "0.73.5", - "@react-native/typescript-config": "0.73.1", - "@storybook/addon-ondevice-controls": "7.6.14", - "@storybook/addon-ondevice-notes": "7.6.15", - "@storybook/react-native": "7.6.14", - "@types/jest": "29.5.12", - "@types/react": "18.2.6", - "@types/react-native": "0.71.7", - "@types/react-native-datepicker": "1.7.1", - "@types/react-native-vector-icons": "6.4.13", - "@types/react-test-renderer": "18.0.7", - "@types/styled-components-react-native": "5.2.1", - "babel-loader": "9.1.3", - "babel-plugin-module-resolver": "5.0.0", + "@react-native-async-storage/async-storage": "2.0.0", + "@react-native-community/datetimepicker": "8.2.0", + "@react-native-community/slider": "4.5.5", + "@react-native/babel-preset": "0.76.1", + "@react-native/eslint-config": "0.76.1", + "@react-native/metro-config": "0.76.1", + "@react-native/typescript-config": "0.76.1", + "@storybook/addon-ondevice-controls": "8.4.2", + "@storybook/addon-ondevice-notes": "8.4.2", + "@storybook/react-native": "8.4.2", + "@testing-library/jest-native": "5.4.3", + "@testing-library/react-native": "12.8.1", + "@types/jest": "29.5.14", + "@types/react": "18.3.12", + "@types/react-native": "^0.73.0", + "@types/react-native-datepicker": "1.7.6", + "@types/react-native-vector-icons": "6.4.18", + "@types/react-test-renderer": "18.3.0", + "babel-loader": "9.2.1", + "babel-plugin-module-resolver": "5.0.2", "copyfiles": "2.4.1", "cross-env": "7.0.3", - "eslint": "8.19.0", - "formik": "2.4.1", + "eslint": "8.57.1", + "formik": "2.4.6", "jest": "29.7.0", - "lint-staged": "15.2.2", + "lint-staged": "15.2.10", "lodash": "4.17.21", - "lottie-react-native": "6.7.2", + "lottie-react-native": "7.1.0", "module-resolver": "1.0.0", "patch-package": "8.0.0", - "polished": "4.2.2", - "prettier": "2.8.8", - "react": "18.2.0", - "react-dom": "18.2.0", + "polished": "4.3.1", + "prettier": "3.3.3", + "react": "18.3.1", + "react-dom": "18.3.1", "react-input-mask": "2.0.4", - "react-lottie": "1.2.3", - "react-native": "0.73.5", + "react-lottie": "1.2.4", + "react-native": "0.76.1", "react-native-camera": "4.2.1", "react-native-check-box": "2.1.7", "react-native-checkbox": "2.0.0", - "react-native-collapsible": "1.6.1", + "react-native-collapsible": "1.6.2", "react-native-datepicker": "1.7.2", - "react-native-device-info": "10.6.0", + "react-native-device-info": "14.0.0", "react-native-fast-image": "8.6.3", - "react-native-haptic-feedback": "2.0.3", - "react-native-image-picker": "5.4.0", - "react-native-markdown-display": "7.0.0-alpha.2", - "react-native-safe-area-context": "4.8.2", - "react-native-size-matters": "0.4.0", - "react-native-svg": "13.9.0", + "react-native-haptic-feedback": "2.3.3", + "react-native-image-picker": "7.1.2", + "react-native-markdown-display": "7.0.2", + "react-native-safe-area-context": "4.14.0", + "react-native-svg": "15.8.0", + "react-native-testing-library": "6.0.0", "react-native-typography": "1.4.1", - "react-native-vector-icons": "10.0.3", - "react-native-web": "0.19.10", - "react-router-dom": "6.12.1", - "react-test-renderer": "18.2.0", + "react-native-vector-icons": "10.2.0", + "react-native-web": "0.19.13", + "react-router-dom": "6.28.0", + "react-test-renderer": "18.3.1", "styled-components": "5.3.11", - "ts-jest": "29.1.2", - "typescript": "5.0.4" + "ts-jest": "29.2.5", + "typescript": "5.3.3" }, "peerDependencies": { - "formik": "2.4.1", + "@platformbuilders/helpers": "0.11.3", + "@platformbuilders/theme-toolkit": "0.3.0", + "formik": "2.4.6", "lodash": "4.17.21", - "lottie-react-native": "3.5.0", - "polished": "4.2.2", - "react": "18.2.0", - "react-input-mask": "2.0.4", - "react-lottie": "1.2.3", - "react-native": "0.71.1", + "lottie-react-native": "7.1.0", "react-native-camera": "4.2.1", - "react-native-check-box": "2.1.7", - "react-native-checkbox": "2.0.0", - "react-native-collapsible": "1.6.1", - "react-native-datepicker": "1.7.2", "react-native-fast-image": "8.6.3", - "react-native-haptic-feedback": "2.0.3", - "react-native-image-picker": "5.4.0", - "react-native-markdown-display": "7.0.0-alpha.2", - "react-native-size-matters": "0.4.0", - "react-native-svg": "13.9.0", - "react-native-typography": "1.4.1", - "react-native-vector-icons": "9.2.0", - "react-router-dom": "6.12.1", + "react-native-svg": "15.8.0", + "react-native-vector-icons": "10.2.0", "styled-components": "5.3.11" }, "engines": { - "node": "18" + "node": ">=18" } -} \ No newline at end of file +} diff --git a/patches/react-native-camera+4.2.1.patch b/patches/react-native-camera+4.2.1.patch deleted file mode 100644 index 56b73531..00000000 --- a/patches/react-native-camera+4.2.1.patch +++ /dev/null @@ -1,20 +0,0 @@ -diff --git a/node_modules/react-native-camera/src/RNCamera.js b/node_modules/react-native-camera/src/RNCamera.js -index b7a271a..828e69f 100644 ---- a/node_modules/react-native-camera/src/RNCamera.js -+++ b/node_modules/react-native-camera/src/RNCamera.js -@@ -5,7 +5,6 @@ import { - findNodeHandle, - Platform, - NativeModules, -- ViewPropTypes, - requireNativeComponent, - View, - ActivityIndicator, -@@ -13,6 +12,7 @@ import { - StyleSheet, - PermissionsAndroid, - } from 'react-native'; -+import { ViewPropTypes } from 'deprecated-react-native-prop-types'; - - import type { FaceFeature } from './FaceDetector'; - diff --git a/patches/react-native-markdown-display+7.0.0-alpha.2.patch b/patches/react-native-markdown-display+7.0.0-alpha.2.patch deleted file mode 100644 index 80527eb5..00000000 --- a/patches/react-native-markdown-display+7.0.0-alpha.2.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/node_modules/react-native-markdown-display/src/index.d.ts b/node_modules/react-native-markdown-display/src/index.d.ts -index f0daf4a..ae8e8e0 100644 ---- a/node_modules/react-native-markdown-display/src/index.d.ts -+++ b/node_modules/react-native-markdown-display/src/index.d.ts -@@ -82,6 +82,7 @@ export function stringToTokens( - export function tokensToAST(tokens: ReadonlyArray): ASTNode[]; - - export interface MarkdownProps { -+ children?: ReactNode; - rules?: RenderRules; - style?: StyleSheet.NamedStyles; - renderer?: AstRenderer; diff --git a/src/test/mocks.tsx b/src/__mocks__/platformbuilders-helpers.ts similarity index 77% rename from src/test/mocks.tsx rename to src/__mocks__/platformbuilders-helpers.ts index 9680e5b0..cb5e098f 100644 --- a/src/test/mocks.tsx +++ b/src/__mocks__/platformbuilders-helpers.ts @@ -1,7 +1,5 @@ jest.mock('@platformbuilders/helpers/native', () => ({ isIOS: jest.fn(), - scale: jest.fn(), - moderateScale: jest.fn(), useSpacingsWithSafeArea: () => ({ topSpacing: 20, bottomSpacing: 20, diff --git a/src/__mocks__/react-native-haptic-feedback.ts b/src/__mocks__/react-native-haptic-feedback.ts new file mode 100644 index 00000000..a3603a6b --- /dev/null +++ b/src/__mocks__/react-native-haptic-feedback.ts @@ -0,0 +1,3 @@ +jest.mock('react-native-haptic-feedback', () => ({ + trigger: jest.fn(), +})); diff --git a/src/components/Accordion/__tests__/__snapshots__/Accordion.spec.tsx.snap b/src/components/Accordion/__tests__/__snapshots__/Accordion.spec.tsx.snap index 160f1b5a..39e6e59c 100644 --- a/src/components/Accordion/__tests__/__snapshots__/Accordion.spec.tsx.snap +++ b/src/components/Accordion/__tests__/__snapshots__/Accordion.spec.tsx.snap @@ -392,7 +392,7 @@ exports[` should render Accordion with icon 1`] = ` } accessible={true} collapsable={false} - focusable={true} + focusable={false} onClick={[Function]} onResponderGrant={[Function]} onResponderMove={[Function]} @@ -415,7 +415,7 @@ exports[` should render Accordion with icon 1`] = ` [ { "color": undefined, - "fontSize": 37.714285714285715, + "fontSize": 24, }, undefined, { @@ -534,7 +534,7 @@ exports[` should render Accordion with icon color grey inactive 1`] } accessible={true} collapsable={false} - focusable={true} + focusable={false} onClick={[Function]} onResponderGrant={[Function]} onResponderMove={[Function]} @@ -557,7 +557,7 @@ exports[` should render Accordion with icon color grey inactive 1`] [ { "color": "#95a5a6", - "fontSize": 37.714285714285715, + "fontSize": 24, }, undefined, { @@ -676,7 +676,7 @@ exports[` should render Accordion with icon color red 1`] = ` } accessible={true} collapsable={false} - focusable={true} + focusable={false} onClick={[Function]} onResponderGrant={[Function]} onResponderMove={[Function]} @@ -699,7 +699,7 @@ exports[` should render Accordion with icon color red 1`] = ` [ { "color": undefined, - "fontSize": 37.714285714285715, + "fontSize": 24, }, undefined, { @@ -818,7 +818,7 @@ exports[` should render Accordion with icon down text custom 1`] = } accessible={true} collapsable={false} - focusable={true} + focusable={false} onClick={[Function]} onResponderGrant={[Function]} onResponderMove={[Function]} @@ -841,7 +841,7 @@ exports[` should render Accordion with icon down text custom 1`] = [ { "color": undefined, - "fontSize": 37.714285714285715, + "fontSize": 24, }, undefined, { @@ -960,7 +960,7 @@ exports[` should render Accordion with icon up text custom 1`] = ` } accessible={true} collapsable={false} - focusable={true} + focusable={false} onClick={[Function]} onResponderGrant={[Function]} onResponderMove={[Function]} @@ -983,7 +983,7 @@ exports[` should render Accordion with icon up text custom 1`] = ` [ { "color": undefined, - "fontSize": 37.714285714285715, + "fontSize": 24, }, undefined, { diff --git a/src/components/Accordion/index.tsx b/src/components/Accordion/index.tsx index 25df0d64..42ac1889 100644 --- a/src/components/Accordion/index.tsx +++ b/src/components/Accordion/index.tsx @@ -4,7 +4,6 @@ import { Text, TouchableOpacity, View } from 'react-native'; import Accordion from 'react-native-collapsible/Accordion'; import Markdown from 'react-native-markdown-display'; import { AccordionType } from '../../types'; -import If from '../If'; import { Icon } from './styles'; type Props = { @@ -56,14 +55,14 @@ const AccordionContainer: React.FC = ({ return ( {section.title} - + {hasIcon && ( - + )} ); }; @@ -71,12 +70,8 @@ const AccordionContainer: React.FC = ({ const renderContent = (section: SectionType) => { return ( - - {section.content} - - - {section.content} - + {isMarkdown && {section.content}} + {!isMarkdown && {section.content}} ); }; diff --git a/src/components/Accordion/styles.ts b/src/components/Accordion/styles.ts index bdd2a118..78575c63 100644 --- a/src/components/Accordion/styles.ts +++ b/src/components/Accordion/styles.ts @@ -1,10 +1,9 @@ -import { moderateScale } from 'react-native-size-matters'; import styled from 'styled-components/native'; import DefaultIcon from '../Icon'; export const Icon = styled(DefaultIcon).attrs({ touchable: false, - size: moderateScale(24), + size: 24, })``; export const Container = styled.View``; diff --git a/src/components/Avatar/__tests__/__snapshots__/Avatar.spec.tsx.snap b/src/components/Avatar/__tests__/__snapshots__/Avatar.spec.tsx.snap index 0fd8a9d5..572f3e53 100644 --- a/src/components/Avatar/__tests__/__snapshots__/Avatar.spec.tsx.snap +++ b/src/components/Avatar/__tests__/__snapshots__/Avatar.spec.tsx.snap @@ -22,7 +22,7 @@ exports[` should render Avatar 1`] = ` } accessible={true} collapsable={false} - focusable={true} + focusable={false} onClick={[Function]} onResponderGrant={[Function]} onResponderMove={[Function]} @@ -76,7 +76,7 @@ exports[` should render Avatar with all custom props 1`] = ` } accessible={true} collapsable={false} - focusable={true} + focusable={false} onClick={[Function]} onResponderGrant={[Function]} onResponderMove={[Function]} @@ -130,7 +130,7 @@ exports[` should render Avatar with border 1`] = ` } accessible={true} collapsable={false} - focusable={true} + focusable={false} onClick={[Function]} onResponderGrant={[Function]} onResponderMove={[Function]} @@ -184,7 +184,7 @@ exports[` should render Avatar with custom accessibility label 1`] = ` } accessible={true} collapsable={false} - focusable={true} + focusable={false} onClick={[Function]} onResponderGrant={[Function]} onResponderMove={[Function]} @@ -238,7 +238,7 @@ exports[` should render Avatar with custom border 1`] = ` } accessible={true} collapsable={false} - focusable={true} + focusable={false} onClick={[Function]} onResponderGrant={[Function]} onResponderMove={[Function]} @@ -292,7 +292,7 @@ exports[` should render Avatar with custom image 1`] = ` } accessible={true} collapsable={false} - focusable={true} + focusable={false} onClick={[Function]} onResponderGrant={[Function]} onResponderMove={[Function]} @@ -346,7 +346,7 @@ exports[` should render Avatar with custom size 1`] = ` } accessible={true} collapsable={false} - focusable={true} + focusable={false} onClick={[Function]} onResponderGrant={[Function]} onResponderMove={[Function]} @@ -400,7 +400,7 @@ exports[` should render Avatar with custom test id 1`] = ` } accessible={true} collapsable={false} - focusable={true} + focusable={false} onClick={[Function]} onResponderGrant={[Function]} onResponderMove={[Function]} @@ -454,7 +454,7 @@ exports[` should render Avatar with external image 1`] = ` } accessible={true} collapsable={false} - focusable={true} + focusable={false} onClick={[Function]} onResponderGrant={[Function]} onResponderMove={[Function]} @@ -508,7 +508,7 @@ exports[` should render Avatar with monogram 1`] = ` } accessible={true} collapsable={false} - focusable={true} + focusable={false} onClick={[Function]} onResponderGrant={[Function]} onResponderMove={[Function]} @@ -696,7 +696,7 @@ exports[` should render Avatar with styled monogram 1`] = ` } accessible={true} collapsable={false} - focusable={true} + focusable={false} onClick={[Function]} onResponderGrant={[Function]} onResponderMove={[Function]} diff --git a/src/components/ChipButton/__tests__/ChipButton.spec.tsx b/src/components/Badge/__tests__/Badge.spec.tsx similarity index 61% rename from src/components/ChipButton/__tests__/ChipButton.spec.tsx rename to src/components/Badge/__tests__/Badge.spec.tsx index a2090e4e..8fc2ae7e 100644 --- a/src/components/ChipButton/__tests__/ChipButton.spec.tsx +++ b/src/components/Badge/__tests__/Badge.spec.tsx @@ -2,47 +2,47 @@ import React from 'react'; import { fireEvent, render } from 'react-native-testing-library'; import renderer from 'react-test-renderer'; import { ThemeProvider } from 'styled-components/native'; -import ChipButton from '..'; +import Badge from '..'; import theme from '../../../theme'; import Typography from '../../Typography'; -describe('', () => { - it('should render Chipbutton', () => { +describe('', () => { + it('should render Badge', () => { const wrapper = renderer.create( - + , ); expect(wrapper.toJSON()).toMatchSnapshot(); }); - it('should render Chipbutton when rounded', () => { + it('should render Badge when rounded', () => { const wrapper = renderer.create( - + , ); expect(wrapper.toJSON()).toMatchSnapshot(); }); - it('should render Chipbutton with loading', () => { + it('should render Badge with loading', () => { const wrapper = renderer.create( - + , ); expect(wrapper.toJSON()).toMatchSnapshot(); }); - it('should fire onPress from ChipButton', () => { + it('should fire onPress from Badge', () => { const onPressEvent = jest.fn(); const { getByTestId } = render( - + , ); @@ -55,46 +55,42 @@ describe('', () => { expect(onPressEvent).toHaveBeenCalled(); }); - it('should render Chipbutton with children', () => { + it('should render Badge with children', () => { const wrapper = renderer.create( - + Test - + , ); expect(wrapper.toJSON()).toMatchSnapshot(); }); - it('should render Chipbutton with custom accessibility label', () => { + it('should render Badge with custom accessibility label', () => { const wrapper = renderer.create( - + , ); expect(wrapper.toJSON()).toMatchSnapshot(); }); - it('should render Chipbutton with test id', () => { + it('should render Badge with test id', () => { const wrapper = renderer.create( - + , ); expect(wrapper.toJSON()).toMatchSnapshot(); }); - it('should render Chipbutton with custom style', () => { + it('should render Badge with custom style', () => { const wrapper = renderer.create( - ', () => { expect(wrapper.toJSON()).toMatchSnapshot(); }); - it('should render Chipbutton with custom text style', () => { + it('should render Badge with custom text style', () => { const wrapper = renderer.create( - + , ); expect(wrapper.toJSON()).toMatchSnapshot(); }); - it('should render Chipbutton with disabled', () => { + it('should render Badge with disabled', () => { const wrapper = renderer.create( - + , ); expect(wrapper.toJSON()).toMatchSnapshot(); }); - it('should render Chipbutton with contrast', () => { + it('should render Badge with contrast', () => { const wrapper = renderer.create( - + , ); expect(wrapper.toJSON()).toMatchSnapshot(); }); - it('should render Chipbutton with variant', () => { + it('should render Badge with variant', () => { const wrapper = renderer.create( - + , ); diff --git a/src/components/ChipButton/__tests__/__snapshots__/ChipButton.spec.tsx.snap b/src/components/Badge/__tests__/__snapshots__/Badge.spec.tsx.snap similarity index 96% rename from src/components/ChipButton/__tests__/__snapshots__/ChipButton.spec.tsx.snap rename to src/components/Badge/__tests__/__snapshots__/Badge.spec.tsx.snap index 2793172d..bba8e739 100644 --- a/src/components/ChipButton/__tests__/__snapshots__/ChipButton.spec.tsx.snap +++ b/src/components/Badge/__tests__/__snapshots__/Badge.spec.tsx.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[` should render Chipbutton 1`] = ` +exports[` should render Badge 1`] = ` should render Chipbutton 1`] = ` `; -exports[` should render Chipbutton when rounded 1`] = ` +exports[` should render Badge when rounded 1`] = ` should render Chipbutton when rounded 1`] = ` `; -exports[` should render Chipbutton with children 1`] = ` +exports[` should render Badge with children 1`] = ` should render Chipbutton with children 1`] = ` `; -exports[` should render Chipbutton with contrast 1`] = ` +exports[` should render Badge with contrast 1`] = ` should render Chipbutton with contrast 1`] = ` `; -exports[` should render Chipbutton with custom accessibility label 1`] = ` +exports[` should render Badge with custom accessibility label 1`] = ` should render Chipbutton with custom accessibility label `; -exports[` should render Chipbutton with custom style 1`] = ` +exports[` should render Badge with custom style 1`] = ` should render Chipbutton with custom style 1`] = ` `; -exports[` should render Chipbutton with custom text style 1`] = ` +exports[` should render Badge with custom text style 1`] = ` should render Chipbutton with custom text style 1`] = ` `; -exports[` should render Chipbutton with disabled 1`] = ` +exports[` should render Badge with disabled 1`] = ` should render Chipbutton with disabled 1`] = ` } accessible={true} collapsable={false} - focusable={true} + focusable={false} onClick={[Function]} onResponderGrant={[Function]} onResponderMove={[Function]} @@ -743,7 +743,7 @@ exports[` should render Chipbutton with disabled 1`] = ` `; -exports[` should render Chipbutton with loading 1`] = ` +exports[` should render Badge with loading 1`] = ` should render Chipbutton with loading 1`] = ` } accessible={true} collapsable={false} - focusable={true} + focusable={false} onClick={[Function]} onResponderGrant={[Function]} onResponderMove={[Function]} @@ -813,6 +813,7 @@ exports[` should render Chipbutton with loading 1`] = ` colorFilters={[]} contrast={false} enableMergePathsAndroidForKitKatAndAbove={false} + enableSafeModeAndroid={false} loop={true} onAnimationFailure={[Function]} onAnimationFinish={[Function]} @@ -839,7 +840,7 @@ exports[` should render Chipbutton with loading 1`] = ` `; -exports[` should render Chipbutton with test id 1`] = ` +exports[` should render Badge with test id 1`] = ` should render Chipbutton with test id 1`] = ` `; -exports[` should render Chipbutton with variant 1`] = ` +exports[` should render Badge with variant 1`] = ` = ({ +const Badge: FC = ({ id, children, onPress, @@ -50,12 +49,10 @@ const ChipButton: FC = ({ style={style} {...rest} > - - - - + {loading && } + {!loading && ( <> - + {!!leftIconName && ( = ({ touchable={iconTouchable} isEmoji={isEmoji} /> - + )} = ({ > {children} - + {!!rightIconName && ( = ({ touchable={iconTouchable} isEmoji={isEmoji} /> - + )} - + )} ); }; -export default ChipButton; +export default Badge; diff --git a/src/components/ChipButton/styles.ts b/src/components/Badge/styles.ts similarity index 100% rename from src/components/ChipButton/styles.ts rename to src/components/Badge/styles.ts diff --git a/src/components/Navbar/__tests__/Navbar.spec.tsx b/src/components/BottomNavigation/__tests__/BottomNavigation.spec.tsx similarity index 72% rename from src/components/Navbar/__tests__/Navbar.spec.tsx rename to src/components/BottomNavigation/__tests__/BottomNavigation.spec.tsx index 4d2495f5..69af950a 100644 --- a/src/components/Navbar/__tests__/Navbar.spec.tsx +++ b/src/components/BottomNavigation/__tests__/BottomNavigation.spec.tsx @@ -1,7 +1,7 @@ import React from 'react'; import renderer from 'react-test-renderer'; import { ThemeProvider } from 'styled-components/native'; -import Navbar from '..'; +import BottomNavigation from '..'; import theme from '../../../theme'; const onPressEvent = jest.fn(); @@ -15,25 +15,25 @@ const fields = [ }, ]; -describe('', () => { +describe('', () => { beforeEach(() => { jest.resetAllMocks(); }); - it('should render navbar component', () => { + it('should render BottomNavigation component', () => { const wrapper = renderer.create( - + , ); expect(wrapper.toJSON()).toMatchSnapshot(); }); - it('should render navbar component with custom color', () => { + it('should render BottomNavigation component with custom color', () => { const wrapper = renderer.create( - should render navbar component 1`] = ` +exports[` should render BottomNavigation component 1`] = ` should render navbar component 1`] = ` "width": 0, }, "shadowOpacity": 0.2, - "shadowRadius": 6.285714285714286, + "shadowRadius": 3, "width": "100%", }, ] @@ -61,7 +61,7 @@ exports[` should render navbar component 1`] = ` "alignItems": "center", "justifyContent": "center", "opacity": 1, - "width": 110, + "width": 70, } } testID="Home" @@ -95,7 +95,7 @@ exports[` should render navbar component 1`] = ` } accessible={true} collapsable={false} - focusable={true} + focusable={false} onClick={[Function]} onResponderGrant={[Function]} onResponderMove={[Function]} @@ -118,7 +118,7 @@ exports[` should render navbar component 1`] = ` [ { "color": "#4255EF", - "fontSize": 47.14285714285714, + "fontSize": 30, }, undefined, { @@ -165,7 +165,7 @@ exports[` should render navbar component 1`] = ` `; -exports[` should render navbar component with custom color 1`] = ` +exports[` should render BottomNavigation component with custom color 1`] = ` should render navbar component with custom color 1`] = ` "width": 0, }, "shadowOpacity": 0.2, - "shadowRadius": 6.285714285714286, + "shadowRadius": 3, "width": "100%", }, ] @@ -226,7 +226,7 @@ exports[` should render navbar component with custom color 1`] = ` "alignItems": "center", "justifyContent": "center", "opacity": 1, - "width": 110, + "width": 70, } } testID="Home" @@ -260,7 +260,7 @@ exports[` should render navbar component with custom color 1`] = ` } accessible={true} collapsable={false} - focusable={true} + focusable={false} onClick={[Function]} onResponderGrant={[Function]} onResponderMove={[Function]} @@ -283,7 +283,7 @@ exports[` should render navbar component with custom color 1`] = ` [ { "color": "#000000", - "fontSize": 47.14285714285714, + "fontSize": 30, }, undefined, { diff --git a/src/components/Navbar/index.stories.tsx b/src/components/BottomNavigation/index.stories.tsx similarity index 80% rename from src/components/Navbar/index.stories.tsx rename to src/components/BottomNavigation/index.stories.tsx index ad670285..e2b8cb8b 100644 --- a/src/components/Navbar/index.stories.tsx +++ b/src/components/BottomNavigation/index.stories.tsx @@ -1,9 +1,9 @@ import type { Meta } from '@storybook/react'; -import Navbar from '.'; +import BottomNavigation from '.'; -const meta: Meta = { - title: 'Navbar', - component: Navbar, +const meta: Meta = { + title: 'BottomNavigation', + component: BottomNavigation, argTypes: {}, args: { activeFieldColor: '#fff', diff --git a/src/components/Navbar/index.tsx b/src/components/BottomNavigation/index.tsx similarity index 83% rename from src/components/Navbar/index.tsx rename to src/components/BottomNavigation/index.tsx index 94a9dcdd..1c66d238 100644 --- a/src/components/Navbar/index.tsx +++ b/src/components/BottomNavigation/index.tsx @@ -1,6 +1,6 @@ import React, { useCallback } from 'react'; import { useSpacingsWithSafeArea } from '@platformbuilders/helpers/native'; -import { NavField, NavIcon, NavLabel, NavbarWrapper } from './styles'; +import { BottomNavigationWrapper, NavField, NavIcon, NavLabel } from './styles'; type Props = { fields: { @@ -13,7 +13,7 @@ type Props = { activeFieldColor?: string; }; -const Navbar: React.FC = ({ +const BottomNavigation: React.FC = ({ fields, currentRoute, activeFieldColor, @@ -49,10 +49,10 @@ const Navbar: React.FC = ({ ); return ( - + {renderFields()} - + ); }; -export default Navbar; +export default BottomNavigation; diff --git a/src/components/Navbar/styles.ts b/src/components/BottomNavigation/styles.ts similarity index 82% rename from src/components/Navbar/styles.ts rename to src/components/BottomNavigation/styles.ts index 4b6a775c..d9426d3d 100644 --- a/src/components/Navbar/styles.ts +++ b/src/components/BottomNavigation/styles.ts @@ -1,7 +1,5 @@ -import { moderateScale } from 'react-native-size-matters'; import styled from 'styled-components/native'; import { ThemeProps, getTheme, ifStyle } from '@platformbuilders/theme-toolkit'; -import { getShadow } from '../../utils/helpers'; import Icon from '../Icon'; import Touchable from '../Touchable'; import Typography from '../Typography'; @@ -17,9 +15,9 @@ const smSpacing = getTheme('spacing.sm'); const isActive = ifStyle('active'); -type NavbarWrapperProps = { - safeBottomArea: boolean; - bottomSpacing: number; +type BottomNavigationWrapperProps = { + safeBottomArea?: boolean; + bottomSpacing?: number; }; type FieldsProps = { @@ -27,7 +25,7 @@ type FieldsProps = { activeColor?: string; } & ThemeProps; -export const NavbarWrapper = styled.View` +export const BottomNavigationWrapper = styled.View` width: 100%; padding: ${smSpacing}px; padding-bottom: ${({ bottomSpacing }) => `${bottomSpacing}px`}; @@ -36,17 +34,20 @@ export const NavbarWrapper = styled.View` justify-content: space-evenly; align-items: flex-start; margin-top: auto; - ${getShadow()}; + shadow-offset: 0px 4px; + shadow-opacity: 0.2; + shadow-radius: 3px; + elevation: 3; `; export const NavField = styled(Touchable)` - width: ${moderateScale(70)}px; + width: 70px; justify-content: center; align-items: center; `; export const NavIcon = styled(Icon).attrs((props: FieldsProps) => ({ - size: moderateScale(30), + size: 30, color: isActive( props?.activeColor || primaryMain(props), textColor(props), diff --git a/src/components/Button/__tests__/Button.spec.tsx b/src/components/Button/__tests__/Button.spec.tsx index 85eec7b8..708d3b12 100644 --- a/src/components/Button/__tests__/Button.spec.tsx +++ b/src/components/Button/__tests__/Button.spec.tsx @@ -6,10 +6,6 @@ import Button from '..'; import theme from '../../../theme'; import Typography from '../../Typography'; -jest.mock('react-native-haptic-feedback', () => ({ - trigger: jest.fn(), -})); - describe('