diff --git a/.babelrc b/.babelrc deleted file mode 100644 index 2c3b19e..0000000 --- a/.babelrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "presets": ["@babel/preset-env", "@babel/preset-react", "@babel/preset-typescript"] -} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 103d758..bbe831d 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -37,7 +37,7 @@ jobs: echo "//npm.pkg.github.com/:_authToken=${{ secrets.GITHUB_TOKEN }}" >> ~/.npmrc echo "@miksrv:registry=https://npm.pkg.github.com/" >> ~/.npmrc - - name: Create Release Pull Request or Publish to npm + - name: Create Release and Publish to npm id: changesets uses: changesets/action@v1 with: @@ -45,8 +45,3 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - - - name: Publish to GitHub Packages - run: npm publish - env: - NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/storybook.yml b/.github/workflows/storybook.yml index 77ac4b6..4b0ecc1 100644 --- a/.github/workflows/storybook.yml +++ b/.github/workflows/storybook.yml @@ -5,7 +5,7 @@ on: branches: - main paths: - - 'storybook/**' + - 'storybook/**' jobs: build-storybook: diff --git a/.prettierignore b/.prettierignore index c653966..2508c34 100644 --- a/.prettierignore +++ b/.prettierignore @@ -4,6 +4,7 @@ *.css README.md eslint.config.mjs +rollup.config.js site.webmanifest node_modules dist diff --git a/.yarn/install-state.gz b/.yarn/install-state.gz index ac4bb34..0497964 100644 Binary files a/.yarn/install-state.gz and b/.yarn/install-state.gz differ diff --git a/CHANGELOG.md b/CHANGELOG.md index aa346d1..3c55168 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # simple-react-ui-kit +## 1.0.3 + +### Patch Changes + +- Rebuild UI architecture +- Fixed Button component styles +- Added story for Button component +- Rename concat class names functions (cn) + ## 1.0.2 ### Patch Changes diff --git a/build/index.js b/build/index.js new file mode 100644 index 0000000..b95ab97 --- /dev/null +++ b/build/index.js @@ -0,0 +1,466 @@ +import React from 'react' + +const concatClassNames = (...args) => args.filter((item) => !!item).join(' ') + +const Icon = ({ name, ...props }) => { + let iconToRender + switch (name) { + case 'Address': + iconToRender = React.createElement('path', { + d: 'M13 10h5l3-3-3-3h-5V2h-2v2H4v6h7v2H6l-3 3 3 3h5v4h2v-4h7v-6h-7v-2zM6 6h11.17l1 1-1 1H6V6zm12 10H6.83l-1-1 1-1H18v2z' + }) + break + case 'Map': + iconToRender = React.createElement('path', { + d: 'm20.5 3-.16.03L15 5.1 9 3 3.36 4.9c-.21.07-.36.25-.36.48V20.5c0 .28.22.5.5.5l.16-.03L9 18.9l6 2.1 5.64-1.9c.21-.07.36-.25.36-.48V3.5c0-.28-.22-.5-.5-.5zM10 5.47l4 1.4v11.66l-4-1.4V5.47zm-5 .99 3-1.01v11.7l-3 1.16V6.46zm14 11.08-3 1.01V6.86l3-1.16v11.84z' + }) + break + case 'Menu': + iconToRender = React.createElement('path', { d: 'M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z' }) + break + case 'Eye': + iconToRender = React.createElement('path', { + d: 'M12 6.5c3.79 0 7.17 2.13 8.82 5.5-1.65 3.37-5.02 5.5-8.82 5.5S4.83 15.37 3.18 12C4.83 8.63 8.21 6.5 12 6.5m0-2C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zm0 5c1.38 0 2.5 1.12 2.5 2.5s-1.12 2.5-2.5 2.5-2.5-1.12-2.5-2.5 1.12-2.5 2.5-2.5m0-2c-2.48 0-4.5 2.02-4.5 4.5s2.02 4.5 4.5 4.5 4.5-2.02 4.5-4.5-2.02-4.5-4.5-4.5z' + }) + break + case 'Camera': + iconToRender = React.createElement('path', { + d: 'm14.12 4 1.83 2H20v12H4V6h4.05l1.83-2h4.24M15 2H9L7.17 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2h-3.17L15 2zm-3 7c1.65 0 3 1.35 3 3s-1.35 3-3 3-3-1.35-3-3 1.35-3 3-3m0-2c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5z' + }) + break + case 'Photo': + iconToRender = React.createElement('path', { + d: 'M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-4.86 8.86-3 3.87L9 13.14 6 17h12l-3.86-5.14z' + }) + break + case 'Ruler': + iconToRender = React.createElement('path', { + d: 'M21 6H3c-1.1 0-2 .9-2 2v8c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm0 10H3V8h2v4h2V8h2v4h2V8h2v4h2V8h2v4h2V8h2v8z' + }) + break + case 'Star': + iconToRender = React.createElement('path', { + d: 'm22 9.24-7.19-.62L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21 12 17.27 18.18 21l-1.63-7.03L22 9.24zM12 15.4l-3.76 2.27 1-4.28-3.32-2.88 4.38-.38L12 6.1l1.71 4.04 4.38.38-3.32 2.88 1 4.28L12 15.4z' + }) + break + case 'FilledStar': + iconToRender = React.createElement('path', { + d: 'M12 17.27 18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z' + }) + break + case 'User': + iconToRender = React.createElement('path', { + d: 'M12 5.9c1.16 0 2.1.94 2.1 2.1s-.94 2.1-2.1 2.1S9.9 9.16 9.9 8s.94-2.1 2.1-2.1m0 9c2.97 0 6.1 1.46 6.1 2.1v1.1H5.9V17c0-.64 3.13-2.1 6.1-2.1M12 4C9.79 4 8 5.79 8 8s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm0 9c-2.67 0-8 1.34-8 4v3h16v-3c0-2.66-5.33-4-8-4z' + }) + break + case 'Users': + iconToRender = React.createElement('path', { + d: 'M16.67 13.13C18.04 14.06 19 15.32 19 17v3h4v-3c0-2.18-3.57-3.47-6.33-3.87M15 12c2.21 0 4-1.79 4-4s-1.79-4-4-4c-.47 0-.91.1-1.33.24C14.5 5.27 15 6.58 15 8s-.5 2.73-1.33 3.76c.42.14.86.24 1.33.24m-6 0c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4m0-6c1.1 0 2 .9 2 2s-.9 2-2 2-2-.9-2-2 .9-2 2-2m0 7c-2.67 0-8 1.34-8 4v3h16v-3c0-2.66-5.33-4-8-4m6 5H3v-.99C3.2 16.29 6.3 15 9 15s5.8 1.29 6 2z' + }) + break + case 'Point': + iconToRender = React.createElement('path', { + d: 'M12 12c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zm6-1.8C18 6.57 15.35 4 12 4s-6 2.57-6 6.2c0 2.34 1.95 5.44 6 9.14 4.05-3.7 6-6.8 6-9.14zM12 2c4.2 0 8 3.22 8 8.2 0 3.32-2.67 7.25-8 11.8-5.33-4.55-8-8.48-8-11.8C4 5.22 7.8 2 12 2z' + }) + break + case 'Time': + iconToRender = React.createElement('path', { + d: 'M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8zm.5-13H11v6l5.25 3.15.75-1.23-4.5-2.67z' + }) + break + case 'Clip': + iconToRender = React.createElement('path', { + d: 'M16.5 6v11.5c0 2.21-1.79 4-4 4s-4-1.79-4-4V5c0-1.38 1.12-2.5 2.5-2.5s2.5 1.12 2.5 2.5v10.5c0 .55-.45 1-1 1s-1-.45-1-1V6H10v9.5c0 1.38 1.12 2.5 2.5 2.5s2.5-1.12 2.5-2.5V5c0-2.21-1.79-4-4-4S7 2.79 7 5v12.5c0 3.04 2.46 5.5 5.5 5.5s5.5-2.46 5.5-5.5V6h-1.5z' + }) + break + case 'Search': + iconToRender = React.createElement('path', { + d: 'M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z' + }) + break + case 'Left': + iconToRender = React.createElement('path', { + d: 'M15.41 16.59 10.83 12l4.58-4.59L14 6l-6 6 6 6 1.41-1.41z' + }) + break + case 'LargeLeft': + iconToRender = React.createElement('path', { + d: 'M17.51 3.87 15.73 2.1 5.84 12l9.9 9.9 1.77-1.77L9.38 12z' + }) + break + case 'Right': + iconToRender = React.createElement('path', { d: 'M8.59 16.59 13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.41z' }) + break + case 'Down': + iconToRender = React.createElement('path', { d: 'M7.41 8.59 12 13.17l4.59-4.58L18 10l-6 6-6-6z' }) + break + case 'Up': + iconToRender = React.createElement('path', { d: 'M7.41 15.41 12 10.83l4.59 4.58L18 14l-6-6-6 6z' }) + break + case 'DoubleUp': + iconToRender = React.createElement( + React.Fragment, + null, + React.createElement('path', { d: 'M6 17.59 7.41 19 12 14.42 16.59 19 18 17.59l-6-6z' }), + React.createElement('path', { d: 'm6 11 1.41 1.41L12 7.83l4.59 4.58L18 11l-6-6z' }) + ) + break + case 'Close': + iconToRender = React.createElement('path', { + d: 'M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z' + }) + break + case 'Tune': + iconToRender = React.createElement('path', { + d: 'M3 17v2h6v-2zM3 5v2h10V5zm10 16v-2h8v-2h-8v-2h-2v6zM7 9v2H3v2h4v2h2V9zm14 4v-2H11v2zm-6-4h2V7h4V5h-4V3h-2z' + }) + break + case 'PlusCircle': + iconToRender = React.createElement('path', { + d: 'M13 7h-2v4H7v2h4v4h2v-4h4v-2h-4zm-1-5C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2m0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8' + }) + break + case 'Pencil': + iconToRender = React.createElement('path', { + d: 'M3 17.25V21h3.75L17.81 9.94l-3.75-3.75zM5.92 19H5v-.92l9.06-9.06.92.92zM20.71 5.63l-2.34-2.34c-.2-.2-.45-.29-.71-.29s-.51.1-.7.29l-1.83 1.83 3.75 3.75 1.83-1.83c.39-.39.39-1.02 0-1.41' + }) + break + case 'EditLocation': + iconToRender = React.createElement('path', { + d: 'M18.17 4.91 17.1 3.84l-5.55 5.55v1.08h1.08zM16 2.74l1.29-1.29a1.49 1.49 0 0 1 2.12 0l1.15 1.15c.59.59.59 1.54 0 2.12l-.68.68-.02.02-.58.58-6 6H10V8.74zm-2.28-.55-.55.55-1.27 1.27c-3.3.05-5.9 2.6-5.9 6.2 0 2.34 1.95 5.44 6 9.14 4.05-3.7 6-6.79 6-9.14v-.1l1.8-1.8c.13.6.2 1.24.2 1.9 0 3.32-2.67 7.25-8 11.8-5.33-4.55-8-8.48-8-11.8 0-4.98 3.8-8.2 8-8.2.58 0 1.16.06 1.72.18' + }) + break + case 'Link': + iconToRender = React.createElement('path', { + d: 'M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1M8 13h8v-2H8zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5' + }) + break + case 'Award': + iconToRender = React.createElement('path', { + d: 'M17 10.43V2H7v8.43c0 .35.18.68.49.86l4.18 2.51-.99 2.34-3.41.29 2.59 2.24L9.07 22 12 20.23 14.93 22l-.78-3.33 2.59-2.24-3.41-.29-.99-2.34 4.18-2.51c.3-.18.48-.5.48-.86m-6 .64-2-1.2V4h2zm4-1.2-2 1.2V4h2z' + }) + break + case 'FullscreenIn': + iconToRender = React.createElement('path', { + d: 'M7 14H5v5h5v-2H7zm-2-4h2V7h3V5H5zm12 7h-3v2h5v-5h-2zM14 5v2h3v3h2V5z' + }) + break + case 'FullscreenOut': + iconToRender = React.createElement('path', { + d: 'M5 16h3v3h2v-5H5zm3-8H5v2h5V5H8zm6 11h2v-3h3v-2h-5zm2-11V5h-2v5h5V8z' + }) + break + case 'Layers': + iconToRender = React.createElement('path', { + d: 'm11.99 18.54-7.37-5.73L3 14.07l9 7 9-7-1.63-1.27zM12 16l7.36-5.73L21 9l-9-7-9 7 1.63 1.27zm0-11.47L17.74 9 12 13.47 6.26 9z' + }) + break + case 'RadioButtonUnchecked': + iconToRender = React.createElement('path', { + d: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2m0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8' + }) + break + case 'RadioButtonChecked': + iconToRender = React.createElement('path', { + d: 'M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2m-2 15-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8z' + }) + break + case 'CheckboxChecked': + iconToRender = React.createElement('path', { + d: 'M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.11 0 2-.9 2-2V5c0-1.1-.89-2-2-2m-9 14-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8z' + }) + break + case 'CheckboxUnchecked': + iconToRender = React.createElement('path', { + d: 'M19 5v14H5V5zm0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2' + }) + break + case 'CheckboxIndeterminate': + iconToRender = React.createElement('path', { + d: 'M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2m-2 10H7v-2h10z' + }) + break + case 'CheckCircle': + iconToRender = React.createElement('path', { + d: 'M16.59 7.58 10 14.17l-3.59-3.58L5 12l5 5 8-8zM12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2m0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8' + }) + break + case 'ReportError': + iconToRender = React.createElement( + React.Fragment, + null, + React.createElement('path', { + d: 'M15.73 3H8.27L3 8.27v7.46L8.27 21h7.46L21 15.73V8.27zM19 14.9 14.9 19H9.1L5 14.9V9.1L9.1 5h5.8L19 9.1z' + }), + React.createElement('path', { d: 'M11 7h2v6h-2zm0 8h2v2h-2z' }) + ) + break + case 'Notifications': + iconToRender = React.createElement('path', { + d: 'M12 22c1.1 0 2-.9 2-2h-4c0 1.1.9 2 2 2m6-6v-5c0-3.07-1.63-5.64-4.5-6.32V4c0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5v.68C7.64 5.36 6 7.92 6 11v5l-2 2v1h16v-1zm-2 1H8v-6c0-2.48 1.51-4.5 4-4.5s4 2.02 4 4.5z' + }) + break + case 'Gps': + iconToRender = React.createElement('path', { + d: 'M12 8c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4m8.94 3c-.46-4.17-3.77-7.48-7.94-7.94V1h-2v2.06C6.83 3.52 3.52 6.83 3.06 11H1v2h2.06c.46 4.17 3.77 7.48 7.94 7.94V23h2v-2.06c4.17-.46 7.48-3.77 7.94-7.94H23v-2zM12 19c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7' + }) + break + case 'Rotate': + iconToRender = React.createElement('path', { + d: 'M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4z' + }) + break + case 'External': + iconToRender = React.createElement('path', { + d: 'M19 19H5V5h7V3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2v-7h-2zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3z' + }) + break + case 'Telegram': + iconToRender = React.createElement('path', { + transform: 'translate(-2, 0)', + d: 'M9.78 18.65l.28-4.23 7.68-6.92c.34-.31-.07-.46-.52-.19L7.74 13.3 3.64 12c-.88-.25-.89-.86.2-1.3l15.97-6.16c.73-.33 1.43.18 1.15 1.3l-2.72 12.81c-.19.91-.74 1.13-1.5.71L12.6 16.3l-1.99 1.93c-.23.23-.42.42-.83.42z' + }) + break + case 'Category': + iconToRender = React.createElement('path', { + d: 'M18 2H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2m0 18H6V4h5v7l2.5-1.5L16 11V4h2zm-4.38-6.5L17 18H7l2.38-3.17L11 17z' + }) + break + case 'Place': + iconToRender = React.createElement('path', { + d: 'M12 12c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2m6-1.8C18 6.57 15.35 4 12 4s-6 2.57-6 6.2c0 2.34 1.95 5.44 6 9.14 4.05-3.7 6-6.8 6-9.14M12 2c4.2 0 8 3.22 8 8.2 0 3.32-2.67 7.25-8 11.8-5.33-4.55-8-8.48-8-11.8C4 5.22 7.8 2 12 2' + }) + break + case 'Tag': + iconToRender = React.createElement('path', { + d: 'm21.41 11.41-8.83-8.83c-.37-.37-.88-.58-1.41-.58H4c-1.1 0-2 .9-2 2v7.17c0 .53.21 1.04.59 1.41l8.83 8.83c.78.78 2.05.78 2.83 0l7.17-7.17c.78-.78.78-2.04-.01-2.83M12.83 20 4 11.17V4h7.17L20 12.83z' + }) + break + case 'Feed': + iconToRender = React.createElement('path', { + d: 'M16 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V8zm3 16H5V5h10v4h4zM7 17h10v-2H7zm5-10H7v2h5zm-5 6h10v-2H7z' + }) + break + case 'Comment': + iconToRender = React.createElement('path', { + d: 'M21.99 4c0-1.1-.89-2-1.99-2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h14l4 4zM20 4v13.17L18.83 16H4V4zM6 12h12v2H6zm0-3h12v2H6zm0-3h12v2H6z' + }) + break + case 'HeartEmpty': + iconToRender = React.createElement('path', { + d: 'M16.5 3c-1.74 0-3.41.81-4.5 2.09C10.91 3.81 9.24 3 7.5 3 4.42 3 2 5.42 2 8.5c0 3.78 3.4 6.86 8.55 11.54L12 21.35l1.45-1.32C18.6 15.36 22 12.28 22 8.5 22 5.42 19.58 3 16.5 3m-4.4 15.55-.1.1-.1-.1C7.14 14.24 4 11.39 4 8.5 4 6.5 5.5 5 7.5 5c1.54 0 3.04.99 3.57 2.36h1.87C13.46 5.99 14.96 5 16.5 5c2 0 3.5 1.5 3.5 3.5 0 2.89-3.14 5.74-7.9 10.05' + }) + break + case 'HeartFull': + iconToRender = React.createElement('path', { + d: 'm12 21.35-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54z' + }) + break + case 'PinDrop': + iconToRender = React.createElement('path', { + d: 'M18 8c0-3.31-2.69-6-6-6S6 4.69 6 8c0 4.5 6 11 6 11s6-6.5 6-11m-8 0c0-1.1.9-2 2-2s2 .9 2 2-.89 2-2 2c-1.1 0-2-.9-2-2M5 20v2h14v-2z' + }) + break + case 'Settings': + iconToRender = React.createElement('path', { + d: 'M19.43 12.98c.04-.32.07-.64.07-.98 0-.34-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.09-.16-.26-.25-.44-.25-.06 0-.12.01-.17.03l-2.49 1c-.52-.4-1.08-.73-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38 2.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.06-.02-.12-.03-.18-.03-.17 0-.34.09-.43.25l-2 3.46c-.13.22-.07.49.12.64l2.11 1.65c-.04.32-.07.65-.07.98 0 .33.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.09.16.26.25.44.25.06 0 .12-.01.17-.03l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.06.02.12.03.18.03.17 0 .34-.09.43-.25l2-3.46c.12-.22.07-.49-.12-.64zm-1.98-1.71c.04.31.05.52.05.73 0 .21-.02.43-.05.73l-.14 1.13.89.7 1.08.84-.7 1.21-1.27-.51-1.04-.42-.9.68c-.43.32-.84.56-1.25.73l-1.06.43-.16 1.13-.2 1.35h-1.4l-.19-1.35-.16-1.13-1.06-.43c-.43-.18-.83-.41-1.23-.71l-.91-.7-1.06.43-1.27.51-.7-1.21 1.08-.84.89-.7-.14-1.13c-.03-.31-.05-.54-.05-.74s.02-.43.05-.73l.14-1.13-.89-.7-1.08-.84.7-1.21 1.27.51 1.04.42.9-.68c.43-.32.84-.56 1.25-.73l1.06-.43.16-1.13.2-1.35h1.39l.19 1.35.16 1.13 1.06.43c.43.18.83.41 1.23.71l.91.7 1.06-.43 1.27-.51.7 1.21-1.07.85-.89.7zM12 8c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4m0 6c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2' + }) + break + case 'Exit': + iconToRender = React.createElement('path', { + d: 'M10.09 15.59 11.5 17l5-5-5-5-1.41 1.41L12.67 11H3v2h9.67zM19 3H5c-1.11 0-2 .9-2 2v4h2V5h14v14H5v-4H3v4c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2' + }) + break + case 'VerticalDots': + iconToRender = React.createElement('path', { + d: 'M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2m0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2m0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2' + }) + break + case 'Light': + iconToRender = React.createElement('path', { + d: 'M12 9c1.65 0 3 1.35 3 3s-1.35 3-3 3-3-1.35-3-3 1.35-3 3-3m0-2c-2.76 0-5 2.24-5 5s2.24 5 5 5 5-2.24 5-5-2.24-5-5-5M2 13h2c.55 0 1-.45 1-1s-.45-1-1-1H2c-.55 0-1 .45-1 1s.45 1 1 1m18 0h2c.55 0 1-.45 1-1s-.45-1-1-1h-2c-.55 0-1 .45-1 1s.45 1 1 1M11 2v2c0 .55.45 1 1 1s1-.45 1-1V2c0-.55-.45-1-1-1s-1 .45-1 1m0 18v2c0 .55.45 1 1 1s1-.45 1-1v-2c0-.55-.45-1-1-1s-1 .45-1 1M5.99 4.58c-.39-.39-1.03-.39-1.41 0-.39.39-.39 1.03 0 1.41l1.06 1.06c.39.39 1.03.39 1.41 0s.39-1.03 0-1.41zm12.37 12.37c-.39-.39-1.03-.39-1.41 0-.39.39-.39 1.03 0 1.41l1.06 1.06c.39.39 1.03.39 1.41 0 .39-.39.39-1.03 0-1.41zm1.06-10.96c.39-.39.39-1.03 0-1.41-.39-.39-1.03-.39-1.41 0l-1.06 1.06c-.39.39-.39 1.03 0 1.41s1.03.39 1.41 0zM7.05 18.36c.39-.39.39-1.03 0-1.41-.39-.39-1.03-.39-1.41 0l-1.06 1.06c-.39.39-.39 1.03 0 1.41s1.03.39 1.41 0z' + }) + break + case 'Dark': + iconToRender = React.createElement('path', { + d: 'M14 4c.34 0 .68.02 1.01.07C13.1 6.23 12 9.05 12 12s1.1 5.77 3.01 7.93c-.33.05-.67.07-1.01.07-4.41 0-8-3.59-8-8s3.59-8 8-8m0-2C8.48 2 4 6.48 4 12s4.48 10 10 10c1.82 0 3.53-.5 5-1.35-2.99-1.73-5-4.95-5-8.65s2.01-6.92 5-8.65C17.53 2.5 15.82 2 14 2' + }) + break + } + return React.createElement('svg', { viewBox: '0 0 24 24', ...props }, iconToRender) +} + +const iconNames = { + Address: 'Address', + Award: 'Award', + Camera: 'Camera', + Category: 'Category', + CheckCircle: 'CheckCircle', + CheckboxChecked: 'CheckboxChecked', + CheckboxIndeterminate: 'CheckboxIndeterminate', + CheckboxUnchecked: 'CheckboxUnchecked', + Clip: 'Clip', + Close: 'Close', + Comment: 'Comment', + Dark: 'Dark', + Down: 'Down', + DoubleUp: 'DoubleUp', + EditLocation: 'EditLocation', + Exit: 'Exit', + External: 'External', + Eye: 'Eye', + Feed: 'Feed', + FilledStar: 'FilledStar', + FullscreenIn: 'FullscreenIn', + FullscreenOut: 'FullscreenOut', + Gps: 'Gps', + HeartEmpty: 'HeartEmpty', + HeartFull: 'HeartFull', + Layers: 'Layers', + LargeLeft: 'LargeLeft', + Left: 'Left', + Light: 'Light', + Link: 'Link', + Map: 'Map', + Menu: 'Menu', + Notifications: 'Notifications', + Pencil: 'Pencil', + PinDrop: 'PinDrop', + Place: 'Place', + PlusCircle: 'PlusCircle', + Point: 'Point', + Photo: 'Photo', + RadioButtonChecked: 'RadioButtonChecked', + RadioButtonUnchecked: 'RadioButtonUnchecked', + ReportError: 'ReportError', + Right: 'Right', + Rotate: 'Rotate', + Ruler: 'Ruler', + Search: 'Search', + Settings: 'Settings', + Star: 'Star', + Tag: 'Tag', + Telegram: 'Telegram', + Time: 'Time', + Tune: 'Tune', + Up: 'Up', + User: 'User', + Users: 'Users', + VerticalDots: 'VerticalDots' +} + +function styleInject(css, ref) { + if (ref === void 0) ref = {} + var insertAt = ref.insertAt + + if (!css || typeof document === 'undefined') { + return + } + + var head = document.head || document.getElementsByTagName('head')[0] + var style = document.createElement('style') + style.type = 'text/css' + + if (insertAt === 'top') { + if (head.firstChild) { + head.insertBefore(style, head.firstChild) + } else { + head.appendChild(style) + } + } else { + head.appendChild(style) + } + + if (style.styleSheet) { + style.styleSheet.cssText = css + } else { + style.appendChild(document.createTextNode(css)) + } +} + +var css_248z$1 = + '@keyframes styles-module_animation-fadeIn__M94ve {\n 0% {\n visibility: hidden;\n opacity: 0;\n }\n 100% {\n visibility: visible;\n opacity: 1;\n }\n}\n@keyframes styles-module_animation-fadeOut__Sjhiu {\n 0% {\n visibility: visible;\n opacity: 1;\n }\n 100% {\n visibility: hidden;\n opacity: 0;\n }\n}\n@keyframes styles-module_animation-spin__GL5qF {\n to {\n transform: rotate(360deg);\n }\n}\n@keyframes styles-module_left-to-right-wave__BRBL1 {\n 0% {\n -webkit-transform: translateX(-100%);\n -moz-transform: translateX(-100%);\n -ms-transform: translateX(-100%);\n transform: translateX(-100%);\n }\n 50% {\n -webkit-transform: translateX(100%);\n -moz-transform: translateX(100%);\n -ms-transform: translateX(100%);\n transform: translateX(100%);\n }\n 100% {\n -webkit-transform: translateX(100%);\n -moz-transform: translateX(100%);\n -ms-transform: translateX(100%);\n transform: translateX(100%);\n }\n}\n.styles-module_spinner__AzIFX {\n animation: styles-module_animation-spin__GL5qF 1s linear infinite;\n}' +var styles$1 = { + spinner: 'styles-module_spinner__AzIFX', + 'animation-spin': 'styles-module_animation-spin__GL5qF', + 'animation-fadeIn': 'styles-module_animation-fadeIn__M94ve', + 'animation-fadeOut': 'styles-module_animation-fadeOut__Sjhiu', + 'left-to-right-wave': 'styles-module_left-to-right-wave__BRBL1' +} +styleInject(css_248z$1) + +const Spinner = ({ className }) => + React.createElement( + 'svg', + { viewBox: '0 0 100 101', className: concatClassNames(className, styles$1.spinner) }, + React.createElement('path', { + d: 'M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z', + fill: 'rgb(229, 231, 235, 1)' + }), + React.createElement('path', { + d: 'M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z', + fill: '#616161' + }) + ) + +var css_248z = + '.styles-module_buttonLink__uS8Nm {\n text-decoration: none !important;\n}\n.styles-module_buttonLink__uS8Nm button {\n margin: 0 auto;\n}\n\n.styles-module_button__vh7mr {\n cursor: pointer;\n padding: 6px 10px;\n border: 0;\n border-radius: var(--border-radius);\n min-height: 28px;\n color: var(--button-default-color);\n background: var(--button-default-background);\n font-family: var(--font-family), serif;\n font-size: var(--font-size);\n font-weight: 500;\n display: flex;\n align-content: center;\n justify-content: center;\n align-items: center;\n outline: none;\n transition: background-color 0.15s ease-out, color 0.15s ease-out;\n}\n.styles-module_button__vh7mr svg {\n width: 16px;\n height: 16px;\n margin-right: 5px;\n fill: var(--button-default-color);\n}\n.styles-module_button__vh7mr img {\n margin-right: 5px;\n}\n.styles-module_button__vh7mr.styles-module_stretched__S-ixI {\n width: 100%;\n}\n.styles-module_button__vh7mr.styles-module_noText__gRcNy svg {\n margin-right: 0;\n}\n.styles-module_button__vh7mr:hover, .styles-module_button__vh7mr:focus {\n background-color: var(--button-default-background-hover);\n}\n.styles-module_button__vh7mr:active {\n background-color: var(--button-default-background-active);\n}\n.styles-module_button__vh7mr.styles-module_small__Dad5u {\n padding: 6px 10px;\n height: 28px;\n line-height: 15px;\n}\n.styles-module_button__vh7mr.styles-module_small__Dad5u .styles-module_loader__fN82b {\n height: 20px;\n width: 20px;\n margin-top: 0;\n}\n.styles-module_button__vh7mr.styles-module_medium__DepVh {\n padding: 8px 10px;\n height: 34px;\n}\n.styles-module_button__vh7mr.styles-module_medium__DepVh svg {\n width: 18px;\n height: 18px;\n}\n.styles-module_button__vh7mr.styles-module_primary__yNXpF {\n background-color: var(--button-primary-background);\n color: var(--button-primary-color);\n}\n.styles-module_button__vh7mr.styles-module_primary__yNXpF svg {\n fill: var(--button-primary-color);\n}\n.styles-module_button__vh7mr.styles-module_primary__yNXpF:hover, .styles-module_button__vh7mr.styles-module_primary__yNXpF:focus {\n background-color: var(--button-primary-background-hover);\n}\n.styles-module_button__vh7mr.styles-module_primary__yNXpF:active {\n background-color: var(--button-primary-background-active);\n}\n.styles-module_button__vh7mr.styles-module_primary__yNXpF.styles-module_negative__TVXHZ {\n background-color: var(--button-negative-background);\n color: var(--button-negative-color);\n}\n.styles-module_button__vh7mr.styles-module_primary__yNXpF.styles-module_negative__TVXHZ:hover, .styles-module_button__vh7mr.styles-module_primary__yNXpF.styles-module_negative__TVXHZ:focus {\n background-color: var(--button-negative-background-hover);\n}\n.styles-module_button__vh7mr.styles-module_primary__yNXpF.styles-module_negative__TVXHZ:active {\n background-color: var(--button-negative-background-active);\n}\n.styles-module_button__vh7mr.styles-module_secondary__LLIKV {\n background-color: var(--button-secondary-background);\n color: var(--button-secondary-color);\n}\n.styles-module_button__vh7mr.styles-module_secondary__LLIKV:hover, .styles-module_button__vh7mr.styles-module_secondary__LLIKV:focus {\n background-color: var(--button-secondary-background-hover);\n color: var(--button-secondary-color-hover);\n}\n.styles-module_button__vh7mr.styles-module_secondary__LLIKV:active {\n background-color: var(--button-secondary-background-active);\n color: var(--button-secondary-color-active);\n}\n.styles-module_button__vh7mr[disabled] {\n opacity: 0.64;\n pointer-events: none !important;\n cursor: not-allowed !important;\n}' +var styles = { + buttonLink: 'styles-module_buttonLink__uS8Nm', + button: 'styles-module_button__vh7mr', + stretched: 'styles-module_stretched__S-ixI', + noText: 'styles-module_noText__gRcNy', + small: 'styles-module_small__Dad5u', + loader: 'styles-module_loader__fN82b', + medium: 'styles-module_medium__DepVh', + primary: 'styles-module_primary__yNXpF', + negative: 'styles-module_negative__TVXHZ', + secondary: 'styles-module_secondary__LLIKV' +} +styleInject(css_248z) + +const Button = ({ + className, + link, + noIndex, + stretched, + loading, + size, + mode = 'primary', + variant, + icon, + children, + content, + ...props +}) => { + const button = React.createElement( + 'button', + { + ...props, + type: props.type ?? 'button', + className: concatClassNames( + className, + styles.button, + mode && styles[mode], + variant && styles[variant], + size && styles[size], + stretched && styles.stretched, + !children && styles.noText + ) + }, + loading + ? React.createElement(Spinner, { className: styles.loader }) + : icon && React.createElement(Icon, { name: icon }), + React.createElement('div', null, content ?? children) + ) + return link + ? React.createElement( + 'a', + { className: styles.buttonLink, href: link, title: '', rel: noIndex ? 'noindex nofollow' : '' }, + button + ) + : button +} + +export { Button, Icon, iconNames } +//# sourceMappingURL=index.js.map diff --git a/build/index.js.map b/build/index.js.map new file mode 100644 index 0000000..cab46dd --- /dev/null +++ b/build/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sources":["../node_modules/style-inject/dist/style-inject.es.js"],"sourcesContent":["function styleInject(css, ref) {\n if ( ref === void 0 ) ref = {};\n var insertAt = ref.insertAt;\n\n if (!css || typeof document === 'undefined') { return; }\n\n var head = document.head || document.getElementsByTagName('head')[0];\n var style = document.createElement('style');\n style.type = 'text/css';\n\n if (insertAt === 'top') {\n if (head.firstChild) {\n head.insertBefore(style, head.firstChild);\n } else {\n head.appendChild(style);\n }\n } else {\n head.appendChild(style);\n }\n\n if (style.styleSheet) {\n style.styleSheet.cssText = css;\n } else {\n style.appendChild(document.createTextNode(css));\n }\n}\n\nexport default styleInject;\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE;AAC/B,EAAE,KAAK,GAAG,KAAK,KAAK,CAAC,GAAG,GAAG,GAAG,EAAE,CAAC;AACjC,EAAE,IAAI,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC;AAC9B;AACA,EAAE,IAAI,CAAC,GAAG,IAAI,OAAO,QAAQ,KAAK,WAAW,EAAE,EAAE,OAAO,EAAE;AAC1D;AACA,EAAE,IAAI,IAAI,GAAG,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;AACvE,EAAE,IAAI,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;AAC9C,EAAE,KAAK,CAAC,IAAI,GAAG,UAAU,CAAC;AAC1B;AACA,EAAE,IAAI,QAAQ,KAAK,KAAK,EAAE;AAC1B,IAAI,IAAI,IAAI,CAAC,UAAU,EAAE;AACzB,MAAM,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;AAChD,KAAK,MAAM;AACX,MAAM,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;AAC9B,KAAK;AACL,GAAG,MAAM;AACT,IAAI,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;AAC5B,GAAG;AACH;AACA,EAAE,IAAI,KAAK,CAAC,UAAU,EAAE;AACxB,IAAI,KAAK,CAAC,UAAU,CAAC,OAAO,GAAG,GAAG,CAAC;AACnC,GAAG,MAAM;AACT,IAAI,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC;AACpD,GAAG;AACH;;;;;;;;;;;;;;;;;;;;;;;","x_google_ignoreList":[0]} \ No newline at end of file diff --git a/eslint.config.js b/eslint.config.cjs similarity index 100% rename from eslint.config.js rename to eslint.config.cjs diff --git a/eslint.config.mjs b/eslint.config.mjs index 58cf272..26cc928 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -34,17 +34,22 @@ export default [ '**/.yarn/**', '**/eslint.config.mjs', '**/eslint.config.js', + '**/eslint.config.cjs', '**/jest.config.ts', + '**/declarations.d.ts', '**/node_modules/**', + '**/build/**', '**/dist/**', '**/fixtures/**', '**/coverage/**', '**/__snapshots__/**', '**/.docusaurus/**', - '**/build/**', // WebPack - '**/webpack.config.js', + // '**/webpack.config.js', + + // RollUp + '**/rollup.config.js', // PM2 Server // '**/ecosystem.config.js', @@ -84,7 +89,7 @@ export default [ // in the rare case that we do - just need to manually restart their IDE. glob: 'Infinity' }, - project: ['tsconfig.json'], + project: ['eslint.tsconfig.json'], warnOnUnsupportedTypeScriptVersion: false } }, diff --git a/eslint.tsconfig.json b/eslint.tsconfig.json new file mode 100644 index 0000000..a659753 --- /dev/null +++ b/eslint.tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "baseUrl": "src", + + "target": "es2022", + "module": "es2020", + "lib": ["dom", "dom.iterable", "esnext", "es2018"], + + "strict": true, + "allowJs": false, + "skipLibCheck": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "forceConsistentCasingInFileNames": true, + "noFallthroughCasesInSwitch": true, + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "react-jsx", + "downlevelIteration": true, + "declaration": true, + "declarationDir": "dist" + }, + "include": ["src", "storybook"], + "exclude": ["node_modules", "dist"] +} diff --git a/index.tsx b/index.tsx deleted file mode 100644 index 092a46a..0000000 --- a/index.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import React from 'react' -import { createRoot } from 'react-dom/client' - -import { Button } from '@/index' - -const App = () => ( -
-

UI Components Demo

-
-) - -const container = document.getElementById('app') as HTMLElement -const root = createRoot(container) -root.render() diff --git a/package.json b/package.json index 325412f..eaa93c4 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,10 @@ { "name": "simple-react-ui-kit", - "version": "1.0.2", + "version": "1.0.3", "description": "My small UI framework for projects", "repository": "https://github.com/miksrv/simple-react-ui-kit.git", "scripts": { - "build": "webpack", + "build": "rollup -c", "changeset": "npx changeset", "changeversion": "npx changeset version", "release": "changeset publish", @@ -17,8 +17,10 @@ "publishConfig": { "access": "public" }, + "type": "module", "access": "public", - "main": "dist/index.js", + "main": "dist/index.cjs.js", + "module": "dist/index.esm.js", "types": "dist/index.d.ts", "files": [ "dist", @@ -29,18 +31,15 @@ "author": "Misha Topchilo <20854498+miksrv@users.noreply.github.com>", "license": "ISC", "devDependencies": { - "@babel/core": "^7.25.2", - "@babel/preset-env": "^7.25.4", - "@babel/preset-react": "^7.24.7", - "@babel/preset-typescript": "^7.24.7", "@changesets/cli": "^2.27.8", "@eslint/compat": "^1.1.1", "@eslint/js": "^9.11.1", + "@rollup/plugin-commonjs": "^28.0.0", + "@rollup/plugin-node-resolve": "^15.3.0", + "@rollup/plugin-terser": "^0.4.4", "@types/lodash-es": "^4.17.12", "@types/react": "^18.3.10", "@types/react-dom": "^18.3.0", - "babel-loader": "^9.2.1", - "css-loader": "^7.1.2", "eslint": "^9.11.1", "eslint-plugin-eslint-comments": "^3.2.0", "eslint-plugin-eslint-plugin": "^6.2.0", @@ -49,19 +48,18 @@ "eslint-plugin-react": "^7.37.1", "eslint-plugin-simple-import-sort": "^12.1.1", "globals": "^15.10.0", - "html-webpack-plugin": "^5.6.0", "jest": "^29.7.0", + "postcss-sass": "^0.5.0", "prettier": "^3.3.3", + "rollup": "^4.24.0", + "rollup-plugin-postcss": "^4.0.2", + "rollup-plugin-terser": "^7.0.2", + "rollup-plugin-typescript2": "^0.36.0", "sass": "^1.79.4", "sass-loader": "^16.0.2", "style-loader": "^4.0.0", - "ts-loader": "^9.5.1", - "tsconfig-paths-webpack-plugin": "^4.1.0", "typescript": "^5.6.2", - "typescript-eslint": "^8.8.0", - "webpack": "^5.95.0", - "webpack-cli": "^5.1.4", - "webpack-dev-server": "^5.1.0" + "typescript-eslint": "^8.8.0" }, "dependencies": { "embla-carousel-react": "^8.3.0", diff --git a/rollup.config.js b/rollup.config.js new file mode 100644 index 0000000..1431bf4 --- /dev/null +++ b/rollup.config.js @@ -0,0 +1,35 @@ +import typescript from 'rollup-plugin-typescript2'; +import resolve from '@rollup/plugin-node-resolve'; +import commonjs from '@rollup/plugin-commonjs'; +import postcss from 'rollup-plugin-postcss'; +import { terser } from 'rollup-plugin-terser'; + +export default { + input: 'src/index.ts', + output: [ + { + file: 'dist/index.esm.js', + format: 'esm', + sourcemap: false + } + ], + plugins: [ + resolve(), + commonjs(), + terser(), // Минификация + typescript({ + tsconfig: './tsconfig.json', + useTsconfigDeclarationDir: true, + clean: true + }), + postcss({ + extensions: ['.sass', '.scss'], + extract: false, + modules: true, + use: [ + ['sass', { includePaths: ['./src/styles'] }] + ] + }) + ], + external: ['react', 'react-dom'] +}; diff --git a/src/autocomplete/Autocomplete.tsx b/src/autocomplete/Autocomplete.tsx deleted file mode 100644 index 08fb049..0000000 --- a/src/autocomplete/Autocomplete.tsx +++ /dev/null @@ -1,247 +0,0 @@ -import React, { useCallback, useEffect, useRef, useState } from 'react' -import debounce from 'lodash-es/debounce' - -import styles from './styles.module.sass' - -import Icon from '@/icon' -import { IconTypes } from '@/icon/types' -import { Spinner } from '@/index' -import { concatClassNames as cn } from '@/tools' - -export type DropdownOption = { - title: string - value: any - type?: string - image?: string - description?: string -} - -interface DropdownProps { - className?: string - options?: DropdownOption[] - loading?: boolean - disabled?: boolean - clearable?: boolean - hideArrow?: boolean - debouncing?: boolean - debounceDelay?: number - notFoundCaption?: string - placeholder?: string - label?: string - value?: T - minLength?: number - leftIcon?: IconTypes - onSelect?: (option: T) => void - onSearch?: (value: string) => void - onClear?: () => void -} - -// TODO: If Enter key press and focus on the input field and options list not empty - select first option -const Autocomplete: React.FC> = ({ - className, - options, - disabled, - loading, - clearable, - hideArrow, - debouncing = true, - debounceDelay = 1000, - value, - minLength = 3, - notFoundCaption, - placeholder, - label, - leftIcon, - onSelect, - onSearch, - onClear -}) => { - const dropdownRef = useRef(null) - const [search, setSearch] = useState() - const [localLoading, setLocalLoading] = useState(false) - const [isOpen, setIsOpen] = useState(false) - const [selectedOption, setSelectedOption] = useState(undefined) - - const toggleDropdown = () => { - setIsOpen(!isOpen) - } - - const handleDebouncedSearch = useCallback( - debounce((value) => { - onSearch?.(value) - setLocalLoading(false) - }, debounceDelay ?? 1000), - [] - ) - - const handleChangeInput = (event: React.ChangeEvent) => { - const value = event.target.value - - if (value.length >= minLength) { - setLocalLoading(true) - } else { - setLocalLoading(false) - } - - setSearch(value) - - if (value === '' && isOpen) { - setIsOpen(false) - } - - if (debouncing) { - handleDebouncedSearch(value) - } else { - onSearch?.(value) - setLocalLoading(false) - } - } - - const handleKeyPress = (event: React.KeyboardEvent) => { - if (event.key === 'Enter' && options?.length && options.length >= 1 && search !== '') { - handleSelect(options[0]) - } - } - - const handleSelect = (option: DropdownOption | undefined) => { - if (selectedOption?.title !== option?.title) { - setSelectedOption(option) - setSearch(option?.title) - } - - onSelect?.(option) - - setIsOpen(false) - } - - const handleClickOutside = (event: MouseEvent) => { - if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) { - setIsOpen(false) - } - } - - const handleClearClick = (event: React.MouseEvent) => { - event.stopPropagation() - setSearch(undefined) - handleSelect(undefined) - onClear?.() - } - - useEffect(() => { - document.addEventListener('mousedown', handleClickOutside) - - return () => { - document.removeEventListener('mousedown', handleClickOutside) - } - }, []) - - useEffect(() => { - if (!value) { - setSelectedOption(undefined) - } - - if (value) { - setSearch(value.title) - setSelectedOption(options?.find(({ title }) => value === title) ?? value ?? undefined) - } - }, [value]) - - useEffect(() => { - if (search) { - setIsOpen(true) - } - }, [options]) - - return ( -
- {label && } -
-
- {leftIcon && ( - - - - )} - e.stopPropagation()} - onWheelCapture={(e) => e.stopPropagation()} - onKeyDown={handleKeyPress} - onChange={handleChangeInput} - /> - - {loading || localLoading ? ( - - ) : clearable && selectedOption?.title ? ( - - ) : !hideArrow ? ( - - ) : ( - <> - )} - -
- {isOpen && !loading && ( -
    e.stopPropagation()} - > - {!options?.length &&
  • {notFoundCaption ?? 'Nothing found'}
  • } - {options?.map((option, i) => ( -
  • - -
  • - ))} -
- )} -
-
- ) -} - -export default Autocomplete diff --git a/src/autocomplete/index.ts b/src/autocomplete/index.ts deleted file mode 100644 index 1daaef3..0000000 --- a/src/autocomplete/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from './Autocomplete' -export type { DropdownOption } from './Autocomplete' diff --git a/src/autocomplete/styles.module.sass b/src/autocomplete/styles.module.sass deleted file mode 100644 index a13df39..0000000 --- a/src/autocomplete/styles.module.sass +++ /dev/null @@ -1,174 +0,0 @@ -@import ../variables - -.autocomplete - display: block - - .label - display: block - color: var(--input-label-color) - overflow: hidden - padding-bottom: 4px - padding-top: 2px - text-overflow: ellipsis - white-space: nowrap - font-size: $fontSizeHeadline - - .loader - width: 18px !important - height: 18px !important - - .container - position: relative - border-radius: var(--border-radius) - - .searchContainer - width: 100% - line-height: 20px - position: relative - background-color: var(--input-background-color) - -webkit-tap-highlight-color: transparent - align-items: center - border-radius: inherit - box-sizing: border-box - border: var(--input-border) - color: var(--text-color-primary) - height: 34px - margin: 0 - padding: 0 10px 0 0 - display: flex - justify-content: space-between - transition: border-color 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,background-color 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,box-shadow 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms - - .leftIcon - svg - width: 24px - height: 24px - margin: 4px 1px 0 8px - fill: var(--icon-color-secondary) - - .searchInput - background: transparent - border: none - outline: none - width: 90% - height: inherit - padding-left: 12px - padding-bottom: 0 - font-family: var(--font-family) - font-size: var(--font-size) - color: inherit - - &::placeholder - font-size: var(--font-size) - - &:focus, &:active, &:hover - outline: none - border-color: var(--input-border-focus-color) - //box-shadow: rgba(25, 118, 210, 0.25) 0 0 0 0.05rem - - &.selected - color: var(--text-color-primary) - - span - overflow: hidden - white-space: nowrap - display: block - text-overflow: ellipsis - - img - width: 18px - height: 20px - margin-right: 5px - float: left - - .arrow - display: flex - margin-top: 1px - min-width: 24px - - svg - width: 24px - height: 24px - fill: var(--icon-color-secondary) - - .clear, .toggleButton - background: transparent - border: none - margin: 0 - padding: 0 - cursor: pointer - - svg - margin-top: 2px - width: 18px !important - height: 18px !important - - &:hover - fill: var(--icon-color-secondary-hover) - - &.open - .searchContainer - border-bottom-left-radius: 0 - border-bottom-right-radius: 0 - - &.disabled - opacity: .5 - cursor: default - - .optionsList - position: absolute - background-color: var(--dropdown-background-color) - box-shadow: $boxShadow2 - border: var(--input-border) - list-style: none - padding: 0 - width: 100% - z-index: 405 - top: 33px - border-bottom-left-radius: 8px - border-bottom-right-radius: 8px - max-height: 200px - overflow: hidden - overflow-y: scroll - - li - button - margin: 0 - padding: 8px 10px - height: 100% - width: 100% - cursor: pointer - background: transparent - border: none - text-align: left - display: flex - align-items: center - flex-wrap: wrap - color: var(--text-color-primary) - - img - width: 14px - height: 15px - margin-right: 4px - margin-top: 1px - float: left - - .content - text-overflow: ellipsis - overflow: hidden - white-space: nowrap - - .description - color: var(--text-color-secondary) - font-size: $fontSizeCaption - flex-basis: 100% - - &:hover, &.active - background-color: var(--dropdown-background-color-hover) - - &:last-of-type - border-bottom-left-radius: 8px - border-bottom-right-radius: 8px - - .emptyItem - padding: 8px 10px diff --git a/src/badge/Badge.tsx b/src/badge/Badge.tsx deleted file mode 100644 index 47eb2e0..0000000 --- a/src/badge/Badge.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import React from 'react' - -import styles from './styles.module.sass' - -import Icon from '@/icon' -import { IconTypes } from '@/icon/types' - -interface BadgeProps { - icon?: IconTypes - children?: React.ReactNode - content?: React.ReactNode -} - -const Badge: React.FC = ({ icon, children, content }) => ( -
- {icon && } - {children || content} -
-) - -export default Badge diff --git a/src/badge/index.ts b/src/badge/index.ts deleted file mode 100644 index 36f88ab..0000000 --- a/src/badge/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './Badge' diff --git a/src/badge/styles.module.sass b/src/badge/styles.module.sass deleted file mode 100644 index f6b9c1e..0000000 --- a/src/badge/styles.module.sass +++ /dev/null @@ -1,14 +0,0 @@ -@import ../variables - -.badge - color: #FFF - background: transparent - display: flex - align-items: center - font-size: $fontSizeCaption - margin-right: 8px - - svg - fill: #FFF - height: 16px - margin-right: 5px diff --git a/src/breadcrumbs/Breadcrumbs.tsx b/src/breadcrumbs/Breadcrumbs.tsx deleted file mode 100644 index 27eee76..0000000 --- a/src/breadcrumbs/Breadcrumbs.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import React from 'react' - -import styles from './styles.module.sass' - -import { concatClassNames as cn } from '@/tools' - -export type BreadcrumbLink = { - link: string - text: string -} - -export interface BreadcrumbsProps { - homePageTitle?: string - currentPage?: string - className?: string - links?: BreadcrumbLink[] -} - -const Breadcrumbs: React.FC = ({ homePageTitle, links, className, currentPage }) => ( -
    - {!!homePageTitle?.length && ( -
  • - - {homePageTitle} - -
  • - )} - {!!links?.length && - links.map(({ link, text }) => ( -
  • - - {text} - -
  • - ))} - {currentPage &&
  • {currentPage}
  • } -
-) - -export default Breadcrumbs diff --git a/src/breadcrumbs/index.ts b/src/breadcrumbs/index.ts deleted file mode 100644 index 58f86ec..0000000 --- a/src/breadcrumbs/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from './Breadcrumbs' -export type { BreadcrumbsProps, BreadcrumbLink } from './Breadcrumbs' diff --git a/src/breadcrumbs/styles.module.sass b/src/breadcrumbs/styles.module.sass deleted file mode 100644 index 35187ca..0000000 --- a/src/breadcrumbs/styles.module.sass +++ /dev/null @@ -1,16 +0,0 @@ -@import ../variables - -.breadcrumbs - display: flex - - li - font-size: $fontSizeHeadline - color: var(--text-color-secondary) - - &:not(:last-of-type) - &:after - content: '/' - user-select: none - margin-left: 8px - margin-right: 8px - diff --git a/src/carousel/Carousel.tsx b/src/carousel/Carousel.tsx deleted file mode 100644 index 7377cf8..0000000 --- a/src/carousel/Carousel.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import React from 'react' -import { EmblaOptionsType } from 'embla-carousel' -import useEmblaCarousel from 'embla-carousel-react' - -import { NextButton, PrevButton, usePrevNextButtons } from './CarouselButtons' -import styles from './styles.module.sass' - -interface CarouselProps { - options?: EmblaOptionsType - children?: any -} - -const Carousel: React.FC = ({ options, children }) => { - const [emblaRef, emblaApi] = useEmblaCarousel(options) - - const { prevBtnDisabled, nextBtnDisabled, onPrevButtonClick, onNextButtonClick } = usePrevNextButtons(emblaApi) - - return ( -
-
-
{children}
-
- -
- - -
-
- ) -} - -export default Carousel diff --git a/src/carousel/CarouselButtons.tsx b/src/carousel/CarouselButtons.tsx deleted file mode 100644 index 1a0e293..0000000 --- a/src/carousel/CarouselButtons.tsx +++ /dev/null @@ -1,85 +0,0 @@ -import React, { PropsWithChildren, useCallback, useEffect, useState } from 'react' -import { EmblaCarouselType } from 'embla-carousel' - -import styles from './styles.module.sass' - -import Icon from '@/icon' -import { concatClassNames as cn } from '@/tools' - -type UsePrevNextButtonsType = { - prevBtnDisabled: boolean - nextBtnDisabled: boolean - onPrevButtonClick: () => void - onNextButtonClick: () => void -} - -export const usePrevNextButtons = (emblaApi: EmblaCarouselType | undefined): UsePrevNextButtonsType => { - const [prevBtnDisabled, setPrevBtnDisabled] = useState(true) - const [nextBtnDisabled, setNextBtnDisabled] = useState(true) - - const onPrevButtonClick = useCallback(() => { - if (!emblaApi) { - return - } - emblaApi.scrollPrev() - }, [emblaApi]) - - const onNextButtonClick = useCallback(() => { - if (!emblaApi) { - return - } - emblaApi.scrollNext() - }, [emblaApi]) - - const onSelect = useCallback((emblaApi: EmblaCarouselType) => { - setPrevBtnDisabled(!emblaApi.canScrollPrev()) - setNextBtnDisabled(!emblaApi.canScrollNext()) - }, []) - - useEffect(() => { - if (!emblaApi) { - return - } - - onSelect(emblaApi) - emblaApi.on('reInit', onSelect) - emblaApi.on('select', onSelect) - }, [emblaApi, onSelect]) - - return { - nextBtnDisabled, - onNextButtonClick, - onPrevButtonClick, - prevBtnDisabled - } -} - -type PropType = PropsWithChildren< - React.DetailedHTMLProps, HTMLButtonElement> -> - -export const PrevButton: React.FC = ({ children, ...restProps }) => ( - -) - -export const NextButton: React.FC = ({ children, ...restProps }) => ( - -) diff --git a/src/carousel/index.ts b/src/carousel/index.ts deleted file mode 100644 index 0cca671..0000000 --- a/src/carousel/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './Carousel' diff --git a/src/carousel/styles.module.sass b/src/carousel/styles.module.sass deleted file mode 100644 index 8400109..0000000 --- a/src/carousel/styles.module.sass +++ /dev/null @@ -1,156 +0,0 @@ -@import ../variables - -.theme-light - --brand-primary: rgb(47, 112, 193) - --brand-secondary: rgb(116, 97, 195) - --brand-alternative: rgb(19, 120, 134) - --background-site: rgb(249, 249, 249) - --background-code: rgb(244, 244, 244) - --text-body: rgb(54, 49, 61) - --text-comment: rgb(99, 94, 105) - --text-high-contrast: rgb(49, 49, 49) - --text-medium-contrast: rgb(99, 94, 105) - --text-low-contrast: rgb(116, 109, 118) - --detail-high-contrast: rgb(192, 192, 192) - --detail-medium-contrast: rgb(234, 234, 234) - --detail-low-contrast: rgb(240, 240, 242) - --admonition-note: rgb(46, 109, 188) - --admonition-warning: rgb(255, 196, 9) - --admonition-danger: rgb(220, 38, 38) - --brand-primary-rgb-value: 47, 112, 193 - --brand-secondary-rgb-value: 116, 97, 195 - --brand-alternative-rgb-value: 19, 120, 134 - --background-site-rgb-value: 249, 249, 249 - --background-code-rgb-value: 244, 244, 244 - --text-body-rgb-value: 54, 49, 61 - --text-comment-rgb-value: 99, 94, 105 - --text-high-contrast-rgb-value: 49, 49, 49 - --text-medium-contrast-rgb-value: 99, 94, 105 - --text-low-contrast-rgb-value: 116, 109, 118 - --detail-high-contrast-rgb-value: 192, 192, 192 - --detail-medium-contrast-rgb-value: 234, 234, 234 - --detail-low-contrast-rgb-value: 240, 240, 242 - --admonition-note-rgb-value: 46, 109, 188 - --admonition-warning-rgb-value: 255, 196, 9 - --admonition-danger-rgb-value: 220, 38, 38 - -//.theme-dark -// --brand-primary: rgb(138, 180, 248) -// --brand-secondary: rgb(193, 168, 226) -// --brand-alternative: rgb(136, 186, 191) -// --background-site: rgb(0, 0, 0) -// --background-code: rgb(12, 12, 12) -// --text-body: rgb(222, 222, 222) -// --text-comment: rgb(170, 170, 170) -// --text-high-contrast: rgb(230, 230, 230) -// --text-medium-contrast: rgb(202, 202, 202) -// --text-low-contrast: rgb(170, 170, 170) -// --detail-high-contrast: rgb(101, 101, 101) -// --detail-medium-contrast: rgb(25, 25, 25) -// --detail-low-contrast: rgb(21, 21, 21) -// --admonition-note: rgb(138, 180, 248) -// --admonition-warning: rgb(253, 186, 116) -// --admonition-danger: rgb(220, 38, 38) -// --brand-primary-rgb-value: 138, 180, 248 -// --brand-secondary-rgb-value: 193, 168, 226 -// --brand-alternative-rgb-value: 136, 186, 191 -// --background-site-rgb-value: 0, 0, 0 -// --background-code-rgb-value: 12, 12, 12 -// --text-body-rgb-value: 222, 222, 222 -// --text-comment-rgb-value: 170, 170, 170 -// --text-high-contrast-rgb-value: 230, 230, 230 -// --text-medium-contrast-rgb-value: 202, 202, 202 -// --text-low-contrast-rgb-value: 170, 170, 170 -// --detail-high-contrast-rgb-value: 101, 101, 101 -// --detail-medium-contrast-rgb-value: 25, 25, 25 -// --detail-low-contrast-rgb-value: 21, 21, 21 -// --admonition-note-rgb-value: 138, 180, 248 -// --admonition-warning-rgb-value: 253, 186, 116 -// --admonition-danger-rgb-value: 220, 38, 38 -// - -.carousel - position: relative - max-width: 870px - margin-top: 10px - --slide-size: 100% - - .viewport - overflow: hidden - - .container - backface-visibility: hidden - display: flex - touch-action: pan-y - margin-left: calc(var(--slide-spacing) * -1) - - & > div, & > article - flex: 0 0 var(--slide-size) - min-width: 0 - max-width: 283px - padding-left: var(--slide-spacing) - - @media only screen and (max-width: $mobileMaxWidth) - max-width: 500px - - .buttonsContainer - opacity: 0 - display: flex - align-items: center - position: absolute - top: 50% - transform: translateY(-50%) - width: 100% - transition: opacity .15s - - @media only screen and (max-width: $mobileMaxWidth) - opacity: 1 - - .arrowButton - z-index: 1 - background: none - border: none - display: flex - align-items: center - justify-content: center - cursor: pointer - width: 48px - min-height: 346px - height: 100% - position: absolute - color: #a6a6a6 - - @media only screen and (max-width: $mobileMaxWidth) - min-height: 402px - - span - background-color: var(--modal-background) - display: flex - align-items: center - justify-content: center - width: 36px - height: 36px - opacity: .7 - border-radius: 50% - transition: opacity .15s ease-out - - svg - width: 32px - height: 32px - fill: #737373 - - &:hover - span - opacity: 1 - - .arrowButtonLeft - left: 10px - right: auto - - .arrowButtonRight - left: auto - right: 10px - - &:hover - .buttonsContainer - opacity: 1 diff --git a/src/checkbox/Checkbox.tsx b/src/checkbox/Checkbox.tsx deleted file mode 100644 index c1214c6..0000000 --- a/src/checkbox/Checkbox.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import React from 'react' - -import styles from './styles.module.sass' - -import Icon from '@/icon' -import { concatClassNames as cn } from '@/tools' - -interface CheckboxProps extends React.InputHTMLAttributes { - label?: string | React.ReactNode - indeterminate?: boolean -} - -const Checkbox: React.FC = ({ label, indeterminate, ...props }): JSX.Element => ( -
-
- {indeterminate ? ( - - ) : props.checked ? ( - - ) : ( - - )} - -
- {label && } -
-) - -export default Checkbox diff --git a/src/checkbox/index.ts b/src/checkbox/index.ts deleted file mode 100644 index 3b28771..0000000 --- a/src/checkbox/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './Checkbox' diff --git a/src/checkbox/styles.module.sass b/src/checkbox/styles.module.sass deleted file mode 100644 index aa3ec20..0000000 --- a/src/checkbox/styles.module.sass +++ /dev/null @@ -1,29 +0,0 @@ -@import ../variables - -.checkbox - display: flex - align-items: center - - .formField - margin-right: 5px - margin-bottom: -3px - - input - display: none - - svg - fill: #aeb7c2 - width: 16px - height: 16px - margin-bottom: -1.1px - - &.checked - svg - fill: #447bba - - label - cursor: pointer - color: var(--text-color-primary) - font-size: $fontSizeParagraph - width: 100% - display: flex diff --git a/src/chips-select/Chip.tsx b/src/chips-select/Chip.tsx deleted file mode 100644 index 154cdf1..0000000 --- a/src/chips-select/Chip.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import React from 'react' - -import styles from './styles.module.sass' - -import Icon from '@/icon' - -interface ChipProps { - text: string - onClickRemove?: (text: string) => void -} - -const Chip: React.FC = ({ text, onClickRemove }) => ( -
- {text} - -
-) - -export default Chip diff --git a/src/chips-select/ChipsSelect.tsx b/src/chips-select/ChipsSelect.tsx deleted file mode 100644 index d5e909a..0000000 --- a/src/chips-select/ChipsSelect.tsx +++ /dev/null @@ -1,183 +0,0 @@ -import React, { useCallback, useEffect, useRef, useState } from 'react' -import debounce from 'lodash-es/debounce' - -import styles from './styles.module.sass' - -import Chip from '@/chips-select/Chip' -import Icon from '@/icon' -import Spinner from '@/spinner' -import { concatClassNames as cn } from '@/tools' - -interface ChipsSelectProps { - className?: string - options?: string[] - loading?: boolean - disabled?: boolean - placeholder?: string - notFoundCaption?: string - label?: string - value?: string[] - onSelect?: (options: string[]) => void - onSearch?: (value: string) => void -} - -const ChipsSelect: React.FC = ({ - className, - options, - disabled, - loading, - value, - placeholder, - notFoundCaption, - label, - onSelect, - onSearch -}) => { - const dropdownRef = useRef(null) - const [search, setSearch] = useState() - const [localLoading, setLocaLoading] = useState(false) - const [isOpen, setIsOpen] = useState(false) - - const toggleDropdown = () => { - setIsOpen(!isOpen) - } - - const handleDebouncedSearch = useCallback( - debounce((value) => { - onSearch?.(value) - setLocaLoading(false) - }, 500), - [] - ) - - const optionInValue = (option?: string): boolean => - !!value?.find((item) => item?.toLowerCase() === option?.toLowerCase()) - - const handleKeyPress = (event: React.KeyboardEvent) => { - if (event.key === 'Enter' && search?.length) { - if (!optionInValue(search)) { - onSelect?.([...(value ?? []), search]) - } - - setIsOpen(false) - setSearch(undefined) - } - - if (event.key === 'Backspace' && value?.length && !search?.length) { - const updateValue = [...value] - - updateValue.pop() - - onSelect?.(updateValue) - } - } - - const handleChangeInput = (event: React.ChangeEvent) => { - const value = event.target.value.trim() - - if (value.length > 0) { - setLocaLoading(true) - } else { - setLocaLoading(false) - } - - setSearch(value) - handleDebouncedSearch(value) - } - - const handleSelect = (option: string) => { - if (!optionInValue(option)) { - onSelect?.([...(value ?? []), option]) - } - - setSearch(undefined) - setIsOpen(false) - } - - const handleClickRemove = (option: string): void => { - onSelect?.([...(value?.filter((item) => item !== option) ?? [])]) - } - - const handleClickOutside = (event: MouseEvent) => { - if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) { - setIsOpen(false) - } - } - - useEffect(() => { - document.addEventListener('mousedown', handleClickOutside) - - return () => { - document.removeEventListener('mousedown', handleClickOutside) - } - }, []) - - useEffect(() => { - if (search) { - setIsOpen(true) - } - }, [options]) - - return ( -
- {label && } -
-
- {value?.map((item, i) => ( - - ))} - - - {loading || localLoading ? ( - - ) : ( - - )} - -
- {isOpen && !loading && ( -
    e.stopPropagation()} - > - {!options?.length &&
  • {notFoundCaption}
  • } - {options?.map((option) => ( -
  • - -
  • - ))} -
- )} -
-
- ) -} - -export default ChipsSelect diff --git a/src/chips-select/index.ts b/src/chips-select/index.ts deleted file mode 100644 index 9ba2ddf..0000000 --- a/src/chips-select/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './ChipsSelect' diff --git a/src/chips-select/styles.module.sass b/src/chips-select/styles.module.sass deleted file mode 100644 index 98a1924..0000000 --- a/src/chips-select/styles.module.sass +++ /dev/null @@ -1,195 +0,0 @@ -@import ../variables - -.chipsSelect - display: block - - .label - display: block - color: var(--input-label-color) - overflow: hidden - padding-bottom: 4px - padding-top: 2px - text-overflow: ellipsis - white-space: nowrap - font-size: $fontSizeHeadline - - .loader - width: 18px !important - height: 18px !important - - .container - position: relative - background-color: var(--input-background-color) - border-radius: var(--border-radius) - - .searchContainer - width: 100% - line-height: 20px - position: relative - background-color: var(--input-background-color) - -webkit-tap-highlight-color: transparent - align-items: center - border-radius: inherit - box-sizing: border-box - border: var(--input-border) - color: var(--text-color-primary) - min-height: 36px - margin: 0 - padding: 0 12px 0 2px - //justify-content: space-between - display: flex - flex-grow: 1 - flex-shrink: 1 - flex-wrap: wrap - transition: border-color 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,background-color 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,box-shadow 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms - - .searchInput - background: transparent - border: none - outline: none - height: inherit - padding-left: 12px - flex: 1 - flex-direction: column - justify-content: center - color: inherit - font-family: var(--font-family) - font-size: var(--font-size) - - &:focus, &:active, &:hover - outline: none - border-color: var(--input-border-focus-color) - //box-shadow: rgba(25, 118, 210, 0.25) 0 0 0 0.05rem - - &.selected - color: var(--text-color-primary) - - span - overflow: hidden - white-space: nowrap - display: block - text-overflow: ellipsis - - img - width: 18px - height: 20px - margin-right: 5px - float: left - - .arrow - display: flex - margin-top: 1px - - svg - width: 24px - height: 24px - fill: var(--icon-color-secondary) - - .clear, .toggleButton - background: transparent - border: none - margin: 0 - padding: 0 - cursor: pointer - height: 24px - - .clear - svg - margin-top: 2px - width: 18px !important - height: 18px !important - - &:hover - fill: var(--icon-color-secondary-hover) - - &.open - .searchContainer - border-bottom-left-radius: 0 - border-bottom-right-radius: 0 - - .optionsList - position: absolute - background-color: var(--dropdown-background-color) - box-shadow: $boxShadow2 - border: var(--input-border) - list-style: none - padding: 0 - width: 100% - z-index: 405 - top: 35px - border-bottom-left-radius: 8px - border-bottom-right-radius: 8px - max-height: 200px - overflow: hidden - overflow-y: scroll - - li - font-size: $fontSizeParagraph - - button - margin: 0 - padding: 8px 10px - height: 100% - width: 100% - cursor: pointer - background: transparent - border: none - text-align: left - display: flex - align-items: center - - img - width: 14px - height: 15px - margin-right: 4px - - &:hover, &.active - background-color: var(--dropdown-background-color-hover) - - &:last-of-type - border-bottom-left-radius: 8px - border-bottom-right-radius: 8px - - .emptyItem - padding: 8px 10px - - &.disabled - .label - opacity: 0.7 - - .searchContainer - opacity: 0.5 - cursor: default - - .arrow - button - cursor: default - -.chip - display: inline-flex - margin: 2px - border-radius: var(--border-radius) - font-size: $fontSizeHeadline - box-sizing: border-box - border: 0.5px solid rgba(0, 0, 0, 0.08) - background: var(--input-background-content) - align-items: center - height: 28px - - .text - overflow: hidden - padding-left: 8px - - .close - border: none - background: none - cursor: pointer - - svg - width: 16px - height: 16px - fill: var(--icon-color-secondary) - vertical-align: middle - - &:hover - opacity: .7 diff --git a/src/button/Button.tsx b/src/components/button/Button.tsx similarity index 80% rename from src/button/Button.tsx rename to src/components/button/Button.tsx index 820b8e9..2da6f6a 100644 --- a/src/button/Button.tsx +++ b/src/components/button/Button.tsx @@ -1,15 +1,15 @@ import React from 'react' -import styles from './styles.module.sass' +import { cn } from '../../utils' +import Icon, { IconTypes } from '../icon' +import Spinner from '../spinner' -import Icon, { IconTypes } from '@/icon' -import Spinner from '@/spinner' -import { concatClassNames as cn } from '@/tools' +import styles from './styles.module.sass' /** * Button component properties */ -export interface ButtonProps extends Omit, 'content'> { +export interface ButtonProps extends React.ButtonHTMLAttributes { /** Additional class names for custom styling */ className?: string /** URL for link if button acts as a link */ @@ -25,13 +25,13 @@ export interface ButtonProps extends Omit = ({ @@ -45,7 +45,7 @@ const Button: React.FC = ({ variant, icon, children, - content, + label, ...props }) => { const button = ( @@ -59,11 +59,12 @@ const Button: React.FC = ({ variant && styles[variant], size && styles[size], stretched && styles.stretched, + loading && styles.loading, !children && styles.noText )} > {loading ? : icon && } -
{content ?? children}
+
{label?.length ? label : children}
) diff --git a/src/button/index.ts b/src/components/button/index.ts similarity index 100% rename from src/button/index.ts rename to src/components/button/index.ts diff --git a/src/button/styles.module.sass b/src/components/button/styles.module.sass similarity index 66% rename from src/button/styles.module.sass rename to src/components/button/styles.module.sass index fef9e99..819256d 100644 --- a/src/button/styles.module.sass +++ b/src/components/button/styles.module.sass @@ -1,5 +1,3 @@ -@import ../variables - .buttonLink text-decoration: none !important @@ -7,16 +5,16 @@ margin: 0 auto .button + font-family: var(--font-family), sans-serif + font-size: var(--font-size) + font-weight: var(--button-font-weight) + color: var(--button-default-color) + background: var(--button-default-background) + border-radius: var(--border-radius) cursor: pointer padding: 6px 10px border: 0 - border-radius: var(--border-radius) min-height: 28px - color: var(--button-default-color) - background: var(--button-default-background) - font-family: var(--font-family), serif - font-size: var(--font-size) - font-weight: 500 display: flex align-content: center justify-content: center @@ -36,6 +34,10 @@ &.stretched width: 100% + &.loading + cursor: wait + pointer-events: none + &.noText svg margin-right: 0 @@ -52,9 +54,8 @@ line-height: 15px .loader - height: 20px - width: 20px - margin-top: 0 + height: 16px + width: 16px &.medium padding: 8px 10px @@ -78,14 +79,24 @@ background-color: var(--button-primary-background-active) &.negative - background-color: var(--button-negative-background) - color: var(--button-negative-color) + background-color: var(--color-red) + color: var(--color-contrast) &:hover, &:focus - background-color: var(--button-negative-background-hover) + background-color: var(--color-red-hover) &:active - background-color: var(--button-negative-background-active) + background-color: var(--color-red-active) + + &.positive + background-color: var(--color-green) + color: var(--color-contrast) + + &:hover, &:focus + background-color: var(--color-green-hover) + + &:active + background-color: var(--color-green-active) &.secondary background-color: var(--button-secondary-background) @@ -99,6 +110,24 @@ background-color: var(--button-secondary-background-active) color: var(--button-secondary-color-active) + &.negative + color: var(--color-red) + + &:hover, &:focus + color: var(--color-red-hover) + + &:active + color: var(--color-red-active) + + &.positive + color: var(--color-green) + + &:hover, &:focus + color: var(--color-green-hover) + + &:active + color: var(--color-green-active) + &[disabled] opacity: .64 pointer-events: none !important diff --git a/src/icon/Icon.tsx b/src/components/icon/Icon.tsx similarity index 99% rename from src/icon/Icon.tsx rename to src/components/icon/Icon.tsx index 18ae5b8..79aea7d 100644 --- a/src/icon/Icon.tsx +++ b/src/components/icon/Icon.tsx @@ -4,6 +4,7 @@ import { IconTypes } from './types' interface IconProps extends React.SVGProps { name: IconTypes + className?: string } const Icon: React.FC = ({ name, ...props }) => { diff --git a/src/icon/index.ts b/src/components/icon/index.ts similarity index 100% rename from src/icon/index.ts rename to src/components/icon/index.ts diff --git a/src/icon/types.ts b/src/components/icon/types.ts similarity index 100% rename from src/icon/types.ts rename to src/components/icon/types.ts diff --git a/src/spinner/Spinner.tsx b/src/components/spinner/Spinner.tsx similarity index 96% rename from src/spinner/Spinner.tsx rename to src/components/spinner/Spinner.tsx index f994a9d..10fb5d8 100644 --- a/src/spinner/Spinner.tsx +++ b/src/components/spinner/Spinner.tsx @@ -1,8 +1,8 @@ import React from 'react' -import styles from './styles.module.sass' +import { cn } from '../../utils' -import { concatClassNames as cn } from '@/tools' +import styles from './styles.module.sass' interface SpinnerProps { className?: string diff --git a/src/spinner/index.ts b/src/components/spinner/index.ts similarity index 100% rename from src/spinner/index.ts rename to src/components/spinner/index.ts diff --git a/src/components/spinner/styles.module.sass b/src/components/spinner/styles.module.sass new file mode 100644 index 0000000..85fc76c --- /dev/null +++ b/src/components/spinner/styles.module.sass @@ -0,0 +1,4 @@ +@import ../../styles/animations + +.spinner + animation: animation-spin 1s linear infinite diff --git a/src/container/Container.tsx b/src/container/Container.tsx deleted file mode 100644 index c96f2d9..0000000 --- a/src/container/Container.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import React from 'react' - -import styles from './styles.module.sass' - -import { concatClassNames as cn } from '@/tools' - -/** - * Interface for the properties of a container component. - */ -export interface ContainerProps extends React.HTMLAttributes { - /** The title of the container. Displayed at the top of the container */ - title?: string - /** Additional class names to apply to the container */ - className?: string - /** An action element, typically a button or link, displayed in the container header */ - action?: React.ReactNode - /** Custom header content for the container */ - header?: React.ReactNode - /** The content of the container */ - children?: React.ReactNode - /** Custom footer content for the container */ - footer?: React.ReactNode -} - -const Container: React.FC = ({ className, title, action, header, children, footer, ...props }) => ( -
- {(header || title || action) && ( -
- {title &&

{title}

} - {header} - {action &&
{action}
} -
- )} - {children} - {footer} -
-) - -export default Container diff --git a/src/container/index.ts b/src/container/index.ts deleted file mode 100644 index 0f4b8a6..0000000 --- a/src/container/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from './Container' -export type { ContainerProps } from './Container' diff --git a/src/container/styles.module.sass b/src/container/styles.module.sass deleted file mode 100644 index edf8016..0000000 --- a/src/container/styles.module.sass +++ /dev/null @@ -1,38 +0,0 @@ -@import ../variables - -.container - margin-top: 15px - padding: 15px - width: 100% - background: var(--container-background) - border-radius: var(--border-radius) - box-shadow: var(--container-shadow) - position: relative - transition: background-color 0.5s ease - - &:before - border-radius: inherit - box-shadow: inherit - content: "" - height: 100% - left: 0 - pointer-events: none - position: absolute - top: 0 - width: 100% - - .header - margin: -5px -15px 5px -15px - padding: 0 10px 0 15px - display: flex - justify-content: space-between - - .title - line-height: 29px - - .actions - display: flex - align-items: center - - button - margin-left: 10px diff --git a/src/counter/Counter.tsx b/src/counter/Counter.tsx deleted file mode 100644 index de4ad46..0000000 --- a/src/counter/Counter.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import React from 'react' - -import styles from './styles.module.sass' - -import { concatClassNames as cn } from '@/tools' - -interface CounterProps { - value?: number - className?: string -} - -const Counter: React.FC = ({ value, className }) => - value ?
{value}
: <> - -export default Counter diff --git a/src/counter/index.ts b/src/counter/index.ts deleted file mode 100644 index 7bf5fdd..0000000 --- a/src/counter/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './Counter' diff --git a/src/counter/styles.module.sass b/src/counter/styles.module.sass deleted file mode 100644 index 73314b9..0000000 --- a/src/counter/styles.module.sass +++ /dev/null @@ -1,14 +0,0 @@ -@import ../variables - -.counter - height: 16px - min-width: 16px - align-items: center - box-sizing: border-box - display: flex - justify-content: center - text-align: center - background: var(--color-red) - color: #FFF - border-radius: 50% - font-size: $fontSizeCaption diff --git a/src/dialog/Dialog.tsx b/src/dialog/Dialog.tsx deleted file mode 100644 index f0369df..0000000 --- a/src/dialog/Dialog.tsx +++ /dev/null @@ -1,131 +0,0 @@ -import React, { useEffect, useRef, useState } from 'react' - -import styles from './styles.module.sass' - -import Icon from '@/icon' - -/** - * Dialog component properties - */ -export interface DialogProps extends React.HTMLAttributes { - /** Whether the dialog is open or closed */ - open?: boolean - /** Header text for the dialog */ - header?: string - /** Height for the content area of the dialog (e.g., in 'px', 'rem', etc.) */ - contentHeight?: string - /** Maximum width for the dialog (e.g., in 'px', 'rem', etc.) */ - maxWidth?: string - /** Text for the back link (if applicable) */ - backLinkCaption?: string - /** Show or hide the back link in the dialog */ - showBackLink?: boolean - /** Actions or buttons to be displayed at the bottom of the dialog */ - actions?: React.ReactNode - /** Content inside the dialog */ - children?: React.ReactNode - /** Callback function triggered when the back link is clicked */ - onBackClick?: () => void - /** Callback function triggered when the dialog is closed */ - onCloseDialog?: () => void -} - -const Dialog: React.FC = ({ - open, - header, - contentHeight, - maxWidth = '500px', - backLinkCaption, - showBackLink, - actions, - children, - onBackClick, - onCloseDialog, - ...props -}) => { - const dialogRef = useRef(null) - const [dialogStyle, setDialogStyle] = useState({}) - - const handleResize = () => { - // const viewportWidth = window.innerWidth - const viewportHeight = window.innerHeight - - // const dialogWidth = dialogRef?.current?.offsetWidth || 0 - const dialogHeight = dialogRef.current?.offsetHeight || 0 - - // const left = (viewportWidth - dialogWidth) / 2 - const top = (viewportHeight - dialogHeight) / 2 - - setDialogStyle({ - // left: `${left}px`, - maxWidth, - top: `${top}px` - }) - } - - const handleKeyDown = (event: KeyboardEvent) => { - if (event.key === 'Escape') { - onCloseDialog?.() - } - } - - const handleClickOutside = (event: MouseEvent) => { - if (dialogRef.current && !dialogRef.current.contains(event.target as Node)) { - onCloseDialog?.() - } - } - - useEffect(() => { - document.addEventListener('resize', handleResize) - document.addEventListener('mousedown', handleClickOutside) - document.addEventListener('keydown', handleKeyDown) - - return () => { - document.removeEventListener('resize', handleResize) - document.removeEventListener('mousedown', handleClickOutside) - document.removeEventListener('keydown', handleKeyDown) - } - }, []) - - useEffect(() => { - if (open) { - handleResize() - } - }, [open]) - - return open ? ( - - {(header || showBackLink) && ( -
- {showBackLink && ( - - )} -

{header}

- {actions &&
{actions}
} -
- )} -
- {children} -
-
- ) : ( - <> - ) -} - -export default Dialog diff --git a/src/dialog/index.ts b/src/dialog/index.ts deleted file mode 100644 index 3813c6c..0000000 --- a/src/dialog/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from './Dialog' -export type { DialogProps } from './Dialog' diff --git a/src/dialog/styles.module.sass b/src/dialog/styles.module.sass deleted file mode 100644 index 8c0d4ce..0000000 --- a/src/dialog/styles.module.sass +++ /dev/null @@ -1,54 +0,0 @@ -@import ../variables - -.dialog - position: fixed - background-color: var(--modal-background) - border-radius: var(--border-radius) - border: none - box-shadow: $boxShadow5 - width: 100% - z-index: 600 - max-height: 80vh - overflow: hidden - padding: 0 - - @media only screen and (max-width: $mobileMaxWidth) - width: 96% - - .header - padding: 15px - text-align: center - border-bottom: var(--input-border) - - .backLink - position: absolute - border: 0 - background: transparent - cursor: pointer - display: flex - align-items: center - margin-left: 0 - font-family: var(--font-family), serif - - svg - width: 24px - height: 24px - fill: var(--input-label-color) - - div - color: var(--input-label-color) - - .actions - position: absolute - right: 15px - top: 13px - display: flex - align-items: center - - .content - max-height: 70vh - overflow-y: auto - padding: 20px - - .header + .content - padding: 10px 20px diff --git a/src/dropdown/Dropdown.tsx b/src/dropdown/Dropdown.tsx deleted file mode 100644 index 8321538..0000000 --- a/src/dropdown/Dropdown.tsx +++ /dev/null @@ -1,146 +0,0 @@ -import React, { useEffect, useRef, useState } from 'react' - -import styles from './styles.module.sass' - -import OptionsList from '@/dropdown/OptionsList' -import Icon from '@/icon' -import { concatClassNames as cn } from '@/tools' - -export type DropdownOption = { - key: string | number - value: React.ReactNode | string | number - image?: string - disabled?: boolean -} - -interface DropdownProps { - className?: string - options?: DropdownOption[] - required?: boolean - disabled?: boolean - clearable?: boolean - placeholder?: string - label?: string - error?: string - value?: T - onSelect?: (selectedOption: DropdownOption | undefined) => void - onOpen?: () => void -} - -const Dropdown: React.FC> = ({ - className, - required, - options, - disabled, - clearable, - value, - placeholder, - label, - error, - onSelect, - onOpen -}) => { - const dropdownRef = useRef(null) - const [isOpen, setIsOpen] = useState(false) - const [selectedOption, setSelectedOption] = useState(undefined) - - const toggleDropdown = () => { - if (onOpen) { - onOpen() - } else { - setIsOpen(!isOpen) - } - } - - const handleSelect = (option: DropdownOption | undefined) => { - if (selectedOption?.key !== option?.key) { - setSelectedOption(option) - onSelect?.(option ?? undefined) - } - - setIsOpen(false) - } - - const handleClickOutside = (event: MouseEvent) => { - if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) { - setIsOpen(false) - } - } - - const handleClearClick = (event: React.MouseEvent) => { - event.stopPropagation() - handleSelect(undefined) - } - - useEffect(() => { - document.addEventListener('mousedown', handleClickOutside) - - return () => { - document.removeEventListener('mousedown', handleClickOutside) - } - }, []) - - useEffect(() => { - if (!value) { - setSelectedOption(undefined) - } else { - setSelectedOption(value) - } - }, [value]) - - return ( -
- {label && } -
- - )} - {isOpen ? : } - - - {isOpen && ( - - )} -
-
- ) -} - -export default Dropdown diff --git a/src/dropdown/OptionsList.tsx b/src/dropdown/OptionsList.tsx deleted file mode 100644 index 6a5e10f..0000000 --- a/src/dropdown/OptionsList.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import React from 'react' - -import type { DropdownOption } from './Dropdown' -import styles from './styles.module.sass' - -import { concatClassNames as cn } from '@/tools' - -interface DropdownProps { - options?: DropdownOption[] - selectedOption?: DropdownOption - onSelect?: (selectedOption: DropdownOption) => void -} - -const OptionsList: React.FC = ({ selectedOption, options, onSelect }) => ( -
    - {options?.map((option) => ( -
  • - -
  • - ))} -
-) - -export default OptionsList diff --git a/src/dropdown/index.ts b/src/dropdown/index.ts deleted file mode 100644 index 293f6fd..0000000 --- a/src/dropdown/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default } from './Dropdown' -export type { DropdownOption } from './Dropdown' diff --git a/src/dropdown/styles.module.sass b/src/dropdown/styles.module.sass deleted file mode 100644 index 5050636..0000000 --- a/src/dropdown/styles.module.sass +++ /dev/null @@ -1,165 +0,0 @@ -@import ../variables - -.optionsList - list-style: none - padding: 0 - width: 100% - z-index: 405 - - li - button - margin: 0 - height: 100% - width: 100% - padding: 8px 10px - color: var(--text-color-primary) - font-size: $fontSizeParagraph - cursor: pointer - background: transparent - border: none - text-align: left - display: flex - align-items: center - - img - width: 14px - height: 15px - margin-right: 4px - - &.disabled - pointer-events: none - cursor: not-allowed - opacity: .5 - - &:hover, &.active - background-color: var(--input-background-color) - -.dropdown - display: block - - .label - display: block - color: var(--input-label-color) - overflow: hidden - padding-bottom: 4px - padding-top: 2px - text-overflow: ellipsis - white-space: nowrap - font-size: $fontSizeHeadline - - .container - position: relative - background-color: var(--input-background-color) - border-radius: var(--border-radius) - - .dropdownButton - width: 100% - font-size: $fontSizeParagraph - line-height: 20px - position: relative - -webkit-tap-highlight-color: transparent - align-items: center - border-radius: inherit - box-sizing: border-box - border: var(--input-border) - background-color: transparent - color: var(--input-label-color) - height: 36px - margin: 0 - padding: 0 12px - cursor: pointer - display: flex - justify-content: space-between - transition: border-color 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,background-color 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,box-shadow 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms - - &:focus, &:active, &:hover - outline: none - border-color: var(--input-border-focus-color) - //box-shadow: rgba(25, 118, 210, 0.25) 0 0 0 0.05rem - - &.selected - color: var(--text-color-primary) - - span - overflow: hidden - white-space: nowrap - display: block - text-overflow: ellipsis - - img - width: 18px - height: 20px - margin-right: 5px - float: left - - .placeHolder - color: var(--input-label-color) - - .arrow - display: flex - margin-top: 1px - - svg - width: 24px - height: 24px - fill: var(--icon-color-secondary) - - .clear - background: transparent - border: none - margin: 0 - padding: 0 - cursor: pointer - - svg - margin-top: 2px - width: 18px !important - height: 18px !important - - &:hover - fill: var(--icon-color-secondary-hover) - - &.disabled - .label - opacity: 0.7 - - .dropdownButton - opacity: 0.5 - cursor: default - - &.required - .label:after - content: '*' - margin-left: 3px - color: var(--color-red) - - &.error - .dropdownButton - background-color: var(--input-background-color-error) - border-color: #e64646 !important - - &.open - .dropdownButton - border-bottom-left-radius: 0 - border-bottom-right-radius: 0 - - .optionsList - position: absolute - background-color: var(--dropdown-background-color) - box-shadow: $boxShadow2 - border: var(--input-border) - top: 33px - border-bottom-left-radius: var(--border-radius) - border-bottom-right-radius: var(--border-radius) - max-height: 200px - z-index: 405 - overflow: hidden - overflow-y: scroll - - li - &:hover, &.active - background-color: var(--dropdown-background-color-hover) - - &:last-of-type - border-bottom-left-radius: var(--border-radius) - border-bottom-right-radius: var(--border-radius) diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..f073cee --- /dev/null +++ b/src/index.ts @@ -0,0 +1,11 @@ +// Button Component +export { default as Button } from './components/button' +export type { ButtonProps } from './components/button' + +// Icon Component +export { default as Icon } from './components/icon' +export { iconNames } from './components/icon' +export type { IconTypes } from './components/icon' + +// Tools +export { cn } from './utils' diff --git a/src/index.tsx b/src/index.tsx deleted file mode 100644 index 708fc74..0000000 --- a/src/index.tsx +++ /dev/null @@ -1,24 +0,0 @@ -export { default as Autocomplete } from './autocomplete' -export { default as Badge } from './badge' -export { default as Breadcrumbs } from './breadcrumbs' -export * as Button from './button' -export { default as Carousel } from './carousel' -export { default as Checkbox } from './checkbox' -export { default as ChipsSelect } from './chips-select' -export { default as Container } from './container' -export { default as Counter } from './counter' -export { default as Dialog } from './dialog' -export { default as Dropdown } from './dropdown' -export * as Icon from './icon' -export { default as Input } from './input' -export { default as Message } from './message' -export { default as Pagination } from './pagination' -export { default as Popout } from './popout' -export { default as Progress } from './progress' -export { default as RadioButton } from './radio-button' -export { default as Rating } from './rating' -export { default as RatingColored } from './rating-colored' -export { default as ScreenSpinner } from './screen-spinner' -export { default as Spinner } from './spinner' -export { default as TabHeader } from './tabs' -export { default as Textarea } from './textarea' diff --git a/src/input/Input.tsx b/src/input/Input.tsx deleted file mode 100644 index e8d3b42..0000000 --- a/src/input/Input.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import React from 'react' - -import styles from './styles.module.sass' - -import { concatClassNames as cn } from '@/tools' - -interface InputProps extends React.InputHTMLAttributes { - label?: string - error?: string -} - -const Input: React.FC = ({ label, error, ...props }: InputProps): JSX.Element => ( -
- {label && } - - - -
-) - -export default Input diff --git a/src/input/index.ts b/src/input/index.ts deleted file mode 100644 index aa97178..0000000 --- a/src/input/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './Input' diff --git a/src/input/styles.module.sass b/src/input/styles.module.sass deleted file mode 100644 index b6a4d20..0000000 --- a/src/input/styles.module.sass +++ /dev/null @@ -1,76 +0,0 @@ -@import ../variables - -.input - display: block - - .label - display: block - color: var(--input-label-color) - overflow: hidden - padding-bottom: 6px - padding-top: 2px - text-overflow: ellipsis - white-space: nowrap - font-size: $fontSizeHeadline - - .formField - line-height: 20px - position: relative - background-color: var(--input-background-color) - -webkit-tap-highlight-color: transparent - align-items: center - border-radius: var(--border-radius) - box-sizing: border-box - display: flex - font-family: var(--font-family) - - .input - appearance: none - background: transparent - border: var(--input-border) - border-radius: inherit - box-shadow: none - box-sizing: border-box - color: var(--text-color-primary) - height: 36px - margin: 0 - padding: 0 12px - position: relative - width: 100% - outline: none - font-family: inherit - font-size: var(--font-size) - transition: border-color 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,background-color 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms,box-shadow 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms - - &:focus, &:active - outline: none - border-color: var(--input-border-focus-color) - //box-shadow: rgba(25, 118, 210, 0.25) 0 0 0 0.05rem - - &.disabled - .label - opacity: 0.7 - - .formField - .input - opacity: 0.5 - - &:focus, &:active - border-color: inherit - - &.required - .label:after - content: '*' - margin-left: 3px - color: var(--color-red) - - &.error - .formField - background-color: var(--input-background-color-error) - - input - border-color: #e64646 !important - - [readonly] - cursor: default - color: rgba(0, 0, 0, 0.41) !important diff --git a/src/message/Message.tsx b/src/message/Message.tsx deleted file mode 100644 index 8f1f895..0000000 --- a/src/message/Message.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import React from 'react' - -import styles from './styles.module.sass' - -import { concatClassNames as cn } from '@/tools' - -interface MessageProps extends React.HTMLAttributes { - title?: string - list?: string[] - text?: string - type?: 'negative' | 'positive' -} - -const Message: React.FC = ({ title, text, list, type, ...props }) => ( -
- {title &&

{title}

} - {text &&

{text}

} - {list &&
    {list.map((item) => (item.length ?
  • {item}
  • : ''))}
} -
-) - -export default Message diff --git a/src/message/index.ts b/src/message/index.ts deleted file mode 100644 index b75f433..0000000 --- a/src/message/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './Message' diff --git a/src/message/styles.module.sass b/src/message/styles.module.sass deleted file mode 100644 index ffa86cb..0000000 --- a/src/message/styles.module.sass +++ /dev/null @@ -1,38 +0,0 @@ -@import ../variables - -.message - width: 100% - padding: 8px 12px - position: relative - border-radius: var(--border-radius) - margin-bottom: 15px - - p - width: 100% - display: block - - ul - list-style: inherit - margin-left: 20px - - .title - margin: 0 0 5px - font-weight: 600 - - .content - margin: 0 - - li - font-size: $fontSizeHeadline - - &.negative - background-color: var(--container-background-color-error) - - p, li - color: var(--container-color-error) - - &.positive - background-color: var(--container-background-color-success) - - p, li - color: var(--container-color-success) diff --git a/src/pagination/Pagination.tsx b/src/pagination/Pagination.tsx deleted file mode 100644 index f4292bf..0000000 --- a/src/pagination/Pagination.tsx +++ /dev/null @@ -1,162 +0,0 @@ -import React, { useMemo } from 'react' - -import styles from './styles.module.sass' - -import Icon from '@/icon' -import { concatClassNames as cn, encodeQueryData } from '@/tools' - -const LEFT_PAGE = 'LEFT' -const RIGHT_PAGE = 'RIGHT' - -interface PaginationProps { - currentPage?: number - totalItemsCount?: number - linkPart?: string - captionPage?: string - captionNextPage?: string - captionPrevPage?: string - urlParam?: T - perPage?: number - neighbours?: number - hideIfOnePage?: boolean - hideArrows?: boolean - onChangePage?: (page: number) => void -} - -const Pagination: React.FC> = ({ - currentPage = 1, - totalItemsCount = 0, - linkPart, - captionPage, - captionNextPage, - captionPrevPage, - urlParam, - hideIfOnePage, - hideArrows, - perPage = 4, - neighbours = 2, - onChangePage -}) => { - const pageNeighbours = Math.max(0, Math.min(neighbours, 2)) - const totalPages = Math.ceil(totalItemsCount / perPage) - - const link = `/${linkPart}` - - const fetchPageNumbers: (string | number)[] = useMemo(() => { - const totalNumbers = pageNeighbours * 2 + 3 - const totalBlocks = totalNumbers + 2 - - if (totalPages > totalBlocks) { - let pages = [] - - const leftBound = currentPage - pageNeighbours - const rightBound = currentPage + pageNeighbours - const beforeLastPage = totalPages - 1 - - const startPage = leftBound > 2 ? leftBound : 2 - const endPage = rightBound < beforeLastPage ? rightBound : beforeLastPage - - pages = range(startPage, endPage) - - const pagesCount = pages.length - const singleSpillOffset = totalNumbers - pagesCount - 1 - - const leftSpill = startPage > 2 - const rightSpill = endPage < beforeLastPage - - if (leftSpill && !rightSpill) { - const extraPages = range(startPage - singleSpillOffset, startPage - 1) - pages = [LEFT_PAGE, ...extraPages, ...pages] - } else if (!leftSpill && rightSpill) { - const extraPages = range(endPage + 1, endPage + singleSpillOffset) - pages = [...pages, ...extraPages, RIGHT_PAGE] - } else if (leftSpill && rightSpill) { - pages = [LEFT_PAGE, ...pages, RIGHT_PAGE] - } - - return [1, ...pages, totalPages] - } - - return range(1, totalPages) - }, [currentPage, pageNeighbours, totalPages]) - - return hideIfOnePage && totalPages === 1 ? ( - <> - ) : ( - - ) -} - -/** - * Generates an array of numbers in a certain range and with a given step - * @param from - * @param to - * @param step - */ -export const range = (from: number, to: number, step = 1) => { - let i = from - const range: number[] = [] - - while (i <= to) { - range.push(i) - i += step - } - - return range -} - -export default Pagination diff --git a/src/pagination/index.ts b/src/pagination/index.ts deleted file mode 100644 index 40ac52f..0000000 --- a/src/pagination/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './Pagination' diff --git a/src/pagination/styles.module.sass b/src/pagination/styles.module.sass deleted file mode 100644 index da14bbf..0000000 --- a/src/pagination/styles.module.sass +++ /dev/null @@ -1,35 +0,0 @@ -@import ../variables - -.pagination - display: flex - justify-content: center - - .item - color: var(--text-color-secondary) - vertical-align: middle - text-align: center - border-radius: var(--border-radius) - text-decoration: none - width: 32px - height: 32px - line-height: 30px - padding: 0 6px - margin: 0 3px - border: 1px solid rgba(255, 255, 255, 0.23) - transition: color 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms, background-color 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms - - svg - margin-top: 6px - fill: var(--icon-color-secondary) - - &:hover - color: var(--text-color-primary) - background-color: rgba(0,16,61,.04) - - svg - fill: var(--text-color-primary) - - &.active, &:active - color: var(--text-color-primary) - background-color: rgba(0,16,61,.08) - font-weight: 500 diff --git a/src/popout/Popout.tsx b/src/popout/Popout.tsx deleted file mode 100644 index 195c00b..0000000 --- a/src/popout/Popout.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import React, { useEffect, useRef, useState } from 'react' - -import styles from './styles.module.sass' - -import { concatClassNames as cn } from '@/tools' - -interface PaginationProps { - className?: string - position?: 'left' | 'right' - action?: React.ReactNode | string - children?: React.ReactNode -} - -const Popout: React.FC = ({ className, position, action, children }) => { - const popoutRef = useRef(null) - const popoutChildrenRef = useRef(null) - const [isOpen, setIsOpen] = useState(false) - - const toggleDropdown = (event: React.MouseEvent) => { - event.stopPropagation() - - setIsOpen(!isOpen) - } - - const handleClickOutside = (event: MouseEvent) => { - if (popoutRef.current && !popoutRef.current.contains(event.target as Node)) { - setIsOpen(false) - } - - if (popoutChildrenRef.current && !popoutChildrenRef.current.contains(event.target as Node)) { - setIsOpen(false) - } - } - - useEffect(() => { - document.addEventListener('mousedown', handleClickOutside) - - return () => { - document.removeEventListener('mousedown', handleClickOutside) - } - }, []) - - return ( -
- - - {isOpen && ( -
setIsOpen(false)} - style={position === 'left' ? { left: 0 } : { right: 0 }} - > - {children} -
- )} -
- ) -} - -export default Popout diff --git a/src/popout/index.ts b/src/popout/index.ts deleted file mode 100644 index 2c9e709..0000000 --- a/src/popout/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './Popout' diff --git a/src/popout/styles.module.sass b/src/popout/styles.module.sass deleted file mode 100644 index 2205b52..0000000 --- a/src/popout/styles.module.sass +++ /dev/null @@ -1,31 +0,0 @@ -@import ../variables - -.popout - position: relative - display: inline-block - - .trigger - background-color: transparent - border: none - padding: 0 - margin: 0 - cursor: pointer - - .content - background-color: var(--modal-background) - border-radius: var(--border-radius) - position: absolute - min-width: 160px - //box-shadow: 0 0 2px rgba(0,0,0,.08), 0 4px 16px rgba(0,0,0,.08) - box-shadow: $boxShadow4 - z-index: 405 - - //&::after - // content: '' - // position: absolute - // top: -20px - // right: 7px - // border-width: 10px - // border-style: solid - // border-color: transparent transparent white transparent - // z-index: 1 diff --git a/src/progress/Progress.tsx b/src/progress/Progress.tsx deleted file mode 100644 index 9fcc059..0000000 --- a/src/progress/Progress.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import React from 'react' - -import styles from './styles.module.sass' - -import { concatClassNames as cn } from '@/tools' - -interface ProgressProps { - value?: number - className?: string -} - -const Progress: React.FC = ({ value, className }) => ( -
-
-
-) - -export default Progress diff --git a/src/progress/index.ts b/src/progress/index.ts deleted file mode 100644 index ba7fd79..0000000 --- a/src/progress/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './Progress' diff --git a/src/progress/styles.module.sass b/src/progress/styles.module.sass deleted file mode 100644 index 141375e..0000000 --- a/src/progress/styles.module.sass +++ /dev/null @@ -1,12 +0,0 @@ -@import ../variables - -.progress - height: 2px - background-color: var(--text-color-secondary) - min-width: 100px - border-radius: var(--border-radius) - - .line - border-radius: var(--border-radius) - background-color: var(--link-color) - height: inherit diff --git a/src/radio-button/RadioButton.tsx b/src/radio-button/RadioButton.tsx deleted file mode 100644 index fff9107..0000000 --- a/src/radio-button/RadioButton.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import React from 'react' - -import styles from './styles.module.sass' - -import Icon from '@/icon' -import { concatClassNames as cn } from '@/tools' - -interface RadioButtonProps extends React.InputHTMLAttributes { - label?: string -} - -const RadioButton: React.FC = ({ label, ...props }) => ( -
-
- {props.checked ? : } - -
- {label && } -
-) - -export default RadioButton diff --git a/src/radio-button/index.ts b/src/radio-button/index.ts deleted file mode 100644 index 9be8fbc..0000000 --- a/src/radio-button/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './RadioButton' diff --git a/src/radio-button/styles.module.sass b/src/radio-button/styles.module.sass deleted file mode 100644 index 6452cb5..0000000 --- a/src/radio-button/styles.module.sass +++ /dev/null @@ -1,28 +0,0 @@ -@import ../variables - -.radioButton - display: flex - align-items: center - - .formField - margin-right: 5px - margin-bottom: -3px - - input - display: none - - svg - fill: #aeb7c2 - width: 16px - height: 16px - margin-bottom: -1.1px - - &.checked - svg - fill: #447bba - - label - cursor: pointer - color: var(--text-color-primary) - font-size: $fontSizeParagraph - width: 100% diff --git a/src/rating-colored/RatingColored.tsx b/src/rating-colored/RatingColored.tsx deleted file mode 100644 index 993e668..0000000 --- a/src/rating-colored/RatingColored.tsx +++ /dev/null @@ -1,54 +0,0 @@ -'use client' - -import React from 'react' - -import styles from './styles.module.sass' - -import { concatClassNames as cn } from '@/tools' - -interface RatingColoredProps { - className?: string - value?: number - children?: React.ReactNode -} - -const RatingColored: React.FC = ({ className, value, children }) => - value ? ( -
- {children} -
- ) : ( - <> - ) - -const interpolateColor = (value: number, startColor: string, endColor: string): string => { - const rgb = (color: any) => color.match(/\w\w/g).map((x: string) => parseInt(x, 16)) - - const [startR, startG, startB] = rgb(startColor) - const [endR, endG, endB] = rgb(endColor) - - const r = Math.round(startR + (endR - startR) * value) - const g = Math.round(startG + (endG - startG) * value) - const b = Math.round(startB + (endB - startB) * value) - - return `rgb(${r}, ${g}, ${b})` -} - -const getColorByValue = (value: number): string => { - if (value <= 2) { - return interpolateColor(value - 1, '#e64646', '#ea5d2e') - } - if (value <= 3) { - return interpolateColor(value - 2, '#ea5d2e', '#eaae2e') - } - if (value <= 4) { - return interpolateColor(value - 3, '#eaae2e', '#9ec528') - } - - return interpolateColor(value - 4, '#9ec528', '#4bb34b') -} - -export default RatingColored diff --git a/src/rating-colored/index.ts b/src/rating-colored/index.ts deleted file mode 100644 index 5e2898e..0000000 --- a/src/rating-colored/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './RatingColored' diff --git a/src/rating-colored/styles.module.sass b/src/rating-colored/styles.module.sass deleted file mode 100644 index 40466f7..0000000 --- a/src/rating-colored/styles.module.sass +++ /dev/null @@ -1,9 +0,0 @@ -@import ../variables - -.ratingColored - text-align: center - color: #FFF - box-shadow: 0 2px 24px 0 rgba(0,0,0,.08),0 0 2px 0 rgba(0,0,0,.08) - padding: 2px 6px - border-radius: var(--border-radius) - opacity: .8 diff --git a/src/rating/Rating.tsx b/src/rating/Rating.tsx deleted file mode 100644 index bce788b..0000000 --- a/src/rating/Rating.tsx +++ /dev/null @@ -1,63 +0,0 @@ -'use client' - -import React, { useState } from 'react' - -import styles from './styles.module.sass' - -import Icon from '@/icon' -import { concatClassNames as cn } from '@/tools' - -interface RatingProps { - value?: number - voted?: boolean - disabled?: boolean - onChange?: (rating: number) => void -} - -const Rating: React.FC = ({ value, voted, disabled, onChange }) => { - const [hoverRating, setHoverRating] = useState() - - const showFullStar = (rating: number) => - (!hoverRating && value && value >= (rating || 0)) || (hoverRating && hoverRating >= rating) - - return ( -
    - {[1, 2, 3, 4, 5].map((rating) => ( -
  • = rating ? styles.hovered : undefined, - voted && styles.voted, - hoverRating === rating ? styles.current : undefined - )} - onMouseEnter={() => { - setHoverRating(rating) - }} - onMouseLeave={() => { - setHoverRating(undefined) - }} - > - -
  • - ))} -
- ) -} - -export default Rating diff --git a/src/rating/index.ts b/src/rating/index.ts deleted file mode 100644 index 3169e5d..0000000 --- a/src/rating/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './Rating' diff --git a/src/rating/styles.module.sass b/src/rating/styles.module.sass deleted file mode 100644 index a700ae4..0000000 --- a/src/rating/styles.module.sass +++ /dev/null @@ -1,36 +0,0 @@ -@import ../variables - -.rating - display: flex - - svg - margin-right: 0 !important - fill: var(--icon-color-secondary) !important - transform: scale(1) - transition: transform 0.15s ease - width: 22px - height: 22px - - .voted - svg - fill: #faaf00 !important - - .hovered, .fullStar - svg - fill: #faaf00 !important - - .current - svg - transform: scale(1.2) - - label - cursor: pointer - padding: 0 - margin: 0 - - input[type="radio"] - display: none - - li - margin: 0 !important - height: 22px diff --git a/src/screen-spinner/ScreenSpinner.tsx b/src/screen-spinner/ScreenSpinner.tsx deleted file mode 100644 index 559a989..0000000 --- a/src/screen-spinner/ScreenSpinner.tsx +++ /dev/null @@ -1,36 +0,0 @@ -'use client' - -import React, { useEffect } from 'react' - -import styles from './styles.module.sass' - -import Spinner from '@/spinner' - -interface ScreenSpinnerProps { - text?: string -} - -const ScreenSpinner: React.FC = ({ text }) => { - useEffect(() => { - const globalDiv = document.createElement('div') - - globalDiv.className = styles.overlay - - document.body.appendChild(globalDiv) - - return () => { - document.body.removeChild(globalDiv) - } - }, []) - - return ( -
-
- - {text &&
{text}
} -
-
- ) -} - -export default ScreenSpinner diff --git a/src/screen-spinner/index.ts b/src/screen-spinner/index.ts deleted file mode 100644 index 4e87355..0000000 --- a/src/screen-spinner/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './ScreenSpinner' diff --git a/src/screen-spinner/styles.module.sass b/src/screen-spinner/styles.module.sass deleted file mode 100644 index 159ce66..0000000 --- a/src/screen-spinner/styles.module.sass +++ /dev/null @@ -1,45 +0,0 @@ -@import ../variables -@import ../animations - -.overlay - opacity: 1 - height: 100% - width: 100% - z-index: 600 - position: fixed - top: 0 - left: 0 - -.screenSpinner - position: absolute - z-index: 605 - height: 100% - width: 100% - display: flex - align-items: center - justify-content: center - left: 0 - top: 0 - - .container - background-color: var(--input-background-color) - border-radius: var(--border-radius) - box-shadow: 0 0 8px rgba(0,0,0,.12),0 16px 16px rgba(0,0,0,.16) - display: flex - flex-direction: column - align-items: center - justify-content: center - flex-wrap: wrap - min-height: 130px - min-width: 130px - - svg - margin: 30px - width: 50px - height: 50px - animation: animation-spin 1s linear infinite - - .text - margin: 0 20px 20px - min-width: 200px - text-align: center diff --git a/src/skeleton/Skeleton.tsx b/src/skeleton/Skeleton.tsx deleted file mode 100644 index 749ff95..0000000 --- a/src/skeleton/Skeleton.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import React from 'react' - -import styles from './styles.module.sass' - -import { concatClassNames as cn } from '@/tools' - -interface SkeletonProps extends React.HTMLAttributes { - className?: string -} - -const Skeleton: React.FC = ({ ...props }) => ( -
-) - -export default Skeleton diff --git a/src/skeleton/index.ts b/src/skeleton/index.ts deleted file mode 100644 index 3ec6c00..0000000 --- a/src/skeleton/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './Skeleton' diff --git a/src/skeleton/styles.module.sass b/src/skeleton/styles.module.sass deleted file mode 100644 index 59b1f37..0000000 --- a/src/skeleton/styles.module.sass +++ /dev/null @@ -1,26 +0,0 @@ -@import ../variables -@import ../animations - -.skeleton - display: block - border-radius: var(--border-radius) - background-color: rgba(0, 0, 0, 0.11) - position: relative - overflow: hidden - height: 100% - width: auto - box-sizing: border-box - - &:after - animation: left-to-right-wave 2s linear 0.5s infinite - background: linear-gradient( 90deg, transparent, rgba(0, 0, 0, 0.04), transparent ) - content: '' - position: absolute - -webkit-transform: translateX(-100%) - -moz-transform: translateX(-100%) - -ms-transform: translateX(-100%) - transform: translateX(-100%) - bottom: 0 - left: 0 - right: 0 - top: 0 diff --git a/src/spinner/styles.module.sass b/src/spinner/styles.module.sass deleted file mode 100644 index a474022..0000000 --- a/src/spinner/styles.module.sass +++ /dev/null @@ -1,5 +0,0 @@ -@import ../variables -@import ../animations - -.spinner - animation: animation-spin 1s linear infinite diff --git a/src/styles.d.ts b/src/styles.d.ts new file mode 100644 index 0000000..c16c1f7 --- /dev/null +++ b/src/styles.d.ts @@ -0,0 +1,4 @@ +declare module '*.module.sass' { + const classes: { [key: string]: string } + export default classes +} diff --git a/src/animations.sass b/src/styles/animations.sass similarity index 100% rename from src/animations.sass rename to src/styles/animations.sass diff --git a/src/global.css b/src/styles/global.css similarity index 88% rename from src/global.css rename to src/styles/global.css index 90cccb6..4a44849 100644 --- a/src/global.css +++ b/src/styles/global.css @@ -1,5 +1,19 @@ /* global.css */ :root { + --color-green: #4bb34b; + --color-green-hover: #48AC4A; + --color-green-active: #45A64A; + + --color-orange: #F8A01C; + --color-orange-hover: #EE9A1D; + --color-orange-active: #E4941F; + + --color-red: #e64646; + --color-red-hover: #DD4446; + --color-red-active: #D44245; + + --color-contrast: #FFF; + --font-size: 14px; --font-family: -apple-system, system-ui, 'Helvetica Neue', Roboto, sans-serif; --letter-spacing: 0.00938em; @@ -47,28 +61,24 @@ --overlay-background: rgba(242, 243, 252, 0.7); + /* Buttons */ + --button-font-weight: 500; --button-default-background: transparent; --button-default-color: #3770b1; --button-default-background-hover: #f7f8fa; --button-default-background-active: #f1f2f5; + --button-primary-background: #2688eb; --button-primary-color: #ffffff; --button-primary-background-hover: #2483e4; --button-primary-background-active: #237edd; - --button-negative-background: #e64646; - --button-negative-color: #ffffff; - --button-negative-background-hover: #DD4446; - --button-negative-background-active: #D44245; + --button-secondary-background: rgba(235,242,250,.99); - --button-secondary-color: #3770b1; --button-secondary-background-hover: rgba(223,234,246,.99); + --button-secondary-color: #3770b1; --button-secondary-color-hover: #356cac; --button-secondary-background-active: rgba(213,226,241,.99); --button-secondary-color-active: #3368a8; - - --color-green: #4bb34b; - --color-orange: #ea5d2e; - --color-red: #e64646; } body { diff --git a/src/tabs/TabHeader.tsx b/src/tabs/TabHeader.tsx deleted file mode 100644 index c7f6882..0000000 --- a/src/tabs/TabHeader.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import React from 'react' - -import styles from './styles.module.sass' - -import { concatClassNames as cn } from '@/tools' - -interface TabItemProps extends React.InputHTMLAttributes { - label?: string - isActive?: boolean -} - -const TabHeader: React.FC = ({ label, isActive, ...props }) => ( - -) - -export default TabHeader diff --git a/src/tabs/Tabs.tsx b/src/tabs/Tabs.tsx deleted file mode 100644 index e80a78f..0000000 --- a/src/tabs/Tabs.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import React from 'react' - -import styles from './styles.module.sass' -import TabHeader from './TabHeader' - -import Container, { ContainerProps } from '@/container' -import { concatClassNames as cn } from '@/tools' - -type TabType = { - label: string - key: T -} - -interface TabsProps extends ContainerProps { - children?: React.ReactNode - tabs?: TabType[] - activeTab?: T - onChangeTab?: (key?: T) => void -} - -const Tabs = ({ tabs, activeTab, children, onChangeTab, ...props }: TabsProps) => ( - - {tabs?.map(({ label, key }) => ( - onChangeTab?.(key)} - isActive={activeTab === key} - /> - ))} -
- } - > - {children} - -) - -export default Tabs diff --git a/src/tabs/index.ts b/src/tabs/index.ts deleted file mode 100644 index 07f8ccc..0000000 --- a/src/tabs/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './Tabs' diff --git a/src/tabs/styles.module.sass b/src/tabs/styles.module.sass deleted file mode 100644 index 3a83263..0000000 --- a/src/tabs/styles.module.sass +++ /dev/null @@ -1,68 +0,0 @@ -@import ../variables - -.tabs - .tabsHeader - display: flex - align-items: stretch - width: 100% - overflow-y: auto - - .tabsHeaderItem - position: relative - flex-basis: auto - flex-grow: 1 - flex-shrink: 0 - min-width: 48px - padding: 10px 30px - max-width: 100% - overflow: hidden - text-overflow: ellipsis - transition: color .15s ease-out, background-color .15s ease-out - white-space: nowrap - cursor: pointer - border: none - background-color: transparent - border-radius: var(--border-radius) - color: var(--text-color-secondary) - font-family: var(--font-family) - font-size: var(--font-size) - margin-right: 10px - font-weight: 500 - - @media only screen and (max-width: $mobileMaxWidth) - min-width: 24px - padding: 6px 10px - - &:last-of-type - margin-right: 0 - - &:hover - background-color: var(--overlay-background) - - &.active - color: var(--text-color-primary) - background-color: var(--input-background-content) - - .itemBottom - background: var(--link-color) - border-radius: 2px - bottom: 3px - left: 5px - right: 5px - height: 2px - opacity: 0 - pointer-events: none - position: absolute - transition: opacity .15s ease-out - display: none - - &.active - opacity: 1 - - &.noContent - padding-bottom: 0 - - & > div:first-of-type - border-bottom: 0 - margin-bottom: 0 - padding: 0 10px 10px diff --git a/src/textarea/Textarea.tsx b/src/textarea/Textarea.tsx deleted file mode 100644 index 6b0d9da..0000000 --- a/src/textarea/Textarea.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import React, { useRef } from 'react' - -import styles from './styles.module.sass' - -import { concatClassNames as cn } from '@/tools' - -interface TextareaProps extends Omit, 'onChange'> { - label?: string - disableAutoresize?: boolean - onChange?: (value?: string) => void -} - -const Textarea: React.FC = ({ label, onChange, disableAutoresize, ...props }) => { - const textAreaRef = useRef(null) - - const handleChange = (evt: React.ChangeEvent): void => { - onChange?.(evt.target.value) - - if (textAreaRef.current && !disableAutoresize) { - textAreaRef.current.style.height = 'inherit' - textAreaRef.current.style.height = `${textAreaRef.current.scrollHeight}px` - } - } - - return ( -
- {label && } - -