diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 00000000..2e764cea --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,196 @@ +const rulesReact = { + 'react/prop-types': 'off', + 'react/display-name': 'off', + 'react/no-unescaped-entities': 'off', + 'react-perf/jsx-no-new-function-as-prop': 'off', + + 'react/jsx-key': 'warn', + 'react/jsx-pascal-case': 'warn', + 'react/self-closing-comp': 'warn', + 'react/no-unstable-nested-components': 'warn', + 'react-perf/jsx-no-new-array-as-prop': 'warn', + 'react-perf/jsx-no-new-object-as-prop': 'warn', + 'react/jsx-sort-props': [ + 'warn', + { + callbacksLast: true, + shorthandFirst: true, + shorthandLast: false, + ignoreCase: true, + noSortAlphabetically: true, + reservedFirst: false + } + ], + + 'react/no-danger': 'error', + 'react/jsx-boolean-value': 'error', + 'react/boolean-prop-naming': 'error' +} + +const rulesEslint = { + 'no-redeclare': 'off', + 'default-param-last': 'off', + 'no-duplicate-imports': 'off', + 'no-use-before-define': 'off', + 'no-unused-expressions': 'off', + + radix: 'warn', + 'no-nested-ternary': 'warn', + 'no-else-return': ['warn', { allowElseIf: false }], + + 'no-var': 'error', + 'no-sequences': 'error', + 'no-console': ['error', { allow: ['error'] }], + 'prefer-const': ['error', { destructuring: 'all' }], + + '@stylistic/max-len': ['error', { code: 85 }], + '@stylistic/key-spacing': [ + 'error', + { beforeColon: false, afterColon: true } + ], + '@stylistic/padding-line-between-statements': [ + 'error', + { blankLine: 'always', prev: '*', next: 'return' }, + { blankLine: 'always', prev: ['const', 'let'], next: '*' }, + { + blankLine: 'any', + prev: ['const', 'let'], + next: ['const', 'let'] + }, + { + blankLine: 'always', + prev: ['if', 'function', 'for'], + next: ['if', 'function', 'for'] + } + ] +} + +const rulesImport = { + 'import/no-duplicates': 'error', + 'import/order': [ + 'error', + { + groups: [ + 'external', + 'builtin', + 'type', + 'internal', + 'parent', + 'sibling', + 'index' + ], + pathGroups: [ + { + pattern: 'react', + group: 'external', + position: 'before' + }, + { + pattern: 'react-**', + group: 'external', + position: 'before' + }, + { + pattern: 'react-dom/**', + group: 'external', + position: 'before' + }, + { + pattern: '../styles', + group: 'index', + position: 'after' + }, + { + pattern: './styles', + group: 'index', + position: 'after' + }, + { + pattern: '@/theme', + group: 'index', + position: 'after' + } + ], + pathGroupsExcludedImportTypes: ['react', 'react-dom'], + 'newlines-between': 'never', + alphabetize: { + order: 'asc', + caseInsensitive: true + } + } + ] +} + +const rulesTypescript = { + '@typescript-eslint/no-namespace': 'off', + '@typescript-eslint/no-inferrable-types': 'off', + '@typescript-eslint/no-confusing-void-expression': 'off', + '@typescript-eslint/explicit-module-boundary-types': 'off', + + '@typescript-eslint/ban-types': 'warn', + '@typescript-eslint/no-var-requires': 'warn', + '@typescript-eslint/no-unsafe-argument': 'warn', + '@typescript-eslint/no-non-null-assertion': 'warn', + '@typescript-eslint/no-unused-expressions': 'warn', + '@typescript-eslint/prefer-optional-chain': 'warn', + '@typescript-eslint/restrict-plus-operands': 'warn', + '@typescript-eslint/no-unnecessary-condition': 'warn', + '@typescript-eslint/switch-exhaustiveness-check': 'warn', + '@typescript-eslint/prefer-reduce-type-parameter': 'warn', + '@typescript-eslint/no-unnecessary-type-constraint': 'warn', + '@typescript-eslint/no-non-null-asserted-optional-chain': 'warn', + + '@typescript-eslint/no-redeclare': 'error', + '@typescript-eslint/no-explicit-any': 'error', + '@typescript-eslint/default-param-last': 'error', + '@typescript-eslint/no-use-before-define': 'error', + '@typescript-eslint/consistent-type-imports': 'error' +} + +module.exports = { + parser: '@typescript-eslint/parser', + parserOptions: { + ecmaFeatures: { + jsx: true + }, + sourceType: 'module', + project: ['./tsconfig.json'] + }, + settings: { + react: { + version: 'detect' + }, + 'import/parsers': { + '@typescript-eslint/parser': ['.ts', '.tsx'] + }, + 'import/resolver': { + typescript: true + } + }, + extends: [ + 'eslint:recommended', + 'plugin:react/jsx-runtime', + 'plugin:react-hooks/recommended', + 'plugin:react/recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:import/recommended', + 'plugin:import/typescript', + 'plugin:prettier/recommended', + 'prettier' + ], + rules: { + 'prettier/prettier': 'error', + ...rulesReact, + ...rulesEslint, + ...rulesImport, + ...rulesTypescript + }, + plugins: [ + 'react-hooks', + 'react-perf', + '@typescript-eslint', + 'import', + '@stylistic' + ], + ignorePatterns: ['.eslintrc.js'] +} diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index d4fce68f..00000000 --- a/.eslintrc.json +++ /dev/null @@ -1,173 +0,0 @@ -{ - "parser": "@typescript-eslint/parser", - "parserOptions": { - "jsx": true, - "useJSXTextNode": true - }, - "extends": [ - "plugin:@typescript-eslint/recommended", - "plugin:react/recommended", - "plugin:react-hooks/recommended", - "plugin:prettier/recommended", - "eslint:recommended", - "prettier", - "plugin:ramda/recommended" - ], - "rules": { - "@typescript-eslint/ban-types": 1, - "prettier/prettier": [ - "error", - { - "singleQuote": true, - "parser": "typescript", - "arrowParens": "avoid" - } - ], - "@typescript-eslint/no-use-before-define": "off", - "template-curly-spacing": "warn", - "no-sequences": "error", - "spaced-comment": ["error", "always"], - "key-spacing": [ - "error", - { - "mode": "strict" - } - ], - "max-len": [ - "error", - { - "code": 85 - } - ], - "max-lines": [ - "error", - { - "max": 350, - "skipBlankLines": true - } - ], - "prefer-const": [ - "error", - { - "destructuring": "all" - } - ], - "no-var": "error", - "newline-before-return": "error", - "arrow-parens": ["error", "as-needed"], - "no-bitwise": "error", - "max-classes-per-file": "error", - "no-duplicate-imports": "error", - "lines-between-class-members": ["error", "always"], - "padding-line-between-statements": [ - "error", - { - "blankLine": "always", - "prev": "*", - "next": "return" - } - ], - "sort-imports": [ - "error", - { - "ignoreCase": true, - "ignoreDeclarationSort": true, - "ignoreMemberSort": true, - "memberSyntaxSortOrder": ["none", "all", "multiple", "single"] - } - ], - "no-irregular-whitespace": "error", - "space-before-blocks": "error", - "no-multi-spaces": "error", - "no-trailing-spaces": "error", - "no-whitespace-before-property": "error", - "curly": "error", - "no-undef": "off", - "no-case-declarations": "off", - "indent": "off", - "no-unused-vars": ["off"], - "no-console": [ - "error", - { - "allow": ["log", "error"] - } - ], - "comma-dangle": ["error", "never"], - "semi": ["error", "never"], - "no-multiple-empty-lines": [ - "error", - { - "max": 1 - } - ], - "quotes": ["error", "single"], - "eol-last": ["error", "always"], - "no-new-wrappers": "error", - "arrow-spacing": [ - "error", - { - "after": true, - "before": true - } - ], - "object-curly-spacing": ["error", "always"], - "react/jsx-closing-bracket-location": [ - 1, - { - "selfClosing": "line-aligned", - "nonEmpty": "after-props" - } - ], - "react/prop-types": "off", - "react/display-name": "off", - "react/jsx-boolean-value": "off", - "react/jsx-wrap-multilines": "off", - "react/no-unescaped-entities": "off", - "prefer-arrow/prefer-arrow-functions": [ - "warn", - { - "disallowPrototype": true, - "singleReturnOnly": true, - "classPropertiesAllowed": false - } - ], - "@typescript-eslint/no-unused-vars": [ - "error", - { - "ignoreRestSiblings": true - } - ], - "@typescript-eslint/no-explicit-any": "error", - "@typescript-eslint/member-ordering": [ - "error", - { - "classes": [ - "public-static-field", - "public-instance-field", - "private-static-field", - "private-instance-field", - "private-constructor", - "public-constructor", - "private-instance-method", - "protected-instance-method", - "public-instance-method" - ] - } - ], - "@typescript-eslint/prefer-interface": "off", - "@typescript-eslint/explicit-member-accessibility": "off", - "@typescript-eslint/no-var-requires": "off", - "@typescript-eslint/no-non-null-assertion": "off", - "@typescript-eslint/no-object-literal-type-assertion": "off", - "@typescript-eslint/interface-name-prefix": "off", - "@typescript-eslint/array-type": "off", - "@typescript-eslint/explicit-function-return-type": "off" - }, - "plugins": ["react", "prefer-arrow", "@typescript-eslint", "ramda", "eslint-plugin-prettier"], - "settings": { - "react": { - "pragma": "React", - "version": "16.8.6" - } - } -} diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000..04c01ba7 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,2 @@ +node_modules/ +dist/ \ No newline at end of file diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index dade0ceb..00000000 --- a/.prettierrc +++ /dev/null @@ -1,10 +0,0 @@ -{ - "trailingComma": "none", - "tabWidth": 4, - "semi": false, - "jsxBracketSameLine": true, - "jsxSingleQuote": true, - "singleQuote": true, - "parser": "typescript", - "arrowParens": "avoid" -} diff --git a/.prettierrc.yaml b/.prettierrc.yaml new file mode 100644 index 00000000..2d0a7f45 --- /dev/null +++ b/.prettierrc.yaml @@ -0,0 +1,11 @@ +singleQuote: true +semi: false +trailingComma: none +bracketSameLine: true +jsxSingleQuote: true +tabWidth: 4 +arrowParens: avoid +printWidth: 80 +parser: typescript +bracketSpacing: true +useTabs: false \ No newline at end of file diff --git a/package.json b/package.json index bcf68521..d186afca 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,11 @@ { "name": "flipper-ui", - "version": "0.30.10", + "version": "0.4.0", "description": "", "main": "dist/index.js", "homepage": "https://flipper-ui.ngi.com.br/", + "author": "NG Informática", + "license": "MIT", "repository": { "type": "git", "url": "https://github.com/nginformatica/flipper-ui.git" @@ -12,26 +14,26 @@ "wrap-ansi": "7.0.0" }, "scripts": { - "test": "jest --silent --passWithNoTests --noStackTrace --runInBand", - "test:ci": "yarn test --coverage", "start": "storybook dev -p 6006", - "clean": "rm -rf ./dist/*", - "copy:package": "cp package.json dist/", - "publish:yalc": "cd dist/ && yalc publish && cd ..", "build": "yarn clean && yarn build:ts && yarn build:babel", - "build:link": "yarn build && yarn copy:package && yarn publish:yalc", "build:ts": "tsc --emitDeclarationOnly", "build:babel": "babel src --out-dir dist --extensions \".ts,.tsx\" --ignore \"**/*.spec.tsx\" --ignore \"**/*.stories.tsx\"", - "lint": "eslint -c .eslintrc.json 'src/**/*.{ts,tsx}'", - "lint:fix": "eslint -c .eslintrc.json --fix 'src/**/*.{ts,tsx}'", - "predeploy": "yarn build && yarn storybook:build", + "build:link": "yarn build && yarn copy:package && yarn publish:yalc", + "lint": "eslint -c .eslintrc.js 'src/**/*.{ts,tsx}'", + "lint:fix": "eslint -c .eslintrc.js --fix 'src/**/*.{ts,tsx}'", + "lint:quiet": "eslint --quiet .eslintrc.js 'src/**/*.{ts,tsx}'", + "format": "prettier -w 'src/**/*.{ts,tsx}'", "docs:build": "storybook build -o docs", + "clean": "rm -rf ./dist/*", "type-check": "tsc --noEmit", + "copy:package": "cp package.json dist/", + "publish:yalc": "cd dist/ && yalc publish && cd ..", + "predeploy": "yarn build && yarn storybook:build", "deploy": "gh-pages -d docs", - "release": "yarn build && node pre-publish.js && npm publish ./dist --access public" + "release": "yarn build && node pre-publish.js && npm publish ./dist --access public", + "test:ci": "yarn test --coverage", + "test": "jest --silent --passWithNoTests --noStackTrace --runInBand" }, - "author": "NG Informática", - "license": "MIT", "dependencies": { "@date-io/date-fns": "1.3.6", "@emotion/react": "11.11.3", @@ -40,9 +42,9 @@ "@material-ui/icons": "4.11.3", "@material-ui/lab": "4.0.0-alpha.61", "@material-ui/pickers": "3.3.11", - "@mui/icons-material": "5.15.3", - "@mui/material": "5.15.3", - "@mui/styles": "5.15.3", + "@mui/icons-material": "5.15.6", + "@mui/material": "5.15.6", + "@mui/styles": "5.15.6", "date-fns": "2.30.0", "faker": "5.5.3", "material-table": "1.69.3", @@ -58,56 +60,52 @@ "@babel/cli": "7.23.4", "@babel/core": "7.23.7", "@babel/plugin-transform-runtime": "7.23.7", - "@babel/preset-env": "7.23.7", + "@babel/preset-env": "7.23.8", "@babel/preset-typescript": "7.23.3", - "@storybook/addon-essentials": "7.6.7", + "@storybook/addon-essentials": "7.6.10", "@storybook/addon-styling-webpack": "0.0.6", - "@storybook/react": "7.6.7", - "@storybook/react-webpack5": "7.6.7", + "@storybook/react": "7.6.10", + "@storybook/react-webpack5": "7.6.10", + "@stylistic/eslint-plugin": "1.5.4", "@testing-library/react": "14.1.2", "@testing-library/user-event": "14.5.2", "@types/faker": "5.5.3", "@types/history": "5.0.0", "@types/jest": "29.5.11", - "@types/node": "20.10.6", + "@types/node": "20.11.6", "@types/ramda": "0.25.36", - "@types/react": "18.2.46", - "@types/react-router": "5.1.20", - "@types/react-router-dom": "5.3.3", + "@types/react": "18.2.48", "@types/sprintf-js": "1.1.4", "@types/styled-components": "5.1.34", "@types/uuid": "9.0.7", - "@typescript-eslint/eslint-plugin": "6.17.0", - "@typescript-eslint/parser": "6.17.0", + "@typescript-eslint/eslint-plugin": "6.19.1", + "@typescript-eslint/parser": "6.19.1", "babel-loader": "9.1.3", "babel-plugin-module-resolver": "5.0.0", "babel-plugin-transform-class-properties": "6.24.1", "babel-plugin-transform-imports": "2.0.0", "eslint": "8.56.0", "eslint-config-prettier": "9.1.0", + "eslint-import-resolver-typescript": "3.6.1", "eslint-plugin-import": "2.29.1", - "eslint-plugin-prefer-arrow": "1.2.3", - "eslint-plugin-prettier": "5.1.2", - "eslint-plugin-ramda": "2.5.1", + "eslint-plugin-prettier": "5.1.3", "eslint-plugin-react": "7.33.2", "eslint-plugin-react-hooks": "4.6.0", - "eslint-plugin-storybook": "0.6.15", + "eslint-plugin-react-perf": "3.3.2", "fs-extra": "11.2.0", "identity-obj-proxy": "3.0.0", "jest": "29.7.0", "jest-environment-jsdom": "29.7.0", "node-fetch": "3.3.2", - "prettier": "3.1.1", + "prettier": "3.2.4", "react": "18.2.0", "react-dom": "18.2.0", - "react-router": "6.21.1", - "react-router-dom": "6.21.1", - "storybook": "7.6.7", - "styled-components": "6.1.6", - "ts-jest": "29.1.1", + "storybook": "7.6.10", + "styled-components": "6.1.8", + "ts-jest": "29.1.2", "ts-loader": "9.5.1", "typescript": "5.3.3", - "webpack": "5.89.0" + "webpack": "5.90.0" }, "peerDependencies": { "date-fns": "^2.30.0", diff --git a/src/core/context/theme-provider/index.tsx b/src/core/context/theme-provider/index.tsx index e442db72..2cb6e238 100644 --- a/src/core/context/theme-provider/index.tsx +++ b/src/core/context/theme-provider/index.tsx @@ -1,13 +1,11 @@ -import { - createTheme, - ThemeOptions, - ThemeProvider -} from '@material-ui/core/styles' import React from 'react' +import type { ReactNode } from 'react' +import { createTheme, ThemeProvider } from '@material-ui/core/styles' +import type { ThemeOptions } from '@material-ui/core/styles' interface ThemeProviderProps { options?: ThemeOptions - children: React.ReactNode + children: ReactNode } const ThemeProviderFlipper = ({ diff --git a/src/core/context/theme-provider/theme-provider.spec.tsx b/src/core/context/theme-provider/theme-provider.spec.tsx index ea12c80a..1abe4c91 100644 --- a/src/core/context/theme-provider/theme-provider.spec.tsx +++ b/src/core/context/theme-provider/theme-provider.spec.tsx @@ -10,6 +10,7 @@ describe('ThemeProvider', () => { ) const child = screen.getByText('Test') + expect(child).toBeDefined() }) }) diff --git a/src/core/data-display/advertise/__snapshots__/advertise.spec.tsx.snap b/src/core/data-display/advertise/__snapshots__/advertise.spec.tsx.snap index 77696936..c65d9955 100644 --- a/src/core/data-display/advertise/__snapshots__/advertise.spec.tsx.snap +++ b/src/core/data-display/advertise/__snapshots__/advertise.spec.tsx.snap @@ -3,7 +3,7 @@ exports[`Advertise should match snapshot 1`] = `
diff --git a/src/core/data-display/advertise/advertise.spec.tsx b/src/core/data-display/advertise/advertise.spec.tsx index cdb89cd3..0803b296 100644 --- a/src/core/data-display/advertise/advertise.spec.tsx +++ b/src/core/data-display/advertise/advertise.spec.tsx @@ -3,6 +3,9 @@ import { render, screen } from '@testing-library/react' import Advertise from '.' describe('Advertise', () => { + const newPadding = '10px 10px' + const CUSTOM = { padding: newPadding } + it('should render', () => { render() @@ -17,12 +20,9 @@ describe('Advertise', () => { it('should render with custom author style', () => { const newPadding = '10px 10px' + render( - + ) const author = screen.getByText('author') @@ -33,11 +33,12 @@ describe('Advertise', () => { it('should render with custom comment style', () => { const newPadding = '10px 10px' + render( ) @@ -51,6 +52,7 @@ describe('Advertise', () => { const { container } = render( ) + expect(container).toMatchSnapshot() }) }) diff --git a/src/core/data-display/advertise/advertise.stories.tsx b/src/core/data-display/advertise/advertise.stories.tsx index 6dc48ec0..96b81d88 100644 --- a/src/core/data-display/advertise/advertise.stories.tsx +++ b/src/core/data-display/advertise/advertise.stories.tsx @@ -1,5 +1,5 @@ import React from 'react' -import { Meta, StoryFn } from '@storybook/react' +import type { Meta, StoryFn } from '@storybook/react' import Advertise from '.' export default { diff --git a/src/core/data-display/advertise/index.tsx b/src/core/data-display/advertise/index.tsx index a920cd9c..6a0e7e94 100644 --- a/src/core/data-display/advertise/index.tsx +++ b/src/core/data-display/advertise/index.tsx @@ -1,8 +1,9 @@ import React from 'react' -import styled from 'styled-components' -import MuiPaper from '@/core/surfaces/paper' -import Typography from '@/core/data-display/typography' +import type { CSSProperties } from 'react' +import { default as styled } from 'styled-components' import type { DefaultProps } from '../../types' +import { Typography } from '@/core/data-display/typography' +import MuiPaper from '@/core/surfaces/paper' import { theme } from '@/theme' const { grays } = theme.colors @@ -20,12 +21,12 @@ export interface AdvertiseProps extends DefaultProps { * The style of the comment * @optional */ - commentStyle?: React.CSSProperties + commentStyle?: CSSProperties /** * The style of the author * @optional */ - authorStyle?: React.CSSProperties + authorStyle?: CSSProperties } const styles = { diff --git a/src/core/data-display/avatar/avatar.spec.tsx b/src/core/data-display/avatar/avatar.spec.tsx index 4cc58b0b..9c388b1e 100644 --- a/src/core/data-display/avatar/avatar.spec.tsx +++ b/src/core/data-display/avatar/avatar.spec.tsx @@ -1,7 +1,7 @@ import * as React from 'react' import { render, screen } from '@testing-library/react' -import Avatar from '.' -import Typography from '@/core/data-display/typography' +import { Typography } from '@/core/data-display/typography' +import { Avatar } from '.' describe('Avatar', () => { it('should render first letter', () => { @@ -30,6 +30,7 @@ describe('Avatar', () => { it('should render with custom className', () => { const customClass = 'custom-class' + render( { it('should render', () => { @@ -29,6 +29,7 @@ describe('Badge', () => { describe('Badges - Snapshots', () => { it('should match snapshot', () => { const { container } = render(Badge) + expect(container).toMatchSnapshot() }) }) diff --git a/src/core/data-display/badge/badge.stories.tsx b/src/core/data-display/badge/badge.stories.tsx index bfc6d8c7..0dce0a80 100644 --- a/src/core/data-display/badge/badge.stories.tsx +++ b/src/core/data-display/badge/badge.stories.tsx @@ -1,7 +1,7 @@ import React from 'react' -import { Meta, StoryFn } from '@storybook/react' -import Badge from '.' -import Button from '@/core/inputs/button' +import type { Meta, StoryFn } from '@storybook/react' +import { Button } from '@/core/inputs/button' +import { Badge } from '.' export default { title: 'DataDisplay/Badge', diff --git a/src/core/data-display/badge/index.tsx b/src/core/data-display/badge/index.tsx index 71c941a3..ad2dd811 100644 --- a/src/core/data-display/badge/index.tsx +++ b/src/core/data-display/badge/index.tsx @@ -1,11 +1,12 @@ -import { Badge as MuiBadge } from '@material-ui/core' import React from 'react' -import { BadgeProps as MuiBadgeProps } from '@material-ui/core/Badge' +import type { ReactNode } from 'react' +import { Badge as MuiBadge } from '@material-ui/core' import { makeStyles } from '@material-ui/core/styles' import type { DefaultProps } from '../../types' +import type { BadgeProps as MuiBadgeProps } from '@material-ui/core/Badge' export interface BadgeProps extends DefaultProps, MuiBadgeProps { - children: React.ReactNode + children: ReactNode /** * The number to display in the badge. */ diff --git a/src/core/data-display/chapter/chapter.spec.tsx b/src/core/data-display/chapter/chapter.spec.tsx index 5f63ea36..03b4a475 100644 --- a/src/core/data-display/chapter/chapter.spec.tsx +++ b/src/core/data-display/chapter/chapter.spec.tsx @@ -1,11 +1,12 @@ import * as React from 'react' import { render, screen } from '@testing-library/react' -import Chapter from '.' +import { Chapter } from '.' describe('Chapter', () => { it('should render', () => { render(Chapter) const chapter = screen.getByText('Chapter') + expect(chapter).toBeDefined() }) @@ -16,6 +17,7 @@ describe('Chapter', () => { ) const chapter = screen.getByTestId('chapter-container') + expect(chapter).toBeDefined() }) }) diff --git a/src/core/data-display/chapter/chapter.stories.tsx b/src/core/data-display/chapter/chapter.stories.tsx index e406fdb4..3885f704 100644 --- a/src/core/data-display/chapter/chapter.stories.tsx +++ b/src/core/data-display/chapter/chapter.stories.tsx @@ -1,6 +1,6 @@ import React from 'react' -import { Meta, StoryFn } from '@storybook/react' -import Chapter from '.' +import type { Meta, StoryFn } from '@storybook/react' +import { Chapter } from '.' export default { title: 'DataDisplay/Chapter', diff --git a/src/core/data-display/chapter/index.tsx b/src/core/data-display/chapter/index.tsx index 1ea56b78..21e793df 100644 --- a/src/core/data-display/chapter/index.tsx +++ b/src/core/data-display/chapter/index.tsx @@ -1,8 +1,9 @@ -import React, { CSSProperties } from 'react' -import styled from 'styled-components' -import { DefaultProps } from '../../types' -import Typography from '@/core/data-display/typography' +import React from 'react' +import type { CSSProperties, ReactNode } from 'react' +import { default as styled } from 'styled-components' +import type { DefaultProps } from '../../types' import type { TypographyProps } from '@material-ui/core/Typography' +import { Typography } from '@/core/data-display/typography' import { theme } from '@/theme' const { grays } = theme.colors @@ -27,7 +28,7 @@ export interface LineProps extends DefaultProps { /** * The children of the component. */ - children?: React.ReactNode + children?: ReactNode 'data-testid'?: string } diff --git a/src/core/data-display/chip/chip.spec.tsx b/src/core/data-display/chip/chip.spec.tsx index 286544b0..1a112523 100644 --- a/src/core/data-display/chip/chip.spec.tsx +++ b/src/core/data-display/chip/chip.spec.tsx @@ -1,6 +1,6 @@ import * as React from 'react' import { render, screen, waitFor } from '@testing-library/react' -import Chip from '.' +import { Chip } from '.' describe('Chip', () => { it('should render', () => { @@ -27,6 +27,7 @@ describe('Chip', () => { it('should call onDelete', () => { const onDelete = jest.fn() + render() const svg = screen.getByRole('button') diff --git a/src/core/data-display/chip/chip.stories.tsx b/src/core/data-display/chip/chip.stories.tsx index 8375c821..d37043a1 100644 --- a/src/core/data-display/chip/chip.stories.tsx +++ b/src/core/data-display/chip/chip.stories.tsx @@ -1,8 +1,8 @@ import React from 'react' -import { Meta, StoryFn } from '@storybook/react' -import Chip from '.' -import Avatar from '@/core/data-display/avatar' -import { Face } from '../../../icons' +import type { Meta, StoryFn } from '@storybook/react' +import { Avatar } from '@/core/data-display/avatar' +import { Face } from '@/icons' +import { Chip } from '.' export default { title: 'DataDisplay/Chip', diff --git a/src/core/data-display/chip/index.tsx b/src/core/data-display/chip/index.tsx index 838c4bc3..0a2b76f9 100644 --- a/src/core/data-display/chip/index.tsx +++ b/src/core/data-display/chip/index.tsx @@ -1,7 +1,8 @@ -import { Chip as MuiChip, ChipProps as MuiChipProps } from '@material-ui/core' -import { makeStyles } from '@material-ui/core/styles' import React from 'react' -import { DefaultProps } from '../../types' +import { Chip as MuiChip } from '@material-ui/core' +import { makeStyles } from '@material-ui/core/styles' +import type { DefaultProps } from '../../types' +import type { ChipProps as MuiChipProps } from '@material-ui/core' export interface IChipProps extends MuiChipProps, diff --git a/src/core/data-display/data-table/data-table-action.tsx b/src/core/data-display/data-table/data-table-action.tsx index 2de5f882..ddf384fa 100644 --- a/src/core/data-display/data-table/data-table-action.tsx +++ b/src/core/data-display/data-table/data-table-action.tsx @@ -1,4 +1,5 @@ -import React, { ReactNode } from 'react' +import type { ReactNode } from 'react' +import React from 'react' import IconButton from '@material-ui/core/IconButton' export type DataTableActionProps = { diff --git a/src/core/data-display/data-table/data-table-field.tsx b/src/core/data-display/data-table/data-table-field.tsx new file mode 100644 index 00000000..eafe6758 --- /dev/null +++ b/src/core/data-display/data-table/data-table-field.tsx @@ -0,0 +1,268 @@ +// eslint-disable-next-line @typescript-eslint/consistent-type-imports +import React from 'react' +import type { ChangeEvent, Dispatch, SetStateAction } from 'react' +import { + Checkbox, + Table, + TableBody, + TableCell, + TableHead, + TableRow +} from '@mui/material' +import { default as styled } from 'styled-components' +import { TextField } from '@/index' + +interface IHeader { + title: string + field: string + type?: string + editable?: boolean +} + +interface ITable> { + rows: D[] + setRows: Dispatch> + header: IHeader[] + checkbox?: boolean + checkboxProps?: { + checkRow?: boolean[] + checkAllRows?: boolean + setSelectedRow?: Dispatch> + setSelectedAllRows?: Dispatch> + } +} + +const TableCellRows = styled(TableCell)` + && { + width: 400px; + height: 60px; + padding: 0 10px; + } +` + +const RowTable = styled(TableRow)` + width: 100%; + cursor: pointer; + + &:hover { + background: -moz-linear-gradient( + left, + rgba(189, 189, 189, 0) 0%, + rgba(189, 189, 189, 1) 100% + ); + background: -webkit-linear-gradient( + left, + rgba(189, 189, 189, 0) 0%, + rgba(189, 189, 189, 1) 100% + ); + background: linear-gradient( + to right, + rgba(189, 189, 189, 0) 0%, + rgba(189, 189, 189, 1) 100% + ); + } + + &.no-hover { + background: none; + } +` + +export const DataTableField = >( + props: ITable +) => { + const { rows, header, checkbox, checkboxProps, setRows } = props + + const handleFieldChange = ( + event: ChangeEvent, + fieldName: keyof D, + rowIndex: number, + setRows: Dispatch> + ) => { + const { value } = event.target + + setRows(prevRows => { + const updatedRows = prevRows.map((row, i) => { + if (i === rowIndex) { + return { + ...row, + [fieldName]: value + } + } + + return row + }) + + return updatedRows as D[] + }) + } + + const handleSelectCheckbox = ( + index: number, + setSelected: Dispatch>, + setSelectedAll: Dispatch> + ) => { + setSelected(state => { + const newState = state.map((row, i: number) => + index === i ? !row : row + ) + + if (newState.includes(false)) { + setSelectedAll(false) + } + + if (newState.every(item => item === true)) { + setSelectedAll(true) + } + + return newState + }) + } + + const handleSelectAllCheckbox = ( + setSelected: Dispatch>, + setSelectedAll: Dispatch> + ) => { + setSelectedAll(selectedAll => !selectedAll) + setSelected(state => + state.map(() => + checkboxProps !== undefined + ? !checkboxProps.checkAllRows + : false + ) + ) + } + + const handleSelect = (index: number) => { + if (checkboxProps?.setSelectedRow && checkboxProps.setSelectedAllRows) { + handleSelectCheckbox( + index, + checkboxProps.setSelectedRow, + checkboxProps.setSelectedAllRows + ) + } + } + + const handleTableRow = ( + event: React.MouseEvent, + index: number + ) => { + const isCheckboxClick = + (event.target as HTMLElement).closest('input[type="checkbox"]') !== + null + + if ( + !isCheckboxClick && + (!checkboxProps?.checkRow || !checkboxProps.checkRow[index]) + ) { + handleSelect(index) + } + } + + const tableBody = (rows: D[], header: IHeader[]) => + rows.map((row, index) => { + const columns = header.map((column, i) => { + if (Object.keys(row).includes(column.field)) { + return ( + + {column.editable && + checkboxProps?.checkRow && + checkboxProps.checkRow[index] ? ( + event.stopPropagation()} + onChange={event => + handleFieldChange( + event, + column.field, + index, + setRows + ) + } + /> + ) : ( + + {column.editable + ? checkboxProps?.checkRow?.[index] + ? (row[column.field] as string) + : '' + : (row[column.field] as string)} + + )} + + ) + } + + return + }) + + return ( + handleTableRow(event, index)}> + {checkbox && ( + + handleSelect(index)} + /> + + )} + {columns} + + ) + }) + + return ( + + + {checkbox && ( + + { + if ( + checkboxProps?.setSelectedRow && + checkboxProps.setSelectedAllRows + ) { + handleSelectAllCheckbox( + checkboxProps.setSelectedRow, + checkboxProps.setSelectedAllRows + ) + } + }} + /> + + )} + {header.map((item, i) => ( + + {item.title} + + ))} + + {tableBody(rows, header)} +
+ ) +} diff --git a/src/core/data-display/data-table/data-table-pagination-actions.tsx b/src/core/data-display/data-table/data-table-pagination-actions.tsx index a9395c23..b94101c8 100644 --- a/src/core/data-display/data-table/data-table-pagination-actions.tsx +++ b/src/core/data-display/data-table/data-table-pagination-actions.tsx @@ -1,20 +1,18 @@ import React from 'react' -import IconButton from '@/core/inputs/icon-button' +import type { MouseEvent } from 'react' +import { IconButton } from '@/core/inputs/icon-button' import { FirstPage, LastPage, KeyboardArrowLeft, KeyboardArrowRight -} from '../../../icons' +} from '@/icons' interface DataTablePaginationActionsProps { count: number page: number rowsPerPage: number - onPageChange( - event: React.MouseEvent, - newPage: number - ): void + onPageChange(event: MouseEvent, newPage: number): void } interface DataTablePaginationActionsBuilder { @@ -40,25 +38,25 @@ export const makeDataTablePaginationActions = const totalPages = Math.ceil(count / rowsPerPage) - 1 const handleFirstPageButtonClick = ( - event: React.MouseEvent + event: MouseEvent ) => { onPageChange(event, 0) } const handleBackButtonClick = ( - event: React.MouseEvent + event: MouseEvent ) => { onPageChange(event, page - 1) } const handleNextButtonClick = ( - event: React.MouseEvent + event: MouseEvent ) => { onPageChange(event, page + 1) } const handleLastPageButtonClick = ( - event: React.MouseEvent + event: MouseEvent ) => { onPageChange(event, Math.max(0, totalPages)) } @@ -67,29 +65,29 @@ export const makeDataTablePaginationActions =
{showFirstButton && ( + aria-label='first page' + onClick={handleFirstPageButtonClick}> )} + aria-label='previous page' + onClick={handleBackButtonClick}> = totalPages || clickable} - aria-label='next page'> + aria-label='next page' + onClick={handleNextButtonClick}> {showLastButton && ( = totalPages || clickable} - aria-label='last page'> + aria-label='last page' + onClick={handleLastPageButtonClick}> )} diff --git a/src/core/data-display/data-table/data-table-query-paginated.stories.tsx b/src/core/data-display/data-table/data-table-query-paginated.stories.tsx index e7d9a9d4..78f4b1c4 100644 --- a/src/core/data-display/data-table/data-table-query-paginated.stories.tsx +++ b/src/core/data-display/data-table/data-table-query-paginated.stories.tsx @@ -1,15 +1,13 @@ /* eslint-disable @typescript-eslint/ban-ts-comment */ /* eslint-disable max-lines */ +import React, { useMemo, useRef, useState } from 'react' +import type { ReactNode } from 'react' import { TableCell, TableRow, Typography } from '@material-ui/core' import { Skeleton } from '@mui/material' -import { Meta } from '@storybook/react' import format from 'date-fns/format' -import React, { ReactNode, useMemo, useRef, useState } from 'react' -import Button from '@/core/inputs/button' -import { DataTableAction } from './data-table-action' -import DataTableQueryPaginated from './data-table-query-paginated' -import { ColumnSpec, DataTableController, Identifier, RowMode } from './types' -import { usePaginated } from './use-paginated' +import type { ColumnSpec, DataTableController, Identifier } from './types' +import type { Meta } from '@storybook/react' +import { Button } from '@/core/inputs/button' import { Cancel as CancelIcon, Check as CheckIcon, @@ -17,6 +15,10 @@ import { Edit as EditIcon, Save as SaveIcon } from '@/icons' +import { DataTableAction } from './data-table-action' +import { DataTableQueryPaginated } from './data-table-query-paginated' +import { RowMode } from './types' +import { usePaginated } from './use-paginated' export default { title: 'DataDisplay/DataTableQueryPaginated', @@ -91,6 +93,7 @@ const generateSkeleton = ( ))} ) + result.push(table) } @@ -108,7 +111,7 @@ export const Default = () => { loading } = usePaginated() - const LoadNode: React.ReactNode = useMemo( + const LoadNode: ReactNode = useMemo( () => generateSkeleton(size, columnsData), [size] ) @@ -132,6 +135,28 @@ export const Default = () => { ) } +const columnsEmpty: ColumnSpec[] = [ + { + title: 'Product', + field: 'product', + type: 'text', + cellStyle: { + maxWidth: '72px', + whiteSpace: 'nowrap', + overflow: 'hidden', + textOverflow: 'ellipsis' + }, + editable: true + }, + { + title: 'Price (R$)', + field: 'price', + type: 'numeric-float', + editable: false, + getValue: (value: number) => value.toFixed(2).replace('.', ',') + } +] + export const Empty = () => { const { totalElements, @@ -142,28 +167,6 @@ export const Empty = () => { loading } = usePaginated() - const columns: ColumnSpec[] = [ - { - title: 'Product', - field: 'product', - type: 'text', - cellStyle: { - maxWidth: '72px', - whiteSpace: 'nowrap', - overflow: 'hidden', - textOverflow: 'ellipsis' - }, - editable: true - }, - { - title: 'Price (R$)', - field: 'price', - type: 'numeric-float', - editable: false, - getValue: (value: number) => value.toFixed(2).replace('.', ',') - } - ] - const componentForEmpty: ReactNode = ( { ) - const LoadNode: React.ReactNode = loading + const LoadNode: ReactNode = loading ? generateSkeleton(size, columnsData) : componentForEmpty @@ -202,11 +205,52 @@ export const Empty = () => { rowsPerPage: 5, labelRowsPerPage: 'Row per page' }} - columns={columns} + columns={columnsEmpty} /> ) } +const columnsNoHeader: ColumnSpec[] = [ + { + title: 'Product', + field: 'product', + type: 'text', + cellStyle: { + maxWidth: '72px', + whiteSpace: 'nowrap', + overflow: 'hidden', + textOverflow: 'ellipsis' + }, + editable: true + }, + { + title: 'Price (R$)', + field: 'price', + type: 'numeric-float', + editable: false, + getValue: (value: number) => value.toFixed(2).replace('.', ',') + }, + { + title: 'Quantity', + field: 'quantity', + type: 'numeric-int', + editable: true, + cellStyle: { + width: '82px' + } + }, + { + title: 'Date', + field: 'date', + type: 'datetime', + editable: true, + getValue: (value: Date) => format(value, 'dd/MM/yyyy HH:mm'), + cellStyle: { + width: '200px' + } + } +] + export const NoHeader = () => { const { totalElements, @@ -218,61 +262,20 @@ export const NoHeader = () => { data } = usePaginated() - const LoadNode: React.ReactNode = useMemo( + const LoadNode: ReactNode = useMemo( () => generateSkeleton(size, columnsData), [size] ) - const columns: ColumnSpec[] = [ - { - title: 'Product', - field: 'product', - type: 'text', - cellStyle: { - maxWidth: '72px', - whiteSpace: 'nowrap', - overflow: 'hidden', - textOverflow: 'ellipsis' - }, - editable: true - }, - { - title: 'Price (R$)', - field: 'price', - type: 'numeric-float', - editable: false, - getValue: (value: number) => value.toFixed(2).replace('.', ',') - }, - { - title: 'Quantity', - field: 'quantity', - type: 'numeric-int', - editable: true, - cellStyle: { - width: '82px' - } - }, - { - title: 'Date', - field: 'date', - type: 'datetime', - editable: true, - getValue: (value: Date) => format(value, 'dd/MM/yyyy HH:mm'), - cellStyle: { - width: '200px' - } - } - ] - return ( { labelRowsPerPage: 'Row per page', clickable: !loading }} - columns={columns} + columns={columnsNoHeader} /> ) } @@ -313,7 +316,7 @@ export const Crud = () => { } ] - const LoadNode: React.ReactNode = useMemo( + const LoadNode: ReactNode = useMemo( () => generateSkeleton(size, newData), [size] ) diff --git a/src/core/data-display/data-table/data-table-query-paginated.tsx b/src/core/data-display/data-table/data-table-query-paginated.tsx index 7381b0cd..f842a0e6 100644 --- a/src/core/data-display/data-table/data-table-query-paginated.tsx +++ b/src/core/data-display/data-table/data-table-query-paginated.tsx @@ -1,35 +1,34 @@ -import React, { - useMemo, - useState, - useRef, - useEffect, +import React, { useMemo, useState, useRef, useEffect } from 'react' +import type { + MouseEvent, MutableRefObject, - CSSProperties + CSSProperties, + ReactNode } from 'react' -import { last } from 'ramda' +import Paper from '@material-ui/core/Paper' import Table from '@material-ui/core/Table' import TableBody from '@material-ui/core/TableBody' import TableCell from '@material-ui/core/TableCell' import TableContainer from '@material-ui/core/TableContainer' +import TableFooter from '@material-ui/core/TableFooter' import TableHead from '@material-ui/core/TableHead' -import TableRow from '@material-ui/core/TableRow' -import Paper from '@material-ui/core/Paper' import TablePagination from '@material-ui/core/TablePagination' -import TableFooter from '@material-ui/core/TableFooter' -import { +import TableRow from '@material-ui/core/TableRow' +import { last } from 'ramda' +import type { ColumnSpec, Data, DataTableController, Errors, PaginationOptions, - RowMode, RowViewComponent, StackView, PartialData } from './types' -import { useRowsState } from './use-rows-state' -import { StatefulRow, NewRow } from './rows' import { makeDataTablePaginationActions } from './data-table-pagination-actions' +import { StatefulRow, NewRow } from './rows' +import { RowMode } from './types' +import { useRowsState } from './use-rows-state' export type DataTableProps< D extends Data, @@ -75,7 +74,7 @@ export type DataTableProps< /** * Component to show when there are no data */ - componentForEmpty?: React.ReactNode + componentForEmpty?: ReactNode /** * Custom style to be applied to the table body */ @@ -113,10 +112,7 @@ export type DataTableProps< * Custom rowViews used as a Stac */ rowViews?: Record> - onRowClick?: ( - event: React.MouseEvent, - rowData: D - ) => void + onRowClick?: (event: MouseEvent, rowData: D) => void } const defaultPagination: PaginationOptions = { @@ -287,7 +283,8 @@ export const DataTableQueryPaginated = ( height: hiddenRowHeight && `${hiddenRowHeight * hiddenRowsNumber}px` - }}> + }} + /> ) @@ -347,6 +344,7 @@ export const DataTableQueryPaginated = ( labelDisplayedRows={ pagination.labelDisplayedRows } + ActionsComponent={paginationActionsComponent} onPageChange={(_, page) => { handleChangePage(page) }} @@ -355,7 +353,6 @@ export const DataTableQueryPaginated = ( parseInt(event.target.value, 10) ) }} - ActionsComponent={paginationActionsComponent} /> diff --git a/src/core/data-display/data-table/data-table.spec.tsx b/src/core/data-display/data-table/data-table.spec.tsx index 86126a0f..a0e611e8 100644 --- a/src/core/data-display/data-table/data-table.spec.tsx +++ b/src/core/data-display/data-table/data-table.spec.tsx @@ -1,12 +1,12 @@ import * as React from 'react' +import { act } from 'react-dom/test-utils' import { fireEvent, render, screen, waitFor } from '@testing-library/react' -import DataTable from '.' -import DataTableWithCrud from '@/test/mocks/data-table-mock' -import DataTableWithHidden from '@/test/mocks/data-table-hidden-mock' -import { ColumnSpec } from './types' +import { userEvent } from '@testing-library/user-event' import format from 'date-fns/format' -import userEvent from '@testing-library/user-event' -import { act } from 'react-dom/test-utils' +import type { ColumnSpec } from './types' +import DataTableWithHidden from '@/test/mocks/data-table-hidden-mock' +import DataTableWithCrud from '@/test/mocks/data-table-mock' +import DataTable from '.' type Data = { id: number diff --git a/src/core/data-display/data-table/data-table.stories.tsx b/src/core/data-display/data-table/data-table.stories.tsx index 02af1b4c..9b95b10f 100644 --- a/src/core/data-display/data-table/data-table.stories.tsx +++ b/src/core/data-display/data-table/data-table.stories.tsx @@ -1,13 +1,13 @@ +/* eslint-disable react-perf/jsx-no-new-array-as-prop */ /* eslint-disable @typescript-eslint/ban-ts-comment */ /* eslint-disable max-lines */ import React, { useState, useRef } from 'react' -import { Meta } from '@storybook/react' import format from 'date-fns/format' -import DataTable from './data-table' -import Button from '@/core/inputs/button' -import Typography from '@/core/data-display/typography' -import { DataTableAction } from './data-table-action' -import { ColumnSpec, DataTableController, Identifier, RowMode } from './types' +import { v4 as uuid } from 'uuid' +import type { ColumnSpec, DataTableController, Identifier } from './types' +import type { Meta } from '@storybook/react' +import { Typography } from '@/core/data-display/typography' +import { Button } from '@/core/inputs/button' import { Delete as DeleteIcon, Edit as EditIcon, @@ -17,7 +17,10 @@ import { Visibility as VisibilityIcon, VisibilityOff as VisibilityOffIcon } from '@/icons' -import { v4 as uuid } from 'uuid' +import { DataTable } from './data-table' +import { DataTableAction } from './data-table-action' +import { DataTableField } from './data-table-field' +import { RowMode } from './types' export default { title: 'DataDisplay/DataTable', @@ -32,9 +35,6 @@ type Data = { date: Date } -// const Template: ComponentStory = args => -// - export const Default = () => { type Data = { id: number @@ -245,8 +245,8 @@ export const NoHeader = () => { return ( { (id: Identifier, isNew = false) => () => { const nextItem = controllerRef.current?.getEditedRowData(id) + if (!nextItem) { return } @@ -896,3 +897,102 @@ export const CrudWithHidden = () => { ) } + +const dataInput = [ + { + branch: 'Keepfy Joinville', + local: 'Joiville', + status: 'Ativo', + companyCode: '', + branchCode: '' + }, + { + branch: 'Keepfy São Paulo', + local: 'São Paulo', + status: 'Ativo', + companyCode: '', + branchCode: '' + }, + { + branch: 'Keepfy Rio Grande do Sul', + local: 'Rio Grande do Sul', + status: 'Ativo', + companyCode: '', + branchCode: '' + }, + { + branch: 'Keepfy Rio de Janeiro', + local: 'Rio de Janeiro', + status: 'Ativo', + companyCode: '', + branchCode: '' + }, + { + branch: 'Keepfy Curitiba', + local: 'Curitiba', + status: 'Ativo', + companyCode: '', + branchCode: '' + }, + { + branch: 'Keepfy Teresópolis', + local: 'Teresópolis', + status: 'Ativo', + companyCode: '', + branchCode: '' + } +] + +const tableHead = [ + { + title: 'Nome da Filial', + field: 'branch', + type: 'text', + editable: false + }, + { + title: 'Localidade', + field: 'local', + type: 'text', + editable: false + }, + { + title: 'Status', + field: 'status', + type: 'text', + editable: false + }, + { + title: 'Código da Empresa', + field: 'companyCode', + type: 'number', + editable: true + }, + { + title: 'Código da Filial', + field: 'branchCode', + type: 'text', + editable: true + } +] + +export const WithField = () => { + const [data, setData] = useState(() => dataInput) + const [selectedAll, setSelectedAll] = useState(false) + const [selected, setSelected] = useState(Array(data.length).fill(false)) + + return ( + + ) +} diff --git a/src/core/data-display/data-table/data-table.tsx b/src/core/data-display/data-table/data-table.tsx index 7fb45074..d98dbf1f 100644 --- a/src/core/data-display/data-table/data-table.tsx +++ b/src/core/data-display/data-table/data-table.tsx @@ -1,35 +1,38 @@ -import React, { - useMemo, - useState, - useRef, - useEffect, +/* eslint-disable max-lines */ +import React, { useMemo, useState, useRef, useEffect } from 'react' +import type { + MouseEvent, MutableRefObject, - CSSProperties + CSSProperties, + ReactNode, + Dispatch, + SetStateAction } from 'react' -import { last } from 'ramda' +import { Checkbox } from '@material-ui/core' +import Paper from '@material-ui/core/Paper' import Table from '@material-ui/core/Table' import TableBody from '@material-ui/core/TableBody' import TableCell from '@material-ui/core/TableCell' import TableContainer from '@material-ui/core/TableContainer' +import TableFooter from '@material-ui/core/TableFooter' import TableHead from '@material-ui/core/TableHead' -import TableRow from '@material-ui/core/TableRow' -import Paper from '@material-ui/core/Paper' import TablePagination from '@material-ui/core/TablePagination' -import TableFooter from '@material-ui/core/TableFooter' -import { +import TableRow from '@material-ui/core/TableRow' +import { last } from 'ramda' +import type { ColumnSpec, Data, DataTableController, Errors, PaginationOptions, - RowMode, RowViewComponent, StackView, PartialData } from './types' -import { useRowsState } from './use-rows-state' -import { StatefulRow, NewRow } from './rows' import { makeDataTablePaginationActions } from './data-table-pagination-actions' +import { StatefulRow, NewRow } from './rows' +import { RowMode } from './types' +import { useRowsState } from './use-rows-state' export type DataTableProps< D extends Data, @@ -55,7 +58,7 @@ export type DataTableProps< /** * Component to show when there are no data */ - componentForEmpty?: React.ReactNode + componentForEmpty?: ReactNode /** * Custom style to be applied to the table body */ @@ -93,10 +96,20 @@ export type DataTableProps< * Custom rowViews used as a Stac */ rowViews?: Record> - onRowClick?: ( - event: React.MouseEvent, - rowData: D - ) => void + /** + * Hide or show the checkbox + */ + checkbox?: boolean + /** + * Handle the selected states and values + */ + checkboxProps?: { + checkRow?: boolean[] + checkAllRows?: boolean + setSelectedRow?: Dispatch> + setSelectedAllRows?: Dispatch> + } + onRowClick?: (event: MouseEvent, rowData: D) => void } const defaultPagination: PaginationOptions = { @@ -139,7 +152,9 @@ export const DataTable = ( bodyStyle, headStyle, hiddenRowHeight, - hidden + hidden, + checkbox, + checkboxProps } = props const [newRow, setNewRow] = useState | undefined>() @@ -148,6 +163,7 @@ export const DataTable = ( if (pagination.disabled) { return data } + // this case is not good for the useRowsMode hook if (newRow && page === 0) { return sliceData(data, page, rowsPerPage - 1) @@ -204,9 +220,45 @@ export const DataTable = ( } }, [setRowState, pushRowView, popRowView, getRowState, controllerRef]) + const handleSelectCheckbox = ( + index: number, + setSelected: Dispatch>, + setSelectedAll: Dispatch> + ) => { + setSelected(state => { + const newState = state.map((row, i: number) => + index === i ? !row : row + ) + + if (newState.includes(false)) { + setSelectedAll(false) + } + + if (newState.every(item => item === true)) { + setSelectedAll(true) + } + + return newState + }) + } + + const handleSelectAllCheckbox = ( + setSelected: Dispatch>, + setSelectedAll: Dispatch> + ) => { + setSelectedAll(selectedAll => !selectedAll) + setSelected(state => + state.map(() => + checkboxProps !== undefined + ? !checkboxProps.checkAllRows + : false + ) + ) + } + const rowsList = useMemo( () => - rows.map(row => { + rows.map((row, index) => { const rowState = getRowState(row.id) const lastView = rowState?.stackView && last(rowState.stackView) const view = lastView && rowViews?.[lastView] @@ -219,6 +271,31 @@ export const DataTable = ( data-id={row.id} style={bodyRowStyle} onClick={event => onRowClick?.(event, row)}> + {checkbox && ( + + { + if ( + checkboxProps?.setSelectedRow && + checkboxProps.setSelectedAllRows + ) { + handleSelectCheckbox( + index, + checkboxProps.setSelectedRow, + checkboxProps.setSelectedAllRows + ) + } + }} + /> + + )} {view ? ( view({ data: row }) ) : ( @@ -237,13 +314,15 @@ export const DataTable = ( [ rows, getRowState, - onRowClick, - setEditableRowState, - errors, rowViews, + hidden, bodyRowStyle, + checkbox, columns, - hidden + errors, + setEditableRowState, + onRowClick, + checkboxProps ] ) @@ -276,7 +355,8 @@ export const DataTable = ( height: hiddenRowHeight && `${hiddenRowHeight * hiddenRowsNumber}px` - }}> + }} + /> ) @@ -308,7 +388,33 @@ export const DataTable = ( {!noHeader && ( - {columnsList} + + {checkbox && ( + + { + if ( + checkboxProps?.setSelectedRow && + checkboxProps.setSelectedAllRows + ) { + handleSelectAllCheckbox( + checkboxProps.setSelectedRow, + checkboxProps.setSelectedAllRows + ) + } + }} + /> + + )} + {columnsList} + )} @@ -329,6 +435,7 @@ export const DataTable = ( labelDisplayedRows={ pagination.labelDisplayedRows } + ActionsComponent={paginationActionsComponent} onPageChange={(_, page) => { setPage(page) }} @@ -338,7 +445,6 @@ export const DataTable = ( ) setPage(0) }} - ActionsComponent={paginationActionsComponent} /> diff --git a/src/core/data-display/data-table/index.ts b/src/core/data-display/data-table/index.ts index 73c06a57..d8d2e6ea 100644 --- a/src/core/data-display/data-table/index.ts +++ b/src/core/data-display/data-table/index.ts @@ -3,6 +3,7 @@ export { default as DataTableQueryPaginated } from './data-table-query-paginated export type { DataTableProps } from './data-table' export { RowMode } from './types' export { DataTableAction } from './data-table-action' +export { DataTableField } from './data-table-field' export type { DataTableActionProps } from './data-table-action' export type { ActionsCellProps, diff --git a/src/core/data-display/data-table/rows.tsx b/src/core/data-display/data-table/rows.tsx index 8e242b39..9cc031f2 100644 --- a/src/core/data-display/data-table/rows.tsx +++ b/src/core/data-display/data-table/rows.tsx @@ -1,10 +1,12 @@ -import { ColumnSpec, Data, Errors, PartialData, RowMode } from './types' -import TextField from '@/core/inputs/text-field' -import MaskField from '@/core/inputs/mask-field' -import DateTime from '@/core/inputs/date-time' -import React, { ReactNode, useState, useCallback } from 'react' +import type { ReactNode } from 'react' +import React, { useState, useCallback } from 'react' import TableCell from '@material-ui/core/TableCell' import TableRow from '@material-ui/core/TableRow' +import type { ColumnSpec, Data, Errors, PartialData } from './types' +import { DateTime } from '@/core/inputs/date-time' +import { MaskField } from '@/core/inputs/mask-field' +import { TextField } from '@/core/inputs/text-field' +import { RowMode } from './types' type RowStateUpdater = ( field: keyof D, @@ -44,9 +46,9 @@ const renderEditMode = ( return ( { @@ -56,7 +58,7 @@ const renderEditMode = ( ) } - if (column.type?.includes('numeric')) { + if (column.type.includes('numeric')) { const decimalScale = column.type === 'numeric-int' ? 0 : 2 const numeric = row[column.field] as number @@ -64,8 +66,8 @@ const renderEditMode = ( return ( ( return ( @@ -169,6 +171,7 @@ export const StatefulRow = ({ [`${String(field)}`]: value })) const patch: Partial = {} + patch[field] = value onUpdate?.(patch) }, diff --git a/src/core/data-display/data-table/types.ts b/src/core/data-display/data-table/types.ts index 280d38ba..4b509fb4 100644 --- a/src/core/data-display/data-table/types.ts +++ b/src/core/data-display/data-table/types.ts @@ -1,5 +1,5 @@ -import { IOption } from '@/core/inputs/text-field' import type { CSSProperties, FunctionComponent } from 'react' +import type { IOption } from '@/core/inputs/text-field' export type RecordUnknown = Record export type StackView = RecordUnknown @@ -22,7 +22,7 @@ export type ColumnType = export type Align = 'right' | 'left' | 'center' | 'justify' | 'inherit' -type ColumnSpecBase = { +type ColumnSpecBase = { title: string type: string cellStyle?: CSSProperties diff --git a/src/core/data-display/data-table/use-paginated.ts b/src/core/data-display/data-table/use-paginated.ts index 50174c7a..9a08a216 100644 --- a/src/core/data-display/data-table/use-paginated.ts +++ b/src/core/data-display/data-table/use-paginated.ts @@ -1,8 +1,8 @@ +import { useState, useMemo, useEffect } from 'react' import faker from 'faker' import { splitEvery } from 'ramda' -import { useState, useMemo, useEffect } from 'react' // import { v4 as uuid } from 'uuid' -import { Data } from './types' +import type { Data } from './types' export interface IDataProps { id: string @@ -21,6 +21,7 @@ interface IPaginated { export const generateRandomDate = (size: number): Data[] => { const content: Array = [] + for (let i = 0; i < size; i++) { content.push({ id: i, diff --git a/src/core/data-display/data-table/use-rows-state.ts b/src/core/data-display/data-table/use-rows-state.ts index c90eb4e3..a18f2070 100644 --- a/src/core/data-display/data-table/use-rows-state.ts +++ b/src/core/data-display/data-table/use-rows-state.ts @@ -1,5 +1,6 @@ import { useCallback, useEffect, useState } from 'react' -import { Data, Identifier, RowState, StackView, RowMode } from './types' +import type { Data, Identifier, RowState, StackView } from './types' +import { RowMode } from './types' export const useRowsState = ( rows: D[], @@ -16,6 +17,7 @@ export const useRowsState = ( for (const row of rows) { const elem = state.internal.get(row.id) + if (elem) { nextState.set(row.id, elem) } else { @@ -43,6 +45,7 @@ export const useRowsState = ( (id: Identifier, partial: Partial>) => { setState(state => { const elem = state.internal.get(id) + if (elem) { state.internal.set(id, { ...elem, ...partial }) } @@ -56,6 +59,7 @@ export const useRowsState = ( const pushRowView = useCallback((id: Identifier, view: keyof V) => { setState(state => { const elem = state.internal.get(id) + if (elem) { elem.stackView.push(view) state.internal.set(id, elem) @@ -70,7 +74,7 @@ export const useRowsState = ( const elem = state.internal.get(id) if (elem) { - elem?.stackView.pop() + elem.stackView.pop() state.internal.set(id, elem) } diff --git a/src/core/data-display/divider/divider.spec.tsx b/src/core/data-display/divider/divider.spec.tsx index a513f693..f709a622 100644 --- a/src/core/data-display/divider/divider.spec.tsx +++ b/src/core/data-display/divider/divider.spec.tsx @@ -1,11 +1,12 @@ import * as React from 'react' import { render, screen } from '@testing-library/react' -import Divider from '.' +import { Divider } from '.' describe('Divider', () => { it('should render', () => { render() const divider = screen.getByTestId('divider') + expect(divider).toBeDefined() }) @@ -27,6 +28,7 @@ describe('Divider', () => { it('should match snapshot', () => { const { container } = render() + expect(container).toMatchSnapshot() }) }) diff --git a/src/core/data-display/divider/divider.stories.tsx b/src/core/data-display/divider/divider.stories.tsx index 60cefb50..6fd8c082 100644 --- a/src/core/data-display/divider/divider.stories.tsx +++ b/src/core/data-display/divider/divider.stories.tsx @@ -1,8 +1,8 @@ import React from 'react' -import { Meta } from '@storybook/react' -import Divider from '.' -import List from '@/core/data-display/list' +import type { Meta } from '@storybook/react' +import { List } from '@/core/data-display/list' import ListItem from '@/core/data-display/list-item' +import { Divider } from '.' export default { title: 'DataDisplay/Divider', diff --git a/src/core/data-display/divider/index.tsx b/src/core/data-display/divider/index.tsx index e712fdd7..c1d5cf62 100644 --- a/src/core/data-display/divider/index.tsx +++ b/src/core/data-display/divider/index.tsx @@ -1,9 +1,7 @@ -import { - Divider as MuiDivider, - DividerProps as MuiDividerProps -} from '@material-ui/core' import React from 'react' -import { DefaultProps } from '../../types' +import { Divider as MuiDivider } from '@material-ui/core' +import type { DefaultProps } from '../../types' +import type { DividerProps as MuiDividerProps } from '@material-ui/core' export interface DividerProps extends DefaultProps, MuiDividerProps { 'data-testid'?: string diff --git a/src/core/data-display/editable-table/editTable.stories.tsx b/src/core/data-display/editable-table/editTable.stories.tsx index d4c9d750..14c43eef 100644 --- a/src/core/data-display/editable-table/editTable.stories.tsx +++ b/src/core/data-display/editable-table/editTable.stories.tsx @@ -1,14 +1,16 @@ import React from 'react' -import { Meta, StoryFn } from '@storybook/react' -import EditableTable from '.' +import type { Meta, StoryFn } from '@storybook/react' +import { EditableTable } from '.' export default { title: 'DataDisplay/EditTable', component: EditableTable, args: { title: 'adicionar', + // eslint-disable-next-line no-console onAddRow: (item: object) => Promise.resolve(console.log(item)), onRowClick: () => window.alert('hello'), + // eslint-disable-next-line no-console onDeleteRow: (item: object) => Promise.resolve(console.log(item)), onUpdateRow: () => Promise.resolve(), onClickAdd: () => window.alert('hello') diff --git a/src/core/data-display/editable-table/editable-table-with-date.spec.tsx b/src/core/data-display/editable-table/editable-table-with-date.spec.tsx index 83c091d5..8a8fe54a 100644 --- a/src/core/data-display/editable-table/editable-table-with-date.spec.tsx +++ b/src/core/data-display/editable-table/editable-table-with-date.spec.tsx @@ -1,10 +1,10 @@ /* eslint-disable max-lines */ -import WithDate from '@/test/mocks/editable-table-date-mock' -import { render, screen } from '@testing-library/react' -import userEvent from '@testing-library/user-event/' -import { Column } from 'material-table' import * as React from 'react' import { act } from 'react-dom/test-utils' +import { render, screen } from '@testing-library/react' +import { userEvent } from '@testing-library/user-event/' +import type { Column } from 'material-table' +import WithDate from '@/test/mocks/editable-table-date-mock' const COLUMNS_WITH_DATE: Column[] = [ { title: 'Data', @@ -52,9 +52,11 @@ const AUTO_COMPLETE_SUGGESTIONS = [ { label: 'some values', value: '5000' }, { label: 'any values', value: '12' } ] + beforeEach(() => { // prevent
cannot appear as a child of
warning on console const spy = jest.spyOn(console, 'error') + spy.mockImplementation(jest.fn()) }) diff --git a/src/core/data-display/editable-table/editable-table.spec.tsx b/src/core/data-display/editable-table/editable-table.spec.tsx index 45b5a448..00fabe02 100644 --- a/src/core/data-display/editable-table/editable-table.spec.tsx +++ b/src/core/data-display/editable-table/editable-table.spec.tsx @@ -1,11 +1,11 @@ /* eslint-disable max-lines */ -import WithDate from '@/test/mocks/editable-table-date-mock' -import EditableTable from '@/test/mocks/editable-table-mock' -import { fireEvent, render, screen } from '@testing-library/react' -import { Column } from 'material-table' import * as React from 'react' -import userEvent from '@testing-library/user-event/' import { act } from 'react-dom/test-utils' +import { fireEvent, render, screen } from '@testing-library/react' +import { userEvent } from '@testing-library/user-event/' +import type { Column } from 'material-table' +import WithDate from '@/test/mocks/editable-table-date-mock' +import EditableTable from '@/test/mocks/editable-table-mock' const COLUMNS: Column[] = [ { @@ -94,9 +94,11 @@ const AUTO_COMPLETE_SUGGESTIONS = [ { label: 'some values', value: '5000' }, { label: 'any values', value: '12' } ] + beforeEach(() => { // prevent
cannot appear as a child of
warning on console const spy = jest.spyOn(console, 'error') + spy.mockImplementation(jest.fn()) }) @@ -475,8 +477,7 @@ describe('EditableTable', () => { expect(onClickAddSpy).toHaveBeenCalled() }) - // eslint-disable-next-line max-len - it('should render with no autoCompleteSuggestions not have add button', async () => { + it('should render with no autoCompleteSuggestions no add button', async () => { const onClickAddSpy = jest .fn() .mockImplementation(() => Promise.resolve()) @@ -544,6 +545,6 @@ describe('EditableTable', () => { const textInput = screen.getAllByTestId('text-field')[0] expect(dateInput.parentElement?.classList).toContain('Mui-error') - expect(textInput?.classList).toContain('Mui-error') + expect(textInput.classList).toContain('Mui-error') }) }) diff --git a/src/core/data-display/editable-table/index.tsx b/src/core/data-display/editable-table/index.tsx index 45a84436..5ce49e8e 100644 --- a/src/core/data-display/editable-table/index.tsx +++ b/src/core/data-display/editable-table/index.tsx @@ -1,9 +1,9 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable max-lines */ import React, { forwardRef, useRef } from 'react' +import type { MouseEvent } from 'react' +import ptBRLocale from 'date-fns/locale/pt-BR' import MaterialTable, { - Column, - Options, MTableEditRow, MTableBodyRow, MTableEditField, @@ -11,6 +11,16 @@ import MaterialTable, { MTablePagination, MTableActions } from 'material-table' +import { omit, contains, propOr } from 'ramda' +import { default as styled } from 'styled-components' +import type { Column, Options } from 'material-table' +import ListItem from '@/core/data-display/list-item' +import { Typography } from '@/core/data-display/typography' +import { AutoComplete } from '@/core/inputs/auto-complete' +import { Button } from '@/core/inputs/button' +import { DateTime } from '@/core/inputs/date-time' +import { MaskField } from '@/core/inputs/mask-field' +import { TextField } from '@/core/inputs/text-field' import { NoteAdd as IconAdd, Done as IconDone, @@ -22,16 +32,6 @@ import { FirstPage as IconFirstPage, LastPage } from '@/icons' -import Typography from '@/core/data-display/typography' -import { omit, contains, propOr } from 'ramda' -import styled from 'styled-components' -import Button from '@/core/inputs/button' -import DateTime from '@/core/inputs/date-time' -import ptBRLocale from 'date-fns/locale/pt-BR' -import AutoComplete from '@/core/inputs/auto-complete' -import ListItem from '@/core/data-display/list-item' -import TextField from '@/core/inputs/text-field' -import MaskField from '@/core/inputs/mask-field' import { getLocalization } from '@/lib/localization' export interface EditableTableProps { @@ -87,7 +87,7 @@ export interface EditableTableProps { * The input value */ value?: string - onRowClick?: (event?: React.MouseEvent, rowData?: T) => void + onRowClick?: (event?: MouseEvent, rowData?: T) => void onUpdateRow?: (newData: object, oldData?: object) => Promise onDeleteRow?: (newData: object, oldData?: object) => Promise onAddRow?: (oldData: object) => Promise @@ -152,6 +152,7 @@ const Wrapper = styled.div` justify-content: flex-end; } ` + export const EditableTable = ( props: EditableTableProps ) => { @@ -213,7 +214,6 @@ export const EditableTable = ( selectTextOnFocus data-testid='autocomplete-container' value={inputProps.value} - onChange={inputProps.onChange} suggestions={propOr([], 'autoCompleteSuggestions', props)} renderSuggestion={(item: TSuggestion, props, selected) => ( @@ -241,13 +241,13 @@ export const EditableTable = ( ) } + onChange={inputProps.onChange} /> ) return (
, Row: props => , @@ -441,6 +441,7 @@ export const EditableTable = ( onRowAddCancelled: props.onRowAddCancelled, onRowUpdateCancelled: props.onRowUpdateCancelled }} + onRowClick={props.onRowClick} />
) diff --git a/src/core/data-display/fab/fab.spec.tsx b/src/core/data-display/fab/fab.spec.tsx index 775f8116..281feac4 100644 --- a/src/core/data-display/fab/fab.spec.tsx +++ b/src/core/data-display/fab/fab.spec.tsx @@ -1,6 +1,6 @@ import * as React from 'react' import { render, screen } from '@testing-library/react' -import Fab from '.' +import { Fab } from '.' describe('Fab', () => { it('should render', () => { @@ -41,6 +41,7 @@ describe('Fab', () => { <>Fab ) + expect(container).toMatchSnapshot() }) }) diff --git a/src/core/data-display/fab/fab.stories.tsx b/src/core/data-display/fab/fab.stories.tsx index 816d75e5..0832d7a8 100644 --- a/src/core/data-display/fab/fab.stories.tsx +++ b/src/core/data-display/fab/fab.stories.tsx @@ -1,6 +1,6 @@ import React from 'react' -import { Meta, StoryFn } from '@storybook/react' -import Fab from '.' +import type { Meta, StoryFn } from '@storybook/react' +import { Fab } from '.' export default { title: 'DataDisplay/Fab', @@ -8,6 +8,7 @@ export default { } as Meta const Template: StoryFn = args => + export const Default = Template.bind({}) Default.args = { diff --git a/src/core/data-display/fab/index.tsx b/src/core/data-display/fab/index.tsx index 0ed27ba0..e03bfb80 100644 --- a/src/core/data-display/fab/index.tsx +++ b/src/core/data-display/fab/index.tsx @@ -1,10 +1,12 @@ -import { Fab as MuiFab, FabProps as MuiFabProps } from '@material-ui/core' -import React, { MouseEvent } from 'react' -import { DefaultProps } from '../../types' +import React from 'react' +import type { MouseEvent, ReactElement } from 'react' +import { Fab as MuiFab } from '@material-ui/core' +import type { DefaultProps } from '../../types' +import type { FabProps as MuiFabProps } from '@material-ui/core' export interface FabProps extends DefaultProps, MuiFabProps { onClick?: (event?: MouseEvent) => void - children: React.ReactElement> + children: ReactElement> } export const Fab = ({ diff --git a/src/core/data-display/line/index.tsx b/src/core/data-display/line/index.tsx index 48a52c23..65975076 100644 --- a/src/core/data-display/line/index.tsx +++ b/src/core/data-display/line/index.tsx @@ -1,5 +1,5 @@ import React from 'react' -import { DefaultProps } from '../../types' +import type { DefaultProps } from '../../types' import { theme } from '@/theme' const { grays, secondary } = theme.colors diff --git a/src/core/data-display/line/line.spec.tsx b/src/core/data-display/line/line.spec.tsx index cdd18542..0532940c 100644 --- a/src/core/data-display/line/line.spec.tsx +++ b/src/core/data-display/line/line.spec.tsx @@ -1,6 +1,6 @@ import * as React from 'react' import { render, screen } from '@testing-library/react' -import Line from '.' +import { Line } from '.' import { theme } from '@/theme' const { grays, secondary } = theme.colors @@ -37,7 +37,7 @@ describe('Line', () => { }) it('should render with color primary', () => { - render() + render() const element = screen.getByTestId('line-component') @@ -49,6 +49,7 @@ describe('Line', () => { it('should match snapshot', () => { const { container } = render() + expect(container).toMatchSnapshot() }) }) diff --git a/src/core/data-display/line/line.stories.tsx b/src/core/data-display/line/line.stories.tsx index 3b201c6b..0210fd27 100644 --- a/src/core/data-display/line/line.stories.tsx +++ b/src/core/data-display/line/line.stories.tsx @@ -1,6 +1,6 @@ import React from 'react' -import { Meta, StoryFn } from '@storybook/react' -import Line from '.' +import type { Meta, StoryFn } from '@storybook/react' +import { Line } from '.' export default { title: 'DataDisplay/Line', diff --git a/src/core/data-display/list-item/index.tsx b/src/core/data-display/list-item/index.tsx index 250a6cf2..7c31d106 100644 --- a/src/core/data-display/list-item/index.tsx +++ b/src/core/data-display/list-item/index.tsx @@ -1,18 +1,19 @@ +import type { MouseEvent } from 'react' +import React, { Fragment } from 'react' import { ListItem as MuiListItem, ListItemAvatar as MuiListItemAvatar, ListItemIcon as MuiListItemIcon, ListItemSecondaryAction as MuiListItemSecondaryAction, ListItemText as MuiListItemText, - MenuItem, - Theme + MenuItem } from '@material-ui/core' import { makeStyles } from '@material-ui/core/styles' -import React, { Fragment, MouseEvent } from 'react' -import { DefaultProps } from '../../types' -import { Omit } from 'ramda' +import type { DefaultProps } from '../../types' +import type { Theme } from '@material-ui/core' +import type { Omit } from 'ramda' -interface ListItemProps extends Omit { +export interface ListItemProps extends Omit { avatar?: JSX.Element icon?: JSX.Element action?: JSX.Element diff --git a/src/core/data-display/list/index.tsx b/src/core/data-display/list/index.tsx index 479eed9b..7eb43083 100644 --- a/src/core/data-display/list/index.tsx +++ b/src/core/data-display/list/index.tsx @@ -1,10 +1,11 @@ +import React from 'react' import { List as MuiList, ListSubheader as MuiListHeader } from '@material-ui/core' -import { makeStyles, createStyles, Theme } from '@material-ui/core/styles' -import React from 'react' -import { DefaultProps } from '../../types' +import { makeStyles, createStyles } from '@material-ui/core/styles' +import type { DefaultProps } from '../../types' +import type { Theme } from '@material-ui/core/styles' export interface ListProps extends DefaultProps { /** diff --git a/src/core/data-display/list/list.spec.tsx b/src/core/data-display/list/list.spec.tsx index 924f05bf..86e849f1 100644 --- a/src/core/data-display/list/list.spec.tsx +++ b/src/core/data-display/list/list.spec.tsx @@ -1,7 +1,7 @@ import * as React from 'react' import { render, screen } from '@testing-library/react' -import List from '.' import ListItem from '@/core/data-display/list-item' +import { List } from '.' describe('List', () => { it('should render', () => { diff --git a/src/core/data-display/list/list.stories.tsx b/src/core/data-display/list/list.stories.tsx index 6a19d66f..d2673a7f 100644 --- a/src/core/data-display/list/list.stories.tsx +++ b/src/core/data-display/list/list.stories.tsx @@ -1,9 +1,9 @@ import React from 'react' -import { Meta, StoryFn } from '@storybook/react' -import List from '.' +import type { Meta, StoryFn } from '@storybook/react' import ListItem from '@/core/data-display/list-item' -import { Backup } from '../../../icons' -import Avatar from '../avatar' +import { Backup } from '@/icons' +import { Avatar } from '../avatar' +import { List } from '.' export default { title: 'DataDisplay/List', diff --git a/src/core/data-display/menu-item/index.tsx b/src/core/data-display/menu-item/index.tsx index 906d2edd..073d9af8 100644 --- a/src/core/data-display/menu-item/index.tsx +++ b/src/core/data-display/menu-item/index.tsx @@ -1,10 +1,11 @@ -import React, { MouseEvent } from 'react' -import { DefaultProps } from '../../types' -import { Omit } from 'ramda' -import styled from 'styled-components' +import React from 'react' +import type { MouseEvent, MutableRefObject } from 'react' import { MenuItem as MuiMenuItem } from '@mui/material' -import { MenuItemClassKey } from '@material-ui/core/MenuItem' -import { ClassNameMap } from '@material-ui/core/styles/withStyles' +import { default as styled } from 'styled-components' +import type { DefaultProps } from '../../types' +import type { MenuItemClassKey } from '@material-ui/core/MenuItem' +import type { ClassNameMap } from '@material-ui/core/styles/withStyles' +import type { Omit } from 'ramda' export interface ListItemProps extends Omit { title?: string @@ -13,7 +14,7 @@ export interface ListItemProps extends Omit { disabled?: boolean onClick?: (event?: MouseEvent) => void children?: string - ref?: React.MutableRefObject + ref?: MutableRefObject classes?: Partial> | undefined } diff --git a/src/core/data-display/node/index.tsx b/src/core/data-display/node/index.tsx index 5ac86692..2ed08184 100644 --- a/src/core/data-display/node/index.tsx +++ b/src/core/data-display/node/index.tsx @@ -1,6 +1,6 @@ -import React from 'react' -import styled from 'styled-components' -import { DefaultProps } from '../../types' +import React, { useState } from 'react' +import { default as styled } from 'styled-components' +import type { DefaultProps } from '../../types' import { KeyboardArrowDown as IconArrowDown, KeyboardArrowUp as IconArrowUp @@ -48,7 +48,7 @@ const Li = styled.li` ` export const Node = (props: NodeProps) => { - const [open, setOpen] = React.useState(false) + const [open, setOpen] = useState(false) const { id, name, children, style = {}, className } = props const handleToggleOpen = () => { diff --git a/src/core/data-display/node/node.spec.tsx b/src/core/data-display/node/node.spec.tsx index 12a27adc..56128e7d 100644 --- a/src/core/data-display/node/node.spec.tsx +++ b/src/core/data-display/node/node.spec.tsx @@ -1,8 +1,8 @@ import * as React from 'react' -import { render, screen } from '@testing-library/react' -import Node from '.' -import userEvent from '@testing-library/user-event' import { act } from 'react-dom/test-utils' +import { render, screen } from '@testing-library/react' +import { userEvent } from '@testing-library/user-event' +import { Node } from '.' describe('Node', () => { it('should render', () => { diff --git a/src/core/data-display/node/node.stories.tsx b/src/core/data-display/node/node.stories.tsx index 1ca6a4b5..7bd74b41 100644 --- a/src/core/data-display/node/node.stories.tsx +++ b/src/core/data-display/node/node.stories.tsx @@ -1,6 +1,6 @@ import React from 'react' -import { Meta, StoryFn } from '@storybook/react' -import Node from '.' +import type { Meta, StoryFn } from '@storybook/react' +import { Node } from '.' export default { title: 'DataDisplay/Node', diff --git a/src/core/data-display/table/index.tsx b/src/core/data-display/table/index.tsx index d10e5040..48298753 100644 --- a/src/core/data-display/table/index.tsx +++ b/src/core/data-display/table/index.tsx @@ -1,6 +1,7 @@ -import MuiTable, { TableProps as MuiTableProps } from '@material-ui/core/Table' import React from 'react' -import { DefaultProps } from '../../types' +import MuiTable from '@material-ui/core/Table' +import type { DefaultProps } from '../../types' +import type { TableProps as MuiTableProps } from '@material-ui/core/Table' import { theme } from '@/theme' const { grays } = theme.colors diff --git a/src/core/data-display/table/table-body.tsx b/src/core/data-display/table/table-body.tsx index c6b8eefe..51fa2d16 100644 --- a/src/core/data-display/table/table-body.tsx +++ b/src/core/data-display/table/table-body.tsx @@ -1,6 +1,6 @@ -import MuiTableBody from '@material-ui/core/TableBody' import React from 'react' -import { DefaultProps } from '../../types' +import MuiTableBody from '@material-ui/core/TableBody' +import type { DefaultProps } from '../../types' const TableBody = ({ style, diff --git a/src/core/data-display/table/table-cell.tsx b/src/core/data-display/table/table-cell.tsx index 89dfd983..a93971b7 100644 --- a/src/core/data-display/table/table-cell.tsx +++ b/src/core/data-display/table/table-cell.tsx @@ -1,16 +1,15 @@ -import MuiTableCell, { - TableCellProps as MuiTableCellProps -} from '@material-ui/core/TableCell' -import MuiTableSortLabel from '@material-ui/core/TableSortLabel' import React, { useContext } from 'react' -import { DefaultProps } from '../../types' -import { Omit } from 'ramda' +import MuiTableCell from '@material-ui/core/TableCell' +import MuiTableSortLabel from '@material-ui/core/TableSortLabel' +import type { DefaultProps } from '../../types' +import type { TableCellProps as MuiTableProps } from '@material-ui/core/TableCell' +import type { Omit } from 'ramda' import { SortContext } from './table-head' interface TableCellProps extends DefaultProps { numeric?: boolean variant?: 'head' | 'body' | 'footer' - spacing?: MuiTableCellProps['padding'] + spacing?: MuiTableProps['padding'] padding?: number | string align?: 'inherit' | 'left' | 'center' | 'right' | 'justify' } @@ -22,7 +21,7 @@ const TableCell = ({ children, spacing, ...otherProps -}: Omit & TableCellProps) => { +}: Omit & TableCellProps) => { const { onSort, active, direction } = useContext(SortContext) const handleSort = () => { @@ -38,9 +37,9 @@ const TableCell = ({ padding={spacing}> {onSort ? ( + direction={direction} + onClick={handleSort}> {children} ) : ( diff --git a/src/core/data-display/table/table-head.tsx b/src/core/data-display/table/table-head.tsx index c1e136cb..d57ca8bf 100644 --- a/src/core/data-display/table/table-head.tsx +++ b/src/core/data-display/table/table-head.tsx @@ -1,7 +1,7 @@ +import React, { createContext } from 'react' import { withStyles } from '@material-ui/core/styles' import MuiTableHead from '@material-ui/core/TableHead' -import React, { createContext } from 'react' -import { DefaultProps } from '../../types' +import type { DefaultProps } from '../../types' interface TableHeadProps extends DefaultProps, ISort { color?: 'primary' | 'secondary' | 'default' | 'inherit' diff --git a/src/core/data-display/table/table-row.tsx b/src/core/data-display/table/table-row.tsx index 7d62f5fb..15433123 100644 --- a/src/core/data-display/table/table-row.tsx +++ b/src/core/data-display/table/table-row.tsx @@ -1,8 +1,8 @@ -import React, { MouseEvent } from 'react' -import { DefaultProps } from '../../types' -import MuiTableRow, { - TableRowProps as MuiTableRowProps -} from '@material-ui/core/TableRow' +import type { MouseEvent } from 'react' +import React from 'react' +import MuiTableRow from '@material-ui/core/TableRow' +import type { DefaultProps } from '../../types' +import type { TableRowProps as MuiTableRowProps } from '@material-ui/core/TableRow' import { theme } from '@/theme' const { grays } = theme.colors diff --git a/src/core/data-display/table/table.spec.tsx b/src/core/data-display/table/table.spec.tsx index 11676ac4..b88b9868 100644 --- a/src/core/data-display/table/table.spec.tsx +++ b/src/core/data-display/table/table.spec.tsx @@ -1,12 +1,12 @@ import * as React from 'react' +import { act } from 'react-dom/test-utils' import { render } from '@testing-library/react' -import Table from '.' -import TableHead from './table-head' +import { userEvent } from '@testing-library/user-event' import TableBody from './table-body' -import TableRow from './table-row' import TableCell from './table-cell' -import userEvent from '@testing-library/user-event' -import { act } from 'react-dom/test-utils' +import TableHead from './table-head' +import TableRow from './table-row' +import { Table } from '.' interface IProps { onSort?: (name: string) => void diff --git a/src/core/data-display/table/table.stories.tsx b/src/core/data-display/table/table.stories.tsx index 1802abdc..3321758a 100644 --- a/src/core/data-display/table/table.stories.tsx +++ b/src/core/data-display/table/table.stories.tsx @@ -1,10 +1,10 @@ import React from 'react' -import { Meta, StoryFn } from '@storybook/react' -import Table from '.' -import TableHead from './table-head' +import type { Meta, StoryFn } from '@storybook/react' import TableBody from './table-body' -import TableRow from './table-row' import TableCell from './table-cell' +import TableHead from './table-head' +import TableRow from './table-row' +import { Table } from '.' export default { title: 'DataDisplay/Table', diff --git a/src/core/data-display/tree/index.tsx b/src/core/data-display/tree/index.tsx index a0d4d327..42f78307 100644 --- a/src/core/data-display/tree/index.tsx +++ b/src/core/data-display/tree/index.tsx @@ -1,6 +1,7 @@ -import { omit } from 'ramda' import React from 'react' -import Node from '../node' +import type { ReactNode } from 'react' +import { omit } from 'ramda' +import { Node } from '../node' export interface INode { id: string | number @@ -17,7 +18,7 @@ export const Tree = ({ nodes = [], ...otherProps }: TreeProps): JSX.Element => { node: INode, index: string, root = false - ): React.ReactNode => { + ): ReactNode => { const { id, name, nodes } = node return ( @@ -26,13 +27,9 @@ export const Tree = ({ nodes = [], ...otherProps }: TreeProps): JSX.Element => { name={name} key={id || index} style={root ? { padding: 0 } : {}}> - {nodes && - nodes.map(node => { - return renderNode( - omit(['array'], node), - index.toString() - ) - })} + {nodes?.map(node => { + return renderNode(omit(['array'], node), index.toString()) + })} ) } diff --git a/src/core/data-display/tree/tree.spec.tsx b/src/core/data-display/tree/tree.spec.tsx index acaf5615..3c5ad55b 100644 --- a/src/core/data-display/tree/tree.spec.tsx +++ b/src/core/data-display/tree/tree.spec.tsx @@ -1,8 +1,8 @@ import * as React from 'react' -import { render, screen } from '@testing-library/react' -import Tree from '.' -import userEvent from '@testing-library/user-event' import { act } from 'react-dom/test-utils' +import { render, screen } from '@testing-library/react' +import { userEvent } from '@testing-library/user-event' +import { Tree } from '.' describe('Tree', () => { const NODES = [ diff --git a/src/core/data-display/tree/tree.stories.tsx b/src/core/data-display/tree/tree.stories.tsx index 176dfd3c..51c70900 100644 --- a/src/core/data-display/tree/tree.stories.tsx +++ b/src/core/data-display/tree/tree.stories.tsx @@ -1,6 +1,6 @@ import React from 'react' -import { Meta, StoryFn } from '@storybook/react' -import Tree from '.' +import type { Meta, StoryFn } from '@storybook/react' +import { Tree } from '.' export default { title: 'DataDisplay/Tree', diff --git a/src/core/data-display/typography/index.tsx b/src/core/data-display/typography/index.tsx index c1ecb096..1d02bc3f 100644 --- a/src/core/data-display/typography/index.tsx +++ b/src/core/data-display/typography/index.tsx @@ -1,6 +1,7 @@ import React from 'react' -import { DefaultProps } from '../../types' -import MuiTypography, { TypographyProps } from '@material-ui/core/Typography' +import MuiTypography from '@material-ui/core/Typography' +import type { DefaultProps } from '../../types' +import type { TypographyProps } from '@material-ui/core/Typography' export const Typography = ({ children, diff --git a/src/core/data-display/typography/typography.spec.tsx b/src/core/data-display/typography/typography.spec.tsx index 81a55607..8a0f6340 100644 --- a/src/core/data-display/typography/typography.spec.tsx +++ b/src/core/data-display/typography/typography.spec.tsx @@ -1,6 +1,6 @@ import * as React from 'react' import { render, screen } from '@testing-library/react' -import Typography from '.' +import { Typography } from '.' describe('Typography', () => { it('should render with no variant', () => { diff --git a/src/core/data-display/typography/typography.stories.tsx b/src/core/data-display/typography/typography.stories.tsx index 81bcfa8c..6b5080ce 100644 --- a/src/core/data-display/typography/typography.stories.tsx +++ b/src/core/data-display/typography/typography.stories.tsx @@ -1,6 +1,6 @@ import React from 'react' -import { Meta, StoryFn } from '@storybook/react' -import Typography from '.' +import type { Meta, StoryFn } from '@storybook/react' +import { Typography } from '.' export default { title: 'DataDisplay/Typography', diff --git a/src/core/feedback/collapse/collapse.spec.tsx b/src/core/feedback/collapse/collapse.spec.tsx index 47c06ab0..89c07341 100644 --- a/src/core/feedback/collapse/collapse.spec.tsx +++ b/src/core/feedback/collapse/collapse.spec.tsx @@ -1,11 +1,11 @@ import * as React from 'react' import { render, screen } from '@testing-library/react' -import Collapse from '.' +import { Collapse } from '.' describe('Collapse', () => { it('should render opened', () => { render( - + I am open for discussions ) diff --git a/src/core/feedback/collapse/collapse.stories.tsx b/src/core/feedback/collapse/collapse.stories.tsx index 090b059c..025e712b 100644 --- a/src/core/feedback/collapse/collapse.stories.tsx +++ b/src/core/feedback/collapse/collapse.stories.tsx @@ -1,7 +1,7 @@ import React, { useState } from 'react' -import { Meta, StoryFn } from '@storybook/react' -import Collapse from '.' -import Button from '@/core/inputs/button' +import type { Meta, StoryFn } from '@storybook/react' +import { Button } from '@/core/inputs/button' +import { Collapse } from '.' export default { title: 'Feedback/Collapse', diff --git a/src/core/feedback/collapse/index.tsx b/src/core/feedback/collapse/index.tsx index 41c669b0..61c4c0ec 100644 --- a/src/core/feedback/collapse/index.tsx +++ b/src/core/feedback/collapse/index.tsx @@ -1,12 +1,13 @@ -import { Collapse as MuiCollapse } from '@material-ui/core' import React from 'react' -import { DefaultProps } from '../../types' +import type { ReactNode } from 'react' +import { Collapse as MuiCollapse } from '@material-ui/core' +import type { DefaultProps } from '../../types' export interface CollapseProps extends DefaultProps { collapsedHeight?: string in: boolean timeout?: number | { enter?: number; exit?: number } | 'auto' - children?: React.ReactNode + children?: ReactNode } export const Collapse = ({ diff --git a/src/core/feedback/dialog/dialog.spec.tsx b/src/core/feedback/dialog/dialog.spec.tsx index 09a18c1e..e529d19a 100644 --- a/src/core/feedback/dialog/dialog.spec.tsx +++ b/src/core/feedback/dialog/dialog.spec.tsx @@ -1,7 +1,7 @@ import * as React from 'react' import { render, screen } from '@testing-library/react' -import Dialog from '.' -import Button from '@/core/inputs/button' +import { Button } from '@/core/inputs/button' +import { Dialog } from '.' describe('Dialog', () => { it('should render opened', () => { @@ -10,8 +10,8 @@ describe('Dialog', () => { open title='My beautiful Dialog' text={'Is not it?'} - onClose={jest.fn()} actions={} + onClose={jest.fn()} /> ) @@ -30,9 +30,9 @@ describe('Dialog', () => { open title='My beautiful Dialog' text={'Is not it?'} - onClose={jest.fn()} actions={} snippet='Snippet' + onClose={jest.fn()} /> ) @@ -53,7 +53,6 @@ describe('Dialog', () => { open title='My beautiful Dialog' text={'Is not it?'} - onClose={jest.fn()} actions={} titleAction={ } + onClose={jest.fn()} /> ) @@ -75,9 +75,9 @@ describe('Dialog', () => { Close} content={
Content
} + onClose={jest.fn()} /> ) @@ -97,9 +97,9 @@ describe('Dialog', () => { aria-title='dialog-paper' title='My beautiful Dialog' text={'Is not it?'} - onClose={jest.fn()} actions={} scroll='body' + onClose={jest.fn()} /> ) @@ -118,9 +118,9 @@ describe('Dialog', () => { aria-title='dialog-paper' title='My beautiful Dialog' text={'Is not it?'} - onClose={jest.fn()} actions={} scroll='unset-body' + onClose={jest.fn()} /> ) @@ -139,9 +139,9 @@ describe('Dialog', () => { aria-title='dialog-paper' title='My beautiful Dialog' text={'Is not it?'} - onClose={jest.fn()} actions={} scroll='paper' + onClose={jest.fn()} /> ) @@ -160,9 +160,9 @@ describe('Dialog', () => { aria-title='dialog-paper' title='My beautiful Dialog' text={'Is not it?'} - onClose={jest.fn()} actions={} scroll='unset-paper' + onClose={jest.fn()} /> ) diff --git a/src/core/feedback/dialog/dialog.stories.tsx b/src/core/feedback/dialog/dialog.stories.tsx index 8dfb7406..7222ee0d 100644 --- a/src/core/feedback/dialog/dialog.stories.tsx +++ b/src/core/feedback/dialog/dialog.stories.tsx @@ -1,8 +1,8 @@ import React, { useState } from 'react' -import { Meta } from '@storybook/react' -import Dialog from '.' -import Button from '@/core/inputs/button' -import Typography from '@/core/data-display/typography' +import type { Meta } from '@storybook/react' +import { Typography } from '@/core/data-display/typography' +import { Button } from '@/core/inputs/button' +import { Dialog } from '.' export default { title: 'Feedback/Dialog', @@ -19,10 +19,10 @@ export const Default = () => { open={open} title='My beautiful Dialog' text={'Is not it?'} - onClose={() => setOpen(false)} actions={ } + onClose={() => setOpen(false)} /> ) @@ -42,10 +42,10 @@ export const WithAlertOnClose = () => { open={open} title='My beautiful Dialog' text={'Is not it?'} - onClose={handleClose} actions={ } + onClose={handleClose} /> ) @@ -65,10 +65,10 @@ export const WithTypography = () => { } text='Simple Text' - onClose={() => setOpen(false)} actions={ } + onClose={() => setOpen(false)} /> ) @@ -84,11 +84,11 @@ export const WithSnippet = () => { open={open} title='My beautiful Dialog' text={'Is not it?'} - onClose={() => setOpen(false)} actions={ } snippet='const a = 1' + onClose={() => setOpen(false)} /> ) diff --git a/src/core/feedback/dialog/index.tsx b/src/core/feedback/dialog/index.tsx index fa4f77be..f3c6a9b2 100644 --- a/src/core/feedback/dialog/index.tsx +++ b/src/core/feedback/dialog/index.tsx @@ -1,13 +1,14 @@ +import type { CSSProperties, ReactNode } from 'react' +import React from 'react' import MuiDialog from '@material-ui/core/Dialog' -import { DialogProps as MuiDialogProps } from '@material-ui/core' import MuiDialogActions from '@material-ui/core/DialogActions' import MuiDialogContent from '@material-ui/core/DialogContent' import MuiDialogContentText from '@material-ui/core/DialogContentText' import MuiDialogTitle from '@material-ui/core/DialogTitle' -import React, { CSSProperties, ReactNode } from 'react' -import { DefaultProps } from '../../types' import { makeStyles } from '@material-ui/core/styles' -import styled from 'styled-components' +import { default as styled } from 'styled-components' +import type { DefaultProps } from '../../types' +import type { DialogProps as MuiDialogProps } from '@material-ui/core' export interface DialogProps extends DefaultProps, diff --git a/src/core/feedback/fade/fade.spec.tsx b/src/core/feedback/fade/fade.spec.tsx index 98aa8beb..3bc97a0a 100644 --- a/src/core/feedback/fade/fade.spec.tsx +++ b/src/core/feedback/fade/fade.spec.tsx @@ -1,6 +1,6 @@ import * as React from 'react' import { render, screen } from '@testing-library/react' -import Fade from '.' +import { Fade } from '.' describe('Fade', () => { it('should render closed', () => { diff --git a/src/core/feedback/fade/fade.stories.tsx b/src/core/feedback/fade/fade.stories.tsx index 13a35367..4debee40 100644 --- a/src/core/feedback/fade/fade.stories.tsx +++ b/src/core/feedback/fade/fade.stories.tsx @@ -1,7 +1,7 @@ import React, { useState } from 'react' -import { Meta } from '@storybook/react' -import Fade from '.' -import Button from '@/core/inputs/button' +import type { Meta } from '@storybook/react' +import { Button } from '@/core/inputs/button' +import { Fade } from '.' export default { title: 'Feedback/Fade', diff --git a/src/core/feedback/fade/index.tsx b/src/core/feedback/fade/index.tsx index 46657771..5413a9ba 100644 --- a/src/core/feedback/fade/index.tsx +++ b/src/core/feedback/fade/index.tsx @@ -1,11 +1,12 @@ -import { Fade as MuiFade } from '@material-ui/core' import React from 'react' -import { DefaultProps } from '../../types' +import type { ReactElement } from 'react' +import { Fade as MuiFade } from '@material-ui/core' +import type { DefaultProps } from '../../types' export interface FadeProps extends DefaultProps { in: boolean timeout?: number | { enter?: number; exit?: number } - children: React.ReactElement> + children: ReactElement> } export const Fade = ({ diff --git a/src/core/feedback/grow/grow.spec.tsx b/src/core/feedback/grow/grow.spec.tsx index 315e7158..bd9258f6 100644 --- a/src/core/feedback/grow/grow.spec.tsx +++ b/src/core/feedback/grow/grow.spec.tsx @@ -1,6 +1,6 @@ import * as React from 'react' import { render, screen } from '@testing-library/react' -import Grow from '.' +import { Grow } from '.' describe('Grow', () => { it('should render closed', () => { diff --git a/src/core/feedback/grow/grow.stories.tsx b/src/core/feedback/grow/grow.stories.tsx index e9d62efc..b7a3599d 100644 --- a/src/core/feedback/grow/grow.stories.tsx +++ b/src/core/feedback/grow/grow.stories.tsx @@ -1,7 +1,7 @@ import React, { useState } from 'react' -import { Meta } from '@storybook/react' -import Grow from '.' -import Button from '@/core/inputs/button' +import type { Meta } from '@storybook/react' +import { Button } from '@/core/inputs/button' +import { Grow } from '.' export default { title: 'Feedback/Grow', @@ -25,8 +25,8 @@ export const Default = () => { diff --git a/src/core/feedback/grow/index.tsx b/src/core/feedback/grow/index.tsx index f8532bcb..518d0587 100644 --- a/src/core/feedback/grow/index.tsx +++ b/src/core/feedback/grow/index.tsx @@ -1,11 +1,12 @@ -import { Grow as MuiGrow } from '@material-ui/core' import React from 'react' -import { DefaultProps } from '../../types' +import type { ReactElement } from 'react' +import { Grow as MuiGrow } from '@material-ui/core' +import type { DefaultProps } from '../../types' export interface GrowProps extends DefaultProps { in: boolean timeout?: number | { enter?: number; exit?: number } | 'auto' - children?: React.ReactElement> + children?: ReactElement> } export const Grow = ({ diff --git a/src/core/feedback/progress/index.tsx b/src/core/feedback/progress/index.tsx index c247488c..6f8ed938 100644 --- a/src/core/feedback/progress/index.tsx +++ b/src/core/feedback/progress/index.tsx @@ -1,9 +1,9 @@ +import React from 'react' import { CircularProgress as MuiCircularProgress, LinearProgress as MuiLinearProgress } from '@material-ui/core' -import React from 'react' -import { DefaultProps } from '../../types' +import type { DefaultProps } from '../../types' export interface ILinear { color?: 'primary' | 'secondary' diff --git a/src/core/feedback/progress/progress.spec.tsx b/src/core/feedback/progress/progress.spec.tsx index e042eb9b..a5f5df49 100644 --- a/src/core/feedback/progress/progress.spec.tsx +++ b/src/core/feedback/progress/progress.spec.tsx @@ -1,6 +1,6 @@ import * as React from 'react' import { render, screen } from '@testing-library/react' -import Progress from '.' +import { Progress } from '.' describe('Progress', () => { it('should render circular', () => { diff --git a/src/core/feedback/progress/progress.stories.tsx b/src/core/feedback/progress/progress.stories.tsx index 8ec1c924..67c88e34 100644 --- a/src/core/feedback/progress/progress.stories.tsx +++ b/src/core/feedback/progress/progress.stories.tsx @@ -1,6 +1,6 @@ import React from 'react' -import { Meta, StoryFn } from '@storybook/react' -import Progress from '.' +import type { Meta, StoryFn } from '@storybook/react' +import { Progress } from '.' export default { title: 'Feedback/Progress', diff --git a/src/core/feedback/slide/index.tsx b/src/core/feedback/slide/index.tsx index ee50f4a7..06508eaa 100644 --- a/src/core/feedback/slide/index.tsx +++ b/src/core/feedback/slide/index.tsx @@ -1,12 +1,13 @@ -import { Slide as MuiSlide } from '@material-ui/core' import React from 'react' -import { DefaultProps } from '../../types' +import type { ReactElement } from 'react' +import { Slide as MuiSlide } from '@material-ui/core' +import type { DefaultProps } from '../../types' export interface SlideProps extends DefaultProps { in: boolean direction: 'left' | 'right' | 'up' | 'down' timeout?: number | { enter?: number; exit?: number } - children?: React.ReactElement> + children?: ReactElement> } export const Slide = ({ diff --git a/src/core/feedback/slide/slide.spec.tsx b/src/core/feedback/slide/slide.spec.tsx index 66cf398d..8828850d 100644 --- a/src/core/feedback/slide/slide.spec.tsx +++ b/src/core/feedback/slide/slide.spec.tsx @@ -1,6 +1,6 @@ import * as React from 'react' import { render, screen } from '@testing-library/react' -import Slide from '.' +import { Slide } from '.' describe('Slide', () => { it('should render closed', () => { @@ -16,7 +16,7 @@ describe('Slide', () => { it('should render opened', () => { render( - + Slide Text ) @@ -28,7 +28,7 @@ describe('Slide', () => { it('should match snapshot', () => { const { container: opened } = render( - + Slide Text ) diff --git a/src/core/feedback/slide/slide.stories.tsx b/src/core/feedback/slide/slide.stories.tsx index 059d893a..5284c134 100644 --- a/src/core/feedback/slide/slide.stories.tsx +++ b/src/core/feedback/slide/slide.stories.tsx @@ -1,7 +1,7 @@ import React, { useState } from 'react' -import { Meta, StoryFn } from '@storybook/react' -import Slide from '.' -import Button from '@/core/inputs/button' +import type { Meta, StoryFn } from '@storybook/react' +import { Button } from '@/core/inputs/button' +import { Slide } from '.' export default { title: 'Feedback/Slide', diff --git a/src/core/feedback/snackbar/index.tsx b/src/core/feedback/snackbar/index.tsx index e4a09474..b2feab3d 100644 --- a/src/core/feedback/snackbar/index.tsx +++ b/src/core/feedback/snackbar/index.tsx @@ -1,20 +1,22 @@ +import type { ReactNode, FunctionComponent, MouseEvent } from 'react' +import React from 'react' import { IconButton as MuiIconButton, Snackbar as MuiSnackbar, SnackbarContent as MuiSnackbarContent } from '@material-ui/core' import { amber, blue, green, red } from '@material-ui/core/colors' -import { makeStyles, createStyles, Theme } from '@material-ui/core/styles' +import { makeStyles, createStyles } from '@material-ui/core/styles' +import type { DefaultProps } from '../../types' +import type { Theme } from '@material-ui/core/styles' +import type { TransitionProps } from '@material-ui/core/transitions/transition' import { CheckCircle as IconCheck, Close as IconClose, Error as IconError, Info as IconInfo, Warning as IconWarning -} from '../../../icons' -import React, { ReactNode, FunctionComponent, MouseEvent } from 'react' -import { DefaultProps } from '../../types' -import { TransitionProps } from '@material-ui/core/transitions/transition' +} from '@/icons' export interface SnackBarProps extends DefaultProps { autoHide?: number diff --git a/src/core/feedback/snackbar/snackbar.spec.tsx b/src/core/feedback/snackbar/snackbar.spec.tsx index 85361db3..d1e913bf 100644 --- a/src/core/feedback/snackbar/snackbar.spec.tsx +++ b/src/core/feedback/snackbar/snackbar.spec.tsx @@ -1,8 +1,8 @@ import * as React from 'react' +import { act } from 'react-dom/test-utils' import { render, screen, waitFor } from '@testing-library/react' +import { userEvent } from '@testing-library/user-event' import Snackbar from '@/test/mocks/snackbar-mock' -import { act } from 'react-dom/test-utils' -import userEvent from '@testing-library/user-event' describe('Snackbar', () => { it('should render a Snackbar', async () => { @@ -15,11 +15,13 @@ describe('Snackbar', () => { }) const message = screen.getByText('Snackbar Message') + expect(message).toBeDefined() }) it('should render with action', async () => { const onClose = jest.fn() + render( { it('should call onClick', async () => { const onClick = jest.fn() + render( { }) it('should call onClose', async () => { const onClose = jest.fn() + render( void diff --git a/src/core/feedback/tooltip/tool-tip.spec.tsx b/src/core/feedback/tooltip/tool-tip.spec.tsx index 05ed0e35..ed5e2504 100644 --- a/src/core/feedback/tooltip/tool-tip.spec.tsx +++ b/src/core/feedback/tooltip/tool-tip.spec.tsx @@ -1,9 +1,9 @@ import * as React from 'react' -import { render, screen } from '@testing-library/react' -import Tooltip from '.' -import userEvent from '@testing-library/user-event' import { act } from 'react-dom/test-utils' import { Button } from '@material-ui/core' +import { render, screen } from '@testing-library/react' +import { userEvent } from '@testing-library/user-event' +import { Tooltip } from '.' describe('Tooltip', () => { it('should render a Tooltip', async () => { diff --git a/src/core/feedback/tooltip/tooltip.stories.tsx b/src/core/feedback/tooltip/tooltip.stories.tsx index 6b1310dc..69f075af 100644 --- a/src/core/feedback/tooltip/tooltip.stories.tsx +++ b/src/core/feedback/tooltip/tooltip.stories.tsx @@ -1,7 +1,7 @@ import React from 'react' -import { Meta, StoryFn } from '@storybook/react' -import Tooltip from '.' -import Button from '@/core/inputs/button' +import type { Meta, StoryFn } from '@storybook/react' +import { Button } from '@/core/inputs/button' +import { Tooltip } from '.' export default { title: 'Feedback/Tooltip', diff --git a/src/core/feedback/validation-dialog/index.tsx b/src/core/feedback/validation-dialog/index.tsx index a931f12e..36a781e3 100644 --- a/src/core/feedback/validation-dialog/index.tsx +++ b/src/core/feedback/validation-dialog/index.tsx @@ -1,9 +1,10 @@ import React from 'react' -import styled from 'styled-components' -import Dialog from '../dialog' -import Button from '@/core/inputs/button' -import Actions from '../../../experimental/actions' -import Typography from '../../data-display/typography' +import type { FC, ReactNode } from 'react' +import { default as styled } from 'styled-components' +import { Typography } from '@/core/data-display/typography' +import { Button } from '@/core/inputs/button' +import { Actions } from '@/experimental/actions' +import { Dialog } from '../dialog' export interface IValidateProps { open: boolean @@ -13,9 +14,9 @@ export interface IValidateProps { responses: string[] validations: IValidations[] icons: { - success: React.ReactNode - error: React.ReactNode - loading: React.ReactNode + success: ReactNode + error: ReactNode + loading: ReactNode } onClose(): void onCancel(): void @@ -40,9 +41,9 @@ export interface IValidations { interface IIcon { status: string icons: { - success: React.ReactNode - error: React.ReactNode - loading: React.ReactNode + success: ReactNode + error: ReactNode + loading: ReactNode } } @@ -71,7 +72,7 @@ const ValidationWrapper = styled.div` gap: 15px; ` -const ValidationDialog: React.FC = ({ +const ValidationDialog: FC = ({ open, failed, success, @@ -133,9 +134,9 @@ const ValidationDialog: React.FC = ({ const renderContent = ( validations: IValidations[], icons: { - success: React.ReactNode - error: React.ReactNode - loading: React.ReactNode + success: ReactNode + error: ReactNode + loading: ReactNode } ) => { return validations.map((item, i) => { diff --git a/src/core/feedback/validation-dialog/validation-dialog.spec.tsx b/src/core/feedback/validation-dialog/validation-dialog.spec.tsx index 680079a3..0a769175 100644 --- a/src/core/feedback/validation-dialog/validation-dialog.spec.tsx +++ b/src/core/feedback/validation-dialog/validation-dialog.spec.tsx @@ -1,8 +1,9 @@ import React from 'react' -import { render, screen, fireEvent } from '@testing-library/react' -import ValidationDialog, { ITitles, ValidationStatus } from '.' import CircularProgress from '@mui/material/CircularProgress' -import { CheckCircleOutline, CancelOutlined } from '../../../icons' +import { render, screen, fireEvent } from '@testing-library/react' +import type { ITitles } from '.' +import { CheckCircleOutline, CancelOutlined } from '@/icons' +import ValidationDialog, { ValidationStatus } from '.' import { theme } from '@/theme' const { action, secondary } = theme.colors @@ -43,7 +44,6 @@ describe('ValidationDialog', () => { { responses={responses} validations={[]} icons={stepsIcons} - onCancel={jest.fn()} handleCreate={jest.fn()} + onClose={jest.fn()} + onCancel={jest.fn()} /> ) const result = renderTitle(stepsTitle, responses) + expect(result).toBe(stepsTitle.loading) }) @@ -68,7 +70,6 @@ describe('ValidationDialog', () => { { responses={responses} validations={[]} icons={stepsIcons} - onCancel={jest.fn()} handleCreate={jest.fn()} + onClose={jest.fn()} + onCancel={jest.fn()} /> ) const result = renderTitle(stepsTitle, responses) + expect(result).toBe(stepsTitle.success) }) @@ -93,7 +96,6 @@ describe('ValidationDialog', () => { { responses={responses} validations={[]} icons={stepsIcons} - onCancel={jest.fn()} handleCreate={jest.fn()} + onClose={jest.fn()} + onCancel={jest.fn()} /> ) const result = renderTitle(stepsTitle, responses) + expect(result).toBe(stepsTitle.loading) }) @@ -118,7 +122,6 @@ describe('ValidationDialog', () => { { responses={responses} validations={[]} icons={stepsIcons} - onCancel={jest.fn()} handleCreate={jest.fn()} + onClose={jest.fn()} + onCancel={jest.fn()} /> ) const result = renderTitle(stepsTitle, responses) + expect(result).toBe(stepsTitle.error) }) @@ -143,7 +148,6 @@ describe('ValidationDialog', () => { { responses={responses} validations={[]} icons={stepsIcons} - onCancel={jest.fn()} handleCreate={jest.fn()} + onClose={jest.fn()} + onCancel={jest.fn()} /> ) const closeButton = screen.getByRole('button', { name: 'Cancelar' }) + fireEvent.click(closeButton) expect(closeButton).toBeDefined() @@ -168,7 +174,6 @@ describe('ValidationDialog', () => { { } ]} icons={stepsIcons} - onCancel={jest.fn()} handleCreate={jest.fn()} + onClose={jest.fn()} + onCancel={jest.fn()} /> ) const successDescription = screen.getByText('Success description') + expect(successDescription).toBeDefined() }) @@ -197,7 +204,6 @@ describe('ValidationDialog', () => { { } ]} icons={stepsIcons} - onCancel={jest.fn()} handleCreate={jest.fn()} + onClose={jest.fn()} + onCancel={jest.fn()} /> ) const errorDescription = screen.getByText('Error description') + expect(errorDescription).toBeDefined() }) @@ -226,7 +234,6 @@ describe('ValidationDialog', () => { { } ]} icons={stepsIcons} - onCancel={jest.fn()} handleCreate={jest.fn()} + onClose={jest.fn()} + onCancel={jest.fn()} /> ) const loadingDescription = screen.getByText('Loading description') + expect(loadingDescription).toBeDefined() }) @@ -257,19 +266,20 @@ describe('ValidationDialog', () => { render( ) const createButton = screen.getByRole('button', { name: 'Confirmar' }) + fireEvent.click(createButton) expect(handleCreateMock).toHaveBeenCalled() diff --git a/src/core/feedback/validation-dialog/validaton-dialog.stories.tsx b/src/core/feedback/validation-dialog/validaton-dialog.stories.tsx index 58861a88..511fafbf 100644 --- a/src/core/feedback/validation-dialog/validaton-dialog.stories.tsx +++ b/src/core/feedback/validation-dialog/validaton-dialog.stories.tsx @@ -1,11 +1,11 @@ import React, { useCallback, useState } from 'react' -import type { Meta, StoryObj } from '@storybook/react' -import { ThemeProvider } from 'styled-components' -import ThemeProviderFlipper from '../../context/theme-provider' import CircularProgress from '@mui/material/CircularProgress' -import Button from '@/core/inputs/button' +import { ThemeProvider } from 'styled-components' +import type { Meta, StoryObj } from '@storybook/react' +import ThemeProviderFlipper from '@/core/context/theme-provider' +import { Button } from '@/core/inputs/button' +import { CheckCircleOutline, CancelOutlined } from '@/icons' import ValidationDialog, { ValidationStatus } from '.' -import { CheckCircleOutline, CancelOutlined } from '../../../icons' import { muiThemeOptions, theme } from '@/theme' const { action, secondary } = theme.colors @@ -99,10 +99,11 @@ const ValidationDialogStorie = () => { }, []) const stepState = useCallback( - (condition: boolean = true, step: number, value: string) => { + (step: number, value: string, condition: boolean = true) => { if (condition) { setValidationResponses(prevResponses => { const newResponses = [...prevResponses] + newResponses[step] = value return newResponses @@ -134,16 +135,16 @@ const ValidationDialogStorie = () => { validationStatus.initLoading() setTimeout(() => { - validationStatus.stepState(true, 0, 'Success') + validationStatus.stepState(0, 'Success', true) setTimeout(() => { - validationStatus.stepState(true, 1, 'Error') + validationStatus.stepState(1, 'Error', true) setTimeout(() => { - validationStatus.stepState(true, 2, 'Success') + validationStatus.stepState(2, 'Success', true) setTimeout(() => { - validationStatus.stepState(true, 3, 'Success') + validationStatus.stepState(3, 'Success', true) }, 2000) }, 2000) }, 2000) @@ -168,9 +169,9 @@ const ValidationDialogStorie = () => { success={validationResponses.every( item => item === 'Success' )} + handleCreate={handleConfirm} onCancel={handleClose} onClose={handleClose} - handleCreate={handleConfirm} /> diff --git a/src/core/feedback/zoom/index.tsx b/src/core/feedback/zoom/index.tsx index 47675588..ebbab478 100644 --- a/src/core/feedback/zoom/index.tsx +++ b/src/core/feedback/zoom/index.tsx @@ -1,11 +1,12 @@ -import { Zoom as MuiZoom } from '@material-ui/core' import React from 'react' -import { DefaultProps } from '../../types' +import type { ReactElement } from 'react' +import { Zoom as MuiZoom } from '@material-ui/core' +import type { DefaultProps } from '../../types' export interface ZoomProps extends DefaultProps { in: boolean timeout?: number | { enter?: number; exit?: number } - children?: React.ReactElement> + children?: ReactElement> } export const Zoom = ({ diff --git a/src/core/feedback/zoom/zoom.spec.tsx b/src/core/feedback/zoom/zoom.spec.tsx index 84a2eeba..c309d591 100644 --- a/src/core/feedback/zoom/zoom.spec.tsx +++ b/src/core/feedback/zoom/zoom.spec.tsx @@ -1,6 +1,6 @@ import * as React from 'react' import { render, screen } from '@testing-library/react' -import Zoom from '.' +import { Zoom } from '.' describe('Zoom', () => { it('should render closed', () => { diff --git a/src/core/feedback/zoom/zooms.stories.tsx b/src/core/feedback/zoom/zooms.stories.tsx index ad931517..456b4a8d 100644 --- a/src/core/feedback/zoom/zooms.stories.tsx +++ b/src/core/feedback/zoom/zooms.stories.tsx @@ -1,7 +1,7 @@ import React, { useState } from 'react' -import { Meta } from '@storybook/react' -import Zoom from '.' -import Button from '@/core/inputs/button' +import type { Meta } from '@storybook/react' +import { Button } from '@/core/inputs/button' +import { Zoom } from '.' export default { title: 'Feedback/Zoom', diff --git a/src/core/inputs/auto-complete/auto-complete.spec.tsx b/src/core/inputs/auto-complete/auto-complete.spec.tsx index 462e874e..24d1fcb2 100644 --- a/src/core/inputs/auto-complete/auto-complete.spec.tsx +++ b/src/core/inputs/auto-complete/auto-complete.spec.tsx @@ -1,12 +1,13 @@ /* eslint-disable max-lines */ import * as React from 'react' +import { act } from 'react-dom/test-utils' import { fireEvent, render, screen, waitFor } from '@testing-library/react' -import userEvent from '@testing-library/user-event' -import AutoComplete, { ISelected, TSelected } from '.' +import { userEvent } from '@testing-library/user-event' +import type { ISelected, TSelected } from '.' import ListItem from '@/core/data-display/list-item' -import TextField from '../text-field' -import Typography from '@/core/data-display/typography' -import { act } from 'react-dom/test-utils' +import { Typography } from '@/core/data-display/typography' +import { TextField } from '../text-field' +import { AutoComplete } from '.' interface MockProps { initialValue?: TSelected @@ -53,7 +54,7 @@ const MockAtuoComplete = (props: MockProps) => { {item.label}
) : ( - + {label} ) @@ -75,6 +76,7 @@ describe('AutoComplete', () => { { label: 'Genres', subheader: true }, ...SUGGESTIONS ] + it('should render suggestions', () => { render( { it('should select suggestions', async () => { const onChangeSpy = jest.fn() + render( { it('should call onChange with first suggestion for default', () => { const onChangeSpy = jest.fn() + render( { it('should navigate suggestions with arrow key down', () => { const onChangeSpy = jest.fn() + render( { it('should navigate suggestions with arrow key down and up', () => { const onChangeSpy = jest.fn() + render( { it('when typing should call onChange with correct values', async () => { const onChangeSpy = jest.fn() + render( { it('should call onBlur on leave focus', () => { jest.useFakeTimers() const onBlurSpy = jest.fn() + render( { it('should call onFocus', () => { const onFocusSpy = jest.fn() + render( ) @@ -619,6 +628,7 @@ describe('AutoComplete', () => { it('should selects a suggestion when clicking on it', () => { const onChangeSpy = jest.fn() + render( { }) const item = await waitFor(() => screen.findByText('Rock')) + expect(input.value).toBe('R') expect(item).toBeTruthy() }) @@ -709,8 +720,8 @@ describe('AutoComplete', () => { it('should select when selectTextOnFocus', async () => { render( ) diff --git a/src/core/inputs/auto-complete/auto-complete.stories.tsx b/src/core/inputs/auto-complete/auto-complete.stories.tsx index ffe3572b..238e864b 100644 --- a/src/core/inputs/auto-complete/auto-complete.stories.tsx +++ b/src/core/inputs/auto-complete/auto-complete.stories.tsx @@ -1,9 +1,10 @@ -import { Meta } from '@storybook/react' -import React from 'react' -import AutoComplete, { TSelected } from '.' +import React, { useState } from 'react' +import type { TSelected } from '.' +import type { Meta } from '@storybook/react' import ListItem from '@/core/data-display/list-item' -import TextField from '@/core/inputs/text-field' -import Typography from '@/core/data-display/typography' +import { Typography } from '@/core/data-display/typography' +import { TextField } from '@/core/inputs/text-field' +import { AutoComplete } from '.' export default { title: 'Inputs/AutoComplete', @@ -94,11 +95,12 @@ export const WithSubheader = () => ( ) }} + // eslint-disable-next-line no-console onChange={e => console.log('onChange', e)} /> ) export const MockAtuoComplete = () => { - const [value, setValue] = React.useState() + const [value, setValue] = useState() const handleChange = (newValue: TSelected) => { setValue(newValue) @@ -134,7 +136,7 @@ export const MockAtuoComplete = () => { {item.label} ) : ( - + {label} ) diff --git a/src/core/inputs/auto-complete/index.tsx b/src/core/inputs/auto-complete/index.tsx index 044e0b58..d1c8e8ed 100644 --- a/src/core/inputs/auto-complete/index.tsx +++ b/src/core/inputs/auto-complete/index.tsx @@ -1,18 +1,16 @@ -import React, { - Fragment, +import React, { Fragment, useState, useRef, useEffect } from 'react' +import type { ReactNode, - useState, - useRef, ChangeEvent, KeyboardEvent, CSSProperties, Ref, FocusEvent, - useEffect, - MouseEvent + MouseEvent, + ReactElement } from 'react' -import Paper from '@/core/surfaces/paper' -import Fade from '@/core/feedback/fade' +import { Fade } from '@/core/feedback/fade' +import { Paper } from '@/core/surfaces/paper' export interface AutoCompleteProps { autoFocus?: boolean @@ -38,7 +36,7 @@ export interface AutoCompleteProps { onChange: (value: TSelected) => void onFocus?: (event: FocusEvent) => void onBlur?: (event: FocusEvent) => void - renderInput(props: IInputProps): React.ReactElement + renderInput(props: IInputProps): ReactElement } export interface IInputProps { @@ -81,6 +79,7 @@ export const AutoComplete = (props: AutoCompleteProps) => { useEffect(() => { if (props.autoFocus) { const current = inputRef.current + if (current) { current!.focus() @@ -90,6 +89,7 @@ export const AutoComplete = (props: AutoCompleteProps) => { } } else if (props.focusDelay) { const current = inputRef.current + setTimeout(() => { if (current) { current.focus() @@ -174,6 +174,7 @@ export const AutoComplete = (props: AutoCompleteProps) => { if (props.openOnFocus) { setOpen(true) } + if (props.selectTextOnFocus) { const input = event.target @@ -249,6 +250,7 @@ export const AutoComplete = (props: AutoCompleteProps) => { setOpen(false) } else if (event.key === 'Enter') { const item = getSuggestions()[highlighted] + handleSelect(item) } } diff --git a/src/core/inputs/button/button.spec.tsx b/src/core/inputs/button/button.spec.tsx index 74e83e86..5c1ef4c3 100644 --- a/src/core/inputs/button/button.spec.tsx +++ b/src/core/inputs/button/button.spec.tsx @@ -1,6 +1,6 @@ import * as React from 'react' import { render, screen } from '@testing-library/react' -import Button from '.' +import { Button } from '.' describe('Button', () => { it('should render', () => { diff --git a/src/core/inputs/button/button.stories.tsx b/src/core/inputs/button/button.stories.tsx index 29447bf4..287b7355 100644 --- a/src/core/inputs/button/button.stories.tsx +++ b/src/core/inputs/button/button.stories.tsx @@ -1,7 +1,7 @@ import React from 'react' -import { Meta, StoryFn } from '@storybook/react' -import Button from '.' +import type { Meta, StoryFn } from '@storybook/react' import { Add as IconAdd } from '@/icons' +import { Button } from '.' export default { title: 'Inputs/Button', diff --git a/src/core/inputs/button/index.tsx b/src/core/inputs/button/index.tsx index 3d91c556..9cda5b91 100644 --- a/src/core/inputs/button/index.tsx +++ b/src/core/inputs/button/index.tsx @@ -1,6 +1,7 @@ +import React from 'react' +import type { ElementType, MouseEvent, ReactNode } from 'react' import { Button as MuiButton } from '@material-ui/core' -import React, { ElementType, MouseEvent } from 'react' -import { DefaultProps } from '../../types' +import type { DefaultProps } from '../../types' export interface ButtonProps extends DefaultProps { disabled?: boolean @@ -13,7 +14,7 @@ export interface ButtonProps extends DefaultProps { fullWidth?: boolean variant?: 'text' | 'outlined' | 'contained' | 'dashed' target?: string - children?: React.ReactNode + children?: ReactNode 'data-testid'?: string onClick?(event: MouseEvent): void } diff --git a/src/core/inputs/checkbox/checkbox.spec.tsx b/src/core/inputs/checkbox/checkbox.spec.tsx index 40e08042..a3077a16 100644 --- a/src/core/inputs/checkbox/checkbox.spec.tsx +++ b/src/core/inputs/checkbox/checkbox.spec.tsx @@ -1,6 +1,6 @@ import * as React from 'react' import { render, screen, act, waitFor, fireEvent } from '@testing-library/react' -import Checkbox from '.' +import { Checkbox } from '.' describe('Checkbox', () => { it('should render', () => { diff --git a/src/core/inputs/checkbox/checkbox.stories.tsx b/src/core/inputs/checkbox/checkbox.stories.tsx index 287b88bd..5f4531cd 100644 --- a/src/core/inputs/checkbox/checkbox.stories.tsx +++ b/src/core/inputs/checkbox/checkbox.stories.tsx @@ -1,6 +1,6 @@ import React from 'react' -import { Meta, StoryFn } from '@storybook/react' -import Checkbox from '.' +import type { Meta, StoryFn } from '@storybook/react' +import { Checkbox } from '.' export default { title: 'Inputs/Checkbox', diff --git a/src/core/inputs/checkbox/index.tsx b/src/core/inputs/checkbox/index.tsx index ec199d2b..0a58752e 100644 --- a/src/core/inputs/checkbox/index.tsx +++ b/src/core/inputs/checkbox/index.tsx @@ -1,12 +1,13 @@ +import React from 'react' +import type { ChangeEvent, ReactNode } from 'react' import { Checkbox as MuiCheckbox, - CheckboxProps as MuiCheckboxProps, FormControlLabel as MuiFormControlLabel, Switch as MuiSwitch, Typography } from '@material-ui/core' -import React, { ChangeEvent, ReactNode } from 'react' -import { DefaultProps } from '../../types' +import type { DefaultProps } from '../../types' +import type { CheckboxProps as MuiCheckboxProps } from '@material-ui/core' import { HelperBox, TextFieldWrapper as CheckFieldsWrapper @@ -20,7 +21,7 @@ export interface CheckboxProps extends DefaultProps { checked?: boolean dense?: boolean type?: 'switch' | 'checkbox' - helperIcon?: React.ReactNode + helperIcon?: ReactNode onHelperClick?: () => void onChange?: (event: ChangeEvent) => void checkboxProps?: MuiCheckboxProps diff --git a/src/core/inputs/chip-field/chip-field.spec.tsx b/src/core/inputs/chip-field/chip-field.spec.tsx index 5fdbb889..8ec8e23b 100644 --- a/src/core/inputs/chip-field/chip-field.spec.tsx +++ b/src/core/inputs/chip-field/chip-field.spec.tsx @@ -1,16 +1,17 @@ import * as React from 'react' import { render, screen, waitFor, fireEvent } from '@testing-library/react' -import ChipField from '.' +import { ChipField } from '.' describe('ChipField', () => { const values = [{ value: 'alpha' }, { value: 'beta' }, { value: 'gamma' }] + it('should render', () => { render( ) @@ -23,9 +24,9 @@ describe('ChipField', () => { render( ) @@ -36,12 +37,13 @@ describe('ChipField', () => { it('should remove from values', async () => { const onDelete = jest.fn() + render( ) diff --git a/src/core/inputs/chip-field/chip-field.stories.tsx b/src/core/inputs/chip-field/chip-field.stories.tsx index b3ff202a..28b3a20e 100644 --- a/src/core/inputs/chip-field/chip-field.stories.tsx +++ b/src/core/inputs/chip-field/chip-field.stories.tsx @@ -1,6 +1,6 @@ import React, { useState } from 'react' -import { Meta, StoryFn } from '@storybook/react' -import ChipField from '.' +import type { Meta, StoryFn } from '@storybook/react' +import { ChipField } from '.' export default { title: 'Inputs/ChipField', @@ -18,8 +18,8 @@ const Template: StoryFn = args => { return ( ) diff --git a/src/core/inputs/chip-field/index.tsx b/src/core/inputs/chip-field/index.tsx index 4decb025..ee51b341 100644 --- a/src/core/inputs/chip-field/index.tsx +++ b/src/core/inputs/chip-field/index.tsx @@ -1,7 +1,9 @@ import React, { useMemo } from 'react' -import ChipInput, { ChipRenderer } from 'material-ui-chip-input' -import { InputLabelProps } from '@material-ui/core' -import styled from 'styled-components' +import type { ReactNode } from 'react' +import ChipInput from 'material-ui-chip-input' +import { default as styled } from 'styled-components' +import type { InputLabelProps } from '@material-ui/core' +import type { ChipRenderer } from 'material-ui-chip-input' export interface ChipFieldProps { allowDuplicates?: boolean @@ -11,7 +13,7 @@ export interface ChipFieldProps { fullWidth?: boolean fullWidthInput?: boolean InputLabelProps?: InputLabelProps - label?: React.ReactNode + label?: ReactNode placeholder?: string readOnly?: boolean error?: boolean @@ -53,8 +55,8 @@ export const ChipField = (props: ChipFieldProps) => { return ( ) diff --git a/src/core/inputs/date-time/date-time.spec.tsx b/src/core/inputs/date-time/date-time.spec.tsx index 2a530ea5..129860cc 100644 --- a/src/core/inputs/date-time/date-time.spec.tsx +++ b/src/core/inputs/date-time/date-time.spec.tsx @@ -1,9 +1,9 @@ import * as React from 'react' -import { ptBR } from 'date-fns/locale' +import { act } from 'react-dom/test-utils' import { render, screen } from '@testing-library/react' +import { userEvent } from '@testing-library/user-event/' +import { ptBR } from 'date-fns/locale' import DateTime from '@/test/mocks/date-time-mock' -import userEvent from '@testing-library/user-event/' -import { act } from 'react-dom/test-utils' describe('DateTime', () => { it('should render with variant', async () => { diff --git a/src/core/inputs/date-time/date-time.stories.tsx b/src/core/inputs/date-time/date-time.stories.tsx index 3a3d2ec7..3047b35c 100644 --- a/src/core/inputs/date-time/date-time.stories.tsx +++ b/src/core/inputs/date-time/date-time.stories.tsx @@ -1,6 +1,6 @@ import React from 'react' -import { Meta, StoryFn } from '@storybook/react' -import DateTime from '.' +import type { Meta, StoryFn } from '@storybook/react' +import { DateTime } from '.' export default { title: 'Inputs/DateTime', diff --git a/src/core/inputs/date-time/index.tsx b/src/core/inputs/date-time/index.tsx index 4325e8d9..e37c5798 100644 --- a/src/core/inputs/date-time/index.tsx +++ b/src/core/inputs/date-time/index.tsx @@ -1,27 +1,27 @@ import React from 'react' +import type { MouseEvent } from 'react' +import DateFnsUtils from '@date-io/date-fns' import { KeyboardTimePicker, KeyboardDatePicker, KeyboardDateTimePicker, MuiPickersUtilsProvider } from '@material-ui/pickers' -import DateFnsUtils from '@date-io/date-fns' -import { DefaultProps } from '../../types' +import type { DefaultProps } from '../../types' +import type { KeyboardDatePickerProps } from '@material-ui/pickers/DatePicker' +// eslint-disable-next-line @stylistic/max-len +import type { KeyboardDateTimePickerProps } from '@material-ui/pickers/DateTimePicker' +import type { KeyboardTimePickerProps } from '@material-ui/pickers/TimePicker' +import type { MaterialUiPickersDate } from '@material-ui/pickers/typings/date' +import type { Omit } from 'ramda' import { useStyles } from '@/core/inputs/text-field' -import { KeyboardDatePickerProps } from '@material-ui/pickers/DatePicker' -import { KeyboardDateTimePickerProps } from '@material-ui/pickers/DateTimePicker' -import { KeyboardTimePickerProps } from '@material-ui/pickers/TimePicker' -import { Omit } from 'ramda' -import { MaterialUiPickersDate } from '@material-ui/pickers/typings/date' export interface IProps { locale?: DateFnsUtils['locale'] type?: 'date' | 'time' | 'datetime' inputProps?: object - onAuxClick?(event: React.MouseEvent): void - onAuxClickCapture?( - event: React.MouseEvent - ): void + onAuxClick?(event: MouseEvent): void + onAuxClickCapture?(event: MouseEvent): void onChange(date: MaterialUiPickersDate | null, value?: string): void } diff --git a/src/core/inputs/icon-button/icon-button.spec.tsx b/src/core/inputs/icon-button/icon-button.spec.tsx index ca865063..05e6c207 100644 --- a/src/core/inputs/icon-button/icon-button.spec.tsx +++ b/src/core/inputs/icon-button/icon-button.spec.tsx @@ -1,6 +1,6 @@ import * as React from 'react' import { render, screen } from '@testing-library/react' -import IconButton from '.' +import { IconButton } from '.' describe('IconButton', () => { it('should render', () => { @@ -29,6 +29,7 @@ describe('IconButton', () => { it('should match snapshot', () => { const { container } = render(IconButton) + expect(container).toMatchSnapshot() }) }) diff --git a/src/core/inputs/icon-button/icon-button.stories.tsx b/src/core/inputs/icon-button/icon-button.stories.tsx index 6fd13024..dce1a327 100644 --- a/src/core/inputs/icon-button/icon-button.stories.tsx +++ b/src/core/inputs/icon-button/icon-button.stories.tsx @@ -1,7 +1,7 @@ -import { Add as IconAdd } from '@/icons' -import { Meta, StoryFn } from '@storybook/react' import React from 'react' -import IconButton from '.' +import type { Meta, StoryFn } from '@storybook/react' +import { Add as IconAdd } from '@/icons' +import { IconButton } from '.' export default { title: 'Inputs/IconButton', diff --git a/src/core/inputs/icon-button/index.tsx b/src/core/inputs/icon-button/index.tsx index c78f59ff..3ee52598 100644 --- a/src/core/inputs/icon-button/index.tsx +++ b/src/core/inputs/icon-button/index.tsx @@ -1,6 +1,7 @@ +import type { MouseEvent } from 'react' +import React from 'react' import MuiIconButton from '@material-ui/core/IconButton' -import React, { MouseEvent } from 'react' -import { DefaultProps } from '../../types' +import type { DefaultProps } from '../../types' export interface IconButtonProps extends DefaultProps { color?: 'default' | 'inherit' | 'primary' | 'secondary' diff --git a/src/core/inputs/input-adornment/index.tsx b/src/core/inputs/input-adornment/index.tsx index 83b4c3db..f2890167 100644 --- a/src/core/inputs/input-adornment/index.tsx +++ b/src/core/inputs/input-adornment/index.tsx @@ -1,13 +1,9 @@ -import { - InputAdornment as MuiInputAdornment, - InputAdornmentProps as MuiInputAdornmentProps -} from '@material-ui/core' import React from 'react' -import { DefaultProps } from '../../types' +import { InputAdornment as MuiInputAdornment } from '@material-ui/core' +import type { DefaultProps } from '../../types' +import type { InputAdornmentProps as MuiInputProps } from '@material-ui/core' -export interface InputAdornmentProps - extends DefaultProps, - MuiInputAdornmentProps { +export interface InputAdornmentProps extends DefaultProps, MuiInputProps { position: 'start' | 'end' } diff --git a/src/core/inputs/input-adornment/input-adorment.spec.tsx b/src/core/inputs/input-adornment/input-adorment.spec.tsx index ba7e9d3c..f96389a6 100644 --- a/src/core/inputs/input-adornment/input-adorment.spec.tsx +++ b/src/core/inputs/input-adornment/input-adorment.spec.tsx @@ -1,6 +1,6 @@ import * as React from 'react' import { render, screen } from '@testing-library/react' -import InputAdornment from '.' +import { InputAdornment } from '.' describe('InputAdornment', () => { it('should render on start position', () => { diff --git a/src/core/inputs/input-adornment/input-adornment.stories.tsx b/src/core/inputs/input-adornment/input-adornment.stories.tsx index c9a2abdb..5abbf291 100644 --- a/src/core/inputs/input-adornment/input-adornment.stories.tsx +++ b/src/core/inputs/input-adornment/input-adornment.stories.tsx @@ -1,6 +1,6 @@ import React from 'react' -import { Meta, StoryFn } from '@storybook/react' -import InputAdornment from '.' +import type { Meta, StoryFn } from '@storybook/react' +import { InputAdornment } from '.' export default { title: 'Inputs/InputAdornment', @@ -10,6 +10,7 @@ export default { const Template: StoryFn = args => ( ) + export const Default = Template.bind({}) Default.args = { diff --git a/src/core/inputs/input-base/index.tsx b/src/core/inputs/input-base/index.tsx index ef78a14e..1308e7c3 100644 --- a/src/core/inputs/input-base/index.tsx +++ b/src/core/inputs/input-base/index.tsx @@ -1,9 +1,8 @@ -import { - InputBase as MuiInputBase, - InputBaseProps as MuiInputBaseProps -} from '@material-ui/core' -import React, { ChangeEvent, ReactNode } from 'react' -import { DefaultProps } from '../../types' +import type { ChangeEvent, ReactNode } from 'react' +import React from 'react' +import { InputBase as MuiInputBase } from '@material-ui/core' +import type { DefaultProps } from '../../types' +import type { InputBaseProps as MuiInputBaseProps } from '@material-ui/core' export interface InputAdornmentProps extends DefaultProps, diff --git a/src/core/inputs/input-base/input-base.spec.tsx b/src/core/inputs/input-base/input-base.spec.tsx index d65faa8b..f7d31e96 100644 --- a/src/core/inputs/input-base/input-base.spec.tsx +++ b/src/core/inputs/input-base/input-base.spec.tsx @@ -1,6 +1,6 @@ import * as React from 'react' import { render, screen } from '@testing-library/react' -import InputBase from '.' +import { InputBase } from '.' describe('InputBase', () => { it('should render', () => { @@ -42,6 +42,7 @@ describe('InputBase', () => { it('should match snapshot', () => { const { container } = render() + expect(container).toMatchSnapshot() }) }) diff --git a/src/core/inputs/input-base/input-base.stories.tsx b/src/core/inputs/input-base/input-base.stories.tsx index 83767379..c1863e4b 100644 --- a/src/core/inputs/input-base/input-base.stories.tsx +++ b/src/core/inputs/input-base/input-base.stories.tsx @@ -1,6 +1,6 @@ import React from 'react' -import { Meta, StoryFn } from '@storybook/react' -import InputBase from '.' +import type { Meta, StoryFn } from '@storybook/react' +import { InputBase } from '.' export default { title: 'Inputs/InputBase', @@ -18,6 +18,7 @@ export default { } as Meta const Template: StoryFn = args => + export const Default = Template.bind({}) Default.args = { diff --git a/src/core/inputs/mask-field/index.tsx b/src/core/inputs/mask-field/index.tsx index d92b2406..adc53819 100644 --- a/src/core/inputs/mask-field/index.tsx +++ b/src/core/inputs/mask-field/index.tsx @@ -1,6 +1,9 @@ import React from 'react' -import TextField, { TextFieldProps } from '@/core/inputs/text-field' -import NumberFormat, { NumberFormatProps } from 'react-number-format' +import type { ComponentType } from 'react' +import type { NumberFormatProps } from 'react-number-format' +import NumberFormat from 'react-number-format' +import type { TextFieldProps } from '@/core/inputs/text-field' +import { TextField } from '@/core/inputs/text-field' export interface MaskFieldProps extends NumberFormatProps { mask?: string @@ -10,7 +13,7 @@ export interface MaskFieldProps extends NumberFormatProps { decimalScale?: number thousandSeparator?: boolean | string fixedDecimalScale?: boolean - customInput?: React.ComponentType + customInput?: ComponentType } export const MaskField = (props: MaskFieldProps) => { @@ -20,9 +23,7 @@ export const MaskField = (props: MaskFieldProps) => { // Although react-number-format allow use of additional props, // shows problem with some props like have been do this // actually on flipper-ui. (e.g. errors treatment) - + ) } diff --git a/src/core/inputs/mask-field/mask-field.spec.tsx b/src/core/inputs/mask-field/mask-field.spec.tsx index bc54d823..1a25feb5 100644 --- a/src/core/inputs/mask-field/mask-field.spec.tsx +++ b/src/core/inputs/mask-field/mask-field.spec.tsx @@ -1,12 +1,11 @@ import * as React from 'react' -import { render, screen } from '@testing-library/react' -import MaskField from '.' -import userEvent from '@testing-library/user-event' import { act } from 'react-dom/test-utils' +import { render, screen } from '@testing-library/react' +import { userEvent } from '@testing-library/user-event' +import { MaskField } from '.' describe('MaskField', () => { - // eslint-disable-next-line max-len - it('should render with default TextField if customInput is not provided', async () => { + it('should render with default TextField without customInput', async () => { render() const input = screen.getByPlaceholderText( diff --git a/src/core/inputs/mask-field/mask-field.stories.tsx b/src/core/inputs/mask-field/mask-field.stories.tsx index ee124d50..5f5f2d2a 100644 --- a/src/core/inputs/mask-field/mask-field.stories.tsx +++ b/src/core/inputs/mask-field/mask-field.stories.tsx @@ -1,7 +1,7 @@ import React from 'react' -import { Meta, StoryFn } from '@storybook/react' -import InputAdornment from '@/core/inputs/input-adornment' -import MaskField from '.' +import type { Meta, StoryFn } from '@storybook/react' +import { InputAdornment } from '@/core/inputs/input-adornment' +import { MaskField } from '.' export default { title: 'Inputs/MaskField', diff --git a/src/core/inputs/pin-input/index.tsx b/src/core/inputs/pin-input/index.tsx index 24eeaea3..613d9be6 100644 --- a/src/core/inputs/pin-input/index.tsx +++ b/src/core/inputs/pin-input/index.tsx @@ -1,6 +1,12 @@ -import { TextField } from '@material-ui/core' import React, { useEffect, useRef } from 'react' -import styled from 'styled-components' +import type { + ChangeEvent, + ClipboardEvent, + CSSProperties, + KeyboardEvent +} from 'react' +import { TextField } from '@material-ui/core' +import { default as styled } from 'styled-components' export interface PinInputGridProps { pin: Array @@ -10,8 +16,8 @@ export interface PinInputGridProps { validationResult: boolean | undefined isValidating: boolean size: 'small' | 'large' - style?: React.CSSProperties - inputProps?: React.CSSProperties + style?: CSSProperties + inputProps?: CSSProperties variant?: 'outlined' | 'standard' } @@ -42,6 +48,7 @@ export const PinInput = ({ const changePinFocus = (pinIndex: number) => { const ref = inputRefs.current[pinIndex] + if (ref) { ref.focus() } @@ -51,10 +58,11 @@ export const PinInput = ({ changePinFocus(0) }, [isValidating]) - const onPaste = (event: React.ClipboardEvent) => { + const onPaste = (event: ClipboardEvent) => { const pastedValue = event.clipboardData.getData('text/plain') const splitValues = pastedValue.trim().split('') const intValues: number[] = [] + for (const value of splitValues) { intValues.push(parseInt(value)) } @@ -63,7 +71,7 @@ export const PinInput = ({ } const onChange = ( - event: React.ChangeEvent, + event: ChangeEvent, index: number ) => { if (event.target.value.length > 1) { @@ -71,10 +79,12 @@ export const PinInput = ({ } const valuesArray = event.target.value.split('') const value = valuesArray.pop() + if (!value || value === ' ' || value === '') { return } const pinNumber = Number(value.trim()) + if (isNaN(pinNumber) || value.length === 0) { return } @@ -87,11 +97,9 @@ export const PinInput = ({ } } - const onKeyDown = ( - event: React.KeyboardEvent, - index: number - ) => { + const onKeyDown = (event: KeyboardEvent, index: number) => { const keyboardKeyCode = event.nativeEvent.code + if (keyboardKeyCode !== BACKSPACE_KEY) { return } @@ -103,18 +111,18 @@ export const PinInput = ({ } } - const getStyleProps = (): React.CSSProperties => { + const getStyleProps = (): CSSProperties => { const style = { width: size === 'small' ? '40px' : '40px', height: size === 'small' ? '30px' : '40px', marginInline: size === 'small' ? '5px' : '10px', ...styleProps - } as React.CSSProperties + } as CSSProperties return style } - const getInputProps = (): React.CSSProperties => { + const getInputProps = (): CSSProperties => { const style = { width: size === 'small' ? '40px' : '45px', textAlign: 'center', @@ -122,7 +130,7 @@ export const PinInput = ({ fontSize: size === 'small' ? '16px' : '20px', padding: 'auto', ...inputProps - } as React.CSSProperties + } as CSSProperties return style } @@ -133,8 +141,6 @@ export const PinInput = ({ onKeyDown(event, index)} - onPaste={onPaste} color='primary' className='pin-input-field' error={validationResult} @@ -147,10 +153,12 @@ export const PinInput = ({ inputRefs.current[index] = el }} key={index} + value={pin[index] === 0 ? 0 : pin[index] || ''} + onKeyDown={event => onKeyDown(event, index)} + onPaste={onPaste} onChange={event => { onChange(event, index) }} - value={pin[index] === 0 ? 0 : pin[index] || ''} /> ))} diff --git a/src/core/inputs/pin-input/pin-input.spec.tsx b/src/core/inputs/pin-input/pin-input.spec.tsx index d4949bb1..e7ec8840 100644 --- a/src/core/inputs/pin-input/pin-input.spec.tsx +++ b/src/core/inputs/pin-input/pin-input.spec.tsx @@ -1,22 +1,23 @@ import * as React from 'react' +import { act } from 'react-dom/test-utils' import { fireEvent, render, screen } from '@testing-library/react' -import PinInput from '.' +import { userEvent } from '@testing-library/user-event' import MockedComponent from '@/test/mocks/pin-input-mock' -import userEvent from '@testing-library/user-event' -import { act } from 'react-dom/test-utils' +import { PinInput } from '.' describe('PinInput', () => { it('should render', () => { const PIN_LENGTH = 6 + render( ) diff --git a/src/core/inputs/pin-input/pin-input.stories.tsx b/src/core/inputs/pin-input/pin-input.stories.tsx index b53a1516..3ccba889 100644 --- a/src/core/inputs/pin-input/pin-input.stories.tsx +++ b/src/core/inputs/pin-input/pin-input.stories.tsx @@ -1,8 +1,8 @@ import React, { useState } from 'react' -import { Meta } from '@storybook/react' -import PinInput from '.' import { Button } from '@material-ui/core' -import styled from 'styled-components' +import { default as styled } from 'styled-components' +import type { Meta } from '@storybook/react' +import { PinInput } from '.' export default { title: 'Inputs/PinInput', @@ -32,6 +32,7 @@ export const Default = () => { const onPinChanged = (pinEntry: number | undefined, index: number) => { const newPin = [...pin] + newPin[index] = pinEntry setPin(newPin) } @@ -58,12 +59,12 @@ export const Default = () => { diff --git a/src/core/navigation/drawer/index.tsx b/src/core/navigation/drawer/index.tsx index 0c4f8b20..5833ad9e 100644 --- a/src/core/navigation/drawer/index.tsx +++ b/src/core/navigation/drawer/index.tsx @@ -1,9 +1,8 @@ -import MuiDrawer, { - DrawerProps as MuiDrawerProps -} from '@material-ui/core/Drawer' import React from 'react' -import { DefaultProps } from '../../types' +import MuiDrawer from '@material-ui/core/Drawer' import { makeStyles, createStyles } from '@material-ui/core/styles' +import type { DefaultProps } from '../../types' +import type { DrawerProps as MuiDrawerProps } from '@material-ui/core/Drawer' export interface DrawerProps extends MuiDrawerProps, DefaultProps { top?: number diff --git a/src/core/navigation/menu/index.tsx b/src/core/navigation/menu/index.tsx index 08f96fd6..62a336fb 100644 --- a/src/core/navigation/menu/index.tsx +++ b/src/core/navigation/menu/index.tsx @@ -1,7 +1,7 @@ -import { Menu as MuiMenu } from '@material-ui/core' import React from 'react' -import { DefaultProps } from '../../types' -import { MenuProps as MuiMenuProps } from '@material-ui/core/Menu' +import { Menu as MuiMenu } from '@material-ui/core' +import type { DefaultProps } from '../../types' +import type { MenuProps as MuiMenuProps } from '@material-ui/core/Menu' export interface MenuProps extends DefaultProps, MuiMenuProps { open: boolean diff --git a/src/core/navigation/menu/menu.spec.tsx b/src/core/navigation/menu/menu.spec.tsx index f05e15c1..435525f8 100644 --- a/src/core/navigation/menu/menu.spec.tsx +++ b/src/core/navigation/menu/menu.spec.tsx @@ -1,8 +1,8 @@ import * as React from 'react' import { render, screen } from '@testing-library/react' -import Menu from '.' import ListItem from '@/core/data-display/list-item' -import { Backup } from '../../../icons' +import { Backup } from '@/icons' +import { Menu } from '.' describe('Menu', () => { it('should render opened', () => { @@ -41,6 +41,7 @@ describe('Menu', () => { // over it. We are just ignoring it for now since it is not a problem with // our code and do not affect the component behavior. const spy = jest.spyOn(console, 'error') + spy.mockImplementation(jest.fn()) render( @@ -62,6 +63,7 @@ describe('Menu', () => { // over it. We are just ignoring it for now since it is not a problem with // our code and do not affect the component behavior const spy = jest.spyOn(console, 'error') + spy.mockImplementation(jest.fn()) render( diff --git a/src/core/navigation/menu/menu.stories.tsx b/src/core/navigation/menu/menu.stories.tsx index ee9abd69..d3cf7271 100644 --- a/src/core/navigation/menu/menu.stories.tsx +++ b/src/core/navigation/menu/menu.stories.tsx @@ -1,9 +1,9 @@ import React, { useState } from 'react' -import { Meta, StoryFn } from '@storybook/react' -import Menu from '.' -import Button from '@/core/inputs/button' +import type { Meta, StoryFn } from '@storybook/react' import ListItem from '@/core/data-display/list-item' -import { Backup } from '../../../icons' +import { Button } from '@/core/inputs/button' +import { Backup } from '@/icons' +import { Menu } from '.' export default { title: 'Navigation/Menu', diff --git a/src/core/navigation/pagination/index.tsx b/src/core/navigation/pagination/index.tsx index fe6ce0b9..8edf1081 100644 --- a/src/core/navigation/pagination/index.tsx +++ b/src/core/navigation/pagination/index.tsx @@ -1,12 +1,12 @@ -import { inc, times } from 'ramda' import React from 'react' -import styled from 'styled-components' +import { inc, times } from 'ramda' +import { default as styled } from 'styled-components' +import type { DefaultProps } from '../../types' +import { Button } from '@/core/inputs/button' import { KeyboardArrowLeft as IconArrowLeft, KeyboardArrowRight as IconArrowRight } from '@/icons' -import { DefaultProps } from '../../types' -import Button from '@/core/inputs/button' export interface PaginationProps extends DefaultProps { pages?: number diff --git a/src/core/navigation/pagination/pagination.spec.tsx b/src/core/navigation/pagination/pagination.spec.tsx index 69ff4f52..16be6ca9 100644 --- a/src/core/navigation/pagination/pagination.spec.tsx +++ b/src/core/navigation/pagination/pagination.spec.tsx @@ -1,7 +1,7 @@ import * as React from 'react' import { act, render, screen } from '@testing-library/react' -import Pagination from '.' -import userEvent from '@testing-library/user-event' +import { userEvent } from '@testing-library/user-event' +import { Pagination } from '.' describe('Pagination', () => { it('should call navigation with correct values', async () => { @@ -22,6 +22,7 @@ describe('Pagination', () => { const prevButton = screen.getByTestId('prev-page-button') const nextButton = screen.getByTestId('next-page-button') const page3Button = screen.getByTestId('pagination-page-3') + await act(async () => { await userEvent.click(prevButton) await userEvent.click(nextButton) diff --git a/src/core/navigation/pagination/pagination.stories.tsx b/src/core/navigation/pagination/pagination.stories.tsx index 80974d50..5a4e34a0 100644 --- a/src/core/navigation/pagination/pagination.stories.tsx +++ b/src/core/navigation/pagination/pagination.stories.tsx @@ -1,6 +1,6 @@ import React from 'react' -import { Meta, StoryFn } from '@storybook/react' -import Pagination from '.' +import type { Meta, StoryFn } from '@storybook/react' +import { Pagination } from '.' export default { title: 'Navigation/Pagination', diff --git a/src/core/navigation/sidebar/index.tsx b/src/core/navigation/sidebar/index.tsx index ff2f10f4..6caaa7e9 100644 --- a/src/core/navigation/sidebar/index.tsx +++ b/src/core/navigation/sidebar/index.tsx @@ -1,13 +1,15 @@ -import Drawer from '@material-ui/core/Drawer' -import { makeStyles, createStyles, Theme } from '@material-ui/core/styles' import React from 'react' -import styled from 'styled-components' +import Drawer from '@material-ui/core/Drawer' +import { makeStyles, createStyles } from '@material-ui/core/styles' +import { default as styled } from 'styled-components' +import type { DefaultProps } from '../../types' +import type { ButtonProps } from '@/core/inputs/button' +import type { Theme } from '@material-ui/core/styles' +import { Button } from '@/core/inputs/button' import { KeyboardArrowLeft as IconArrowLeft, KeyboardArrowRight as IconArrowRight } from '@/icons' -import { DefaultProps } from '../../types' -import Button, { ButtonProps } from '@/core/inputs/button' export interface SidebarProps extends DefaultProps { open: boolean diff --git a/src/core/navigation/sidebar/sidebar.spec.tsx b/src/core/navigation/sidebar/sidebar.spec.tsx index d826683c..430aa712 100644 --- a/src/core/navigation/sidebar/sidebar.spec.tsx +++ b/src/core/navigation/sidebar/sidebar.spec.tsx @@ -1,9 +1,9 @@ import * as React from 'react' import { render, screen } from '@testing-library/react' -import Sidebar from '.' -import List from '@/core/data-display/list' +import { List } from '@/core/data-display/list' import ListItem from '@/core/data-display/list-item' -import { Backup } from '../../../icons' +import { Backup } from '@/icons' +import { Sidebar } from '.' describe('Sidebar', () => { it('should render', () => { @@ -42,7 +42,7 @@ describe('Sidebar', () => { it('should render unExpanded', () => { render( - + } /> } /> @@ -59,7 +59,7 @@ describe('Sidebar', () => { it('should render with anchor right', () => { render( - + } /> } /> diff --git a/src/core/navigation/sidebar/sidebar.stories.tsx b/src/core/navigation/sidebar/sidebar.stories.tsx index 79ffd0cb..84cc5f9a 100644 --- a/src/core/navigation/sidebar/sidebar.stories.tsx +++ b/src/core/navigation/sidebar/sidebar.stories.tsx @@ -1,9 +1,9 @@ import React from 'react' -import { Meta, StoryFn } from '@storybook/react' -import Sidebar from '.' -import List from '@/core/data-display/list' +import type { Meta, StoryFn } from '@storybook/react' +import { List } from '@/core/data-display/list' import ListItem from '@/core/data-display/list-item' -import { Backup } from '../../../icons' +import { Backup } from '@/icons' +import { Sidebar } from '.' export default { title: 'Navigation/Sidebar', diff --git a/src/core/navigation/stepper/index.tsx b/src/core/navigation/stepper/index.tsx index 703ab67d..9d6b6903 100644 --- a/src/core/navigation/stepper/index.tsx +++ b/src/core/navigation/stepper/index.tsx @@ -1,6 +1,6 @@ +import React, { cloneElement } from 'react' import { Step, StepLabel, Stepper as MuiStepper } from '@material-ui/core' -import React from 'react' -import { DefaultProps } from '../../types' +import type { DefaultProps } from '../../types' export interface StepperProps extends DefaultProps { active?: number @@ -27,7 +27,7 @@ const StepIcon = ({ icon, active }: StepIconProps) => { return icon(active) } - return React.cloneElement(icon, { + return cloneElement(icon, { active: String(active), color: active ? 'primary' : 'disabled' }) diff --git a/src/core/navigation/stepper/stepper.spec.tsx b/src/core/navigation/stepper/stepper.spec.tsx index 5c483faa..aa38be3f 100644 --- a/src/core/navigation/stepper/stepper.spec.tsx +++ b/src/core/navigation/stepper/stepper.spec.tsx @@ -1,7 +1,7 @@ import * as React from 'react' import { render, screen } from '@testing-library/react' -import Stepper from '.' -import { Delete } from '../../../icons' +import { Delete } from '@/icons' +import { Stepper } from '.' describe('Stepper', () => { it('should render', () => { diff --git a/src/core/navigation/stepper/stepper.stories.tsx b/src/core/navigation/stepper/stepper.stories.tsx index 90520630..b6c1094a 100644 --- a/src/core/navigation/stepper/stepper.stories.tsx +++ b/src/core/navigation/stepper/stepper.stories.tsx @@ -1,7 +1,7 @@ import React from 'react' -import { Meta, StoryFn } from '@storybook/react' -import Stepper from '.' -import { Delete } from '../../../icons' +import type { Meta, StoryFn } from '@storybook/react' +import { Delete } from '@/icons' +import { Stepper } from '.' export default { title: 'Navigation/Stepper', diff --git a/src/core/navigation/tab/index.tsx b/src/core/navigation/tab/index.tsx index 8241ec1c..66689ce0 100644 --- a/src/core/navigation/tab/index.tsx +++ b/src/core/navigation/tab/index.tsx @@ -1,6 +1,6 @@ -import { Tab as MuiTab } from '@material-ui/core' import React from 'react' -import { DefaultProps } from '../../types' +import { Tab as MuiTab } from '@material-ui/core' +import type { DefaultProps } from '../../types' interface TabProps extends DefaultProps { disabled?: boolean @@ -18,7 +18,7 @@ const Tab = ({ ...otherProps }: TabProps) => ( diff --git a/src/core/navigation/tabs/index.tsx b/src/core/navigation/tabs/index.tsx index d0d7aec9..957ec7e2 100644 --- a/src/core/navigation/tabs/index.tsx +++ b/src/core/navigation/tabs/index.tsx @@ -1,6 +1,7 @@ +import type { ReactNode } from 'react' +import React from 'react' import { Tabs as MuiTabs } from '@material-ui/core' -import React, { ReactNode } from 'react' -import { DefaultProps } from '../../types' +import type { DefaultProps } from '../../types' export interface TabsProps extends DefaultProps { centered?: boolean diff --git a/src/core/navigation/tabs/tabs.spec.tsx b/src/core/navigation/tabs/tabs.spec.tsx index 69669347..cb106ee6 100644 --- a/src/core/navigation/tabs/tabs.spec.tsx +++ b/src/core/navigation/tabs/tabs.spec.tsx @@ -1,7 +1,7 @@ import * as React from 'react' import { render, screen } from '@testing-library/react' -import Tabs from '.' import Tab from '@/core/navigation/tab' +import { Tabs } from '.' describe('Tabs', () => { it('should render the tab', () => { diff --git a/src/core/navigation/tabs/tabs.stories.tsx b/src/core/navigation/tabs/tabs.stories.tsx index 6eeeb984..38e1ea94 100644 --- a/src/core/navigation/tabs/tabs.stories.tsx +++ b/src/core/navigation/tabs/tabs.stories.tsx @@ -1,7 +1,7 @@ import React from 'react' -import { Meta, StoryFn } from '@storybook/react' -import Tabs from '.' +import type { Meta, StoryFn } from '@storybook/react' import Tab from '@/core/navigation/tab' +import { Tabs } from '.' export default { title: 'Navigation/Tabs', diff --git a/src/core/surfaces/box/box.spec.tsx b/src/core/surfaces/box/box.spec.tsx index 33330f23..ed99db47 100644 --- a/src/core/surfaces/box/box.spec.tsx +++ b/src/core/surfaces/box/box.spec.tsx @@ -1,7 +1,7 @@ import * as React from 'react' import { render, screen } from '@testing-library/react' -import Box from '.' -import Typography from '@/core/data-display/typography' +import { Typography } from '@/core/data-display/typography' +import { Box } from '.' describe('Advertise', () => { it('should render', () => { diff --git a/src/core/surfaces/box/box.stories.tsx b/src/core/surfaces/box/box.stories.tsx index c2f89166..352d62e7 100644 --- a/src/core/surfaces/box/box.stories.tsx +++ b/src/core/surfaces/box/box.stories.tsx @@ -1,6 +1,6 @@ import React from 'react' -import { Meta, StoryFn } from '@storybook/react' -import Box from '.' +import type { Meta, StoryFn } from '@storybook/react' +import { Box } from '.' export default { title: 'Surfaces/Box', diff --git a/src/core/surfaces/box/index.tsx b/src/core/surfaces/box/index.tsx index 6655e422..d8ca1b3a 100644 --- a/src/core/surfaces/box/index.tsx +++ b/src/core/surfaces/box/index.tsx @@ -1,10 +1,11 @@ import React from 'react' +import type { ReactNode } from 'react' import type { DefaultProps } from '../../types' -import Paper from '@/core/surfaces/paper' +import { Paper } from '@/core/surfaces/paper' export interface BoxProps extends DefaultProps { minHeight?: number - children: React.ReactNode + children: ReactNode 'data-testid'?: string } diff --git a/src/core/surfaces/card/card.spec.tsx b/src/core/surfaces/card/card.spec.tsx index 44c0f0a1..c264f16e 100644 --- a/src/core/surfaces/card/card.spec.tsx +++ b/src/core/surfaces/card/card.spec.tsx @@ -1,15 +1,17 @@ import * as React from 'react' import { render, screen } from '@testing-library/react' -import Card, { +import { Button } from '@/core/inputs/button' +import { + Card, CardActionArea, CardActions, CardContent, CardMedia, CardHeader } from '.' -import Button from '@/core/inputs/button' const url = 'valid_url' + describe('Card', () => { it('should render', () => { render( @@ -30,12 +32,14 @@ describe('Card', () => { ) const card = screen.getByText('Content') + expect(card).toBeDefined() }) it('card header should spread props', () => { const title = 'This is a title' const subheader = 'This is a subheader' + render() const cardHeader = screen.getByText(title) diff --git a/src/core/surfaces/card/card.stories.tsx b/src/core/surfaces/card/card.stories.tsx index 29b3b011..ac5bbcc1 100644 --- a/src/core/surfaces/card/card.stories.tsx +++ b/src/core/surfaces/card/card.stories.tsx @@ -1,7 +1,7 @@ -import { Meta } from '@storybook/react' import React from 'react' -import Card, { CardActionArea, CardActions, CardContent, CardMedia } from '.' -import Button from '@/core/inputs/button' +import type { Meta } from '@storybook/react' +import { Button } from '@/core/inputs/button' +import { Card, CardActionArea, CardActions, CardContent, CardMedia } from '.' export default { title: 'Surfaces/Card', diff --git a/src/core/surfaces/card/index.tsx b/src/core/surfaces/card/index.tsx index 5d866bf2..2a38f32c 100644 --- a/src/core/surfaces/card/index.tsx +++ b/src/core/surfaces/card/index.tsx @@ -1,13 +1,17 @@ import React from 'react' -import { DefaultProps } from '../../types' -import MuiCard, { CardProps } from '@material-ui/core/Card' -import MuiCardActionArea, { - CardActionAreaProps -} from '@material-ui/core/CardActionArea' -import MuiCardActions, { CardActionsProps } from '@material-ui/core/CardActions' -import MuiCardContent, { CardContentProps } from '@material-ui/core/CardContent' -import MuiCardMedia, { CardMediaProps } from '@material-ui/core/CardMedia' -import MuiCardHeader, { CardHeaderProps } from '@material-ui/core/CardHeader' +import MuiCard from '@material-ui/core/Card' +import MuiCardActionArea from '@material-ui/core/CardActionArea' +import MuiCardActions from '@material-ui/core/CardActions' +import MuiCardContent from '@material-ui/core/CardContent' +import MuiCardHeader from '@material-ui/core/CardHeader' +import MuiCardMedia from '@material-ui/core/CardMedia' +import type { DefaultProps } from '../../types' +import type { CardProps } from '@material-ui/core/Card' +import type { CardActionAreaProps } from '@material-ui/core/CardActionArea' +import type { CardActionsProps } from '@material-ui/core/CardActions' +import type { CardContentProps } from '@material-ui/core/CardContent' +import type { CardHeaderProps } from '@material-ui/core/CardHeader' +import type { CardMediaProps } from '@material-ui/core/CardMedia' export const CardActionArea = ({ margin, diff --git a/src/core/surfaces/container/container.spec.tsx b/src/core/surfaces/container/container.spec.tsx index a0cb721e..3295609d 100644 --- a/src/core/surfaces/container/container.spec.tsx +++ b/src/core/surfaces/container/container.spec.tsx @@ -1,6 +1,6 @@ import * as React from 'react' import { render, screen } from '@testing-library/react' -import Container from '.' +import { Container } from '.' describe('Container', () => { it('should render', () => { @@ -17,6 +17,7 @@ describe('Container', () => { const { container } = render( I am a container ) + expect(container).toMatchSnapshot() }) }) diff --git a/src/core/surfaces/container/container.stories.tsx b/src/core/surfaces/container/container.stories.tsx index b9c1a6e2..6d60a4b6 100644 --- a/src/core/surfaces/container/container.stories.tsx +++ b/src/core/surfaces/container/container.stories.tsx @@ -1,6 +1,6 @@ import React from 'react' -import { Meta, StoryFn } from '@storybook/react' -import Container from '.' +import type { Meta, StoryFn } from '@storybook/react' +import { Container } from '.' export default { title: 'Surfaces/Container', diff --git a/src/core/surfaces/container/index.tsx b/src/core/surfaces/container/index.tsx index 9cf841d2..6d0a7a5b 100644 --- a/src/core/surfaces/container/index.tsx +++ b/src/core/surfaces/container/index.tsx @@ -1,7 +1,8 @@ import React from 'react' -import { DefaultProps } from '../../types' +import type { CSSProperties } from 'react' +import type { DefaultProps } from '../../types' -const ContainerStyles: React.CSSProperties = { +const ContainerStyles: CSSProperties = { display: 'flex', flex: 1 } @@ -13,7 +14,7 @@ export const Container = ({ style = {}, ...otherProps }: DefaultProps) => { - const componentStyle: React.CSSProperties = Object.assign( + const componentStyle: CSSProperties = Object.assign( {}, ContainerStyles, padding, diff --git a/src/core/surfaces/content/__snapshots__/content.spec.tsx.snap b/src/core/surfaces/content/__snapshots__/content.spec.tsx.snap index e10d0ec8..3e8c7046 100644 --- a/src/core/surfaces/content/__snapshots__/content.spec.tsx.snap +++ b/src/core/surfaces/content/__snapshots__/content.spec.tsx.snap @@ -3,7 +3,7 @@ exports[`Content should match snapshot 1`] = `
diff --git a/src/core/surfaces/content/content.spec.tsx b/src/core/surfaces/content/content.spec.tsx index d3edc84b..315fb5a8 100644 --- a/src/core/surfaces/content/content.spec.tsx +++ b/src/core/surfaces/content/content.spec.tsx @@ -1,6 +1,6 @@ import * as React from 'react' import { render, screen } from '@testing-library/react' -import Content from '.' +import { Content } from '.' describe('Content', () => { it('should render', () => { @@ -17,6 +17,7 @@ describe('Content', () => { const { container } = render( I am a Content ) + expect(container).toMatchSnapshot() }) }) diff --git a/src/core/surfaces/content/content.stories.tsx b/src/core/surfaces/content/content.stories.tsx index 858fdf9b..2561b8d1 100644 --- a/src/core/surfaces/content/content.stories.tsx +++ b/src/core/surfaces/content/content.stories.tsx @@ -1,6 +1,6 @@ import React from 'react' -import { Meta, StoryFn } from '@storybook/react' -import Content from '.' +import type { Meta, StoryFn } from '@storybook/react' +import { Content } from '.' export default { title: 'Surfaces/Content', diff --git a/src/core/surfaces/content/index.tsx b/src/core/surfaces/content/index.tsx index 0a632b56..9a7053ab 100644 --- a/src/core/surfaces/content/index.tsx +++ b/src/core/surfaces/content/index.tsx @@ -1,13 +1,14 @@ import React from 'react' -import styled from 'styled-components' -import { DefaultProps } from '../../types' +import type { CSSProperties } from 'react' +import { default as styled } from 'styled-components' +import type { DefaultProps } from '../../types' const StyledContent = styled.main` flex: 1; transition: all 500ms ease; ` -const ContainerStyles: React.CSSProperties = { +const ContainerStyles: CSSProperties = { flex: 1, transition: 'all 500ms ease' } @@ -19,7 +20,7 @@ export const Content = ({ style = {}, ...otherProps }: DefaultProps) => { - const componentStyle: React.CSSProperties = Object.assign( + const componentStyle: CSSProperties = Object.assign( {}, ContainerStyles, padding, diff --git a/src/core/surfaces/expansion-panel/expansion-panel.spec.tsx b/src/core/surfaces/expansion-panel/expansion-panel.spec.tsx index 04bd62d7..2def1894 100644 --- a/src/core/surfaces/expansion-panel/expansion-panel.spec.tsx +++ b/src/core/surfaces/expansion-panel/expansion-panel.spec.tsx @@ -1,11 +1,12 @@ import * as React from 'react' import { fireEvent, render, screen, waitFor } from '@testing-library/react' -import ExpansionPanel from '.' +import { ExpansionPanel } from '.' const expectToThrow = (fn: () => void, message: string) => { // Even though the error is caught, it still gets printed to the console // so we mock that out to avoid the wall of red text. const spy = jest.spyOn(console, 'error') + spy.mockImplementation(jest.fn()) expect(fn).toThrow(message) spy.mockRestore() @@ -24,6 +25,7 @@ describe('ExpansionPanel', () => { ) const expansionPanel = screen.getByRole('mui-expansion-panel') + expect(expansionPanel.lastChild).toHaveProperty( 'className', 'MuiCollapse-root MuiCollapse-hidden' @@ -42,6 +44,7 @@ describe('ExpansionPanel', () => { ) const expansionPanel = screen.getByRole('mui-expansion-panel') + expect(expansionPanel.lastChild).toHaveProperty( 'className', 'MuiCollapse-root MuiCollapse-entered' @@ -55,12 +58,13 @@ describe('ExpansionPanel', () => { editing={false} summary='Expansion Panel' role='mui-expansion-panel' - onClick={jest.fn()} actions={} + onClick={jest.fn()} /> ) const expansionPanel = screen.getByRole('action-button') + expect(expansionPanel.parentElement?.classList).toContain( 'MuiAccordionActions-root' ) @@ -68,6 +72,7 @@ describe('ExpansionPanel', () => { it('should render helper box on left', () => { const onHelperClick = jest.fn() + render( { it('should call onHelperClick', async () => { const onHelperClick = jest.fn() + render( { it('should call onEditClick', async () => { const onEditClick = jest.fn() + render( { it('should call onSaveClick', async () => { const onSaveClick = jest.fn() + render( { Confirm} - editable + onClick={jest.fn()} /> ) }, 'onSaveClick is required when editable is true') @@ -173,12 +181,12 @@ describe('ExpansionPanel', () => { Confirm} onSaveClick={jest.fn()} onClick={jest.fn()} - actions={} - editable /> ) }, 'onEditClick is required when editable is true') diff --git a/src/core/surfaces/expansion-panel/expansion-panel.stories.tsx b/src/core/surfaces/expansion-panel/expansion-panel.stories.tsx index bddde481..0165944a 100644 --- a/src/core/surfaces/expansion-panel/expansion-panel.stories.tsx +++ b/src/core/surfaces/expansion-panel/expansion-panel.stories.tsx @@ -1,10 +1,11 @@ -import React from 'react' -import { Meta, StoryFn } from '@storybook/react' -import ExpansionPanel from '.' -import Typography from '@/core/data-display/typography' -import { ExpandMore } from '../../../icons' -import Button from '@/core/inputs/button' -import TextField from '@/core/inputs/text-field' +import React, { useRef, useState } from 'react' +import type { KeyboardEvent } from 'react' +import type { Meta, StoryFn } from '@storybook/react' +import { Typography } from '@/core/data-display/typography' +import { Button } from '@/core/inputs/button' +import { TextField } from '@/core/inputs/text-field' +import { ExpandMore } from '@/icons' +import { ExpansionPanel } from '.' export default { title: 'Surfaces/ExpansionPanel', @@ -12,9 +13,9 @@ export default { } as Meta const Template: StoryFn = args => { - const [editing, setEditing] = React.useState(args.editing) - const [details, setDetails] = React.useState(args.details) - const inputRef = React.useRef(null) + const [editing, setEditing] = useState(args.editing) + const [details, setDetails] = useState(args.details) + const inputRef = useRef(null) const handleEditClick = () => { setEditing(true) @@ -25,7 +26,7 @@ const Template: StoryFn = args => { setEditing(false) } - const handleKeyDown = (event: React.KeyboardEvent) => { + const handleKeyDown = (event: KeyboardEvent) => { if (event.key === 'Enter') { handleSaveClick() } @@ -53,12 +54,13 @@ const Template: StoryFn = args => { ) } + export const Default = Template.bind({}) Default.args = { diff --git a/src/core/surfaces/expansion-panel/index.tsx b/src/core/surfaces/expansion-panel/index.tsx index f3ed8c62..5bc92985 100644 --- a/src/core/surfaces/expansion-panel/index.tsx +++ b/src/core/surfaces/expansion-panel/index.tsx @@ -1,10 +1,17 @@ +import React from 'react' +import type { + ReactNode, + MouseEvent, + CSSProperties, + HTMLAttributes, + ChangeEvent +} from 'react' import MuiExpansionPanel from '@material-ui/core/Accordion' import MuiExpansionPanelActions from '@material-ui/core/AccordionActions' import MuiExpansionPanelDetails from '@material-ui/core/AccordionDetails' import MuiExpansionPanelSummary from '@material-ui/core/AccordionSummary' -import React, { ReactNode, MouseEvent } from 'react' -import styled from 'styled-components' -import { PaperProps } from '@/core/surfaces/paper' +import { default as styled } from 'styled-components' +import type { PaperProps } from '@/core/surfaces/paper' import { EditBox, HelperBox } from '@/core/inputs/text-field' export interface ExpansionPanelProps extends Omit { @@ -18,9 +25,9 @@ export interface ExpansionPanelProps extends Omit { summaryStyle?: object detailsStyle?: object actionsStyle?: object - editStyle?: React.CSSProperties - headerProps?: React.HTMLAttributes - helperIcon?: React.ReactNode + editStyle?: CSSProperties + headerProps?: HTMLAttributes + helperIcon?: ReactNode editable?: boolean editing?: boolean role?: string @@ -29,7 +36,7 @@ export interface ExpansionPanelProps extends Omit { onEditClick?: () => void onSaveClick?: () => void onChange?: ( - event?: React.ChangeEvent>, + event?: ChangeEvent>, expanded?: boolean ) => void onClick?: (event: MouseEvent) => void @@ -118,10 +125,10 @@ export const ExpansionPanel = ({ )} @@ -133,9 +140,9 @@ export const ExpansionPanel = ({ style={{ margin, padding, ...style }}> {summary && ( + style={summaryStyle} + onClick={onClick}> {helperButtonPosition === 'left' && renderHelper} {summary} diff --git a/src/core/surfaces/header/header.spec.tsx b/src/core/surfaces/header/header.spec.tsx index dc227e63..c8b0ea87 100644 --- a/src/core/surfaces/header/header.spec.tsx +++ b/src/core/surfaces/header/header.spec.tsx @@ -1,6 +1,6 @@ import * as React from 'react' import { render, screen } from '@testing-library/react' -import Header from '.' +import { Header } from '.' describe('Header', () => { it('should render', () => { @@ -31,6 +31,7 @@ describe('Header', () => { it('should match snapshot', () => { const { container } = render(
Flipper UI
) + expect(container).toMatchSnapshot() }) }) diff --git a/src/core/surfaces/header/header.stories.tsx b/src/core/surfaces/header/header.stories.tsx index 02cd1a37..11923a4e 100644 --- a/src/core/surfaces/header/header.stories.tsx +++ b/src/core/surfaces/header/header.stories.tsx @@ -1,6 +1,6 @@ import React from 'react' -import { Meta, StoryFn } from '@storybook/react' -import Header from '.' +import type { Meta, StoryFn } from '@storybook/react' +import { Header } from '.' export default { title: 'Surfaces/Header', diff --git a/src/core/surfaces/header/index.tsx b/src/core/surfaces/header/index.tsx index fc73b5d0..172ca594 100644 --- a/src/core/surfaces/header/index.tsx +++ b/src/core/surfaces/header/index.tsx @@ -1,6 +1,7 @@ -import { AppBar, Toolbar, AppBarProps } from '@material-ui/core' import React from 'react' -import { PaperProps } from '@/core/surfaces/paper' +import { AppBar, Toolbar } from '@material-ui/core' +import type { PaperProps } from '@/core/surfaces/paper' +import type { AppBarProps } from '@material-ui/core' export interface HeaderProps extends Omit, AppBarProps { position?: 'absolute' | 'fixed' | 'static' | 'sticky' diff --git a/src/core/surfaces/paper/index.tsx b/src/core/surfaces/paper/index.tsx index ac99d6bc..6558aa94 100644 --- a/src/core/surfaces/paper/index.tsx +++ b/src/core/surfaces/paper/index.tsx @@ -1,9 +1,7 @@ -import { - Paper as MuiPaper, - PaperProps as MuiPaperProps -} from '@material-ui/core' import React from 'react' +import { Paper as MuiPaper } from '@material-ui/core' import type { DefaultProps } from '../../types' +import type { PaperProps as MuiPaperProps } from '@material-ui/core' export interface PaperProps extends DefaultProps, MuiPaperProps { square?: boolean diff --git a/src/core/surfaces/paper/paper.spec.tsx b/src/core/surfaces/paper/paper.spec.tsx index e830a6cc..8b8dd833 100644 --- a/src/core/surfaces/paper/paper.spec.tsx +++ b/src/core/surfaces/paper/paper.spec.tsx @@ -1,10 +1,11 @@ import * as React from 'react' import { render, screen } from '@testing-library/react' -import Paper from '.' +import { Paper } from '.' describe('Paper', () => { it('should render children', () => { const children = 'I am a Paper.' + render({children}) const matchingElements = screen.getByText(children) @@ -17,6 +18,7 @@ describe('Paper', () => { it('should render square paper', () => { const children = 'I am a Paper.' + render({children}) const matchingElements = screen.getByText(children) @@ -26,6 +28,7 @@ describe('Paper', () => { it('should render paper with no elevation', () => { const children = 'I am a Paper.' + render({children}) const matchingElements = screen.getByText(children) @@ -37,6 +40,7 @@ describe('Paper', () => { it('should render paper with elevation', () => { const children = 'I am a Paper.' + render({children}) const matchingElements = screen.getByText(children) @@ -48,6 +52,7 @@ describe('Paper', () => { it('should render paper with max elevation', () => { const children = 'I am a Paper.' + render({children}) const matchingElements = screen.getByText(children) diff --git a/src/core/surfaces/paper/paper.stories.tsx b/src/core/surfaces/paper/paper.stories.tsx index ca7279eb..2b745bd6 100644 --- a/src/core/surfaces/paper/paper.stories.tsx +++ b/src/core/surfaces/paper/paper.stories.tsx @@ -1,6 +1,6 @@ import React from 'react' -import { Meta, StoryFn } from '@storybook/react' -import Paper from '.' +import type { Meta, StoryFn } from '@storybook/react' +import { Paper } from '.' export default { title: 'Surfaces/Paper', diff --git a/src/core/surfaces/step-card/index.tsx b/src/core/surfaces/step-card/index.tsx index 51328277..708277e8 100644 --- a/src/core/surfaces/step-card/index.tsx +++ b/src/core/surfaces/step-card/index.tsx @@ -1,13 +1,14 @@ -import { +import React from 'react' +import type { CSSProperties, ChangeEvent, HTMLAttributes } from 'react' +import { Accordion as MuiAccordion } from '@material-ui/core' +import type { Typography } from '@/core/data-display/typography' +import type { LinearProgress, - Accordion as MuiAccordion, AccordionDetails as MuiAccordionDetails } from '@material-ui/core' -import React from 'react' -import StepCardSkeleton from './step-card-skeleton' -import Typography from '@/core/data-display/typography' import { StepCardDetails } from './step-card-details' import { StepCardPanel } from './step-card-panel' +import StepCardSkeleton from './step-card-skeleton' import { Container } from './styles' /** @@ -26,11 +27,11 @@ export interface IStepCardProps { /** * Callback fired when the expansion state changes - * @type {(event: React.ChangeEvent<{}>, expanded: boolean) => void} + * @type {(event: ChangeEvent<{}>, expanded: boolean) => void} * @memberof IStepCardProps * @default undefined * @example - * const handleChange = (event: React.ChangeEvent<{}>, expanded: boolean) => { + * const handleChange = (event: ChangeEvent<{}>, expanded: boolean) => { * setExpanded(expanded) * } * @@ -38,7 +39,7 @@ export interface IStepCardProps { * setExpanded(expanded)} /> */ onChange?: ( - event: React.ChangeEvent>, + event: ChangeEvent>, expanded: boolean ) => void @@ -151,10 +152,10 @@ export interface IStepCardProps { /** * Props to be passed to the root element * - * @type {(React.HTMLAttributes | undefined)} + * @type {(HTMLAttributes | undefined)} * @memberof IStepCardProps */ - rootProps?: React.HTMLAttributes + rootProps?: HTMLAttributes /** * Props to be passed to the title typography @@ -211,17 +212,17 @@ export interface IStepCardProps { /** * Padding applied to the root element - * @type {React.CSSProperties['padding']} + * @type {CSSProperties['padding']} * @memberof IStepCardProps */ - padding?: React.CSSProperties['padding'] + padding?: CSSProperties['padding'] /** * Margin applied to the root element - * @type {React.CSSProperties['margin']} + * @type {CSSProperties['margin']} * @memberof IStepCardProps */ - margin?: React.CSSProperties['margin'] + margin?: CSSProperties['margin'] /** * Whether to show the sub title skeleton diff --git a/src/core/surfaces/step-card/step-card-details.tsx b/src/core/surfaces/step-card/step-card-details.tsx index 89e017dd..a97ea9c7 100644 --- a/src/core/surfaces/step-card/step-card-details.tsx +++ b/src/core/surfaces/step-card/step-card-details.tsx @@ -1,10 +1,10 @@ import React from 'react' import { List } from '@material-ui/core' import MuiAccordionDetails from '@material-ui/core/AccordionDetails' +import type { IStepCardProps } from '.' +import { Typography } from '@/core/data-display/typography' +import { IconButton } from '@/core/inputs/icon-button' import { CheckCircle as CheckCircleIcon, Help as HelpIcon } from '@/icons' -import IconButton from '@/core/inputs/icon-button' -import Typography from '@/core/data-display/typography' -import { IStepCardProps } from '.' import { ListItemContainer, StepCardColumn } from './styles' import { theme } from '@/theme' diff --git a/src/core/surfaces/step-card/step-card-panel.tsx b/src/core/surfaces/step-card/step-card-panel.tsx index 1a38f1d9..77703b7e 100644 --- a/src/core/surfaces/step-card/step-card-panel.tsx +++ b/src/core/surfaces/step-card/step-card-panel.tsx @@ -1,13 +1,14 @@ import React from 'react' +import type { CSSProperties } from 'react' import { LinearProgress } from '@material-ui/core' import MuiAccordionSummary from '@material-ui/core/AccordionSummary' import { sprintf } from 'sprintf-js' -import { IStepCardProps } from '.' +import type { IStepCardProps } from '.' +import { Typography } from '@/core/data-display/typography' import { CheckCircle as CheckCircleIcon, ExpandMore as ExpandMoreIcon } from '@/icons' -import Typography from '@/core/data-display/typography' import { BarWrapper, NormalProgressContainer, @@ -39,7 +40,7 @@ interface IStepCardPanelProps { showIcon: boolean subTitle?: string fullWidth?: boolean - padding?: React.CSSProperties['padding'] + padding?: CSSProperties['padding'] } export const StepCardPanel = (props: IStepCardPanelProps) => { diff --git a/src/core/surfaces/step-card/step-card-skeleton.tsx b/src/core/surfaces/step-card/step-card-skeleton.tsx index a50475e6..f0f3d1ce 100644 --- a/src/core/surfaces/step-card/step-card-skeleton.tsx +++ b/src/core/surfaces/step-card/step-card-skeleton.tsx @@ -1,7 +1,8 @@ +import React from 'react' +import type { CSSProperties } from 'react' import { Box } from '@material-ui/core' import MuiAccordion from '@material-ui/core/Accordion' import { Skeleton } from '@mui/material' -import React from 'react' import { Container, NormalProgressContainer, @@ -16,8 +17,8 @@ interface IStepCardPanelProps { showBottomPercentage: boolean showIcon: boolean subTitle?: boolean - padding?: React.CSSProperties['padding'] - margin?: React.CSSProperties['margin'] + padding?: CSSProperties['padding'] + margin?: CSSProperties['margin'] fullWidth?: boolean subTitleSkeleton?: boolean } diff --git a/src/core/surfaces/step-card/step-card.spec.tsx b/src/core/surfaces/step-card/step-card.spec.tsx index 353ac2f0..bf012b34 100644 --- a/src/core/surfaces/step-card/step-card.spec.tsx +++ b/src/core/surfaces/step-card/step-card.spec.tsx @@ -1,7 +1,7 @@ import * as React from 'react' import { render, screen, waitFor } from '@testing-library/react' +import { userEvent } from '@testing-library/user-event/' import StepCard from '@/test/mocks/step-card-mock' -import userEvent from '@testing-library/user-event/' describe('StepCard', () => { it('should render', () => { @@ -273,6 +273,7 @@ describe('StepCard', () => { it('should call onStepUrlClick with correct values', async () => { const onStepUrlClickSpy = jest.fn() + render( ` margin-right: 40px; } ` - } else { - return '' } + + return '' }} ` diff --git a/src/core/types.ts b/src/core/types.ts index 38d34eaf..19a47aab 100644 --- a/src/core/types.ts +++ b/src/core/types.ts @@ -1,11 +1,11 @@ -import type { CSSProperties } from 'react' +import type { CSSProperties, ReactNode } from 'react' export interface DefaultProps { /** * The children of the component. * @optional */ - children?: React.ReactNode + children?: ReactNode /** * The style of the component. * @optional diff --git a/src/experimental/actions/actions.spec.tsx b/src/experimental/actions/actions.spec.tsx index 93df7a3a..e280192a 100644 --- a/src/experimental/actions/actions.spec.tsx +++ b/src/experimental/actions/actions.spec.tsx @@ -1,6 +1,6 @@ import * as React from 'react' import { render, screen } from '@testing-library/react' -import Actions from '.' +import { Actions } from '.' describe('Actions', () => { it('should render', () => { diff --git a/src/experimental/actions/actions.stories.tsx b/src/experimental/actions/actions.stories.tsx index d665757f..b747fb2f 100644 --- a/src/experimental/actions/actions.stories.tsx +++ b/src/experimental/actions/actions.stories.tsx @@ -1,6 +1,6 @@ import React from 'react' -import { Meta, StoryFn } from '@storybook/react' -import Actions from '.' +import type { Meta, StoryFn } from '@storybook/react' +import { Actions } from '.' export default { title: 'Experimental/Actions', diff --git a/src/experimental/actions/index.tsx b/src/experimental/actions/index.tsx index 391159c0..be70b954 100644 --- a/src/experimental/actions/index.tsx +++ b/src/experimental/actions/index.tsx @@ -1,7 +1,7 @@ -import { ButtonProps } from '@material-ui/core' -import { Button } from '@/index' import React from 'react' -import styled from 'styled-components' +import { default as styled } from 'styled-components' +import type { ButtonProps } from '@material-ui/core' +import { Button } from '@/index' export interface IProps { padding?: number | string diff --git a/src/experimental/auto-complete-lab/auto-complete-lab.stories.tsx b/src/experimental/auto-complete-lab/auto-complete-lab.stories.tsx index 49fd910b..f51e1f66 100644 --- a/src/experimental/auto-complete-lab/auto-complete-lab.stories.tsx +++ b/src/experimental/auto-complete-lab/auto-complete-lab.stories.tsx @@ -1,8 +1,8 @@ import React from 'react' -import { Meta } from '@storybook/react' -import AutoComplete from '@/core/inputs/auto-complete' -import TextField from '@/core/inputs/text-field' -import { Autocomplete } from '@material-ui/lab' +import { Autocomplete as AutocompleteLab } from '@material-ui/lab' +import type { Meta } from '@storybook/react' +import { AutoComplete } from '@/core/inputs/auto-complete' +import { TextField } from '@/core/inputs/text-field' export default { title: 'Experimental/AutoCompleteLab', @@ -10,7 +10,7 @@ export default { } as Meta export const Default = () => ( - ( renderInput={props => ( )} onChange={() => null} diff --git a/src/experimental/avatar/avatar.spec.tsx b/src/experimental/avatar/avatar.spec.tsx index 2c86d925..d59f7c7d 100644 --- a/src/experimental/avatar/avatar.spec.tsx +++ b/src/experimental/avatar/avatar.spec.tsx @@ -1,6 +1,6 @@ import * as React from 'react' import { render, screen } from '@testing-library/react' -import Avatar from '.' +import { Avatar } from '.' describe('Avatar', () => { it('should render first letter', () => { diff --git a/src/experimental/avatar/avatar.stories.tsx b/src/experimental/avatar/avatar.stories.tsx index 32f15178..1330ec28 100644 --- a/src/experimental/avatar/avatar.stories.tsx +++ b/src/experimental/avatar/avatar.stories.tsx @@ -1,6 +1,6 @@ import React from 'react' -import Avatar from '.' -import { Meta, StoryFn } from '@storybook/react' +import type { Meta, StoryFn } from '@storybook/react' +import { Avatar } from '.' const srcImage = 'https://imgflip.com/s/meme/Doge.jpg' diff --git a/src/experimental/avatar/index.tsx b/src/experimental/avatar/index.tsx index c4867f88..f7e50fa4 100644 --- a/src/experimental/avatar/index.tsx +++ b/src/experimental/avatar/index.tsx @@ -1,6 +1,7 @@ -import { Avatar as FlipperAvatar } from '@/index' +import type { CSSProperties, ReactNode } from 'react' +import React from 'react' import { take } from 'ramda' -import React, { CSSProperties, ReactNode } from 'react' +import { Avatar as FlipperAvatar } from '@/index' export interface IProps { /** The avatar name */ diff --git a/src/experimental/breadcrumbs/breadcrumbs.spec.tsx b/src/experimental/breadcrumbs/breadcrumbs.spec.tsx index c01647b8..e0af3900 100644 --- a/src/experimental/breadcrumbs/breadcrumbs.spec.tsx +++ b/src/experimental/breadcrumbs/breadcrumbs.spec.tsx @@ -1,6 +1,6 @@ import * as React from 'react' import { render, screen } from '@testing-library/react' -import Breadcrumbs from '.' +import { Breadcrumbs } from '.' describe('Breadcrumbs', () => { it('should render', () => { @@ -17,6 +17,7 @@ describe('Breadcrumbs', () => { ) const breadcrumbs = screen.getByText('Home') + expect(breadcrumbs).toBeDefined() }) @@ -33,6 +34,7 @@ describe('Breadcrumbs', () => { ) const breadcrumbs = screen.getByText('Home') + expect(breadcrumbs).toBeDefined() }) }) diff --git a/src/experimental/breadcrumbs/breadcrumbs.stories.tsx b/src/experimental/breadcrumbs/breadcrumbs.stories.tsx index 713046cf..d4deb16f 100644 --- a/src/experimental/breadcrumbs/breadcrumbs.stories.tsx +++ b/src/experimental/breadcrumbs/breadcrumbs.stories.tsx @@ -1,6 +1,6 @@ import React from 'react' +import type { Meta, StoryFn } from '@storybook/react' import BreadcrumbsComponent from '.' -import { Meta, StoryFn } from '@storybook/react' export default { title: 'Experimental/Breadcrumbs', diff --git a/src/experimental/breadcrumbs/index.tsx b/src/experimental/breadcrumbs/index.tsx index cfbdfe2f..9473ddda 100644 --- a/src/experimental/breadcrumbs/index.tsx +++ b/src/experimental/breadcrumbs/index.tsx @@ -1,6 +1,7 @@ -import React, { ReactNode } from 'react' -import styled from 'styled-components' +import type { ReactNode } from 'react' +import React from 'react' import { addIndex, map } from 'ramda' +import { default as styled } from 'styled-components' import { ChevronRight as IconChevronRight } from '@/icons' import { Typography, Breadcrumb } from '@/index' import { theme } from '@/theme' diff --git a/src/experimental/button/button.spec.tsx b/src/experimental/button/button.spec.tsx index 1cb708ae..d5ab12fd 100644 --- a/src/experimental/button/button.spec.tsx +++ b/src/experimental/button/button.spec.tsx @@ -5,6 +5,7 @@ import Button from '.' describe('Button', () => { const NAME = 'btnName' const LABEL = 'Click Me' + it('should render', () => { render( + it('should render', () => { render() diff --git a/src/experimental/panel/panel.stories.tsx b/src/experimental/panel/panel.stories.tsx index 1d63f9d6..1ccc038e 100644 --- a/src/experimental/panel/panel.stories.tsx +++ b/src/experimental/panel/panel.stories.tsx @@ -1,6 +1,6 @@ -import { Meta, StoryFn } from '@storybook/react' import React from 'react' -import Panel from '.' +import type { Meta, StoryFn } from '@storybook/react' +import { Panel } from '.' export default { title: 'Experimental/Panel', diff --git a/src/experimental/sidebar/index.tsx b/src/experimental/sidebar/index.tsx index 0c7280f2..1d8516b4 100644 --- a/src/experimental/sidebar/index.tsx +++ b/src/experimental/sidebar/index.tsx @@ -1,12 +1,13 @@ import React, { useEffect, useState, useCallback } from 'react' -import { Sidebar as FlipperSidebar, Tooltip, List, ListItem } from '@/index' -import { times, map } from 'ramda' -import styled from 'styled-components' +import type { ReactElement } from 'react' import { Skeleton } from '@mui/material' +import { times, map } from 'ramda' +import { default as styled } from 'styled-components' +import { Sidebar as FlipperSidebar, Tooltip, List, ListItem } from '@/index' import { theme } from '@/theme' export interface ISidebarOption { - icon: React.ReactElement + icon: ReactElement label: string name: string route: string @@ -140,8 +141,8 @@ export const Sidebar = (props: IProps) => { maxWidth={228} style={{ transition: 'width 100ms ease-in-out', zIndex: 1199 }} expanded={expanded} - onToggle={toggle} - top={top || 0}> + top={top || 0} + onToggle={toggle}> {loading ? sidebarSkeleton : map(renderOption, options)} diff --git a/src/experimental/sidebar/sidebar.spec.tsx b/src/experimental/sidebar/sidebar.spec.tsx index 92e253fa..ce9e210d 100644 --- a/src/experimental/sidebar/sidebar.spec.tsx +++ b/src/experimental/sidebar/sidebar.spec.tsx @@ -1,7 +1,8 @@ import * as React from 'react' import { render, screen, waitFor } from '@testing-library/react' -import userEvent from '@testing-library/user-event' -import Sidebar, { ISidebarOption } from '.' +import { userEvent } from '@testing-library/user-event' +import type { ISidebarOption } from '.' +import { Sidebar } from '.' const options: ISidebarOption[] = [ { @@ -29,8 +30,10 @@ describe('Sidebar', () => { it('calls handleGoTo when an option is clicked', () => { const handleGoTo = jest.fn() + render() const expandBtn = screen.getByTestId('sidebar-option-option1') + expandBtn.addEventListener( 'click', event => event.preventDefault(), @@ -56,6 +59,7 @@ describe('Sidebar', () => { route: '/extraOption2' } ] + render() extraOptions.forEach(option => { expect(screen.getByTitle(option.label)).toBeDefined() @@ -63,32 +67,37 @@ describe('Sidebar', () => { }) it('renders a skeleton when loading', () => { - render() + render() expect(screen.queryAllByRole('skeleton')).toHaveLength(6) }) it('should show labels when expanded', async () => { const handleGoTo = jest.fn() + render() const expandBtn = screen.getByTestId('sidebar-button') + userEvent.click(expandBtn) await waitFor(() => { const labels = options.map(option => screen.getByTestId(`list-item-${option.label}`) ) + labels.forEach(label => expect(label).toBeDefined()) }) }) it('should now show labels when collapsed', async () => { const handleGoTo = jest.fn() + render() await waitFor(() => { const labels = options.map(option => screen.queryByTestId(`list-item-${option.label}`) ) + labels.forEach(label => expect(label).toBeNull()) }) }) diff --git a/src/experimental/sidebar/sidebar.stories.tsx b/src/experimental/sidebar/sidebar.stories.tsx index 930d77a0..d6fa52a8 100644 --- a/src/experimental/sidebar/sidebar.stories.tsx +++ b/src/experimental/sidebar/sidebar.stories.tsx @@ -1,7 +1,7 @@ import React from 'react' -import Sidebar from '.' -import { Home, Computer, Edit } from '../../icons' -import { Meta, StoryFn } from '@storybook/react' +import type { Meta, StoryFn } from '@storybook/react' +import { Home, Computer, Edit } from '@/icons' +import { Sidebar } from '.' export default { title: 'Experimental/Sidebar', diff --git a/src/experimental/skeleton/index.tsx b/src/experimental/skeleton/index.tsx index 850d3838..c4046a4c 100644 --- a/src/experimental/skeleton/index.tsx +++ b/src/experimental/skeleton/index.tsx @@ -1,5 +1,6 @@ import React from 'react' -import SkeletonLoading, { SkeletonProps } from 'react-loading-skeleton' +import type { SkeletonProps } from 'react-loading-skeleton' +import SkeletonLoading from 'react-loading-skeleton' import 'react-loading-skeleton/dist/skeleton.css' import { theme } from '@/theme' diff --git a/src/experimental/skeleton/skeleton.spec.tsx b/src/experimental/skeleton/skeleton.spec.tsx index 850d7988..d2e8a3a3 100644 --- a/src/experimental/skeleton/skeleton.spec.tsx +++ b/src/experimental/skeleton/skeleton.spec.tsx @@ -1,6 +1,6 @@ import * as React from 'react' import { render, screen } from '@testing-library/react' -import Skeleton from '.' +import { Skeleton } from '.' const Simple = () => const WithCustomHeight = () => diff --git a/src/experimental/skeleton/skeleton.stories.tsx b/src/experimental/skeleton/skeleton.stories.tsx index 37f76a1d..22f8026d 100644 --- a/src/experimental/skeleton/skeleton.stories.tsx +++ b/src/experimental/skeleton/skeleton.stories.tsx @@ -1,6 +1,6 @@ import React from 'react' -import Skeleton from '.' -import { Meta, StoryFn } from '@storybook/react' +import type { Meta, StoryFn } from '@storybook/react' +import { Skeleton } from '.' export default { title: 'Experimental/Skeleton', diff --git a/src/experimental/visibility-icon/index.tsx b/src/experimental/visibility-icon/index.tsx index b16db992..2da8eb96 100644 --- a/src/experimental/visibility-icon/index.tsx +++ b/src/experimental/visibility-icon/index.tsx @@ -1,10 +1,10 @@ -import { IconButton } from '@/index' +import React from 'react' +import { default as styled } from 'styled-components' import { Visibility as IconVisibility, VisibilityOff as IconVisibilityOff } from '@/icons' -import React from 'react' -import styled from 'styled-components' +import { IconButton } from '@/index' export interface IProps { name?: string diff --git a/src/experimental/visibility-icon/visibility-icon.spec.tsx b/src/experimental/visibility-icon/visibility-icon.spec.tsx index d505456a..aead7bec 100644 --- a/src/experimental/visibility-icon/visibility-icon.spec.tsx +++ b/src/experimental/visibility-icon/visibility-icon.spec.tsx @@ -1,12 +1,13 @@ import * as React from 'react' import { fireEvent, render, screen } from '@testing-library/react' -import VisibilityIcon from '.' +import { VisibilityIcon } from '.' describe('VisibilityIcon', () => { it('should render visible', () => { render() const svg = screen.getByTestId('icon-off') + expect(svg).toBeDefined() }) @@ -14,6 +15,7 @@ describe('VisibilityIcon', () => { render() const svg = screen.getByTestId('icon-on') + expect(svg).toBeDefined() }) diff --git a/src/experimental/visibility-icon/visibility-icon.stories.tsx b/src/experimental/visibility-icon/visibility-icon.stories.tsx index aaa44936..892078d8 100644 --- a/src/experimental/visibility-icon/visibility-icon.stories.tsx +++ b/src/experimental/visibility-icon/visibility-icon.stories.tsx @@ -1,6 +1,6 @@ import React from 'react' -import VisibilityIcon from '.' -import { Meta, StoryFn } from '@storybook/react' +import type { Meta, StoryFn } from '@storybook/react' +import { VisibilityIcon } from '.' export default { title: 'Experimental/VisibilityIcon', diff --git a/src/index.ts b/src/index.ts index d2948a60..bdb52503 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,3 @@ -/* eslint-disable max-len */ export { default as Advertise } from './core/data-display/advertise' export { default as AutoComplete } from './core/inputs/auto-complete' export { default as Avatar } from './core/data-display/avatar' @@ -63,6 +62,7 @@ export { default as PinInput } from './core/inputs/pin-input' export { default as Chapter } from './core/data-display/chapter' export { default as DataTable } from './core/data-display/data-table' export { default as StepCard } from './core/surfaces/step-card' +// eslint-disable-next-line @stylistic/max-len export { default as StepCardSkeleton } from './core/surfaces/step-card/step-card-skeleton' export { default as ValidationDialog } from './core/feedback/validation-dialog/' export * as Experimental from './experimental' diff --git a/src/test/mocks/data-table-hidden-mock.tsx b/src/test/mocks/data-table-hidden-mock.tsx index 2593504b..ddda6fc9 100644 --- a/src/test/mocks/data-table-hidden-mock.tsx +++ b/src/test/mocks/data-table-hidden-mock.tsx @@ -1,16 +1,16 @@ /* eslint-disable @typescript-eslint/ban-ts-comment */ -import Button from '@/core/inputs/button' -import { - DataTableAction, - DataTableController -} from '@/core/data-display/data-table' -import DataTable from '@/core/data-display/data-table/data-table' -import { +import React, { useRef, useState } from 'react' +import { v4 as uuid } from 'uuid' +import type { DataTableController } from '@/core/data-display/data-table' +import type { ColumnSpec, - Identifier, - RowMode + Identifier } from '@/core/data-display/data-table/types' -import Typography from '@/core/data-display/typography' +import { DataTableAction } from '@/core/data-display/data-table' +import { DataTable } from '@/core/data-display/data-table/data-table' +import { RowMode } from '@/core/data-display/data-table/types' +import { Typography } from '@/core/data-display/typography' +import { Button } from '@/core/inputs/button' import { Cancel as CancelIcon, Check as CheckIcon, @@ -20,8 +20,6 @@ import { Visibility as VisibilityIcon, VisibilityOff as VisibilityOffIcon } from '@/icons' -import React, { useRef, useState } from 'react' -import { v4 as uuid } from 'uuid' const Default = () => { type Data = { @@ -122,6 +120,7 @@ const Default = () => { (id: Identifier, isNew = false) => () => { const nextItem = controllerRef.current?.getEditedRowData(id) + if (!nextItem) { return } diff --git a/src/test/mocks/data-table-mock.tsx b/src/test/mocks/data-table-mock.tsx index 1e8b8d14..e5263662 100644 --- a/src/test/mocks/data-table-mock.tsx +++ b/src/test/mocks/data-table-mock.tsx @@ -1,16 +1,16 @@ /* eslint-disable @typescript-eslint/ban-ts-comment */ -import Button from '@/core/inputs/button' -import { - DataTableAction, - DataTableController -} from '@/core/data-display/data-table' -import DataTable from '@/core/data-display/data-table/data-table' -import { +import React, { useRef, useState } from 'react' +import { format } from 'date-fns' +import type { DataTableController } from '@/core/data-display/data-table' +import type { ColumnSpec, - Identifier, - RowMode + Identifier } from '@/core/data-display/data-table/types' -import Typography from '@/core/data-display/typography' +import { DataTableAction } from '@/core/data-display/data-table' +import { DataTable } from '@/core/data-display/data-table/data-table' +import { RowMode } from '@/core/data-display/data-table/types' +import { Typography } from '@/core/data-display/typography' +import { Button } from '@/core/inputs/button' import { Cancel as CancelIcon, Check as CheckIcon, @@ -18,8 +18,6 @@ import { Edit as EditIcon, Save as SaveIcon } from '@/icons' -import { format } from 'date-fns' -import React, { useRef, useState } from 'react' const Default = () => { type Data = { diff --git a/src/test/mocks/date-time-mock.tsx b/src/test/mocks/date-time-mock.tsx index ecda0afa..bf09ee99 100644 --- a/src/test/mocks/date-time-mock.tsx +++ b/src/test/mocks/date-time-mock.tsx @@ -1,7 +1,8 @@ -import DateTime, { DateTimeProps } from '@/core/inputs/date-time' -import { MaterialUiPickersDate } from '@material-ui/pickers/typings/date' -import { isValid, startOfDay } from 'date-fns' import * as React from 'react' +import { isValid, startOfDay } from 'date-fns' +import type { DateTimeProps } from '@/core/inputs/date-time' +import type { MaterialUiPickersDate } from '@material-ui/pickers/typings/date' +import { DateTime } from '@/core/inputs/date-time' interface IProps { initialValue?: string diff --git a/src/test/mocks/editable-table-date-mock.tsx b/src/test/mocks/editable-table-date-mock.tsx index 10d00ab8..5948a396 100644 --- a/src/test/mocks/editable-table-date-mock.tsx +++ b/src/test/mocks/editable-table-date-mock.tsx @@ -1,7 +1,6 @@ import * as React from 'react' -import EditableTable, { - EditableTableProps -} from '@/core/data-display/editable-table' +import type { EditableTableProps } from '@/core/data-display/editable-table' +import { EditableTable } from '@/core/data-display/editable-table' interface IProps { tableProps?: Partial> @@ -13,4 +12,5 @@ interface IDate { const Default = ({ tableProps }: IProps) => { return } + export default Default diff --git a/src/test/mocks/editable-table-mock.tsx b/src/test/mocks/editable-table-mock.tsx index 5bc9fa02..efe6f6b1 100644 --- a/src/test/mocks/editable-table-mock.tsx +++ b/src/test/mocks/editable-table-mock.tsx @@ -1,7 +1,6 @@ import * as React from 'react' -import EditableTable, { - EditableTableProps -} from '@/core/data-display/editable-table' +import type { EditableTableProps } from '@/core/data-display/editable-table' +import { EditableTable } from '@/core/data-display/editable-table' interface IProps { tableProps?: Partial> diff --git a/src/test/mocks/pin-input-mock.tsx b/src/test/mocks/pin-input-mock.tsx index 663e1eae..da30d850 100644 --- a/src/test/mocks/pin-input-mock.tsx +++ b/src/test/mocks/pin-input-mock.tsx @@ -1,6 +1,8 @@ import React, { useState } from 'react' -import PinInput, { PinInputGridProps } from '../../core/inputs/pin-input' import { Button } from '@material-ui/core' +import type { PinInputGridProps } from '@/core/inputs/pin-input' +import { PinInput } from '@/core/inputs/pin-input' + const PIN_LENGTH = 6 interface IProps { @@ -14,6 +16,7 @@ const Mock = ({ pinInputProps }: IProps) => { const onPinChanged = (pinEntry: number | undefined, index: number) => { const newPin = [...pin] + newPin[index] = pinEntry setPin(newPin) } @@ -37,12 +40,12 @@ const Mock = ({ pinInputProps }: IProps) => {